KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > expr > FieldOperator


1 /* FieldOperator Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: FieldOperator.java.in,v 4.4.2.2 2002/05/28 17:34:06 hoenicke Exp $
18  */

19
20 package jode.expr;
21 import jode.type.Type;
22 import jode.type.NullType;
23 import jode.type.ClassInterfacesType;
24 import jode.bytecode.FieldInfo;
25 import jode.bytecode.ClassInfo;
26 import jode.bytecode.Reference;
27 import jode.bytecode.InnerClassInfo;
28 import jode.bytecode.TypeSignature;
29 import jode.decompiler.MethodAnalyzer;
30 import jode.decompiler.ClassAnalyzer;
31 import jode.decompiler.MethodAnalyzer;
32 import jode.decompiler.FieldAnalyzer;
33 import jode.decompiler.Options;
34 import jode.decompiler.TabbedPrintWriter;
35 import jode.decompiler.Scope;
36
37 import java.lang.reflect.Modifier JavaDoc;
38 import java.util.Collection JavaDoc;
39
40 /**
41  * This class contains everything shared between PutFieldOperator and
42  * GetFieldOperator
43  */

44 public abstract class FieldOperator extends Operator {
45     MethodAnalyzer methodAnalyzer;
46     boolean staticFlag;
47     Reference ref;
48     Type classType;
49
50     public FieldOperator(MethodAnalyzer methodAnalyzer, boolean staticFlag,
51              Reference ref) {
52         super(Type.tType(ref.getType()));
53         this.methodAnalyzer = methodAnalyzer;
54         this.staticFlag = staticFlag;
55         this.classType = Type.tType(ref.getClazz());
56     this.ref = ref;
57         if (staticFlag)
58             methodAnalyzer.useType(classType);
59     initOperands(staticFlag ? 0 : 1);
60     }
61
62     public int getPriority() {
63         return 950;
64     }
65
66     public void updateSubTypes() {
67     if (!staticFlag)
68         subExpressions[0].setType(Type.tSubType(classType));
69     }
70
71     public void updateType() {
72     updateParentType(getFieldType());
73     }
74
75     public boolean isStatic() {
76         return staticFlag;
77     }
78
79     public ClassInfo getClassInfo() {
80     if (classType instanceof ClassInterfacesType)
81         return ((ClassInterfacesType) classType).getClassInfo();
82     return null;
83     }
84
85     /**
86      * Returns the field analyzer for the field, if the field is
87      * declared in the same class or some outer class as the method
88      * containing this instruction. Otherwise it returns null.
89      * @return see above.
90      */

91     public FieldAnalyzer getField() {
92     ClassInfo clazz = getClassInfo();
93     if (clazz != null) {
94         ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer();
95         while (true) {
96         if (clazz == ana.getClazz()) {
97             int field = ana.getFieldIndex
98             (ref.getName(), Type.tType(ref.getType()));
99             if (field >= 0)
100             return ana.getField(field);
101             return null;
102         }
103         if (ana.getParent() == null)
104             return null;
105         if (ana.getParent() instanceof MethodAnalyzer)
106             ana = ((MethodAnalyzer) ana.getParent())
107             .getClassAnalyzer();
108         else if (ana.getParent() instanceof ClassAnalyzer)
109             ana = (ClassAnalyzer) ana.getParent();
110         else
111             throw new jode.AssertError("Unknown parent");
112         }
113     }
114     return null;
115     }
116
117     public String JavaDoc getFieldName() {
118         return ref.getName();
119     }
120
121     public Type getFieldType() {
122         return Type.tType(ref.getType());
123     }
124
125     private static FieldInfo getFieldInfo(ClassInfo clazz,
126                       String JavaDoc name, String JavaDoc type) {
127     while (clazz != null) {
128         FieldInfo field = clazz.findField(name, type);
129         if (field != null)
130         return field;
131
132         ClassInfo[] ifaces = clazz.getInterfaces();
133         for (int i = 0; i < ifaces.length; i++) {
134         field = getFieldInfo(ifaces[i], name, type);
135         if (field != null)
136             return field;
137         }
138
139         clazz = clazz.getSuperclass();
140     }
141     return null;
142     }
143     public FieldInfo getFieldInfo() {
144     ClassInfo clazz;
145     if (ref.getClazz().charAt(0) == '[')
146         clazz = ClassInfo.javaLangObject;
147     else
148         clazz = TypeSignature.getClassInfo(ref.getClazz());
149         return getFieldInfo(clazz, ref.getName(), ref.getType());
150     }
151
152     public boolean needsCast(Type type) {
153     if (type instanceof NullType)
154         return true;
155     if (!(type instanceof ClassInterfacesType
156           && classType instanceof ClassInterfacesType))
157         return false;
158     
159     ClassInfo clazz = ((ClassInterfacesType) classType).getClassInfo();
160     ClassInfo parClazz = ((ClassInterfacesType) type).getClassInfo();
161     FieldInfo field = clazz.findField(ref.getName(), ref.getType());
162
163     find_field:
164     while (field == null) {
165         ClassInfo ifaces[] = clazz.getInterfaces();
166         for (int i = 0; i < ifaces.length; i++) {
167         field = ifaces[i].findField(ref.getName(), ref.getType());
168         if (field != null)
169             break find_field;
170         }
171         clazz = clazz.getSuperclass();
172         if (clazz == null)
173         /* Weird, field not existing? */
174         return false;
175         field = clazz.findField(ref.getName(), ref.getType());
176     }
177     if (Modifier.isPrivate(field.getModifiers()))
178         return parClazz != clazz;
179     else if ((field.getModifiers()
180           & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
181         /* Field is protected. We need a cast if parClazz is in
182          * other package than clazz.
183          */

184         int lastDot = clazz.getName().lastIndexOf('.');
185         if (lastDot == -1
186         || lastDot != parClazz.getName().lastIndexOf('.')
187         || !(parClazz.getName()
188              .startsWith(clazz.getName().substring(0,lastDot))))
189         return true;
190     }
191         
192     while (clazz != parClazz && clazz != null) {
193         FieldInfo[] fields = parClazz.getFields();
194         for (int i = 0; i < fields.length; i++) {
195         if (fields[i].getName().equals(ref.getName()))
196             return true;
197         }
198         parClazz = parClazz.getSuperclass();
199     }
200     return false;
201     }
202
203     public InnerClassInfo getOuterClassInfo(ClassInfo ci) {
204     if (ci != null) {
205         InnerClassInfo[] outers = ci.getOuterClasses();
206         if (outers != null)
207         return outers[0];
208     }
209     return null;
210     }
211
212     /**
213      * We add the named method scoped classes to the declarables.
214      */

215     public void fillDeclarables(Collection JavaDoc used) {
216     ClassInfo clazz = getClassInfo();
217     InnerClassInfo outer = getOuterClassInfo(clazz);
218     ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
219
220     if ((Options.options & Options.OPTION_ANON) != 0
221         && outer != null && outer.outer == null && outer.name != null
222         && clazzAna != null
223         && clazzAna.getParent() == methodAnalyzer) {
224
225         /* This is a named method scope class, declare it.
226          * But first declare all method scoped classes,
227          * that are used inside; order does matter.
228          */

229         clazzAna.fillDeclarables(used);
230         used.add(clazzAna);
231     }
232     super.fillDeclarables(used);
233     }
234
235     public void dumpExpression(TabbedPrintWriter writer)
236     throws java.io.IOException JavaDoc {
237     boolean opIsThis = !staticFlag
238         && subExpressions[0] instanceof ThisOperator;
239     String JavaDoc fieldName = ref.getName();
240     if (staticFlag) {
241         if (!classType.equals(Type.tClass(methodAnalyzer.getClazz()))
242         || methodAnalyzer.findLocal(fieldName) != null) {
243         writer.printType(classType);
244         writer.breakOp();
245         writer.print(".");
246         }
247         writer.print(fieldName);
248     } else if (needsCast(subExpressions[0].getType().getCanonic())) {
249         writer.print("(");
250         writer.startOp(writer.EXPL_PAREN, 1);
251         writer.print("(");
252         writer.printType(classType);
253         writer.print(") ");
254         writer.breakOp();
255         subExpressions[0].dumpExpression(writer, 700);
256         writer.endOp();
257         writer.print(")");
258         writer.breakOp();
259         writer.print(".");
260         writer.print(fieldName);
261     } else {
262         if (opIsThis) {
263         ThisOperator thisOp = (ThisOperator) subExpressions[0];
264         Scope scope = writer.getScope(thisOp.getClassInfo(),
265                           Scope.CLASSSCOPE);
266
267         if (scope == null || writer.conflicts(fieldName, scope,
268                               Scope.FIELDNAME)) {
269             thisOp.dumpExpression(writer, 950);
270             writer.breakOp();
271             writer.print(".");
272         } else if (writer.conflicts(fieldName, scope,
273                         Scope.AMBIGUOUSNAME)
274                || (/* This is a inherited field conflicting
275                 * with a field name in some outer class.
276                 */

277                    getField() == null
278                    && writer.conflicts(fieldName, null,
279                  Scope.NOSUPERFIELDNAME))) {
280             thisOp.dumpExpression(writer, 950);
281             writer.breakOp();
282             writer.print(".");
283         }
284         } else {
285         subExpressions[0].dumpExpression(writer, 950);
286         writer.breakOp();
287         writer.print(".");
288         }
289         writer.print(fieldName);
290     }
291     }
292 }
293
Popular Tags