KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > FieldDeclaration


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16 import org.eclipse.jdt.internal.compiler.codegen.*;
17 import org.eclipse.jdt.internal.compiler.flow.*;
18 import org.eclipse.jdt.internal.compiler.lookup.*;
19
20 public class FieldDeclaration extends AbstractVariableDeclaration {
21     
22     public FieldBinding binding;
23     public Javadoc javadoc;
24
25     //allows to retrieve both the "type" part of the declaration (part1)
26
//and also the part that decribe the name and the init and optionally
27
//some other dimension ! ....
28
//public int[] a, b[] = X, c ;
29
//for b that would give for
30
// - part1 : public int[]
31
// - part2 : b[] = X,
32

33     public int endPart1Position;
34     public int endPart2Position;
35
36 public FieldDeclaration() {
37     // for subtypes or conversion
38
}
39
40 public FieldDeclaration( char[] name, int sourceStart, int sourceEnd) {
41     this.name = name;
42     //due to some declaration like
43
// int x, y = 3, z , x ;
44
//the sourceStart and the sourceEnd is ONLY on the name
45
this.sourceStart = sourceStart;
46     this.sourceEnd = sourceEnd;
47 }
48
49 public FlowInfo analyseCode(MethodScope initializationScope, FlowContext flowContext, FlowInfo flowInfo) {
50     if (this.binding != null && !this.binding.isUsed()) {
51         if (this.binding.isPrivate() || (this.binding.declaringClass != null && this.binding.declaringClass.isLocalType())) {
52             if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
53                 initializationScope.problemReporter().unusedPrivateField(this);
54             }
55         }
56     }
57     // cannot define static non-constant field inside nested class
58
if (this.binding != null
59             && this.binding.isValidBinding()
60             && this.binding.isStatic()
61             && this.binding.constant() == Constant.NotAConstant
62             && this.binding.declaringClass.isNestedType()
63             && !this.binding.declaringClass.isStatic()) {
64         initializationScope.problemReporter().unexpectedStaticModifierForField(
65             (SourceTypeBinding) this.binding.declaringClass,
66             this);
67     }
68
69     if (this.initialization != null) {
70         flowInfo =
71             this.initialization
72                 .analyseCode(initializationScope, flowContext, flowInfo)
73                 .unconditionalInits();
74         flowInfo.markAsDefinitelyAssigned(this.binding);
75     }
76     return flowInfo;
77 }
78
79 /**
80  * Code generation for a field declaration:
81  * standard assignment to a field
82  *
83  * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
84  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
85  */

86 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
87     if ((this.bits & IsReachable) == 0) {
88         return;
89     }
90     // do not generate initialization code if final and static (constant is then
91
// recorded inside the field itself).
92
int pc = codeStream.position;
93     boolean isStatic;
94     if (this.initialization != null
95         && !((isStatic = this.binding.isStatic()) && this.binding.constant() != Constant.NotAConstant)) {
96         // non-static field, need receiver
97
if (!isStatic)
98             codeStream.aload_0();
99         // generate initialization value
100
this.initialization.generateCode(currentScope, codeStream, true);
101         // store into field
102
if (isStatic) {
103             codeStream.putstatic(this.binding);
104         } else {
105             codeStream.putfield(this.binding);
106         }
107     }
108     codeStream.recordPositionsFrom(pc, this.sourceStart);
109 }
110
111 /**
112  * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
113  */

