ScriptClassInfo.java revision 1326:a35490e96dc5
1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.tools.nasgen; 27 28import java.util.Collections; 29import java.util.HashMap; 30import java.util.LinkedList; 31import java.util.List; 32import java.util.Map; 33import jdk.internal.org.objectweb.asm.Type; 34import jdk.nashorn.internal.objects.annotations.Constructor; 35import jdk.nashorn.internal.objects.annotations.Function; 36import jdk.nashorn.internal.objects.annotations.Getter; 37import jdk.nashorn.internal.objects.annotations.Property; 38import jdk.nashorn.internal.objects.annotations.ScriptClass; 39import jdk.nashorn.internal.objects.annotations.Setter; 40import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 41import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 42import jdk.nashorn.internal.objects.annotations.Where; 43import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; 44 45/** 46 * All annotation information from a class that is annotated with 47 * the annotation com.sun.oracle.objects.annotations.ScriptClass. 48 * 49 */ 50public final class ScriptClassInfo { 51 // descriptots for various annotations 52 static final String SCRIPT_CLASS_ANNO_DESC = Type.getDescriptor(ScriptClass.class); 53 static final String CONSTRUCTOR_ANNO_DESC = Type.getDescriptor(Constructor.class); 54 static final String FUNCTION_ANNO_DESC = Type.getDescriptor(Function.class); 55 static final String GETTER_ANNO_DESC = Type.getDescriptor(Getter.class); 56 static final String SETTER_ANNO_DESC = Type.getDescriptor(Setter.class); 57 static final String PROPERTY_ANNO_DESC = Type.getDescriptor(Property.class); 58 static final String WHERE_ENUM_DESC = Type.getDescriptor(Where.class); 59 static final String LINK_LOGIC_DESC = Type.getDescriptor(LinkLogic.class); 60 static final String SPECIALIZED_FUNCTION = Type.getDescriptor(SpecializedFunction.class); 61 62 static final Map<String, Kind> annotations = new HashMap<>(); 63 64 static { 65 annotations.put(SCRIPT_CLASS_ANNO_DESC, Kind.SCRIPT_CLASS); 66 annotations.put(FUNCTION_ANNO_DESC, Kind.FUNCTION); 67 annotations.put(CONSTRUCTOR_ANNO_DESC, Kind.CONSTRUCTOR); 68 annotations.put(GETTER_ANNO_DESC, Kind.GETTER); 69 annotations.put(SETTER_ANNO_DESC, Kind.SETTER); 70 annotations.put(PROPERTY_ANNO_DESC, Kind.PROPERTY); 71 annotations.put(SPECIALIZED_FUNCTION, Kind.SPECIALIZED_FUNCTION); 72 } 73 74 // name of the script class 75 private String name; 76 // member info for script properties 77 private List<MemberInfo> members = Collections.emptyList(); 78 // java class name that is annotated with @ScriptClass 79 private String javaName; 80 81 /** 82 * @return the name 83 */ 84 public String getName() { 85 return name; 86 } 87 88 /** 89 * @param name the name to set 90 */ 91 public void setName(final String name) { 92 this.name = name; 93 } 94 95 /** 96 * @return the members 97 */ 98 public List<MemberInfo> getMembers() { 99 return Collections.unmodifiableList(members); 100 } 101 102 /** 103 * @param members the members to set 104 */ 105 public void setMembers(final List<MemberInfo> members) { 106 this.members = members; 107 } 108 109 MemberInfo getConstructor() { 110 for (final MemberInfo memInfo : members) { 111 if (memInfo.getKind() == Kind.CONSTRUCTOR) { 112 return memInfo; 113 } 114 } 115 return null; 116 } 117 118 List<MemberInfo> getSpecializedConstructors() { 119 final List<MemberInfo> res = new LinkedList<>(); 120 for (final MemberInfo memInfo : members) { 121 if (memInfo.isSpecializedConstructor()) { 122 assert memInfo.getKind() == Kind.SPECIALIZED_FUNCTION; 123 res.add(memInfo); 124 } 125 } 126 return Collections.unmodifiableList(res); 127 } 128 129 boolean isConstructorNeeded() { 130 // Constructor class generation is needed if we one or 131 // more constructor properties are defined or @Constructor 132 // is defined in the class. 133 for (final MemberInfo memInfo : members) { 134 if (memInfo.getKind() == Kind.CONSTRUCTOR || 135 memInfo.getWhere() == Where.CONSTRUCTOR) { 136 return true; 137 } 138 } 139 return false; 140 } 141 142 boolean isPrototypeNeeded() { 143 // Prototype class generation is needed if we have atleast one 144 // prototype property or @Constructor defined in the class. 145 for (final MemberInfo memInfo : members) { 146 if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) { 147 return true; 148 } 149 } 150 return false; 151 } 152 153 int getPrototypeMemberCount() { 154 int count = 0; 155 for (final MemberInfo memInfo : members) { 156 switch (memInfo.getKind()) { 157 case SETTER: 158 case SPECIALIZED_FUNCTION: 159 // SETTER was counted when GETTER was encountered. 160 // SPECIALIZED_FUNCTION was counted as FUNCTION already. 161 continue; 162 } 163 164 if (memInfo.getWhere() == Where.PROTOTYPE) { 165 count++; 166 } 167 } 168 return count; 169 } 170 171 int getConstructorMemberCount() { 172 int count = 0; 173 for (final MemberInfo memInfo : members) { 174 switch (memInfo.getKind()) { 175 case CONSTRUCTOR: 176 case SETTER: 177 case SPECIALIZED_FUNCTION: 178 // SETTER was counted when GETTER was encountered. 179 // Constructor and constructor SpecializedFunctions 180 // are not added as members and so not counted. 181 continue; 182 } 183 184 if (memInfo.getWhere() == Where.CONSTRUCTOR) { 185 count++; 186 } 187 } 188 return count; 189 } 190 191 int getInstancePropertyCount() { 192 int count = 0; 193 for (final MemberInfo memInfo : members) { 194 switch (memInfo.getKind()) { 195 case SETTER: 196 case SPECIALIZED_FUNCTION: 197 // SETTER was counted when GETTER was encountered. 198 // SPECIALIZED_FUNCTION was counted as FUNCTION already. 199 continue; 200 } 201 202 if (memInfo.getWhere() == Where.INSTANCE) { 203 count++; 204 } 205 } 206 return count; 207 } 208 209 MemberInfo find(final String findJavaName, final String findJavaDesc, final int findAccess) { 210 for (final MemberInfo memInfo : members) { 211 if (memInfo.getJavaName().equals(findJavaName) && 212 memInfo.getJavaDesc().equals(findJavaDesc) && 213 memInfo.getJavaAccess() == findAccess) { 214 return memInfo; 215 } 216 } 217 return null; 218 } 219 220 List<MemberInfo> findSpecializations(final String methodName) { 221 final List<MemberInfo> res = new LinkedList<>(); 222 for (final MemberInfo memInfo : members) { 223 if (memInfo.getName().equals(methodName) && 224 memInfo.getKind() == Kind.SPECIALIZED_FUNCTION) { 225 res.add(memInfo); 226 } 227 } 228 return Collections.unmodifiableList(res); 229 } 230 231 MemberInfo findSetter(final MemberInfo getter) { 232 assert getter.getKind() == Kind.GETTER : "getter expected"; 233 final String getterName = getter.getName(); 234 final Where getterWhere = getter.getWhere(); 235 for (final MemberInfo memInfo : members) { 236 if (memInfo.getKind() == Kind.SETTER && 237 getterName.equals(memInfo.getName()) && 238 getterWhere == memInfo.getWhere()) { 239 return memInfo; 240 } 241 } 242 return null; 243 } 244 245 /** 246 * @return the javaName 247 */ 248 public String getJavaName() { 249 return javaName; 250 } 251 252 /** 253 * @param javaName the javaName to set 254 */ 255 void setJavaName(final String javaName) { 256 this.javaName = javaName; 257 } 258 259 String getConstructorClassName() { 260 return getJavaName() + StringConstants.CONSTRUCTOR_SUFFIX; 261 } 262 263 String getPrototypeClassName() { 264 return getJavaName() + StringConstants.PROTOTYPE_SUFFIX; 265 } 266 267 void verify() { 268 boolean constructorSeen = false; 269 for (final MemberInfo memInfo : getMembers()) { 270 if (memInfo.isConstructor()) { 271 if (constructorSeen) { 272 error("more than @Constructor method"); 273 } 274 constructorSeen = true; 275 } 276 try { 277 memInfo.verify(); 278 } catch (final Exception e) { 279 error(e.getMessage()); 280 } 281 } 282 } 283 284 private void error(final String msg) throws RuntimeException { 285 throw new RuntimeException(javaName + " : " + msg); 286 } 287} 288