1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
19 public class FieldDeclaration extends AbstractVariableDeclaration {
20 public FieldBinding binding;
21 boolean hasBeenResolved = false;
22 public Javadoc javadoc;
24 //allows to retrieve both the "type" part of the declaration (part1)
25 //and also the part that decribe the name and the init and optionally
26 //some other dimension ! ....
27 //public int[] a, b[] = X, c ;
28 //for b that would give for
29 // - part1 : public int[]
32 public int endPart1Position;
33 public int endPart2Position;
35 public FieldDeclaration() {
36 // for subtypes or conversion
39 public FieldDeclaration(
46 //due to some declaration like
47 // int x, y = 3, z , x ;
48 //the sourceStart and the sourceEnd is ONLY on the name
49 this.sourceStart = sourceStart;
50 this.sourceEnd = sourceEnd;
53 public FlowInfo analyseCode(
54 MethodScope initializationScope,
55 FlowContext flowContext,
58 if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
59 if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
60 initializationScope.problemReporter().unusedPrivateField(this);
63 // cannot define static non-constant field inside nested class
64 if (this.binding != null
65 && this.binding.isValidBinding()
66 && this.binding.isStatic()
67 && this.binding.constant == NotAConstant
68 && this.binding.declaringClass.isNestedType()
69 && this.binding.declaringClass.isClass()
70 && !this.binding.declaringClass.isStatic()) {
71 initializationScope.problemReporter().unexpectedStaticModifierForField(
72 (SourceTypeBinding) this.binding.declaringClass,
76 if (this.initialization != null) {
79 .analyseCode(initializationScope, flowContext, flowInfo)
80 .unconditionalInits();
81 flowInfo.markAsDefinitelyAssigned(this.binding);
87 * Code generation for a field declaration:
88 * standard assignment to a field
90 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
91 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
93 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
95 if ((this.bits & IsReachableMASK) == 0) {
98 // do not generate initialization code if final and static (constant is then
99 // recorded inside the field itself).
100 int pc = codeStream.position;
102 if (this.initialization != null
103 && !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
104 // non-static field, need receiver
106 codeStream.aload_0();
107 // generate initialization value
108 this.initialization.generateCode(currentScope, codeStream, true);
111 codeStream.putstatic(this.binding);
113 codeStream.putfield(this.binding);
116 codeStream.recordPositionsFrom(pc, this.sourceStart);
119 public TypeBinding getTypeBinding(Scope scope) {
121 return this.type.getTypeBinding(scope);
124 public boolean isField() {
129 public boolean isStatic() {
131 if (this.binding != null)
132 return this.binding.isStatic();
133 return (this.modifiers & AccStatic) != 0;
136 public void resolve(MethodScope initializationScope) {
138 // the two <constant = Constant.NotAConstant> could be regrouped into
139 // a single line but it is clearer to have two lines while the reason of their
140 // existence is not at all the same. See comment for the second one.
142 //--------------------------------------------------------
143 if (!this.hasBeenResolved && this.binding != null && this.binding.isValidBinding()) {
145 this.hasBeenResolved = true;
147 // check if field is hiding some variable - issue is that field binding already got inserted in scope
148 // thus must lookup separately in super type and outer context
149 ClassScope classScope = initializationScope.enclosingClassScope();
151 if (classScope != null) {
152 SourceTypeBinding declaringType = classScope.enclosingSourceType();
153 boolean checkLocal = true;
154 if (declaringType.superclass != null) {
155 Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this, false /*do not resolve hidden field*/);
156 if (existingVariable != null && existingVariable.isValidBinding()){
157 initializationScope.problemReporter().fieldHiding(this, existingVariable);
158 checkLocal = false; // already found a matching field
162 Scope outerScope = classScope.parent;
163 // only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
164 // from outer scope. Subsequent static contexts are detected for free.
165 Binding existingVariable = outerScope.getBinding(this.name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
166 if (existingVariable != null && existingVariable.isValidBinding()
167 && (!(existingVariable instanceof FieldBinding)
168 || ((FieldBinding) existingVariable).isStatic()
169 || !declaringType.isStatic())) {
170 initializationScope.problemReporter().fieldHiding(this, existingVariable);
175 this.type.resolvedType = this.binding.type; // update binding for type reference
177 FieldBinding previousField = initializationScope.initializedField;
178 int previousFieldID = initializationScope.lastVisibleFieldID;
180 initializationScope.initializedField = this.binding;
181 initializationScope.lastVisibleFieldID = this.binding.id;
183 if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
184 initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
186 // the resolution of the initialization hasn't been done
187 if (this.initialization == null) {
188 this.binding.constant = Constant.NotAConstant;
190 // break dead-lock cycles by forcing constant to NotAConstant
191 this.binding.constant = Constant.NotAConstant;
193 TypeBinding typeBinding = this.binding.type;
194 TypeBinding initializationTypeBinding;
196 if (this.initialization instanceof ArrayInitializer) {
198 if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
199 ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
200 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
202 } else if ((initializationTypeBinding = this.initialization.resolveType(initializationScope)) != null) {
204 if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
205 || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
207 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
209 } else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
210 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
213 initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
215 if (this.binding.isFinal()){ // cast from constant actual type to variable type
216 this.binding.constant =
217 this.initialization.constant.castTo(
218 (this.binding.type.id << 4) + this.initialization.constant.typeID());
221 this.binding.constant = NotAConstant;
224 // Resolve Javadoc comment if one is present
225 if (this.javadoc != null) {
227 if (classScope != null) {
228 this.javadoc.resolve(classScope);
231 this.javadoc.resolve(initializationScope);
232 } else if (this.binding != null && this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
233 initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
236 initializationScope.initializedField = previousField;
237 initializationScope.lastVisibleFieldID = previousFieldID;
238 if (this.binding.constant == null)
239 this.binding.constant = Constant.NotAConstant;
244 public void traverse(ASTVisitor visitor, MethodScope scope) {
246 if (visitor.visit(this, scope)) {
247 this.type.traverse(visitor, scope);
248 if (this.initialization != null)
249 this.initialization.traverse(visitor, scope);
251 visitor.endVisit(this, scope);