xref: /aosp_15_r20/external/javassist/src/main/javassist/CtField.java (revision f1fbf3c2ab775ce834e0af96b7a85bdc7a0eac65)
1*f1fbf3c2SXin Li /*
2*f1fbf3c2SXin Li  * Javassist, a Java-bytecode translator toolkit.
3*f1fbf3c2SXin Li  * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
4*f1fbf3c2SXin Li  *
5*f1fbf3c2SXin Li  * The contents of this file are subject to the Mozilla Public License Version
6*f1fbf3c2SXin Li  * 1.1 (the "License"); you may not use this file except in compliance with
7*f1fbf3c2SXin Li  * the License.  Alternatively, the contents of this file may be used under
8*f1fbf3c2SXin Li  * the terms of the GNU Lesser General Public License Version 2.1 or later,
9*f1fbf3c2SXin Li  * or the Apache License Version 2.0.
10*f1fbf3c2SXin Li  *
11*f1fbf3c2SXin Li  * Software distributed under the License is distributed on an "AS IS" basis,
12*f1fbf3c2SXin Li  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13*f1fbf3c2SXin Li  * for the specific language governing rights and limitations under the
14*f1fbf3c2SXin Li  * License.
15*f1fbf3c2SXin Li  */
16*f1fbf3c2SXin Li 
17*f1fbf3c2SXin Li package javassist;
18*f1fbf3c2SXin Li 
19*f1fbf3c2SXin Li import java.util.List;
20*f1fbf3c2SXin Li 
21*f1fbf3c2SXin Li import javassist.bytecode.AccessFlag;
22*f1fbf3c2SXin Li import javassist.bytecode.AnnotationsAttribute;
23*f1fbf3c2SXin Li import javassist.bytecode.AttributeInfo;
24*f1fbf3c2SXin Li import javassist.bytecode.Bytecode;
25*f1fbf3c2SXin Li import javassist.bytecode.ClassFile;
26*f1fbf3c2SXin Li import javassist.bytecode.ConstPool;
27*f1fbf3c2SXin Li import javassist.bytecode.Descriptor;
28*f1fbf3c2SXin Li import javassist.bytecode.FieldInfo;
29*f1fbf3c2SXin Li import javassist.bytecode.SignatureAttribute;
30*f1fbf3c2SXin Li import javassist.compiler.CompileError;
31*f1fbf3c2SXin Li import javassist.compiler.Javac;
32*f1fbf3c2SXin Li import javassist.compiler.SymbolTable;
33*f1fbf3c2SXin Li import javassist.compiler.ast.ASTree;
34*f1fbf3c2SXin Li import javassist.compiler.ast.DoubleConst;
35*f1fbf3c2SXin Li import javassist.compiler.ast.IntConst;
36*f1fbf3c2SXin Li import javassist.compiler.ast.StringL;
37*f1fbf3c2SXin Li 
38*f1fbf3c2SXin Li /**
39*f1fbf3c2SXin Li  * An instance of CtField represents a field.
40*f1fbf3c2SXin Li  *
41*f1fbf3c2SXin Li  * @see CtClass#getDeclaredFields()
42*f1fbf3c2SXin Li  */
43*f1fbf3c2SXin Li public class CtField extends CtMember {
44*f1fbf3c2SXin Li     static final String javaLangString = "java.lang.String";
45*f1fbf3c2SXin Li 
46*f1fbf3c2SXin Li     protected FieldInfo fieldInfo;
47*f1fbf3c2SXin Li 
48*f1fbf3c2SXin Li     /**
49*f1fbf3c2SXin Li      * Creates a <code>CtField</code> object.
50*f1fbf3c2SXin Li      * The created field must be added to a class
51*f1fbf3c2SXin Li      * with <code>CtClass.addField()</code>.
52*f1fbf3c2SXin Li      * An initial value of the field is specified
53*f1fbf3c2SXin Li      * by a <code>CtField.Initializer</code> object.
54*f1fbf3c2SXin Li      *
55*f1fbf3c2SXin Li      * <p>If getter and setter methods are needed,
56*f1fbf3c2SXin Li      * call <code>CtNewMethod.getter()</code> and
57*f1fbf3c2SXin Li      * <code>CtNewMethod.setter()</code>.
58*f1fbf3c2SXin Li      *
59*f1fbf3c2SXin Li      * @param type              field type
60*f1fbf3c2SXin Li      * @param name              field name
61*f1fbf3c2SXin Li      * @param declaring         the class to which the field will be added.
62*f1fbf3c2SXin Li      *
63*f1fbf3c2SXin Li      * @see CtClass#addField(CtField)
64*f1fbf3c2SXin Li      * @see CtNewMethod#getter(String,CtField)
65*f1fbf3c2SXin Li      * @see CtNewMethod#setter(String,CtField)
66*f1fbf3c2SXin Li      * @see CtField.Initializer
67*f1fbf3c2SXin Li      */
CtField(CtClass type, String name, CtClass declaring)68*f1fbf3c2SXin Li     public CtField(CtClass type, String name, CtClass declaring)
69*f1fbf3c2SXin Li         throws CannotCompileException
70*f1fbf3c2SXin Li     {
71*f1fbf3c2SXin Li         this(Descriptor.of(type), name, declaring);
72*f1fbf3c2SXin Li     }
73*f1fbf3c2SXin Li 
74*f1fbf3c2SXin Li     /**
75*f1fbf3c2SXin Li      * Creates a copy of the given field.
76*f1fbf3c2SXin Li      * The created field must be added to a class
77*f1fbf3c2SXin Li      * with <code>CtClass.addField()</code>.
78*f1fbf3c2SXin Li      * An initial value of the field is specified
79*f1fbf3c2SXin Li      * by a <code>CtField.Initializer</code> object.
80*f1fbf3c2SXin Li      *
81*f1fbf3c2SXin Li      * <p>If getter and setter methods are needed,
82*f1fbf3c2SXin Li      * call <code>CtNewMethod.getter()</code> and
83*f1fbf3c2SXin Li      * <code>CtNewMethod.setter()</code>.
84*f1fbf3c2SXin Li      *
85*f1fbf3c2SXin Li      * @param src               the original field
86*f1fbf3c2SXin Li      * @param declaring         the class to which the field will be added.
87*f1fbf3c2SXin Li      * @see CtNewMethod#getter(String,CtField)
88*f1fbf3c2SXin Li      * @see CtNewMethod#setter(String,CtField)
89*f1fbf3c2SXin Li      * @see CtField.Initializer
90*f1fbf3c2SXin Li      */
CtField(CtField src, CtClass declaring)91*f1fbf3c2SXin Li     public CtField(CtField src, CtClass declaring)
92*f1fbf3c2SXin Li         throws CannotCompileException
93*f1fbf3c2SXin Li     {
94*f1fbf3c2SXin Li         this(src.fieldInfo.getDescriptor(), src.fieldInfo.getName(),
95*f1fbf3c2SXin Li              declaring);
96*f1fbf3c2SXin Li         FieldInfo fi = fieldInfo;
97*f1fbf3c2SXin Li         fi.setAccessFlags(src.fieldInfo.getAccessFlags());
98*f1fbf3c2SXin Li         ConstPool cp = fi.getConstPool();
99*f1fbf3c2SXin Li         List<AttributeInfo> attributes = src.fieldInfo.getAttributes();
100*f1fbf3c2SXin Li         for (AttributeInfo ainfo : attributes)
101*f1fbf3c2SXin Li             fi.addAttribute(ainfo.copy(cp, null));
102*f1fbf3c2SXin Li     }
103*f1fbf3c2SXin Li 
CtField(String typeDesc, String name, CtClass clazz)104*f1fbf3c2SXin Li     private CtField(String typeDesc, String name, CtClass clazz)
105*f1fbf3c2SXin Li         throws CannotCompileException
106*f1fbf3c2SXin Li     {
107*f1fbf3c2SXin Li         super(clazz);
108*f1fbf3c2SXin Li         ClassFile cf = clazz.getClassFile2();
109*f1fbf3c2SXin Li         if (cf == null)
110*f1fbf3c2SXin Li             throw new CannotCompileException("bad declaring class: "
111*f1fbf3c2SXin Li                                              + clazz.getName());
112*f1fbf3c2SXin Li 
113*f1fbf3c2SXin Li         fieldInfo = new FieldInfo(cf.getConstPool(), name, typeDesc);
114*f1fbf3c2SXin Li     }
115*f1fbf3c2SXin Li 
CtField(FieldInfo fi, CtClass clazz)116*f1fbf3c2SXin Li     CtField(FieldInfo fi, CtClass clazz) {
117*f1fbf3c2SXin Li         super(clazz);
118*f1fbf3c2SXin Li         fieldInfo = fi;
119*f1fbf3c2SXin Li     }
120*f1fbf3c2SXin Li 
121*f1fbf3c2SXin Li     /**
122*f1fbf3c2SXin Li      * Returns a String representation of the object.
123*f1fbf3c2SXin Li      */
124*f1fbf3c2SXin Li     @Override
toString()125*f1fbf3c2SXin Li     public String toString() {
126*f1fbf3c2SXin Li         return getDeclaringClass().getName() + "." + getName()
127*f1fbf3c2SXin Li                + ":" + fieldInfo.getDescriptor();
128*f1fbf3c2SXin Li     }
129*f1fbf3c2SXin Li 
130*f1fbf3c2SXin Li     @Override
extendToString(StringBuffer buffer)131*f1fbf3c2SXin Li     protected void extendToString(StringBuffer buffer) {
132*f1fbf3c2SXin Li         buffer.append(' ');
133*f1fbf3c2SXin Li         buffer.append(getName());
134*f1fbf3c2SXin Li         buffer.append(' ');
135*f1fbf3c2SXin Li         buffer.append(fieldInfo.getDescriptor());
136*f1fbf3c2SXin Li     }
137*f1fbf3c2SXin Li 
138*f1fbf3c2SXin Li     /* Javac.CtFieldWithInit overrides. */
getInitAST()139*f1fbf3c2SXin Li     protected ASTree getInitAST() { return null; }
140*f1fbf3c2SXin Li 
141*f1fbf3c2SXin Li     /* Called by CtClassType.addField(). */
getInit()142*f1fbf3c2SXin Li     Initializer getInit() {
143*f1fbf3c2SXin Li         ASTree tree = getInitAST();
144*f1fbf3c2SXin Li         if (tree == null)
145*f1fbf3c2SXin Li             return null;
146*f1fbf3c2SXin Li         return Initializer.byExpr(tree);
147*f1fbf3c2SXin Li     }
148*f1fbf3c2SXin Li 
149*f1fbf3c2SXin Li     /**
150*f1fbf3c2SXin Li      * Compiles the given source code and creates a field.
151*f1fbf3c2SXin Li      * Examples of the source code are:
152*f1fbf3c2SXin Li      *
153*f1fbf3c2SXin Li      * <pre>
154*f1fbf3c2SXin Li      * "public String name;"
155*f1fbf3c2SXin Li      * "public int k = 3;"</pre>
156*f1fbf3c2SXin Li      *
157*f1fbf3c2SXin Li      * <p>Note that the source code ends with <code>';'</code>
158*f1fbf3c2SXin Li      * (semicolon).
159*f1fbf3c2SXin Li      *
160*f1fbf3c2SXin Li      * @param src               the source text.
161*f1fbf3c2SXin Li      * @param declaring    the class to which the created field is added.
162*f1fbf3c2SXin Li      */
make(String src, CtClass declaring)163*f1fbf3c2SXin Li     public static CtField make(String src, CtClass declaring)
164*f1fbf3c2SXin Li         throws CannotCompileException
165*f1fbf3c2SXin Li     {
166*f1fbf3c2SXin Li         Javac compiler = new Javac(declaring);
167*f1fbf3c2SXin Li         try {
168*f1fbf3c2SXin Li             CtMember obj = compiler.compile(src);
169*f1fbf3c2SXin Li             if (obj instanceof CtField)
170*f1fbf3c2SXin Li                 return (CtField)obj; // an instance of Javac.CtFieldWithInit
171*f1fbf3c2SXin Li         }
172*f1fbf3c2SXin Li         catch (CompileError e) {
173*f1fbf3c2SXin Li             throw new CannotCompileException(e);
174*f1fbf3c2SXin Li         }
175*f1fbf3c2SXin Li 
176*f1fbf3c2SXin Li         throw new CannotCompileException("not a field");
177*f1fbf3c2SXin Li     }
178*f1fbf3c2SXin Li 
179*f1fbf3c2SXin Li     /**
180*f1fbf3c2SXin Li      * Returns the FieldInfo representing the field in the class file.
181*f1fbf3c2SXin Li      */
getFieldInfo()182*f1fbf3c2SXin Li     public FieldInfo getFieldInfo() {
183*f1fbf3c2SXin Li         declaringClass.checkModify();
184*f1fbf3c2SXin Li         return fieldInfo;
185*f1fbf3c2SXin Li     }
186*f1fbf3c2SXin Li 
187*f1fbf3c2SXin Li     /**
188*f1fbf3c2SXin Li      * Returns the FieldInfo representing the field in the class
189*f1fbf3c2SXin Li      * file (read only).
190*f1fbf3c2SXin Li      * Normal applications do not need calling this method.  Use
191*f1fbf3c2SXin Li      * <code>getFieldInfo()</code>.
192*f1fbf3c2SXin Li      *
193*f1fbf3c2SXin Li      * <p>The <code>FieldInfo</code> object obtained by this method
194*f1fbf3c2SXin Li      * is read only.  Changes to this object might not be reflected
195*f1fbf3c2SXin Li      * on a class file generated by <code>toBytecode()</code>,
196*f1fbf3c2SXin Li      * <code>toClass()</code>, etc in <code>CtClass</code>.
197*f1fbf3c2SXin Li      *
198*f1fbf3c2SXin Li      * <p>This method is available even if the <code>CtClass</code>
199*f1fbf3c2SXin Li      * containing this field is frozen.  However, if the class is
200*f1fbf3c2SXin Li      * frozen, the <code>FieldInfo</code> might be also pruned.
201*f1fbf3c2SXin Li      *
202*f1fbf3c2SXin Li      * @see #getFieldInfo()
203*f1fbf3c2SXin Li      * @see CtClass#isFrozen()
204*f1fbf3c2SXin Li      * @see CtClass#prune()
205*f1fbf3c2SXin Li      */
getFieldInfo2()206*f1fbf3c2SXin Li     public FieldInfo getFieldInfo2() { return fieldInfo; }
207*f1fbf3c2SXin Li 
208*f1fbf3c2SXin Li     /**
209*f1fbf3c2SXin Li      * Returns the class declaring the field.
210*f1fbf3c2SXin Li      */
211*f1fbf3c2SXin Li     @Override
getDeclaringClass()212*f1fbf3c2SXin Li     public CtClass getDeclaringClass() {
213*f1fbf3c2SXin Li         // this is redundant but for javadoc.
214*f1fbf3c2SXin Li         return super.getDeclaringClass();
215*f1fbf3c2SXin Li     }
216*f1fbf3c2SXin Li 
217*f1fbf3c2SXin Li     /**
218*f1fbf3c2SXin Li      * Returns the name of the field.
219*f1fbf3c2SXin Li      */
220*f1fbf3c2SXin Li     @Override
getName()221*f1fbf3c2SXin Li     public String getName() {
222*f1fbf3c2SXin Li         return fieldInfo.getName();
223*f1fbf3c2SXin Li     }
224*f1fbf3c2SXin Li 
225*f1fbf3c2SXin Li     /**
226*f1fbf3c2SXin Li      * Changes the name of the field.
227*f1fbf3c2SXin Li      */
setName(String newName)228*f1fbf3c2SXin Li     public void setName(String newName) {
229*f1fbf3c2SXin Li         declaringClass.checkModify();
230*f1fbf3c2SXin Li         fieldInfo.setName(newName);
231*f1fbf3c2SXin Li     }
232*f1fbf3c2SXin Li 
233*f1fbf3c2SXin Li     /**
234*f1fbf3c2SXin Li      * Returns the encoded modifiers of the field.
235*f1fbf3c2SXin Li      *
236*f1fbf3c2SXin Li      * @see Modifier
237*f1fbf3c2SXin Li      */
238*f1fbf3c2SXin Li     @Override
getModifiers()239*f1fbf3c2SXin Li     public int getModifiers() {
240*f1fbf3c2SXin Li         return AccessFlag.toModifier(fieldInfo.getAccessFlags());
241*f1fbf3c2SXin Li     }
242*f1fbf3c2SXin Li 
243*f1fbf3c2SXin Li     /**
244*f1fbf3c2SXin Li      * Sets the encoded modifiers of the field.
245*f1fbf3c2SXin Li      *
246*f1fbf3c2SXin Li      * @see Modifier
247*f1fbf3c2SXin Li      */
248*f1fbf3c2SXin Li     @Override
setModifiers(int mod)249*f1fbf3c2SXin Li     public void setModifiers(int mod) {
250*f1fbf3c2SXin Li         declaringClass.checkModify();
251*f1fbf3c2SXin Li         fieldInfo.setAccessFlags(AccessFlag.of(mod));
252*f1fbf3c2SXin Li     }
253*f1fbf3c2SXin Li 
254*f1fbf3c2SXin Li     /**
255*f1fbf3c2SXin Li      * Returns true if the class has the specified annotation type.
256*f1fbf3c2SXin Li      *
257*f1fbf3c2SXin Li      * @param typeName      the name of annotation type.
258*f1fbf3c2SXin Li      * @return <code>true</code> if the annotation is found, otherwise <code>false</code>.
259*f1fbf3c2SXin Li      * @since 3.21
260*f1fbf3c2SXin Li      */
261*f1fbf3c2SXin Li     @Override
hasAnnotation(String typeName)262*f1fbf3c2SXin Li     public boolean hasAnnotation(String typeName) {
263*f1fbf3c2SXin Li         FieldInfo fi = getFieldInfo2();
264*f1fbf3c2SXin Li         AnnotationsAttribute ainfo = (AnnotationsAttribute)
265*f1fbf3c2SXin Li                     fi.getAttribute(AnnotationsAttribute.invisibleTag);
266*f1fbf3c2SXin Li         AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
267*f1fbf3c2SXin Li                     fi.getAttribute(AnnotationsAttribute.visibleTag);
268*f1fbf3c2SXin Li         return CtClassType.hasAnnotationType(typeName, getDeclaringClass().getClassPool(),
269*f1fbf3c2SXin Li                                              ainfo, ainfo2);
270*f1fbf3c2SXin Li     }
271*f1fbf3c2SXin Li 
272*f1fbf3c2SXin Li     /**
273*f1fbf3c2SXin Li      * Returns the annotation if the class has the specified annotation class.
274*f1fbf3c2SXin Li      * For example, if an annotation <code>@Author</code> is associated
275*f1fbf3c2SXin Li      * with this field, an <code>Author</code> object is returned.
276*f1fbf3c2SXin Li      * The member values can be obtained by calling methods on
277*f1fbf3c2SXin Li      * the <code>Author</code> object.
278*f1fbf3c2SXin Li      *
279*f1fbf3c2SXin Li      * @param clz the annotation class.
280*f1fbf3c2SXin Li      * @return the annotation if found, otherwise <code>null</code>.
281*f1fbf3c2SXin Li      * @since 3.11
282*f1fbf3c2SXin Li      */
283*f1fbf3c2SXin Li     @Override
getAnnotation(Class<?> clz)284*f1fbf3c2SXin Li     public Object getAnnotation(Class<?> clz) throws ClassNotFoundException {
285*f1fbf3c2SXin Li         FieldInfo fi = getFieldInfo2();
286*f1fbf3c2SXin Li         AnnotationsAttribute ainfo = (AnnotationsAttribute)
287*f1fbf3c2SXin Li                     fi.getAttribute(AnnotationsAttribute.invisibleTag);
288*f1fbf3c2SXin Li         AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
289*f1fbf3c2SXin Li                     fi.getAttribute(AnnotationsAttribute.visibleTag);
290*f1fbf3c2SXin Li         return CtClassType.getAnnotationType(clz, getDeclaringClass().getClassPool(),
291*f1fbf3c2SXin Li                                              ainfo, ainfo2);
292*f1fbf3c2SXin Li     }
293*f1fbf3c2SXin Li 
294*f1fbf3c2SXin Li     /**
295*f1fbf3c2SXin Li      * Returns the annotations associated with this field.
296*f1fbf3c2SXin Li      *
297*f1fbf3c2SXin Li      * @return an array of annotation-type objects.
298*f1fbf3c2SXin Li      * @see #getAvailableAnnotations()
299*f1fbf3c2SXin Li      * @since 3.1
300*f1fbf3c2SXin Li      */
301*f1fbf3c2SXin Li     @Override
getAnnotations()302*f1fbf3c2SXin Li     public Object[] getAnnotations() throws ClassNotFoundException {
303*f1fbf3c2SXin Li         return getAnnotations(false);
304*f1fbf3c2SXin Li     }
305*f1fbf3c2SXin Li 
306*f1fbf3c2SXin Li     /**
307*f1fbf3c2SXin Li      * Returns the annotations associated with this field.
308*f1fbf3c2SXin Li      * If any annotations are not on the classpath, they are not included
309*f1fbf3c2SXin Li      * in the returned array.
310*f1fbf3c2SXin Li      *
311*f1fbf3c2SXin Li      * @return an array of annotation-type objects.
312*f1fbf3c2SXin Li      * @see #getAnnotations()
313*f1fbf3c2SXin Li      * @since 3.3
314*f1fbf3c2SXin Li      */
315*f1fbf3c2SXin Li     @Override
getAvailableAnnotations()316*f1fbf3c2SXin Li     public Object[] getAvailableAnnotations(){
317*f1fbf3c2SXin Li         try {
318*f1fbf3c2SXin Li             return getAnnotations(true);
319*f1fbf3c2SXin Li         }
320*f1fbf3c2SXin Li         catch (ClassNotFoundException e) {
321*f1fbf3c2SXin Li            throw new RuntimeException("Unexpected exception", e);
322*f1fbf3c2SXin Li         }
323*f1fbf3c2SXin Li     }
324*f1fbf3c2SXin Li 
getAnnotations(boolean ignoreNotFound)325*f1fbf3c2SXin Li     private Object[] getAnnotations(boolean ignoreNotFound) throws ClassNotFoundException {
326*f1fbf3c2SXin Li         FieldInfo fi = getFieldInfo2();
327*f1fbf3c2SXin Li         AnnotationsAttribute ainfo = (AnnotationsAttribute)
328*f1fbf3c2SXin Li                     fi.getAttribute(AnnotationsAttribute.invisibleTag);
329*f1fbf3c2SXin Li         AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
330*f1fbf3c2SXin Li                     fi.getAttribute(AnnotationsAttribute.visibleTag);
331*f1fbf3c2SXin Li         return CtClassType.toAnnotationType(ignoreNotFound, getDeclaringClass().getClassPool(),
332*f1fbf3c2SXin Li                                             ainfo, ainfo2);
333*f1fbf3c2SXin Li     }
334*f1fbf3c2SXin Li 
335*f1fbf3c2SXin Li     /**
336*f1fbf3c2SXin Li      * Returns the character string representing the type of the field.
337*f1fbf3c2SXin Li      * The field signature is represented by a character string
338*f1fbf3c2SXin Li      * called a field descriptor, which is defined in the JVM specification.
339*f1fbf3c2SXin Li      * If two fields have the same type,
340*f1fbf3c2SXin Li      * <code>getSignature()</code> returns the same string.
341*f1fbf3c2SXin Li      *
342*f1fbf3c2SXin Li      * <p>Note that the returned string is not the type signature
343*f1fbf3c2SXin Li      * contained in the <code>SignatureAttirbute</code>.  It is
344*f1fbf3c2SXin Li      * a descriptor.
345*f1fbf3c2SXin Li      *
346*f1fbf3c2SXin Li      * @see javassist.bytecode.Descriptor
347*f1fbf3c2SXin Li      * @see #getGenericSignature()
348*f1fbf3c2SXin Li      */
349*f1fbf3c2SXin Li     @Override
getSignature()350*f1fbf3c2SXin Li     public String getSignature() {
351*f1fbf3c2SXin Li         return fieldInfo.getDescriptor();
352*f1fbf3c2SXin Li     }
353*f1fbf3c2SXin Li 
354*f1fbf3c2SXin Li     /**
355*f1fbf3c2SXin Li      * Returns the generic signature of the field.
356*f1fbf3c2SXin Li      * It represents a type including type variables.
357*f1fbf3c2SXin Li      *
358*f1fbf3c2SXin Li      * @see SignatureAttribute#toFieldSignature(String)
359*f1fbf3c2SXin Li      * @since 3.17
360*f1fbf3c2SXin Li      */
361*f1fbf3c2SXin Li     @Override
getGenericSignature()362*f1fbf3c2SXin Li     public String getGenericSignature() {
363*f1fbf3c2SXin Li         SignatureAttribute sa
364*f1fbf3c2SXin Li             = (SignatureAttribute)fieldInfo.getAttribute(SignatureAttribute.tag);
365*f1fbf3c2SXin Li         return sa == null ? null : sa.getSignature();
366*f1fbf3c2SXin Li     }
367*f1fbf3c2SXin Li 
368*f1fbf3c2SXin Li     /**
369*f1fbf3c2SXin Li      * Set the generic signature of the field.
370*f1fbf3c2SXin Li      * It represents a type including type variables.
371*f1fbf3c2SXin Li      * See {@link javassist.CtClass#setGenericSignature(String)}
372*f1fbf3c2SXin Li      * for a code sample.
373*f1fbf3c2SXin Li      *
374*f1fbf3c2SXin Li      * @param sig       a new generic signature.
375*f1fbf3c2SXin Li      * @see javassist.bytecode.SignatureAttribute.ObjectType#encode()
376*f1fbf3c2SXin Li      * @since 3.17
377*f1fbf3c2SXin Li      */
378*f1fbf3c2SXin Li     @Override
setGenericSignature(String sig)379*f1fbf3c2SXin Li     public void setGenericSignature(String sig) {
380*f1fbf3c2SXin Li         declaringClass.checkModify();
381*f1fbf3c2SXin Li         fieldInfo.addAttribute(new SignatureAttribute(fieldInfo.getConstPool(), sig));
382*f1fbf3c2SXin Li     }
383*f1fbf3c2SXin Li 
384*f1fbf3c2SXin Li     /**
385*f1fbf3c2SXin Li      * Returns the type of the field.
386*f1fbf3c2SXin Li      */
getType()387*f1fbf3c2SXin Li     public CtClass getType() throws NotFoundException {
388*f1fbf3c2SXin Li         return Descriptor.toCtClass(fieldInfo.getDescriptor(),
389*f1fbf3c2SXin Li                                     declaringClass.getClassPool());
390*f1fbf3c2SXin Li     }
391*f1fbf3c2SXin Li 
392*f1fbf3c2SXin Li     /**
393*f1fbf3c2SXin Li      * Sets the type of the field.
394*f1fbf3c2SXin Li      *
395*f1fbf3c2SXin Li      * <p>This method does not automatically update method bodies that access
396*f1fbf3c2SXin Li      * this field.  They have to be explicitly updated.  For example,
397*f1fbf3c2SXin Li      * if some method contains an expression {@code t.value} and the type
398*f1fbf3c2SXin Li      * of the variable {@code t} is changed by {@link #setType(CtClass)}
399*f1fbf3c2SXin Li      * from {@code int} to {@code double}, then {@code t.value} has to be modified
400*f1fbf3c2SXin Li      * as well since the bytecode of {@code t.value} contains the type information.
401*f1fbf3c2SXin Li      * </p>
402*f1fbf3c2SXin Li      *
403*f1fbf3c2SXin Li      * @see CodeConverter
404*f1fbf3c2SXin Li      * @see javassist.expr.ExprEditor
405*f1fbf3c2SXin Li      */
setType(CtClass clazz)406*f1fbf3c2SXin Li     public void setType(CtClass clazz) {
407*f1fbf3c2SXin Li         declaringClass.checkModify();
408*f1fbf3c2SXin Li         fieldInfo.setDescriptor(Descriptor.of(clazz));
409*f1fbf3c2SXin Li     }
410*f1fbf3c2SXin Li 
411*f1fbf3c2SXin Li     /**
412*f1fbf3c2SXin Li      * Returns the value of this field if it is a constant field.
413*f1fbf3c2SXin Li      * This method works only if the field type is a primitive type
414*f1fbf3c2SXin Li      * or <code>String</code> type.  Otherwise, it returns <code>null</code>.
415*f1fbf3c2SXin Li      * A constant field is <code>static</code> and <code>final</code>.
416*f1fbf3c2SXin Li      *
417*f1fbf3c2SXin Li      * @return  a <code>Integer</code>, <code>Long</code>, <code>Float</code>,
418*f1fbf3c2SXin Li      *          <code>Double</code>, <code>Boolean</code>,
419*f1fbf3c2SXin Li      *          or <code>String</code> object
420*f1fbf3c2SXin Li      *          representing the constant value.
421*f1fbf3c2SXin Li      *          <code>null</code> if it is not a constant field
422*f1fbf3c2SXin Li      *          or if the field type is not a primitive type
423*f1fbf3c2SXin Li      *          or <code>String</code>.
424*f1fbf3c2SXin Li      */
getConstantValue()425*f1fbf3c2SXin Li     public Object getConstantValue() {
426*f1fbf3c2SXin Li         // When this method is modified,
427*f1fbf3c2SXin Li         // see also getConstantFieldValue() in TypeChecker.
428*f1fbf3c2SXin Li 
429*f1fbf3c2SXin Li         int index = fieldInfo.getConstantValue();
430*f1fbf3c2SXin Li         if (index == 0)
431*f1fbf3c2SXin Li             return null;
432*f1fbf3c2SXin Li 
433*f1fbf3c2SXin Li         ConstPool cp = fieldInfo.getConstPool();
434*f1fbf3c2SXin Li         switch (cp.getTag(index)) {
435*f1fbf3c2SXin Li             case ConstPool.CONST_Long :
436*f1fbf3c2SXin Li                 return Long.valueOf(cp.getLongInfo(index));
437*f1fbf3c2SXin Li             case ConstPool.CONST_Float :
438*f1fbf3c2SXin Li                 return Float.valueOf(cp.getFloatInfo(index));
439*f1fbf3c2SXin Li             case ConstPool.CONST_Double :
440*f1fbf3c2SXin Li                 return Double.valueOf(cp.getDoubleInfo(index));
441*f1fbf3c2SXin Li             case ConstPool.CONST_Integer :
442*f1fbf3c2SXin Li                 int value = cp.getIntegerInfo(index);
443*f1fbf3c2SXin Li                 // "Z" means boolean type.
444*f1fbf3c2SXin Li                 if ("Z".equals(fieldInfo.getDescriptor()))
445*f1fbf3c2SXin Li                     return Boolean.valueOf(value != 0);
446*f1fbf3c2SXin Li                 return Integer.valueOf(value);
447*f1fbf3c2SXin Li             case ConstPool.CONST_String :
448*f1fbf3c2SXin Li                 return cp.getStringInfo(index);
449*f1fbf3c2SXin Li             default :
450*f1fbf3c2SXin Li                 throw new RuntimeException("bad tag: " + cp.getTag(index)
451*f1fbf3c2SXin Li                                            + " at " + index);
452*f1fbf3c2SXin Li         }
453*f1fbf3c2SXin Li     }
454*f1fbf3c2SXin Li 
455*f1fbf3c2SXin Li     /**
456*f1fbf3c2SXin Li      * Obtains an attribute with the given name.
457*f1fbf3c2SXin Li      * If that attribute is not found in the class file, this
458*f1fbf3c2SXin Li      * method returns null.
459*f1fbf3c2SXin Li      *
460*f1fbf3c2SXin Li      * <p>Note that an attribute is a data block specified by
461*f1fbf3c2SXin Li      * the class file format.
462*f1fbf3c2SXin Li      * See {@link javassist.bytecode.AttributeInfo}.
463*f1fbf3c2SXin Li      *
464*f1fbf3c2SXin Li      * @param name              attribute name
465*f1fbf3c2SXin Li      */
466*f1fbf3c2SXin Li     @Override
getAttribute(String name)467*f1fbf3c2SXin Li     public byte[] getAttribute(String name) {
468*f1fbf3c2SXin Li         AttributeInfo ai = fieldInfo.getAttribute(name);
469*f1fbf3c2SXin Li         if (ai == null)
470*f1fbf3c2SXin Li             return null;
471*f1fbf3c2SXin Li         return ai.get();
472*f1fbf3c2SXin Li     }
473*f1fbf3c2SXin Li 
474*f1fbf3c2SXin Li     /**
475*f1fbf3c2SXin Li      * Adds an attribute. The attribute is saved in the class file.
476*f1fbf3c2SXin Li      *
477*f1fbf3c2SXin Li      * <p>Note that an attribute is a data block specified by
478*f1fbf3c2SXin Li      * the class file format.
479*f1fbf3c2SXin Li      * See {@link javassist.bytecode.AttributeInfo}.
480*f1fbf3c2SXin Li      *
481*f1fbf3c2SXin Li      * @param name      attribute name
482*f1fbf3c2SXin Li      * @param data      attribute value
483*f1fbf3c2SXin Li      */
484*f1fbf3c2SXin Li     @Override
setAttribute(String name, byte[] data)485*f1fbf3c2SXin Li     public void setAttribute(String name, byte[] data) {
486*f1fbf3c2SXin Li         declaringClass.checkModify();
487*f1fbf3c2SXin Li         fieldInfo.addAttribute(new AttributeInfo(fieldInfo.getConstPool(),
488*f1fbf3c2SXin Li                                                  name, data));
489*f1fbf3c2SXin Li     }
490*f1fbf3c2SXin Li 
491*f1fbf3c2SXin Li     // inner classes
492*f1fbf3c2SXin Li 
493*f1fbf3c2SXin Li     /**
494*f1fbf3c2SXin Li      * Instances of this class specify how to initialize a field.
495*f1fbf3c2SXin Li      * <code>Initializer</code> is passed to
496*f1fbf3c2SXin Li      * <code>CtClass.addField()</code> with a <code>CtField</code>.
497*f1fbf3c2SXin Li      *
498*f1fbf3c2SXin Li      * <p>This class cannot be instantiated with the <code>new</code> operator.
499*f1fbf3c2SXin Li      * Factory methods such as <code>byParameter()</code> and
500*f1fbf3c2SXin Li      * <code>byNew</code>
501*f1fbf3c2SXin Li      * must be used for the instantiation.  They create a new instance with
502*f1fbf3c2SXin Li      * the given parameters and return it.
503*f1fbf3c2SXin Li      *
504*f1fbf3c2SXin Li      * @see CtClass#addField(CtField,CtField.Initializer)
505*f1fbf3c2SXin Li      */
506*f1fbf3c2SXin Li     public static abstract class Initializer {
507*f1fbf3c2SXin Li         /**
508*f1fbf3c2SXin Li          * Makes an initializer that assigns a constant integer value.
509*f1fbf3c2SXin Li          * The field must be integer, short, char, or byte type.
510*f1fbf3c2SXin Li          */
constant(int i)511*f1fbf3c2SXin Li         public static Initializer constant(int i) {
512*f1fbf3c2SXin Li             return new IntInitializer(i);
513*f1fbf3c2SXin Li         }
514*f1fbf3c2SXin Li 
515*f1fbf3c2SXin Li         /**
516*f1fbf3c2SXin Li          * Makes an initializer that assigns a constant boolean value.
517*f1fbf3c2SXin Li          * The field must be boolean type.
518*f1fbf3c2SXin Li          */
constant(boolean b)519*f1fbf3c2SXin Li         public static Initializer constant(boolean b) {
520*f1fbf3c2SXin Li             return new IntInitializer(b ? 1 : 0);
521*f1fbf3c2SXin Li         }
522*f1fbf3c2SXin Li 
523*f1fbf3c2SXin Li         /**
524*f1fbf3c2SXin Li          * Makes an initializer that assigns a constant long value.
525*f1fbf3c2SXin Li          * The field must be long type.
526*f1fbf3c2SXin Li          */
constant(long l)527*f1fbf3c2SXin Li         public static Initializer constant(long l) {
528*f1fbf3c2SXin Li             return new LongInitializer(l);
529*f1fbf3c2SXin Li         }
530*f1fbf3c2SXin Li 
531*f1fbf3c2SXin Li         /**
532*f1fbf3c2SXin Li          * Makes an initializer that assigns a constant float value.
533*f1fbf3c2SXin Li          * The field must be float type.
534*f1fbf3c2SXin Li          */
constant(float l)535*f1fbf3c2SXin Li         public static Initializer constant(float l) {
536*f1fbf3c2SXin Li             return new FloatInitializer(l);
537*f1fbf3c2SXin Li         }
538*f1fbf3c2SXin Li 
539*f1fbf3c2SXin Li         /**
540*f1fbf3c2SXin Li          * Makes an initializer that assigns a constant double value.
541*f1fbf3c2SXin Li          * The field must be double type.
542*f1fbf3c2SXin Li          */
constant(double d)543*f1fbf3c2SXin Li         public static Initializer constant(double d) {
544*f1fbf3c2SXin Li             return new DoubleInitializer(d);
545*f1fbf3c2SXin Li         }
546*f1fbf3c2SXin Li 
547*f1fbf3c2SXin Li         /**
548*f1fbf3c2SXin Li          * Makes an initializer that assigns a constant string value.
549*f1fbf3c2SXin Li          * The field must be <code>java.lang.String</code> type.
550*f1fbf3c2SXin Li          */
constant(String s)551*f1fbf3c2SXin Li         public static Initializer constant(String s) {
552*f1fbf3c2SXin Li             return new StringInitializer(s);
553*f1fbf3c2SXin Li         }
554*f1fbf3c2SXin Li 
555*f1fbf3c2SXin Li         /**
556*f1fbf3c2SXin Li          * Makes an initializer using a constructor parameter.
557*f1fbf3c2SXin Li          *
558*f1fbf3c2SXin Li          * <p>The initial value is the
559*f1fbf3c2SXin Li          * N-th parameter given to the constructor of the object including
560*f1fbf3c2SXin Li          * the field.  If the constructor takes less than N parameters,
561*f1fbf3c2SXin Li          * the field is not initialized.
562*f1fbf3c2SXin Li          * If the field is static, it is never initialized.
563*f1fbf3c2SXin Li          *
564*f1fbf3c2SXin Li          * @param nth           the n-th (&gt;= 0) parameter is used as
565*f1fbf3c2SXin Li          *                      the initial value.
566*f1fbf3c2SXin Li          *                      If nth is 0, then the first parameter is
567*f1fbf3c2SXin Li          *                      used.
568*f1fbf3c2SXin Li          */
byParameter(int nth)569*f1fbf3c2SXin Li         public static Initializer byParameter(int nth) {
570*f1fbf3c2SXin Li             ParamInitializer i = new ParamInitializer();
571*f1fbf3c2SXin Li             i.nthParam = nth;
572*f1fbf3c2SXin Li             return i;
573*f1fbf3c2SXin Li         }
574*f1fbf3c2SXin Li 
575*f1fbf3c2SXin Li         /**
576*f1fbf3c2SXin Li          * Makes an initializer creating a new object.
577*f1fbf3c2SXin Li          *
578*f1fbf3c2SXin Li          * <p>This initializer creates a new object and uses it as the initial
579*f1fbf3c2SXin Li          * value of the field.  The constructor of the created object receives
580*f1fbf3c2SXin Li          * the parameter:
581*f1fbf3c2SXin Li          *
582*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.
583*f1fbf3c2SXin Li          *
584*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the constructor does
585*f1fbf3c2SXin Li          * not receive any parameters.
586*f1fbf3c2SXin Li          *
587*f1fbf3c2SXin Li          * @param objectType    the class instantiated for the initial value.
588*f1fbf3c2SXin Li          */
byNew(CtClass objectType)589*f1fbf3c2SXin Li         public static Initializer byNew(CtClass objectType) {
590*f1fbf3c2SXin Li             NewInitializer i = new NewInitializer();
591*f1fbf3c2SXin Li             i.objectType = objectType;
592*f1fbf3c2SXin Li             i.stringParams = null;
593*f1fbf3c2SXin Li             i.withConstructorParams = false;
594*f1fbf3c2SXin Li             return i;
595*f1fbf3c2SXin Li         }
596*f1fbf3c2SXin Li 
597*f1fbf3c2SXin Li         /**
598*f1fbf3c2SXin Li          * Makes an initializer creating a new object.
599*f1fbf3c2SXin Li          *
600*f1fbf3c2SXin Li          * <p>This initializer creates a new object and uses it as the initial
601*f1fbf3c2SXin Li          * value of the field.  The constructor of the created object receives
602*f1fbf3c2SXin Li          * the parameters:
603*f1fbf3c2SXin Li          *
604*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.<br>
605*f1fbf3c2SXin Li          *     <code>String[] strs</code> - the character strings specified
606*f1fbf3c2SXin Li          *                              by <code>stringParams</code><br>
607*f1fbf3c2SXin Li          *
608*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the constructor
609*f1fbf3c2SXin Li          * receives only <code>strs</code>.
610*f1fbf3c2SXin Li          *
611*f1fbf3c2SXin Li          * @param objectType    the class instantiated for the initial value.
612*f1fbf3c2SXin Li          * @param stringParams  the array of strings passed to the
613*f1fbf3c2SXin Li          *                      constructor.
614*f1fbf3c2SXin Li          */
byNew(CtClass objectType, String[] stringParams)615*f1fbf3c2SXin Li         public static Initializer byNew(CtClass objectType,
616*f1fbf3c2SXin Li                                              String[] stringParams) {
617*f1fbf3c2SXin Li             NewInitializer i = new NewInitializer();
618*f1fbf3c2SXin Li             i.objectType = objectType;
619*f1fbf3c2SXin Li             i.stringParams = stringParams;
620*f1fbf3c2SXin Li             i.withConstructorParams = false;
621*f1fbf3c2SXin Li             return i;
622*f1fbf3c2SXin Li         }
623*f1fbf3c2SXin Li 
624*f1fbf3c2SXin Li         /**
625*f1fbf3c2SXin Li          * Makes an initializer creating a new object.
626*f1fbf3c2SXin Li          *
627*f1fbf3c2SXin Li          * <p>This initializer creates a new object and uses it as the initial
628*f1fbf3c2SXin Li          * value of the field.  The constructor of the created object receives
629*f1fbf3c2SXin Li          * the parameters:
630*f1fbf3c2SXin Li          *
631*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.<br>
632*f1fbf3c2SXin Li          *     <code>Object[] args</code> - the parameters passed to the
633*f1fbf3c2SXin Li          *                      constructor of the object including the
634*f1fbf3c2SXin Li          *                      filed.
635*f1fbf3c2SXin Li          *
636*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the constructor does
637*f1fbf3c2SXin Li          * not receive any parameters.
638*f1fbf3c2SXin Li          *
639*f1fbf3c2SXin Li          * @param objectType    the class instantiated for the initial value.
640*f1fbf3c2SXin Li          *
641*f1fbf3c2SXin Li          * @see javassist.CtField.Initializer#byNewArray(CtClass,int)
642*f1fbf3c2SXin Li          * @see javassist.CtField.Initializer#byNewArray(CtClass,int[])
643*f1fbf3c2SXin Li          */
byNewWithParams(CtClass objectType)644*f1fbf3c2SXin Li         public static Initializer byNewWithParams(CtClass objectType) {
645*f1fbf3c2SXin Li             NewInitializer i = new NewInitializer();
646*f1fbf3c2SXin Li             i.objectType = objectType;
647*f1fbf3c2SXin Li             i.stringParams = null;
648*f1fbf3c2SXin Li             i.withConstructorParams = true;
649*f1fbf3c2SXin Li             return i;
650*f1fbf3c2SXin Li         }
651*f1fbf3c2SXin Li 
652*f1fbf3c2SXin Li         /**
653*f1fbf3c2SXin Li          * Makes an initializer creating a new object.
654*f1fbf3c2SXin Li          *
655*f1fbf3c2SXin Li          * <p>This initializer creates a new object and uses it as the initial
656*f1fbf3c2SXin Li          * value of the field.  The constructor of the created object receives
657*f1fbf3c2SXin Li          * the parameters:
658*f1fbf3c2SXin Li          *
659*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.<br>
660*f1fbf3c2SXin Li          *     <code>String[] strs</code> - the character strings specified
661*f1fbf3c2SXin Li          *                              by <code>stringParams</code><br>
662*f1fbf3c2SXin Li          *     <code>Object[] args</code> - the parameters passed to the
663*f1fbf3c2SXin Li          *                      constructor of the object including the
664*f1fbf3c2SXin Li          *                      filed.
665*f1fbf3c2SXin Li          *
666*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the constructor receives
667*f1fbf3c2SXin Li          * only <code>strs</code>.
668*f1fbf3c2SXin Li          *
669*f1fbf3c2SXin Li          * @param objectType    the class instantiated for the initial value.
670*f1fbf3c2SXin Li          * @param stringParams  the array of strings passed to the
671*f1fbf3c2SXin Li          *                              constructor.
672*f1fbf3c2SXin Li          */
byNewWithParams(CtClass objectType, String[] stringParams)673*f1fbf3c2SXin Li         public static Initializer byNewWithParams(CtClass objectType,
674*f1fbf3c2SXin Li                                                String[] stringParams) {
675*f1fbf3c2SXin Li             NewInitializer i = new NewInitializer();
676*f1fbf3c2SXin Li             i.objectType = objectType;
677*f1fbf3c2SXin Li             i.stringParams = stringParams;
678*f1fbf3c2SXin Li             i.withConstructorParams = true;
679*f1fbf3c2SXin Li             return i;
680*f1fbf3c2SXin Li         }
681*f1fbf3c2SXin Li 
682*f1fbf3c2SXin Li         /**
683*f1fbf3c2SXin Li          * Makes an initializer calling a static method.
684*f1fbf3c2SXin Li          *
685*f1fbf3c2SXin Li          * <p>This initializer calls a static method and uses the returned
686*f1fbf3c2SXin Li          * value as the initial value of the field.
687*f1fbf3c2SXin Li          * The called method receives the parameters:
688*f1fbf3c2SXin Li          *
689*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.
690*f1fbf3c2SXin Li          *
691*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the method does
692*f1fbf3c2SXin Li          * not receive any parameters.
693*f1fbf3c2SXin Li          *
694*f1fbf3c2SXin Li          * <p>The type of the returned value must be the same as the field
695*f1fbf3c2SXin Li          * type.
696*f1fbf3c2SXin Li          *
697*f1fbf3c2SXin Li          * @param methodClass   the class that the static method is
698*f1fbf3c2SXin Li          *                              declared in.
699*f1fbf3c2SXin Li          * @param methodName    the name of the satic method.
700*f1fbf3c2SXin Li          */
byCall(CtClass methodClass, String methodName)701*f1fbf3c2SXin Li         public static Initializer byCall(CtClass methodClass,
702*f1fbf3c2SXin Li                                               String methodName) {
703*f1fbf3c2SXin Li             MethodInitializer i = new MethodInitializer();
704*f1fbf3c2SXin Li             i.objectType = methodClass;
705*f1fbf3c2SXin Li             i.methodName = methodName;
706*f1fbf3c2SXin Li             i.stringParams = null;
707*f1fbf3c2SXin Li             i.withConstructorParams = false;
708*f1fbf3c2SXin Li             return i;
709*f1fbf3c2SXin Li         }
710*f1fbf3c2SXin Li 
711*f1fbf3c2SXin Li         /**
712*f1fbf3c2SXin Li          * Makes an initializer calling a static method.
713*f1fbf3c2SXin Li          *
714*f1fbf3c2SXin Li          * <p>This initializer calls a static method and uses the returned
715*f1fbf3c2SXin Li          * value as the initial value of the field.  The called method
716*f1fbf3c2SXin Li          * receives the parameters:
717*f1fbf3c2SXin Li          *
718*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.<br>
719*f1fbf3c2SXin Li          *     <code>String[] strs</code> - the character strings specified
720*f1fbf3c2SXin Li          *                              by <code>stringParams</code><br>
721*f1fbf3c2SXin Li          *
722*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the method
723*f1fbf3c2SXin Li          * receive only <code>strs</code>.
724*f1fbf3c2SXin Li          *
725*f1fbf3c2SXin Li          * <p>The type of the returned value must be the same as the field
726*f1fbf3c2SXin Li          * type.
727*f1fbf3c2SXin Li          *
728*f1fbf3c2SXin Li          * @param methodClass   the class that the static method is
729*f1fbf3c2SXin Li          *                              declared in.
730*f1fbf3c2SXin Li          * @param methodName    the name of the satic method.
731*f1fbf3c2SXin Li          * @param stringParams  the array of strings passed to the
732*f1fbf3c2SXin Li          *                              static method.
733*f1fbf3c2SXin Li          */
byCall(CtClass methodClass, String methodName, String[] stringParams)734*f1fbf3c2SXin Li         public static Initializer byCall(CtClass methodClass,
735*f1fbf3c2SXin Li                                               String methodName,
736*f1fbf3c2SXin Li                                               String[] stringParams) {
737*f1fbf3c2SXin Li             MethodInitializer i = new MethodInitializer();
738*f1fbf3c2SXin Li             i.objectType = methodClass;
739*f1fbf3c2SXin Li             i.methodName = methodName;
740*f1fbf3c2SXin Li             i.stringParams = stringParams;
741*f1fbf3c2SXin Li             i.withConstructorParams = false;
742*f1fbf3c2SXin Li             return i;
743*f1fbf3c2SXin Li         }
744*f1fbf3c2SXin Li 
745*f1fbf3c2SXin Li         /**
746*f1fbf3c2SXin Li          * Makes an initializer calling a static method.
747*f1fbf3c2SXin Li          *
748*f1fbf3c2SXin Li          * <p>This initializer calls a static method and uses the returned
749*f1fbf3c2SXin Li          * value as the initial value of the field.  The called method
750*f1fbf3c2SXin Li          * receives the parameters:
751*f1fbf3c2SXin Li          *
752*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.<br>
753*f1fbf3c2SXin Li          *     <code>Object[] args</code> - the parameters passed to the
754*f1fbf3c2SXin Li          *                      constructor of the object including the
755*f1fbf3c2SXin Li          *                      filed.
756*f1fbf3c2SXin Li          *
757*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the method does
758*f1fbf3c2SXin Li          * not receive any parameters.
759*f1fbf3c2SXin Li          *
760*f1fbf3c2SXin Li          * <p>The type of the returned value must be the same as the field
761*f1fbf3c2SXin Li          * type.
762*f1fbf3c2SXin Li          *
763*f1fbf3c2SXin Li          * @param methodClass   the class that the static method is
764*f1fbf3c2SXin Li          *                              declared in.
765*f1fbf3c2SXin Li          * @param methodName    the name of the satic method.
766*f1fbf3c2SXin Li          */
byCallWithParams(CtClass methodClass, String methodName)767*f1fbf3c2SXin Li         public static Initializer byCallWithParams(CtClass methodClass,
768*f1fbf3c2SXin Li                                                         String methodName) {
769*f1fbf3c2SXin Li             MethodInitializer i = new MethodInitializer();
770*f1fbf3c2SXin Li             i.objectType = methodClass;
771*f1fbf3c2SXin Li             i.methodName = methodName;
772*f1fbf3c2SXin Li             i.stringParams = null;
773*f1fbf3c2SXin Li             i.withConstructorParams = true;
774*f1fbf3c2SXin Li             return i;
775*f1fbf3c2SXin Li         }
776*f1fbf3c2SXin Li 
777*f1fbf3c2SXin Li         /**
778*f1fbf3c2SXin Li          * Makes an initializer calling a static method.
779*f1fbf3c2SXin Li          *
780*f1fbf3c2SXin Li          * <p>This initializer calls a static method and uses the returned
781*f1fbf3c2SXin Li          * value as the initial value of the field.  The called method
782*f1fbf3c2SXin Li          * receives the parameters:
783*f1fbf3c2SXin Li          *
784*f1fbf3c2SXin Li          * <p><code>Object obj</code> - the object including the field.<br>
785*f1fbf3c2SXin Li          *     <code>String[] strs</code> - the character strings specified
786*f1fbf3c2SXin Li          *                              by <code>stringParams</code><br>
787*f1fbf3c2SXin Li          *     <code>Object[] args</code> - the parameters passed to the
788*f1fbf3c2SXin Li          *                      constructor of the object including the
789*f1fbf3c2SXin Li          *                      filed.
790*f1fbf3c2SXin Li          *
791*f1fbf3c2SXin Li          * <p>If the initialized field is static, then the method
792*f1fbf3c2SXin Li          * receive only <code>strs</code>.
793*f1fbf3c2SXin Li          *
794*f1fbf3c2SXin Li          * <p>The type of the returned value must be the same as the field
795*f1fbf3c2SXin Li          * type.
796*f1fbf3c2SXin Li          *
797*f1fbf3c2SXin Li          * @param methodClass   the class that the static method is
798*f1fbf3c2SXin Li          *                              declared in.
799*f1fbf3c2SXin Li          * @param methodName    the name of the satic method.
800*f1fbf3c2SXin Li          * @param stringParams  the array of strings passed to the
801*f1fbf3c2SXin Li          *                              static method.
802*f1fbf3c2SXin Li          */
byCallWithParams(CtClass methodClass, String methodName, String[] stringParams)803*f1fbf3c2SXin Li         public static Initializer byCallWithParams(CtClass methodClass,
804*f1fbf3c2SXin Li                                 String methodName, String[] stringParams) {
805*f1fbf3c2SXin Li             MethodInitializer i = new MethodInitializer();
806*f1fbf3c2SXin Li             i.objectType = methodClass;
807*f1fbf3c2SXin Li             i.methodName = methodName;
808*f1fbf3c2SXin Li             i.stringParams = stringParams;
809*f1fbf3c2SXin Li             i.withConstructorParams = true;
810*f1fbf3c2SXin Li             return i;
811*f1fbf3c2SXin Li         }
812*f1fbf3c2SXin Li 
813*f1fbf3c2SXin Li         /**
814*f1fbf3c2SXin Li          * Makes an initializer creating a new array.
815*f1fbf3c2SXin Li          *
816*f1fbf3c2SXin Li          * @param type  the type of the array.
817*f1fbf3c2SXin Li          * @param size  the size of the array.
818*f1fbf3c2SXin Li          * @throws NotFoundException    if the type of the array components
819*f1fbf3c2SXin Li          *                              is not found.
820*f1fbf3c2SXin Li          */
byNewArray(CtClass type, int size)821*f1fbf3c2SXin Li         public static Initializer byNewArray(CtClass type, int size)
822*f1fbf3c2SXin Li             throws NotFoundException
823*f1fbf3c2SXin Li         {
824*f1fbf3c2SXin Li             return new ArrayInitializer(type.getComponentType(), size);
825*f1fbf3c2SXin Li         }
826*f1fbf3c2SXin Li 
827*f1fbf3c2SXin Li         /**
828*f1fbf3c2SXin Li          * Makes an initializer creating a new multi-dimensional array.
829*f1fbf3c2SXin Li          *
830*f1fbf3c2SXin Li          * @param type  the type of the array.
831*f1fbf3c2SXin Li          * @param sizes an <code>int</code> array of the size in every
832*f1fbf3c2SXin Li          *                      dimension.
833*f1fbf3c2SXin Li          *                      The first element is the size in the first
834*f1fbf3c2SXin Li          *                      dimension.  The second is in the second, etc.
835*f1fbf3c2SXin Li          */
byNewArray(CtClass type, int[] sizes)836*f1fbf3c2SXin Li         public static Initializer byNewArray(CtClass type, int[] sizes) {
837*f1fbf3c2SXin Li             return new MultiArrayInitializer(type, sizes);
838*f1fbf3c2SXin Li         }
839*f1fbf3c2SXin Li 
840*f1fbf3c2SXin Li         /**
841*f1fbf3c2SXin Li          * Makes an initializer.
842*f1fbf3c2SXin Li          *
843*f1fbf3c2SXin Li          * @param source        initializer expression.
844*f1fbf3c2SXin Li          */
byExpr(String source)845*f1fbf3c2SXin Li         public static Initializer byExpr(String source) {
846*f1fbf3c2SXin Li             return new CodeInitializer(source);
847*f1fbf3c2SXin Li         }
848*f1fbf3c2SXin Li 
byExpr(ASTree source)849*f1fbf3c2SXin Li         static Initializer byExpr(ASTree source) {
850*f1fbf3c2SXin Li             return new PtreeInitializer(source);
851*f1fbf3c2SXin Li         }
852*f1fbf3c2SXin Li 
853*f1fbf3c2SXin Li         // Check whether this initializer is valid for the field type.
854*f1fbf3c2SXin Li         // If it is invaild, this method throws an exception.
check(String desc)855*f1fbf3c2SXin Li         void check(String desc) throws CannotCompileException {}
856*f1fbf3c2SXin Li 
857*f1fbf3c2SXin Li         // produce codes for initialization
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)858*f1fbf3c2SXin Li         abstract int compile(CtClass type, String name, Bytecode code,
859*f1fbf3c2SXin Li                              CtClass[] parameters, Javac drv)
860*f1fbf3c2SXin Li             throws CannotCompileException;
861*f1fbf3c2SXin Li 
862*f1fbf3c2SXin Li         // produce codes for initialization
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)863*f1fbf3c2SXin Li         abstract int compileIfStatic(CtClass type, String name,
864*f1fbf3c2SXin Li                 Bytecode code, Javac drv) throws CannotCompileException;
865*f1fbf3c2SXin Li 
866*f1fbf3c2SXin Li         // returns the index of CONSTANT_Integer_info etc
867*f1fbf3c2SXin Li         // if the value is constant.  Otherwise, 0.
getConstantValue(ConstPool cp, CtClass type)868*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) { return 0; }
869*f1fbf3c2SXin Li     }
870*f1fbf3c2SXin Li 
871*f1fbf3c2SXin Li     static abstract class CodeInitializer0 extends Initializer {
compileExpr(Javac drv)872*f1fbf3c2SXin Li         abstract void compileExpr(Javac drv) throws CompileError;
873*f1fbf3c2SXin Li 
874*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)875*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
876*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
877*f1fbf3c2SXin Li             throws CannotCompileException
878*f1fbf3c2SXin Li         {
879*f1fbf3c2SXin Li             try {
880*f1fbf3c2SXin Li                 code.addAload(0);
881*f1fbf3c2SXin Li                 compileExpr(drv);
882*f1fbf3c2SXin Li                 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
883*f1fbf3c2SXin Li                 return code.getMaxStack();
884*f1fbf3c2SXin Li             }
885*f1fbf3c2SXin Li             catch (CompileError e) {
886*f1fbf3c2SXin Li                 throw new CannotCompileException(e);
887*f1fbf3c2SXin Li             }
888*f1fbf3c2SXin Li         }
889*f1fbf3c2SXin Li 
890*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)891*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
892*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
893*f1fbf3c2SXin Li         {
894*f1fbf3c2SXin Li             try {
895*f1fbf3c2SXin Li                 compileExpr(drv);
896*f1fbf3c2SXin Li                 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
897*f1fbf3c2SXin Li                 return code.getMaxStack();
898*f1fbf3c2SXin Li             }
899*f1fbf3c2SXin Li             catch (CompileError e) {
900*f1fbf3c2SXin Li                 throw new CannotCompileException(e);
901*f1fbf3c2SXin Li             }
902*f1fbf3c2SXin Li         }
903*f1fbf3c2SXin Li 
getConstantValue2(ConstPool cp, CtClass type, ASTree tree)904*f1fbf3c2SXin Li         int getConstantValue2(ConstPool cp, CtClass type, ASTree tree) {
905*f1fbf3c2SXin Li             if (type.isPrimitive()) {
906*f1fbf3c2SXin Li                 if (tree instanceof IntConst) {
907*f1fbf3c2SXin Li                     long value = ((IntConst)tree).get();
908*f1fbf3c2SXin Li                     if (type == CtClass.doubleType)
909*f1fbf3c2SXin Li                         return cp.addDoubleInfo(value);
910*f1fbf3c2SXin Li                     else if (type == CtClass.floatType)
911*f1fbf3c2SXin Li                         return cp.addFloatInfo(value);
912*f1fbf3c2SXin Li                     else if (type == CtClass.longType)
913*f1fbf3c2SXin Li                         return cp.addLongInfo(value);
914*f1fbf3c2SXin Li                     else  if (type != CtClass.voidType)
915*f1fbf3c2SXin Li                         return cp.addIntegerInfo((int)value);
916*f1fbf3c2SXin Li                 }
917*f1fbf3c2SXin Li                 else if (tree instanceof DoubleConst) {
918*f1fbf3c2SXin Li                     double value = ((DoubleConst)tree).get();
919*f1fbf3c2SXin Li                     if (type == CtClass.floatType)
920*f1fbf3c2SXin Li                         return cp.addFloatInfo((float)value);
921*f1fbf3c2SXin Li                     else if (type == CtClass.doubleType)
922*f1fbf3c2SXin Li                         return cp.addDoubleInfo(value);
923*f1fbf3c2SXin Li                 }
924*f1fbf3c2SXin Li             }
925*f1fbf3c2SXin Li             else if (tree instanceof StringL
926*f1fbf3c2SXin Li                      && type.getName().equals(javaLangString))
927*f1fbf3c2SXin Li                 return cp.addStringInfo(((StringL)tree).get());
928*f1fbf3c2SXin Li 
929*f1fbf3c2SXin Li             return 0;
930*f1fbf3c2SXin Li         }
931*f1fbf3c2SXin Li     }
932*f1fbf3c2SXin Li 
933*f1fbf3c2SXin Li     static class CodeInitializer extends CodeInitializer0 {
934*f1fbf3c2SXin Li         private String expression;
935*f1fbf3c2SXin Li 
CodeInitializer(String expr)936*f1fbf3c2SXin Li         CodeInitializer(String expr) { expression = expr; }
937*f1fbf3c2SXin Li 
938*f1fbf3c2SXin Li         @Override
compileExpr(Javac drv)939*f1fbf3c2SXin Li         void compileExpr(Javac drv) throws CompileError {
940*f1fbf3c2SXin Li             drv.compileExpr(expression);
941*f1fbf3c2SXin Li         }
942*f1fbf3c2SXin Li 
943*f1fbf3c2SXin Li         @Override
getConstantValue(ConstPool cp, CtClass type)944*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) {
945*f1fbf3c2SXin Li             try {
946*f1fbf3c2SXin Li                 ASTree t = Javac.parseExpr(expression, new SymbolTable());
947*f1fbf3c2SXin Li                 return getConstantValue2(cp, type, t);
948*f1fbf3c2SXin Li             }
949*f1fbf3c2SXin Li             catch (CompileError e) {
950*f1fbf3c2SXin Li                 return 0;
951*f1fbf3c2SXin Li             }
952*f1fbf3c2SXin Li         }
953*f1fbf3c2SXin Li     }
954*f1fbf3c2SXin Li 
955*f1fbf3c2SXin Li     static class PtreeInitializer extends CodeInitializer0 {
956*f1fbf3c2SXin Li         private ASTree expression;
957*f1fbf3c2SXin Li 
PtreeInitializer(ASTree expr)958*f1fbf3c2SXin Li         PtreeInitializer(ASTree expr) { expression = expr; }
959*f1fbf3c2SXin Li 
960*f1fbf3c2SXin Li         @Override
compileExpr(Javac drv)961*f1fbf3c2SXin Li         void compileExpr(Javac drv) throws CompileError {
962*f1fbf3c2SXin Li             drv.compileExpr(expression);
963*f1fbf3c2SXin Li         }
964*f1fbf3c2SXin Li 
965*f1fbf3c2SXin Li         @Override
getConstantValue(ConstPool cp, CtClass type)966*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) {
967*f1fbf3c2SXin Li             return getConstantValue2(cp, type, expression);
968*f1fbf3c2SXin Li         }
969*f1fbf3c2SXin Li     }
970*f1fbf3c2SXin Li 
971*f1fbf3c2SXin Li     /**
972*f1fbf3c2SXin Li      * A field initialized with a parameter passed to the constructor
973*f1fbf3c2SXin Li      * of the class containing that field.
974*f1fbf3c2SXin Li      */
975*f1fbf3c2SXin Li     static class ParamInitializer extends Initializer {
976*f1fbf3c2SXin Li         int nthParam;
977*f1fbf3c2SXin Li 
ParamInitializer()978*f1fbf3c2SXin Li         ParamInitializer() {}
979*f1fbf3c2SXin Li 
980*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)981*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
982*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
983*f1fbf3c2SXin Li             throws CannotCompileException
984*f1fbf3c2SXin Li         {
985*f1fbf3c2SXin Li             if (parameters != null && nthParam < parameters.length) {
986*f1fbf3c2SXin Li                 code.addAload(0);
987*f1fbf3c2SXin Li                 int nth = nthParamToLocal(nthParam, parameters, false);
988*f1fbf3c2SXin Li                 int s = code.addLoad(nth, type) + 1;
989*f1fbf3c2SXin Li                 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
990*f1fbf3c2SXin Li                 return s;       // stack size
991*f1fbf3c2SXin Li             }
992*f1fbf3c2SXin Li             return 0;       // do not initialize
993*f1fbf3c2SXin Li         }
994*f1fbf3c2SXin Li 
995*f1fbf3c2SXin Li         /**
996*f1fbf3c2SXin Li          * Computes the index of the local variable that the n-th parameter
997*f1fbf3c2SXin Li          * is assigned to.
998*f1fbf3c2SXin Li          *
999*f1fbf3c2SXin Li          * @param nth           n-th parameter
1000*f1fbf3c2SXin Li          * @param params                list of parameter types
1001*f1fbf3c2SXin Li          * @param isStatic              true if the method is static.
1002*f1fbf3c2SXin Li          */
nthParamToLocal(int nth, CtClass[] params, boolean isStatic)1003*f1fbf3c2SXin Li         static int nthParamToLocal(int nth, CtClass[] params,
1004*f1fbf3c2SXin Li                                    boolean isStatic) {
1005*f1fbf3c2SXin Li             CtClass longType = CtClass.longType;
1006*f1fbf3c2SXin Li             CtClass doubleType = CtClass.doubleType;
1007*f1fbf3c2SXin Li             int k;
1008*f1fbf3c2SXin Li             if (isStatic)
1009*f1fbf3c2SXin Li                 k = 0;
1010*f1fbf3c2SXin Li             else
1011*f1fbf3c2SXin Li                 k = 1;  // 0 is THIS.
1012*f1fbf3c2SXin Li 
1013*f1fbf3c2SXin Li             for (int i = 0; i < nth; ++i) {
1014*f1fbf3c2SXin Li                 CtClass type = params[i];
1015*f1fbf3c2SXin Li                 if (type == longType || type == doubleType)
1016*f1fbf3c2SXin Li                     k += 2;
1017*f1fbf3c2SXin Li                 else
1018*f1fbf3c2SXin Li                     ++k;
1019*f1fbf3c2SXin Li             }
1020*f1fbf3c2SXin Li 
1021*f1fbf3c2SXin Li             return k;
1022*f1fbf3c2SXin Li         }
1023*f1fbf3c2SXin Li 
1024*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1025*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1026*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1027*f1fbf3c2SXin Li         {
1028*f1fbf3c2SXin Li             return 0;
1029*f1fbf3c2SXin Li         }
1030*f1fbf3c2SXin Li     }
1031*f1fbf3c2SXin Li 
1032*f1fbf3c2SXin Li     /**
1033*f1fbf3c2SXin Li      * A field initialized with an object created by the new operator.
1034*f1fbf3c2SXin Li      */
1035*f1fbf3c2SXin Li     static class NewInitializer extends Initializer {
1036*f1fbf3c2SXin Li         CtClass objectType;
1037*f1fbf3c2SXin Li         String[] stringParams;
1038*f1fbf3c2SXin Li         boolean withConstructorParams;
1039*f1fbf3c2SXin Li 
NewInitializer()1040*f1fbf3c2SXin Li         NewInitializer() {}
1041*f1fbf3c2SXin Li 
1042*f1fbf3c2SXin Li         /**
1043*f1fbf3c2SXin Li          * Produces codes in which a new object is created and assigned to
1044*f1fbf3c2SXin Li          * the field as the initial value.
1045*f1fbf3c2SXin Li          */
1046*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1047*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1048*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1049*f1fbf3c2SXin Li             throws CannotCompileException
1050*f1fbf3c2SXin Li         {
1051*f1fbf3c2SXin Li             int stacksize;
1052*f1fbf3c2SXin Li 
1053*f1fbf3c2SXin Li             code.addAload(0);
1054*f1fbf3c2SXin Li             code.addNew(objectType);
1055*f1fbf3c2SXin Li             code.add(Bytecode.DUP);
1056*f1fbf3c2SXin Li             code.addAload(0);
1057*f1fbf3c2SXin Li 
1058*f1fbf3c2SXin Li             if (stringParams == null)
1059*f1fbf3c2SXin Li                 stacksize = 4;
1060*f1fbf3c2SXin Li             else
1061*f1fbf3c2SXin Li                 stacksize = compileStringParameter(code) + 4;
1062*f1fbf3c2SXin Li 
1063*f1fbf3c2SXin Li             if (withConstructorParams)
1064*f1fbf3c2SXin Li                 stacksize += CtNewWrappedMethod.compileParameterList(code,
1065*f1fbf3c2SXin Li                                                             parameters, 1);
1066*f1fbf3c2SXin Li 
1067*f1fbf3c2SXin Li             code.addInvokespecial(objectType, "<init>", getDescriptor());
1068*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1069*f1fbf3c2SXin Li             return stacksize;
1070*f1fbf3c2SXin Li         }
1071*f1fbf3c2SXin Li 
getDescriptor()1072*f1fbf3c2SXin Li         private String getDescriptor() {
1073*f1fbf3c2SXin Li             final String desc3
1074*f1fbf3c2SXin Li         = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)V";
1075*f1fbf3c2SXin Li 
1076*f1fbf3c2SXin Li             if (stringParams == null)
1077*f1fbf3c2SXin Li                 if (withConstructorParams)
1078*f1fbf3c2SXin Li                     return "(Ljava/lang/Object;[Ljava/lang/Object;)V";
1079*f1fbf3c2SXin Li                 else
1080*f1fbf3c2SXin Li                     return "(Ljava/lang/Object;)V";
1081*f1fbf3c2SXin Li 
1082*f1fbf3c2SXin Li             if (withConstructorParams)
1083*f1fbf3c2SXin Li                 return desc3;
1084*f1fbf3c2SXin Li 
1085*f1fbf3c2SXin Li             return "(Ljava/lang/Object;[Ljava/lang/String;)V";
1086*f1fbf3c2SXin Li         }
1087*f1fbf3c2SXin Li 
1088*f1fbf3c2SXin Li         /**
1089*f1fbf3c2SXin Li          * Produces codes for a static field.
1090*f1fbf3c2SXin Li          */
1091*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1092*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1093*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1094*f1fbf3c2SXin Li         {
1095*f1fbf3c2SXin Li             String desc;
1096*f1fbf3c2SXin Li 
1097*f1fbf3c2SXin Li             code.addNew(objectType);
1098*f1fbf3c2SXin Li             code.add(Bytecode.DUP);
1099*f1fbf3c2SXin Li 
1100*f1fbf3c2SXin Li             int stacksize = 2;
1101*f1fbf3c2SXin Li             if (stringParams == null)
1102*f1fbf3c2SXin Li                 desc = "()V";
1103*f1fbf3c2SXin Li             else {
1104*f1fbf3c2SXin Li                 desc = "([Ljava/lang/String;)V";
1105*f1fbf3c2SXin Li                 stacksize += compileStringParameter(code);
1106*f1fbf3c2SXin Li             }
1107*f1fbf3c2SXin Li 
1108*f1fbf3c2SXin Li             code.addInvokespecial(objectType, "<init>", desc);
1109*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1110*f1fbf3c2SXin Li             return stacksize;
1111*f1fbf3c2SXin Li         }
1112*f1fbf3c2SXin Li 
compileStringParameter(Bytecode code)1113*f1fbf3c2SXin Li         protected final int compileStringParameter(Bytecode code)
1114*f1fbf3c2SXin Li             throws CannotCompileException
1115*f1fbf3c2SXin Li         {
1116*f1fbf3c2SXin Li             int nparam = stringParams.length;
1117*f1fbf3c2SXin Li             code.addIconst(nparam);
1118*f1fbf3c2SXin Li             code.addAnewarray(javaLangString);
1119*f1fbf3c2SXin Li             for (int j = 0; j < nparam; ++j) {
1120*f1fbf3c2SXin Li                 code.add(Bytecode.DUP);         // dup
1121*f1fbf3c2SXin Li                 code.addIconst(j);                      // iconst_<j>
1122*f1fbf3c2SXin Li                 code.addLdc(stringParams[j]);   // ldc ...
1123*f1fbf3c2SXin Li                 code.add(Bytecode.AASTORE);             // aastore
1124*f1fbf3c2SXin Li             }
1125*f1fbf3c2SXin Li 
1126*f1fbf3c2SXin Li             return 4;
1127*f1fbf3c2SXin Li         }
1128*f1fbf3c2SXin Li 
1129*f1fbf3c2SXin Li     }
1130*f1fbf3c2SXin Li 
1131*f1fbf3c2SXin Li     /**
1132*f1fbf3c2SXin Li      * A field initialized with the result of a static method call.
1133*f1fbf3c2SXin Li      */
1134*f1fbf3c2SXin Li     static class MethodInitializer extends NewInitializer {
1135*f1fbf3c2SXin Li         String methodName;
1136*f1fbf3c2SXin Li         // the method class is specified by objectType.
1137*f1fbf3c2SXin Li 
MethodInitializer()1138*f1fbf3c2SXin Li         MethodInitializer() {}
1139*f1fbf3c2SXin Li 
1140*f1fbf3c2SXin Li         /**
1141*f1fbf3c2SXin Li          * Produces codes in which a new object is created and assigned to
1142*f1fbf3c2SXin Li          * the field as the initial value.
1143*f1fbf3c2SXin Li          */
1144*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1145*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1146*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1147*f1fbf3c2SXin Li             throws CannotCompileException
1148*f1fbf3c2SXin Li         {
1149*f1fbf3c2SXin Li             int stacksize;
1150*f1fbf3c2SXin Li 
1151*f1fbf3c2SXin Li             code.addAload(0);
1152*f1fbf3c2SXin Li             code.addAload(0);
1153*f1fbf3c2SXin Li 
1154*f1fbf3c2SXin Li             if (stringParams == null)
1155*f1fbf3c2SXin Li                 stacksize = 2;
1156*f1fbf3c2SXin Li             else
1157*f1fbf3c2SXin Li                 stacksize = compileStringParameter(code) + 2;
1158*f1fbf3c2SXin Li 
1159*f1fbf3c2SXin Li             if (withConstructorParams)
1160*f1fbf3c2SXin Li                 stacksize += CtNewWrappedMethod.compileParameterList(code,
1161*f1fbf3c2SXin Li                                                             parameters, 1);
1162*f1fbf3c2SXin Li 
1163*f1fbf3c2SXin Li             String typeDesc = Descriptor.of(type);
1164*f1fbf3c2SXin Li             String mDesc = getDescriptor() + typeDesc;
1165*f1fbf3c2SXin Li             code.addInvokestatic(objectType, methodName, mDesc);
1166*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, typeDesc);
1167*f1fbf3c2SXin Li             return stacksize;
1168*f1fbf3c2SXin Li         }
1169*f1fbf3c2SXin Li 
getDescriptor()1170*f1fbf3c2SXin Li         private String getDescriptor() {
1171*f1fbf3c2SXin Li             final String desc3
1172*f1fbf3c2SXin Li                 = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)";
1173*f1fbf3c2SXin Li 
1174*f1fbf3c2SXin Li             if (stringParams == null)
1175*f1fbf3c2SXin Li                 if (withConstructorParams)
1176*f1fbf3c2SXin Li                     return "(Ljava/lang/Object;[Ljava/lang/Object;)";
1177*f1fbf3c2SXin Li                 else
1178*f1fbf3c2SXin Li                     return "(Ljava/lang/Object;)";
1179*f1fbf3c2SXin Li 
1180*f1fbf3c2SXin Li             if (withConstructorParams)
1181*f1fbf3c2SXin Li                 return desc3;
1182*f1fbf3c2SXin Li 
1183*f1fbf3c2SXin Li             return "(Ljava/lang/Object;[Ljava/lang/String;)";
1184*f1fbf3c2SXin Li         }
1185*f1fbf3c2SXin Li 
1186*f1fbf3c2SXin Li         /**
1187*f1fbf3c2SXin Li          * Produces codes for a static field.
1188*f1fbf3c2SXin Li          */
1189*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1190*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1191*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1192*f1fbf3c2SXin Li         {
1193*f1fbf3c2SXin Li             String desc;
1194*f1fbf3c2SXin Li 
1195*f1fbf3c2SXin Li             int stacksize = 1;
1196*f1fbf3c2SXin Li             if (stringParams == null)
1197*f1fbf3c2SXin Li                 desc = "()";
1198*f1fbf3c2SXin Li             else {
1199*f1fbf3c2SXin Li                 desc = "([Ljava/lang/String;)";
1200*f1fbf3c2SXin Li                 stacksize += compileStringParameter(code);
1201*f1fbf3c2SXin Li             }
1202*f1fbf3c2SXin Li 
1203*f1fbf3c2SXin Li             String typeDesc = Descriptor.of(type);
1204*f1fbf3c2SXin Li             code.addInvokestatic(objectType, methodName, desc + typeDesc);
1205*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, typeDesc);
1206*f1fbf3c2SXin Li             return stacksize;
1207*f1fbf3c2SXin Li         }
1208*f1fbf3c2SXin Li     }
1209*f1fbf3c2SXin Li 
1210*f1fbf3c2SXin Li     static class IntInitializer extends Initializer {
1211*f1fbf3c2SXin Li         int value;
1212*f1fbf3c2SXin Li 
IntInitializer(int v)1213*f1fbf3c2SXin Li         IntInitializer(int v) { value = v; }
1214*f1fbf3c2SXin Li 
1215*f1fbf3c2SXin Li         @Override
check(String desc)1216*f1fbf3c2SXin Li         void check(String desc) throws CannotCompileException {
1217*f1fbf3c2SXin Li             char c = desc.charAt(0);
1218*f1fbf3c2SXin Li             if (c != 'I' && c != 'S' && c != 'B' && c != 'C' && c != 'Z')
1219*f1fbf3c2SXin Li                 throw new CannotCompileException("type mismatch");
1220*f1fbf3c2SXin Li         }
1221*f1fbf3c2SXin Li 
1222*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1223*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1224*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1225*f1fbf3c2SXin Li             throws CannotCompileException
1226*f1fbf3c2SXin Li         {
1227*f1fbf3c2SXin Li             code.addAload(0);
1228*f1fbf3c2SXin Li             code.addIconst(value);
1229*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1230*f1fbf3c2SXin Li             return 2;   // stack size
1231*f1fbf3c2SXin Li         }
1232*f1fbf3c2SXin Li 
1233*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1234*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1235*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1236*f1fbf3c2SXin Li         {
1237*f1fbf3c2SXin Li             code.addIconst(value);
1238*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1239*f1fbf3c2SXin Li             return 1;   // stack size
1240*f1fbf3c2SXin Li         }
1241*f1fbf3c2SXin Li 
1242*f1fbf3c2SXin Li         @Override
getConstantValue(ConstPool cp, CtClass type)1243*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) {
1244*f1fbf3c2SXin Li             return cp.addIntegerInfo(value);
1245*f1fbf3c2SXin Li         }
1246*f1fbf3c2SXin Li     }
1247*f1fbf3c2SXin Li 
1248*f1fbf3c2SXin Li     static class LongInitializer extends Initializer {
1249*f1fbf3c2SXin Li         long value;
1250*f1fbf3c2SXin Li 
LongInitializer(long v)1251*f1fbf3c2SXin Li         LongInitializer(long v) { value = v; }
1252*f1fbf3c2SXin Li 
1253*f1fbf3c2SXin Li         @Override
check(String desc)1254*f1fbf3c2SXin Li         void check(String desc) throws CannotCompileException {
1255*f1fbf3c2SXin Li             if (!desc.equals("J"))
1256*f1fbf3c2SXin Li                 throw new CannotCompileException("type mismatch");
1257*f1fbf3c2SXin Li         }
1258*f1fbf3c2SXin Li 
1259*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1260*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1261*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1262*f1fbf3c2SXin Li             throws CannotCompileException
1263*f1fbf3c2SXin Li         {
1264*f1fbf3c2SXin Li             code.addAload(0);
1265*f1fbf3c2SXin Li             code.addLdc2w(value);
1266*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1267*f1fbf3c2SXin Li             return 3;   // stack size
1268*f1fbf3c2SXin Li         }
1269*f1fbf3c2SXin Li 
1270*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1271*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1272*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1273*f1fbf3c2SXin Li         {
1274*f1fbf3c2SXin Li             code.addLdc2w(value);
1275*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1276*f1fbf3c2SXin Li             return 2;   // stack size
1277*f1fbf3c2SXin Li         }
1278*f1fbf3c2SXin Li 
1279*f1fbf3c2SXin Li         @Override
getConstantValue(ConstPool cp, CtClass type)1280*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) {
1281*f1fbf3c2SXin Li             if (type == CtClass.longType)
1282*f1fbf3c2SXin Li                 return cp.addLongInfo(value);
1283*f1fbf3c2SXin Li             return 0;
1284*f1fbf3c2SXin Li         }
1285*f1fbf3c2SXin Li     }
1286*f1fbf3c2SXin Li 
1287*f1fbf3c2SXin Li     static class FloatInitializer extends Initializer {
1288*f1fbf3c2SXin Li         float value;
1289*f1fbf3c2SXin Li 
FloatInitializer(float v)1290*f1fbf3c2SXin Li         FloatInitializer(float v) { value = v; }
1291*f1fbf3c2SXin Li 
1292*f1fbf3c2SXin Li         @Override
check(String desc)1293*f1fbf3c2SXin Li         void check(String desc) throws CannotCompileException {
1294*f1fbf3c2SXin Li             if (!desc.equals("F"))
1295*f1fbf3c2SXin Li                 throw new CannotCompileException("type mismatch");
1296*f1fbf3c2SXin Li         }
1297*f1fbf3c2SXin Li 
1298*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1299*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1300*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1301*f1fbf3c2SXin Li             throws CannotCompileException
1302*f1fbf3c2SXin Li         {
1303*f1fbf3c2SXin Li             code.addAload(0);
1304*f1fbf3c2SXin Li             code.addFconst(value);
1305*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1306*f1fbf3c2SXin Li             return 3;   // stack size
1307*f1fbf3c2SXin Li         }
1308*f1fbf3c2SXin Li 
1309*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1310*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1311*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1312*f1fbf3c2SXin Li         {
1313*f1fbf3c2SXin Li             code.addFconst(value);
1314*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1315*f1fbf3c2SXin Li             return 2;   // stack size
1316*f1fbf3c2SXin Li         }
1317*f1fbf3c2SXin Li 
1318*f1fbf3c2SXin Li         @Override
getConstantValue(ConstPool cp, CtClass type)1319*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) {
1320*f1fbf3c2SXin Li             if (type == CtClass.floatType)
1321*f1fbf3c2SXin Li                 return cp.addFloatInfo(value);
1322*f1fbf3c2SXin Li             return 0;
1323*f1fbf3c2SXin Li         }
1324*f1fbf3c2SXin Li     }
1325*f1fbf3c2SXin Li 
1326*f1fbf3c2SXin Li     static class DoubleInitializer extends Initializer {
1327*f1fbf3c2SXin Li         double value;
1328*f1fbf3c2SXin Li 
DoubleInitializer(double v)1329*f1fbf3c2SXin Li         DoubleInitializer(double v) { value = v; }
1330*f1fbf3c2SXin Li 
1331*f1fbf3c2SXin Li         @Override
check(String desc)1332*f1fbf3c2SXin Li         void check(String desc) throws CannotCompileException {
1333*f1fbf3c2SXin Li             if (!desc.equals("D"))
1334*f1fbf3c2SXin Li                 throw new CannotCompileException("type mismatch");
1335*f1fbf3c2SXin Li         }
1336*f1fbf3c2SXin Li 
1337*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1338*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1339*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1340*f1fbf3c2SXin Li             throws CannotCompileException
1341*f1fbf3c2SXin Li         {
1342*f1fbf3c2SXin Li             code.addAload(0);
1343*f1fbf3c2SXin Li             code.addLdc2w(value);
1344*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1345*f1fbf3c2SXin Li             return 3;   // stack size
1346*f1fbf3c2SXin Li         }
1347*f1fbf3c2SXin Li 
1348*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1349*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1350*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1351*f1fbf3c2SXin Li         {
1352*f1fbf3c2SXin Li             code.addLdc2w(value);
1353*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1354*f1fbf3c2SXin Li             return 2;   // stack size
1355*f1fbf3c2SXin Li         }
1356*f1fbf3c2SXin Li 
1357*f1fbf3c2SXin Li         @Override
getConstantValue(ConstPool cp, CtClass type)1358*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) {
1359*f1fbf3c2SXin Li             if (type == CtClass.doubleType)
1360*f1fbf3c2SXin Li                 return cp.addDoubleInfo(value);
1361*f1fbf3c2SXin Li             return 0;
1362*f1fbf3c2SXin Li         }
1363*f1fbf3c2SXin Li     }
1364*f1fbf3c2SXin Li 
1365*f1fbf3c2SXin Li     static class StringInitializer extends Initializer {
1366*f1fbf3c2SXin Li         String value;
1367*f1fbf3c2SXin Li 
StringInitializer(String v)1368*f1fbf3c2SXin Li         StringInitializer(String v) { value = v; }
1369*f1fbf3c2SXin Li 
1370*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1371*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1372*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1373*f1fbf3c2SXin Li             throws CannotCompileException
1374*f1fbf3c2SXin Li         {
1375*f1fbf3c2SXin Li             code.addAload(0);
1376*f1fbf3c2SXin Li             code.addLdc(value);
1377*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1378*f1fbf3c2SXin Li             return 2;   // stack size
1379*f1fbf3c2SXin Li         }
1380*f1fbf3c2SXin Li 
1381*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1382*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1383*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1384*f1fbf3c2SXin Li         {
1385*f1fbf3c2SXin Li             code.addLdc(value);
1386*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1387*f1fbf3c2SXin Li             return 1;   // stack size
1388*f1fbf3c2SXin Li         }
1389*f1fbf3c2SXin Li 
1390*f1fbf3c2SXin Li         @Override
getConstantValue(ConstPool cp, CtClass type)1391*f1fbf3c2SXin Li         int getConstantValue(ConstPool cp, CtClass type) {
1392*f1fbf3c2SXin Li             if (type.getName().equals(javaLangString))
1393*f1fbf3c2SXin Li                 return cp.addStringInfo(value);
1394*f1fbf3c2SXin Li             return 0;
1395*f1fbf3c2SXin Li         }
1396*f1fbf3c2SXin Li     }
1397*f1fbf3c2SXin Li 
1398*f1fbf3c2SXin Li     static class ArrayInitializer extends Initializer {
1399*f1fbf3c2SXin Li         CtClass type;
1400*f1fbf3c2SXin Li         int size;
1401*f1fbf3c2SXin Li 
ArrayInitializer(CtClass t, int s)1402*f1fbf3c2SXin Li         ArrayInitializer(CtClass t, int s) { type = t; size = s; }
1403*f1fbf3c2SXin Li 
addNewarray(Bytecode code)1404*f1fbf3c2SXin Li         private void addNewarray(Bytecode code) {
1405*f1fbf3c2SXin Li             if (type.isPrimitive())
1406*f1fbf3c2SXin Li                 code.addNewarray(((CtPrimitiveType)type).getArrayType(),
1407*f1fbf3c2SXin Li                                  size);
1408*f1fbf3c2SXin Li             else
1409*f1fbf3c2SXin Li                 code.addAnewarray(type, size);
1410*f1fbf3c2SXin Li         }
1411*f1fbf3c2SXin Li 
1412*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1413*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1414*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1415*f1fbf3c2SXin Li             throws CannotCompileException
1416*f1fbf3c2SXin Li         {
1417*f1fbf3c2SXin Li             code.addAload(0);
1418*f1fbf3c2SXin Li             addNewarray(code);
1419*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1420*f1fbf3c2SXin Li             return 2;   // stack size
1421*f1fbf3c2SXin Li         }
1422*f1fbf3c2SXin Li 
1423*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1424*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1425*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1426*f1fbf3c2SXin Li         {
1427*f1fbf3c2SXin Li             addNewarray(code);
1428*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1429*f1fbf3c2SXin Li             return 1;   // stack size
1430*f1fbf3c2SXin Li         }
1431*f1fbf3c2SXin Li     }
1432*f1fbf3c2SXin Li 
1433*f1fbf3c2SXin Li     static class MultiArrayInitializer extends Initializer {
1434*f1fbf3c2SXin Li         CtClass type;
1435*f1fbf3c2SXin Li         int[] dim;
1436*f1fbf3c2SXin Li 
MultiArrayInitializer(CtClass t, int[] d)1437*f1fbf3c2SXin Li         MultiArrayInitializer(CtClass t, int[] d) { type = t; dim = d; }
1438*f1fbf3c2SXin Li 
1439*f1fbf3c2SXin Li         @Override
check(String desc)1440*f1fbf3c2SXin Li         void check(String desc) throws CannotCompileException {
1441*f1fbf3c2SXin Li             if (desc.charAt(0) != '[')
1442*f1fbf3c2SXin Li                 throw new CannotCompileException("type mismatch");
1443*f1fbf3c2SXin Li         }
1444*f1fbf3c2SXin Li 
1445*f1fbf3c2SXin Li         @Override
compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1446*f1fbf3c2SXin Li         int compile(CtClass type, String name, Bytecode code,
1447*f1fbf3c2SXin Li                     CtClass[] parameters, Javac drv)
1448*f1fbf3c2SXin Li             throws CannotCompileException
1449*f1fbf3c2SXin Li         {
1450*f1fbf3c2SXin Li             code.addAload(0);
1451*f1fbf3c2SXin Li             int s = code.addMultiNewarray(type, dim);
1452*f1fbf3c2SXin Li             code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
1453*f1fbf3c2SXin Li             return s + 1;       // stack size
1454*f1fbf3c2SXin Li         }
1455*f1fbf3c2SXin Li 
1456*f1fbf3c2SXin Li         @Override
compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1457*f1fbf3c2SXin Li         int compileIfStatic(CtClass type, String name, Bytecode code,
1458*f1fbf3c2SXin Li                             Javac drv) throws CannotCompileException
1459*f1fbf3c2SXin Li         {
1460*f1fbf3c2SXin Li             int s = code.addMultiNewarray(type, dim);
1461*f1fbf3c2SXin Li             code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
1462*f1fbf3c2SXin Li             return s;   // stack size
1463*f1fbf3c2SXin Li         }
1464*f1fbf3c2SXin Li     }
1465*f1fbf3c2SXin Li }
1466