114 public int getKind() {
115     return this.type == null ? ENUM_CONSTANT : FIELD;
116 }
117
118 public boolean isStatic() {
119     if (this.binding != null)
120         return this.binding.isStatic();
121     return (this.modifiers & ClassFileConstants.AccStatic) != 0;
122 }
123
124 public StringBuffer JavaDoc printStatement(int indent, StringBuffer JavaDoc output) {
125     if (this.javadoc != null) {
126         this.javadoc.print(indent, output);
127     }
128     return super.printStatement(indent, output);
129 }
130
131 public void resolve(MethodScope initializationScope) {
132     // the two <constant = Constant.NotAConstant> could be regrouped into
133
// a single line but it is clearer to have two lines while the reason of their
134
// existence is not at all the same. See comment for the second one.
135

136     //--------------------------------------------------------
137
if ((this.bits & ASTNode.HasBeenResolved) != 0) return;
138     if (this.binding == null || !this.binding.isValidBinding()) return;
139     
140     this.bits |= ASTNode.HasBeenResolved;
141
142     // check if field is hiding some variable - issue is that field binding already got inserted in scope
143
// thus must lookup separately in super type and outer context
144
ClassScope classScope = initializationScope.enclosingClassScope();
145     
146     if (classScope != null) {
147         checkHiding: {
148             SourceTypeBinding declaringType = classScope.enclosingSourceType();
149             checkHidingSuperField: {
150                 if (declaringType.superclass == null) break checkHidingSuperField;
151                 Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this, false /*do not resolve hidden field*/);
152                 if (existingVariable == null) break checkHidingSuperField; // keep checking outer scenario
153
if (!existingVariable.isValidBinding()) break checkHidingSuperField; // keep checking outer scenario
154
if (existingVariable instanceof FieldBinding) {
155                     FieldBinding existingField = (FieldBinding) existingVariable;
156                     if (existingField.original() == this.binding) break checkHidingSuperField; // keep checking outer scenario
157
}
158                 // collision with supertype field
159
initializationScope.problemReporter().fieldHiding(this, existingVariable);
160                 break checkHiding; // already found a matching field
161
}
162             // only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
163
// from outer scope. Subsequent static contexts are detected for free.
164
Scope outerScope = classScope.parent;
165             if (outerScope.kind == Scope.COMPILATION_UNIT_SCOPE) break checkHiding;
166             Binding existingVariable = outerScope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
167             if (existingVariable == null) break checkHiding;
168             if (!existingVariable.isValidBinding()) break checkHiding;
169             if (existingVariable == this.binding) break checkHiding;
170             if (existingVariable instanceof FieldBinding) {
171                 FieldBinding existingField = (FieldBinding) existingVariable;
172                 if (existingField.original() == this.binding) break checkHiding;
173                 if (!existingField.isStatic() && declaringType.isStatic()) break checkHiding;
174             }
175             // collision with outer field or local variable
176
initializationScope.problemReporter().fieldHiding(this, existingVariable);
177         }
178     }
179     
180     if (this.type != null ) { // enum constants have no declared type
181
this.type.resolvedType = this.binding.type; // update binding for type reference
182
}
183
184     FieldBinding previousField = initializationScope.initializedField;
185     int previousFieldID = initializationScope.lastVisibleFieldID;
186     try {
187         initializationScope.initializedField = this.binding;
188         initializationScope.lastVisibleFieldID = this.binding.id;
189
190         resolveAnnotations(initializationScope, this.annotations, this.binding);
191         // check @Deprecated annotation presence
192
if ((this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
193                 && (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
194                 && initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
195             initializationScope.problemReporter().missingDeprecatedAnnotationForField(this);
196         }
197         // the resolution of the initialization hasn't been done
198
if (this.initialization == null) {
199             this.binding.setConstant(Constant.NotAConstant);
200         } else {
201             // break dead-lock cycles by forcing constant to NotAConstant
202
this.binding.setConstant(Constant.NotAConstant);
203             
204             TypeBinding fieldType = this.binding.type;
205             TypeBinding initializationType;
206             this.initialization.setExpectedType(fieldType); // needed in case of generic method invocation
207
if (this.initialization instanceof ArrayInitializer) {
208
209                 if ((initializationType = this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) {
210                     ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType;
211                     this.initialization.computeConversion(initializationScope, fieldType, initializationType);
212                 }
213             } else if ((initializationType = this.initialization.resolveType(initializationScope)) != null) {
214
215                 if (fieldType != initializationType) // must call before computeConversion() and typeMismatchError()
216
initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType);
217                 if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType)
218                         || (fieldType.isBaseType() && BaseTypeBinding.isWidening(fieldType.id, initializationType.id))
219                         || initializationType.isCompatibleWith(fieldType)) {
220                     this.initialization.computeConversion(initializationScope, fieldType, initializationType);
221                     if (initializationType.needsUncheckedConversion(fieldType)) {
222                             initializationScope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, fieldType);
223                     }
224                     if (this.initialization instanceof CastExpression
225                             && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
226                         CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization);
227                     }
228                 } else if (initializationScope.isBoxingCompatibleWith(initializationType, fieldType)
229                                     || (initializationType.isBaseType() // narrowing then boxing ?
230
&& initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
231
&& !fieldType.isBaseType()
232                                             && initialization.isConstantValueOfTypeAssignableToType(initializationType, initializationScope.environment().computeBoxingType(fieldType)))) {
233                     this.initialization.computeConversion(initializationScope, fieldType, initializationType);
234                     if (this.initialization instanceof CastExpression
235                             && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
236                         CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization);
237                     }
238                 } else {
239                     initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this);
240                 }
241                 if (this.binding.isFinal()){ // cast from constant actual type to variable type
242
this.binding.setConstant(this.initialization.constant.castTo((this.binding.type.id << 4) + this.initialization.constant.typeID()));
243                 }
244             } else {
245                 this.binding.setConstant(Constant.NotAConstant);
246             }
247             // check for assignment with no effect
248
if (this.binding == Assignment.getDirectBinding(this.initialization)) {
249                 initializationScope.problemReporter().assignmentHasNoEffect(this, this.name);
250             }
251         }
252         // Resolve Javadoc comment if one is present
253
if (this.javadoc != null) {
254             /*
255             if (classScope != null) {
256                 this.javadoc.resolve(classScope);
257             }
258             */

259             this.javadoc.resolve(initializationScope);
260         } else if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
261             initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
262         }
263     } finally {
264         initializationScope.initializedField = previousField;
265         initializationScope.lastVisibleFieldID = previousFieldID;
266         if (this.binding.constant() == null)
267             this.binding.setConstant(Constant.NotAConstant);
268     }
269 }
270
271 public void traverse(ASTVisitor visitor, MethodScope scope) {
272     if (visitor.visit(this, scope)) {
273         if (this.javadoc != null) {
274             this.javadoc.traverse(visitor, scope);
275         }
276         if (this.annotations != null) {
277             int annotationsLength = this.annotations.length;
278             for (int i = 0; i < annotationsLength; i++)
279                 this.annotations[i].traverse(visitor, scope);
280         }
281         if (this.type != null) {
282             this.type.traverse(visitor, scope);
283         }
284         if (this.initialization != null)
285             this.initialization.traverse(visitor, scope);
286     }
287     visitor.endVisit(this, scope);
288 }
289 }
290
Popular Tags