ScriptClassInfo.java revision 1786:80120e9b3273
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.tools.nasgen.MemberInfo.Kind; 35 36import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJ_ANNO_PKG; 37import static jdk.nashorn.internal.tools.nasgen.StringConstants.RUNTIME_PKG; 38 39/** 40 * All annotation information from a class that is annotated with 41 * the annotation com.sun.oracle.objects.annotations.ScriptClass. 42 * 43 */ 44public final class ScriptClassInfo { 45 private static String getTypeDescriptor(final String pkg, final String name) { 46 return "L" + pkg + name + ";"; 47 } 48 49 // descriptors for various annotations 50 static final String SCRIPT_CLASS_ANNO_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "ScriptClass"); 51 static final String CONSTRUCTOR_ANNO_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "Constructor"); 52 static final String FUNCTION_ANNO_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "Function"); 53 static final String GETTER_ANNO_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "Getter"); 54 static final String SETTER_ANNO_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "Setter"); 55 static final String PROPERTY_ANNO_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "Property"); 56 static final String WHERE_ENUM_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "Where"); 57 static final String LINK_LOGIC_DESC = getTypeDescriptor(OBJ_ANNO_PKG, "SpecializedFunction$LinkLogic"); 58 static final String SPECIALIZED_FUNCTION = getTypeDescriptor(OBJ_ANNO_PKG, "SpecializedFunction"); 59 60 static final Map<String, Kind> annotations = new HashMap<>(); 61 62 static { 63 annotations.put(SCRIPT_CLASS_ANNO_DESC, Kind.SCRIPT_CLASS); 64 annotations.put(FUNCTION_ANNO_DESC, Kind.FUNCTION); 65 annotations.put(CONSTRUCTOR_ANNO_DESC, Kind.CONSTRUCTOR); 66 annotations.put(GETTER_ANNO_DESC, Kind.GETTER); 67 annotations.put(SETTER_ANNO_DESC, Kind.SETTER); 68 annotations.put(PROPERTY_ANNO_DESC, Kind.PROPERTY); 69 annotations.put(SPECIALIZED_FUNCTION, Kind.SPECIALIZED_FUNCTION); 70 } 71 72 // name of the script class 73 private String name; 74 // member info for script properties 75 private List<MemberInfo> members = Collections.emptyList(); 76 // java class name that is annotated with @ScriptClass 77 private String javaName; 78 79 /** 80 * @return the name 81 */ 82 public String getName() { 83 return name; 84 } 85 86 /** 87 * @param name the name to set 88 */ 89 public void setName(final String name) { 90 this.name = name; 91 } 92 93 /** 94 * @return the members 95 */ 96 public List<MemberInfo> getMembers() { 97 return Collections.unmodifiableList(members); 98 } 99 100 /** 101 * @param members the members to set 102 */ 103 public void setMembers(final List<MemberInfo> members) { 104 this.members = members; 105 } 106 107 MemberInfo getConstructor() { 108 for (final MemberInfo memInfo : members) { 109 if (memInfo.getKind() == Kind.CONSTRUCTOR) { 110 return memInfo; 111 } 112 } 113 return null; 114 } 115 116 List<MemberInfo> getSpecializedConstructors() { 117 final List<MemberInfo> res = new LinkedList<>(); 118 for (final MemberInfo memInfo : members) { 119 if (memInfo.isSpecializedConstructor()) { 120 assert memInfo.getKind() == Kind.SPECIALIZED_FUNCTION; 121 res.add(memInfo); 122 } 123 } 124 return Collections.unmodifiableList(res); 125 } 126 127 boolean isConstructorNeeded() { 128 // Constructor class generation is needed if we one or 129 // more constructor properties are defined or @Constructor 130 // is defined in the class. 131 for (final MemberInfo memInfo : members) { 132 if (memInfo.getKind() == Kind.CONSTRUCTOR || 133 memInfo.getWhere() == Where.CONSTRUCTOR) { 134 return true; 135 } 136 } 137 return false; 138 } 139 140 boolean isPrototypeNeeded() { 141 // Prototype class generation is needed if we have at least one 142 // prototype property or @Constructor defined in the class. 143 for (final MemberInfo memInfo : members) { 144 if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) { 145 return true; 146 } 147 } 148 return false; 149 } 150 151 int getPrototypeMemberCount() { 152 int count = 0; 153 for (final MemberInfo memInfo : members) { 154 switch (memInfo.getKind()) { 155 case SETTER: 156 case SPECIALIZED_FUNCTION: 157 // SETTER was counted when GETTER was encountered. 158 // SPECIALIZED_FUNCTION was counted as FUNCTION already. 159 continue; 160 } 161 162 if (memInfo.getWhere() == Where.PROTOTYPE) { 163 count++; 164 } 165 } 166 return count; 167 } 168 169 int getConstructorMemberCount() { 170 int count = 0; 171 for (final MemberInfo memInfo : members) { 172 switch (memInfo.getKind()) { 173 case CONSTRUCTOR: 174 case SETTER: 175 case SPECIALIZED_FUNCTION: 176 // SETTER was counted when GETTER was encountered. 177 // Constructor and constructor SpecializedFunctions 178 // are not added as members and so not counted. 179 continue; 180 } 181 182 if (memInfo.getWhere() == Where.CONSTRUCTOR) { 183 count++; 184 } 185 } 186 return count; 187 } 188 189 int getInstancePropertyCount() { 190 int count = 0; 191 for (final MemberInfo memInfo : members) { 192 switch (memInfo.getKind()) { 193 case SETTER: 194 case SPECIALIZED_FUNCTION: 195 // SETTER was counted when GETTER was encountered. 196 // SPECIALIZED_FUNCTION was counted as FUNCTION already. 197 continue; 198 } 199 200 if (memInfo.getWhere() == Where.INSTANCE) { 201 count++; 202 } 203 } 204 return count; 205 } 206 207 MemberInfo find(final String findJavaName, final String findJavaDesc, final int findAccess) { 208 for (final MemberInfo memInfo : members) { 209 if (memInfo.getJavaName().equals(findJavaName) && 210 memInfo.getJavaDesc().equals(findJavaDesc) && 211 memInfo.getJavaAccess() == findAccess) { 212 return memInfo; 213 } 214 } 215 return null; 216 } 217 218 List<MemberInfo> findSpecializations(final String methodName) { 219 final List<MemberInfo> res = new LinkedList<>(); 220 for (final MemberInfo memInfo : members) { 221 if (memInfo.getName().equals(methodName) && 222 memInfo.getKind() == Kind.SPECIALIZED_FUNCTION) { 223 res.add(memInfo); 224 } 225 } 226 return Collections.unmodifiableList(res); 227 } 228 229 MemberInfo findSetter(final MemberInfo getter) { 230 assert getter.getKind() == Kind.GETTER : "getter expected"; 231 final String getterName = getter.getName(); 232 final Where getterWhere = getter.getWhere(); 233 for (final MemberInfo memInfo : members) { 234 if (memInfo.getKind() == Kind.SETTER && 235 getterName.equals(memInfo.getName()) && 236 getterWhere == memInfo.getWhere()) { 237 return memInfo; 238 } 239 } 240 return null; 241 } 242 243 /** 244 * @return the javaName 245 */ 246 public String getJavaName() { 247 return javaName; 248 } 249 250 /** 251 * @param javaName the javaName to set 252 */ 253 void setJavaName(final String javaName) { 254 this.javaName = javaName; 255 } 256 257 String getConstructorClassName() { 258 return getJavaName() + StringConstants.CONSTRUCTOR_SUFFIX; 259 } 260 261 String getPrototypeClassName() { 262 return getJavaName() + StringConstants.PROTOTYPE_SUFFIX; 263 } 264 265 void verify() { 266 boolean constructorSeen = false; 267 for (final MemberInfo memInfo : getMembers()) { 268 if (memInfo.isConstructor()) { 269 if (constructorSeen) { 270 error("more than @Constructor method"); 271 } 272 constructorSeen = true; 273 } 274 try { 275 memInfo.verify(); 276 } catch (final Exception e) { 277 e.printStackTrace(); 278 error(e.getMessage()); 279 } 280 } 281 } 282 283 private void error(final String msg) throws RuntimeException { 284 throw new RuntimeException(javaName + " : " + msg); 285 } 286} 287