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.SpecializedFunction.LinkLogic; 42 import jdk.nashorn.internal.objects.annotations.Where; 43 import 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 */ 50 public 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 int getPrototypeMemberCount() { 130 int count = 0; 131 for (final MemberInfo memInfo : members) { 132 if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) { 133 count++; 134 } 135 } 136 return count; 137 } 138 139 int getConstructorMemberCount() { 140 int count = 0; 141 for (final MemberInfo memInfo : members) { 142 if (memInfo.getWhere() == Where.CONSTRUCTOR) { 143 count++; 144 } 145 } 146 return count; 147 } 148 149 int getInstancePropertyCount() { 150 int count = 0; 151 for (final MemberInfo memInfo : members) { 152 if (memInfo.getWhere() == Where.INSTANCE) { 153 count++; 154 } 155 } 156 return count; 157 } 158 159 MemberInfo find(final String findJavaName, final String findJavaDesc, final int findAccess) { 160 for (final MemberInfo memInfo : members) { 161 if (memInfo.getJavaName().equals(findJavaName) && 162 memInfo.getJavaDesc().equals(findJavaDesc) && 163 memInfo.getJavaAccess() == findAccess) { 164 return memInfo; 165 } 166 } 167 return null; 168 } 169 170 List<MemberInfo> findSpecializations(final String methodName) { 171 final List<MemberInfo> res = new LinkedList<>(); 172 for (final MemberInfo memInfo : members) { 173 if (memInfo.getName().equals(methodName) && 174 memInfo.getKind() == Kind.SPECIALIZED_FUNCTION) { 175 res.add(memInfo); 176 } 177 } 178 return Collections.unmodifiableList(res); 179 } 180 181 MemberInfo findSetter(final MemberInfo getter) { 182 assert getter.getKind() == Kind.GETTER : "getter expected"; 183 final String getterName = getter.getName(); 184 final Where getterWhere = getter.getWhere(); 185 for (final MemberInfo memInfo : members) { 186 if (memInfo.getKind() == Kind.SETTER && 187 getterName.equals(memInfo.getName()) && 188 getterWhere == memInfo.getWhere()) { 189 return memInfo; 190 } 191 } 192 return null; 193 } 194 195 /** 196 * @return the javaName 197 */ 198 public String getJavaName() { 199 return javaName; 200 } 201 202 /** 203 * @param javaName the javaName to set 204 */ 205 void setJavaName(final String javaName) { 206 this.javaName = javaName; 207 } 208 209 String getConstructorClassName() { 210 return getJavaName() + StringConstants.CONSTRUCTOR_SUFFIX; 211 } 212 213 String getPrototypeClassName() { 214 return getJavaName() + StringConstants.PROTOTYPE_SUFFIX; 215 } 216 217 void verify() { 218 boolean constructorSeen = false; 219 for (final MemberInfo memInfo : getMembers()) { 220 if (memInfo.isConstructor()) { 221 if (constructorSeen) { 222 error("more than @Constructor method"); 223 } 224 constructorSeen = true; 225 } 226 try { 227 memInfo.verify(); 228 } catch (final Exception e) { 229 error(e.getMessage()); 230 } 231 } 232 } 233 234 private void error(final String msg) throws RuntimeException { 235 throw new RuntimeException(javaName + " : " + msg); 236 } 237 }