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 26 package jdk.nashorn.internal.tools.nasgen; 27 28 import java.util.Collections; 29 import java.util.HashMap; 30 import java.util.LinkedList; 31 import java.util.List; 32 import java.util.Map; 33 import jdk.internal.org.objectweb.asm.Type; 34 import jdk.nashorn.internal.objects.annotations.Constructor; 35 import jdk.nashorn.internal.objects.annotations.Function; 36 import jdk.nashorn.internal.objects.annotations.Getter; 37 import jdk.nashorn.internal.objects.annotations.Property; 38 import jdk.nashorn.internal.objects.annotations.ScriptClass; 39 import jdk.nashorn.internal.objects.annotations.Setter; 40 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 41 import jdk.nashorn.internal.objects.annotations.Where; 42 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; 43 44 /** 45 * All annotation information from a class that is annotated with 46 * the annotation com.sun.oracle.objects.annotations.ScriptClass. 47 * 48 */ 49 public final class ScriptClassInfo { 50 // descriptots for various annotations 51 static final String SCRIPT_CLASS_ANNO_DESC = Type.getDescriptor(ScriptClass.class); 52 static final String CONSTRUCTOR_ANNO_DESC = Type.getDescriptor(Constructor.class); 53 static final String FUNCTION_ANNO_DESC = Type.getDescriptor(Function.class); 54 static final String GETTER_ANNO_DESC = Type.getDescriptor(Getter.class); 55 static final String SETTER_ANNO_DESC = Type.getDescriptor(Setter.class); 56 static final String PROPERTY_ANNO_DESC = Type.getDescriptor(Property.class); 57 static final String WHERE_ENUM_DESC = Type.getDescriptor(Where.class); 58 static final String SPECIALIZED_FUNCTION = Type.getDescriptor(SpecializedFunction.class); 59 static final String LINK_LOGIC_DESC = "Ljdk/nashorn/internal/objects/annotations/SpecializedFunction$LinkLogic;"; 60 61 static final Map<String, Kind> annotations = new HashMap<>(); 62 63 static { 64 annotations.put(SCRIPT_CLASS_ANNO_DESC, Kind.SCRIPT_CLASS); 65 annotations.put(FUNCTION_ANNO_DESC, Kind.FUNCTION); 66 annotations.put(CONSTRUCTOR_ANNO_DESC, Kind.CONSTRUCTOR); 67 annotations.put(GETTER_ANNO_DESC, Kind.GETTER); 68 annotations.put(SETTER_ANNO_DESC, Kind.SETTER); 69 annotations.put(PROPERTY_ANNO_DESC, Kind.PROPERTY); 70 annotations.put(SPECIALIZED_FUNCTION, Kind.SPECIALIZED_FUNCTION); 71 } 72 73 // name of the script class 74 private String name; 75 // member info for script properties 76 private List<MemberInfo> members = Collections.emptyList(); 77 // java class name that is annotated with @ScriptClass 78 private String javaName; 79 80 /** 81 * @return the name 82 */ 83 public String getName() { 84 return name; 85 } 86 87 /** 88 * @param name the name to set 89 */ 90 public void setName(final String name) { 91 this.name = name; 92 } 93 94 /** 95 * @return the members 96 */ 97 public List<MemberInfo> getMembers() { 98 return Collections.unmodifiableList(members); 99 } 100 101 /** 102 * @param members the members to set 103 */ 104 public void setMembers(final List<MemberInfo> members) { 105 this.members = members; 106 } 107 108 MemberInfo getConstructor() { 109 for (final MemberInfo memInfo : members) { 110 if (memInfo.getKind() == Kind.CONSTRUCTOR) { 111 return memInfo; 112 } 113 } 114 return null; 115 } 116 117 List<MemberInfo> getSpecializedConstructors() { 118 final List<MemberInfo> res = new LinkedList<>(); 119 for (final MemberInfo memInfo : members) { 120 if (memInfo.isSpecializedConstructor()) { 121 assert memInfo.getKind() == Kind.SPECIALIZED_FUNCTION; 122 res.add(memInfo); 123 } 124 } 125 return Collections.unmodifiableList(res); 126 } 127 128 int getPrototypeMemberCount() { 129 int count = 0; 130 for (final MemberInfo memInfo : members) { 131 if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) { 132 count++; 133 } 134 } 135 return count; 136 } 137 138 int getConstructorMemberCount() { 139 int count = 0; 140 for (final MemberInfo memInfo : members) { 141 if (memInfo.getWhere() == Where.CONSTRUCTOR) { 142 count++; 143 } 144 } 145 return count; 146 } 147 148 int getInstancePropertyCount() { 149 int count = 0; 150 for (final MemberInfo memInfo : members) { 151 if (memInfo.getWhere() == Where.INSTANCE) { 152 count++; 153 } 154 } 155 return count; 156 } 157 158 MemberInfo find(final String findJavaName, final String findJavaDesc, final int findAccess) { 159 for (final MemberInfo memInfo : members) { 160 if (memInfo.getJavaName().equals(findJavaName) && 161 memInfo.getJavaDesc().equals(findJavaDesc) && 162 memInfo.getJavaAccess() == findAccess) { 163 return memInfo; 164 } 165 } 166 return null; 167 } 168 169 List<MemberInfo> findSpecializations(final String methodName) { 170 final List<MemberInfo> res = new LinkedList<>(); 171 for (final MemberInfo memInfo : members) { 172 if (memInfo.getName().equals(methodName) && 173 memInfo.getKind() == Kind.SPECIALIZED_FUNCTION) { 174 res.add(memInfo); 175 } 176 } 177 return Collections.unmodifiableList(res); 178 } 179 180 MemberInfo findSetter(final MemberInfo getter) { 181 assert getter.getKind() == Kind.GETTER : "getter expected"; 182 final String getterName = getter.getName(); 183 final Where getterWhere = getter.getWhere(); 184 for (final MemberInfo memInfo : members) { 185 if (memInfo.getKind() == Kind.SETTER && 186 getterName.equals(memInfo.getName()) && 187 getterWhere == memInfo.getWhere()) { 188 return memInfo; 189 } 190 } 191 return null; 192 } 193 194 /** 195 * @return the javaName 196 */ 197 public String getJavaName() { 198 return javaName; 199 } 200 201 /** 202 * @param javaName the javaName to set 203 */ 204 void setJavaName(final String javaName) { 205 this.javaName = javaName; 206 } 207 208 String getConstructorClassName() { 209 return getJavaName() + StringConstants.CONSTRUCTOR_SUFFIX; 210 } 211 212 String getPrototypeClassName() { 213 return getJavaName() + StringConstants.PROTOTYPE_SUFFIX; 214 } 215 216 void verify() { 217 boolean constructorSeen = false; 218 for (final MemberInfo memInfo : getMembers()) { 219 if (memInfo.isConstructor()) { 220 if (constructorSeen) { 221 error("more than @Constructor method"); 222 } 223 constructorSeen = true; 224 } 225 try { 226 memInfo.verify(); 227 } catch (final Exception e) { 228 error(e.getMessage()); 229 } 230 } 231 } 232 233 private void error(final String msg) throws RuntimeException { 234 throw new RuntimeException(javaName + " : " + msg); 235 } 236 }