MemberInfo.java revision 819:e008b751c93f
1104862Sru/*
2104862Sru * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3114402Sru * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4104862Sru *
5104862Sru * This code is free software; you can redistribute it and/or modify it
6104862Sru * under the terms of the GNU General Public License version 2 only, as
7104862Sru * published by the Free Software Foundation.  Oracle designates this
8104862Sru * particular file as subject to the "Classpath" exception as provided
9104862Sru * by Oracle in the LICENSE file that accompanied this code.
10104862Sru *
11151497Sru * This code is distributed in the hope that it will be useful, but WITHOUT
12104862Sru * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13104862Sru * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1479543Sru * version 2 for more details (a copy is included in the LICENSE file that
15104862Sru * accompanied this code).
1618099Spst *
17104862Sru * You should have received a copy of the GNU General Public License version
1818099Spst * 2 along with this work; if not, write to the Free Software Foundation,
19104862Sru * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20151497Sru *
2118099Spst * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22151497Sru * or visit www.oracle.com if you need additional information or have any
23104862Sru * questions.
24104862Sru */
25104862Sru
26104862Srupackage jdk.nashorn.internal.tools.nasgen;
27104862Sru
28104862Sruimport static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DESC;
29104862Sruimport static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
30104862Sru
31104862Sruimport jdk.internal.org.objectweb.asm.Opcodes;
32104862Sruimport jdk.internal.org.objectweb.asm.Type;
33104862Sruimport jdk.nashorn.internal.objects.annotations.Where;
3418099Spst
35104862Sru/**
36104862Sru * Details about a Java method or field annotated with any of the field/method
37104862Sru * annotations from the jdk.nashorn.internal.objects.annotations package.
38104862Sru */
39104862Srupublic final class MemberInfo implements Cloneable {
40151497Sru    /**
41151497Sru     * The different kinds of available class annotations
42151497Sru     */
43104862Sru    public static enum Kind {
44104862Sru        /** This is a script class */
45104862Sru        SCRIPT_CLASS,
46104862Sru        /** This is a constructor */
47104862Sru        CONSTRUCTOR,
4818099Spst        /** This is a function */
49104862Sru        FUNCTION,
50104862Sru        /** This is a getter */
51104862Sru        GETTER,
52104862Sru        /** This is a setter */
53104862Sru        SETTER,
5418099Spst        /** This is a property */
55114402Sru        PROPERTY,
56114402Sru        /** This is a specialized version of a function */
57114402Sru        SPECIALIZED_FUNCTION,
58114402Sru        /** This is a specialized version of a constructor */
59114402Sru        SPECIALIZED_CONSTRUCTOR
60114402Sru    }
61114402Sru
62114402Sru    // keep in sync with jdk.nashorn.internal.objects.annotations.Attribute
63114402Sru    static final int DEFAULT_ATTRIBUTES = 0x0;
64114402Sru
65114402Sru    static final int DEFAULT_ARITY = -2;
66114402Sru
67114402Sru    // the kind of the script annotation - one of the above constants
68114402Sru    private MemberInfo.Kind kind;
69114402Sru    // script property name
70114402Sru    private String name;
71114402Sru    // script property attributes
72114402Sru    private int attributes;
73114402Sru    // name of the java member
74114402Sru    private String javaName;
75104862Sru    // type descriptor of the java member
76114402Sru    private String javaDesc;
77104862Sru    // access bits of the Java field or method
78104862Sru    private int javaAccess;
79114402Sru    // initial value for static @Property fields
80104862Sru    private Object value;
8118099Spst    // class whose object is created to fill property value
82114402Sru    private String initClass;
83114402Sru    // arity of the Function or Constructor
84114402Sru    private int arity;
85114402Sru
86114402Sru    private Where where;
87114402Sru
88114402Sru    /**
89114402Sru     * @return the kind
90114402Sru     */
91114402Sru    public Kind getKind() {
92114402Sru        return kind;
93114402Sru    }
94114402Sru
95114402Sru    /**
96114402Sru     * @param kind the kind to set
9718099Spst     */
98104862Sru    public void setKind(final Kind kind) {
99104862Sru        this.kind = kind;
100104862Sru    }
101104862Sru
102104862Sru    /**
103114402Sru     * @return the name
104104862Sru     */
105104862Sru    public String getName() {
106114402Sru        return name;
107114402Sru    }
108114402Sru
109114402Sru    /**
110114402Sru     * @param name the name to set
11118099Spst     */
112104862Sru    public void setName(final String name) {
113114402Sru        this.name = name;
114114402Sru    }
115114402Sru
116114402Sru    /**
117114402Sru     * @return the attributes
118114402Sru     */
119114402Sru    public int getAttributes() {
12018099Spst        return attributes;
121104862Sru    }
122114402Sru
123114402Sru    /**
124104862Sru     * @param attributes the attributes to set
125114402Sru     */
126114402Sru    public void setAttributes(final int attributes) {
127114402Sru        this.attributes = attributes;
128104862Sru    }
129104862Sru
130114402Sru    /**
131114402Sru     * @return the javaName
132114402Sru     */
133114402Sru    public String getJavaName() {
134114402Sru        return javaName;
135114402Sru    }
136104862Sru
137104862Sru    /**
138114402Sru     * @param javaName the javaName to set
139104862Sru     */
14018099Spst    public void setJavaName(final String javaName) {
141114402Sru        this.javaName = javaName;
14218099Spst    }
143104862Sru
144114402Sru    /**
145114402Sru     * @return the javaDesc
146114402Sru     */
147114402Sru    public String getJavaDesc() {
148114402Sru        return javaDesc;
149114402Sru    }
150114402Sru
151114402Sru    void setJavaDesc(final String javaDesc) {
152114402Sru        this.javaDesc = javaDesc;
153114402Sru    }
154114402Sru
155114402Sru    int getJavaAccess() {
156114402Sru        return javaAccess;
157114402Sru    }
158114402Sru
159114402Sru    void setJavaAccess(final int access) {
160114402Sru        this.javaAccess = access;
161104862Sru    }
162104862Sru
163114402Sru    Object getValue() {
16418099Spst        return value;
16518099Spst    }
166114402Sru
16718099Spst    void setValue(final Object value) {
168104862Sru        this.value = value;
169114402Sru    }
170114402Sru
171114402Sru    Where getWhere() {
172114402Sru        return where;
173114402Sru    }
174114402Sru
175114402Sru    void setWhere(final Where where) {
176114402Sru        this.where = where;
177114402Sru    }
178114402Sru
179114402Sru    boolean isFinal() {
180114402Sru        return (javaAccess & Opcodes.ACC_FINAL) != 0;
181114402Sru    }
182114402Sru
183114402Sru    boolean isStatic() {
184114402Sru        return (javaAccess & Opcodes.ACC_STATIC) != 0;
185114402Sru    }
186104862Sru
187114402Sru    boolean isStaticFinal() {
188104862Sru        return isStatic() && isFinal();
189104862Sru    }
190114402Sru
191114402Sru    boolean isInstanceGetter() {
192114402Sru        return kind == Kind.GETTER && where == Where.INSTANCE;
193114402Sru    }
194114402Sru
195114402Sru    /**
196114402Sru     * Check whether this MemberInfo is a getter that resides in the instance
197114402Sru     * @return true if instance setter
198114402Sru     */
199114402Sru    boolean isInstanceSetter() {
200114402Sru        return kind == Kind.SETTER && where == Where.INSTANCE;
201114402Sru    }
202114402Sru
203114402Sru    boolean isInstanceProperty() {
204114402Sru        return kind == Kind.PROPERTY && where == Where.INSTANCE;
205114402Sru    }
206114402Sru
207114402Sru    boolean isInstanceFunction() {
208114402Sru        return kind == Kind.FUNCTION && where == Where.INSTANCE;
209114402Sru    }
210114402Sru
211114402Sru    boolean isPrototypeGetter() {
212114402Sru        return kind == Kind.GETTER && where == Where.PROTOTYPE;
213114402Sru    }
214114402Sru
215114402Sru    boolean isPrototypeSetter() {
216114402Sru        return kind == Kind.SETTER && where == Where.PROTOTYPE;
217114402Sru    }
218114402Sru
219114402Sru    boolean isPrototypeProperty() {
220114402Sru        return kind == Kind.PROPERTY && where == Where.PROTOTYPE;
221114402Sru    }
222104862Sru
223114402Sru    boolean isPrototypeFunction() {
224104862Sru        return kind == Kind.FUNCTION && where == Where.PROTOTYPE;
225114402Sru    }
22618099Spst
22718099Spst    boolean isConstructorGetter() {
228114402Sru        return kind == Kind.GETTER && where == Where.CONSTRUCTOR;
229114402Sru    }
230114402Sru
231114402Sru    boolean isConstructorSetter() {
232114402Sru        return kind == Kind.SETTER && where == Where.CONSTRUCTOR;
233114402Sru    }
234114402Sru
235114402Sru    boolean isConstructorProperty() {
236114402Sru        return kind == Kind.PROPERTY && where == Where.CONSTRUCTOR;
237114402Sru    }
238114402Sru
239114402Sru    boolean isConstructorFunction() {
240114402Sru        return kind == Kind.FUNCTION && where == Where.CONSTRUCTOR;
241114402Sru    }
242114402Sru
243114402Sru    boolean isConstructor() {
244114402Sru        return kind == Kind.CONSTRUCTOR;
245114402Sru    }
246114402Sru
247114402Sru    void verify() {
248114402Sru        if (kind == Kind.CONSTRUCTOR) {
249114402Sru            final Type returnType = Type.getReturnType(javaDesc);
250114402Sru            if (! returnType.toString().equals(OBJECT_DESC)) {
251114402Sru                error("return value should be of Object type, found " + returnType);
252114402Sru            }
253114402Sru            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
254114402Sru            if (argTypes.length < 2) {
255114402Sru                error("constructor methods should have at least 2 args");
256114402Sru            }
257114402Sru            if (! argTypes[0].equals(Type.BOOLEAN_TYPE)) {
258114402Sru                error("first argument should be of boolean type, found " + argTypes[0]);
259114402Sru            }
260114402Sru            if (! argTypes[1].toString().equals(OBJECT_DESC)) {
261114402Sru                error("second argument should be of Object type, found " + argTypes[0]);
262114402Sru            }
263114402Sru
264114402Sru            if (argTypes.length > 2) {
265114402Sru                for (int i = 2; i < argTypes.length - 1; i++) {
266114402Sru                    if (! argTypes[i].toString().equals(OBJECT_DESC)) {
267114402Sru                        error(i + "'th argument should be of Object type, found " + argTypes[i]);
268114402Sru                    }
269114402Sru                }
270114402Sru
271114402Sru                final String lastArgType = argTypes[argTypes.length - 1].toString();
272114402Sru                final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
273114402Sru                if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
274114402Sru                    error("last argument is neither Object nor Object[] type: " + lastArgType);
275114402Sru                }
276114402Sru
277114402Sru                if (isVarArg && argTypes.length > 3) {
278114402Sru                    error("vararg constructor has more than 3 arguments");
279114402Sru                }
280114402Sru            }
281114402Sru        } else if (kind == Kind.FUNCTION) {
282114402Sru            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
283114402Sru            if (argTypes.length < 1) {
284114402Sru                error("function methods should have at least 1 arg");
28518099Spst            }
286104862Sru            if (! argTypes[0].toString().equals(OBJECT_DESC)) {
287104862Sru                error("first argument should be of Object type, found " + argTypes[0]);
288104862Sru            }
289114402Sru
29018099Spst            if (argTypes.length > 1) {
29118099Spst                for (int i = 1; i < argTypes.length - 1; i++) {
292114402Sru                    if (! argTypes[i].toString().equals(OBJECT_DESC)) {
293114402Sru                        error(i + "'th argument should be of Object type, found " + argTypes[i]);
294114402Sru                    }
295114402Sru                }
29618099Spst
297114402Sru                final String lastArgType = argTypes[argTypes.length - 1].toString();
298114402Sru                final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
299114402Sru                if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
300114402Sru                    error("last argument is neither Object nor Object[] type: " + lastArgType);
301114402Sru                }
302114402Sru
303114402Sru                if (isVarArg && argTypes.length > 2) {
304114402Sru                    error("vararg function has more than 2 arguments");
305114402Sru                }
306114402Sru            }
307114402Sru        } else if (kind == Kind.GETTER) {
308114402Sru            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
309114402Sru            if (argTypes.length != 1) {
310114402Sru                error("getter methods should have one argument");
311114402Sru            }
312114402Sru            if (! argTypes[0].toString().equals(OBJECT_DESC)) {
313114402Sru                error("first argument of getter should be of Object type, found: " + argTypes[0]);
314114402Sru            }
315114402Sru            if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) {
316114402Sru                error("return type of getter should not be void");
317114402Sru            }
318114402Sru        } else if (kind == Kind.SETTER) {
319114402Sru            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
320114402Sru            if (argTypes.length != 2) {
321114402Sru                error("setter methods should have two arguments");
322114402Sru            }
323114402Sru            if (! argTypes[0].toString().equals(OBJECT_DESC)) {
324114402Sru                error("first argument of setter should be of Object type, found: " + argTypes[0]);
325114402Sru            }
326114402Sru            if (!Type.getReturnType(javaDesc).toString().equals("V")) {
327114402Sru                error("return type of setter should be void, found: " + Type.getReturnType(javaDesc));
328114402Sru            }
329114402Sru        }
330114402Sru    }
331114402Sru
332114402Sru    private void error(final String msg) {
333114402Sru        throw new RuntimeException(javaName + javaDesc + " : " + msg);
334114402Sru    }
335114402Sru
336114402Sru    /**
337114402Sru     * @return the initClass
33818099Spst     */
339104862Sru    String getInitClass() {
340104862Sru        return initClass;
341114402Sru    }
34218099Spst
343114402Sru    /**
344114402Sru     * @param initClass the initClass to set
34518099Spst     */
346104862Sru    void setInitClass(final String initClass) {
347114402Sru        this.initClass = initClass;
348114402Sru    }
349114402Sru
35018099Spst    @Override
351104862Sru    protected Object clone() {
352114402Sru        try {
353114402Sru            return super.clone();
354104862Sru        } catch (final CloneNotSupportedException e) {
355104862Sru            assert false : "clone not supported " + e;
356104862Sru            return null;
357104862Sru        }
358104862Sru    }
359104862Sru
360114402Sru    /**
361104862Sru     * @return the arity
362114402Sru     */
363104862Sru    int getArity() {
364104862Sru        return arity;
365104862Sru    }
366104862Sru
367104862Sru    /**
368104862Sru     * @param arity the arity to set
369114402Sru     */
370114402Sru    void setArity(final int arity) {
371114402Sru        this.arity = arity;
372114402Sru    }
373104862Sru}
374104862Sru