Makefile fixup
[org.ibex.tool.git] / repo / org.ibex.tool / src / org / eclipse / jdt / internal / compiler / ast / FieldDeclaration.java
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
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.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18
19 public class FieldDeclaration extends AbstractVariableDeclaration {
20         public FieldBinding binding;
21         boolean hasBeenResolved = false;
22         public Javadoc javadoc;
23
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[]
30         // - part2 : b[] = X,
31
32         public int endPart1Position;
33         public int endPart2Position;
34
35         public FieldDeclaration() {
36                 // for subtypes or conversion
37         }
38
39         public FieldDeclaration(
40                 char[] name,
41                 int sourceStart,
42                 int sourceEnd) {
43
44                 this.name = name;
45
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;
51         }
52
53         public FlowInfo analyseCode(
54                 MethodScope initializationScope,
55                 FlowContext flowContext,
56                 FlowInfo flowInfo) {
57
58                 if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
59                         if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
60                                 initializationScope.problemReporter().unusedPrivateField(this);
61                         }
62                 }
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,
73                                 this);
74                 }
75
76                 if (this.initialization != null) {
77                         flowInfo =
78                                 this.initialization
79                                         .analyseCode(initializationScope, flowContext, flowInfo)
80                                         .unconditionalInits();
81                         flowInfo.markAsDefinitelyAssigned(this.binding);
82                 }
83                 return flowInfo;
84         }
85
86         /**
87          * Code generation for a field declaration:
88          *         standard assignment to a field 
89          *
90          * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
91          * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
92          */
93         public void generateCode(BlockScope currentScope, CodeStream codeStream) {
94
95                 if ((this.bits & IsReachableMASK) == 0) {
96                         return;
97                 }
98                 // do not generate initialization code if final and static (constant is then
99                 // recorded inside the field itself).
100                 int pc = codeStream.position;
101                 boolean isStatic;
102                 if (this.initialization != null
103                         && !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
104                         // non-static field, need receiver
105                         if (!isStatic)
106                                 codeStream.aload_0();
107                         // generate initialization value
108                         this.initialization.generateCode(currentScope, codeStream, true);
109                         // store into field
110                         if (isStatic) {
111                                 codeStream.putstatic(this.binding);
112                         } else {
113                                 codeStream.putfield(this.binding);
114                         }
115                 }
116                 codeStream.recordPositionsFrom(pc, this.sourceStart);
117         }
118
119         public TypeBinding getTypeBinding(Scope scope) {
120
121                 return this.type.getTypeBinding(scope);
122         }
123
124         public boolean isField() {
125
126                 return true;
127         }
128
129         public boolean isStatic() {
130
131                 if (this.binding != null)
132                         return this.binding.isStatic();
133                 return (this.modifiers & AccStatic) != 0;
134         }
135         
136         public void resolve(MethodScope initializationScope) {
137
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.
141
142                 //--------------------------------------------------------
143                 if (!this.hasBeenResolved && this.binding != null && this.binding.isValidBinding()) {
144
145                         this.hasBeenResolved = true;
146
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();
150                         
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
159                                         }
160                                 }
161                                 if (checkLocal) {
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);
171                                         }
172                                 }
173                         }
174                         
175                         this.type.resolvedType = this.binding.type; // update binding for type reference
176
177                         FieldBinding previousField = initializationScope.initializedField;
178                         int previousFieldID = initializationScope.lastVisibleFieldID;
179                         try {
180                                 initializationScope.initializedField = this.binding;
181                                 initializationScope.lastVisibleFieldID = this.binding.id;
182
183                                 if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
184                                         initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
185                                 }
186                                 // the resolution of the initialization hasn't been done
187                                 if (this.initialization == null) {
188                                         this.binding.constant = Constant.NotAConstant;
189                                 } else {
190                                         // break dead-lock cycles by forcing constant to NotAConstant
191                                         this.binding.constant = Constant.NotAConstant;
192                                         
193                                         TypeBinding typeBinding = this.binding.type;
194                                         TypeBinding initializationTypeBinding;
195                                         
196                                         if (this.initialization instanceof ArrayInitializer) {
197
198                                                 if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
199                                                         ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
200                                                         this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
201                                                 }
202                                         } else if ((initializationTypeBinding = this.initialization.resolveType(initializationScope)) != null) {
203
204                                                 if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
205                                                         || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
206
207                                                         this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
208
209                                                 }       else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
210                                                         this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
211
212                                                 } else {
213                                                         initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
214                                                 }
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());
219                                                 }
220                                         } else {
221                                                 this.binding.constant = NotAConstant;
222                                         }
223                                 }
224                                 // Resolve Javadoc comment if one is present
225                                 if (this.javadoc != null) {
226                                         /*
227                                         if (classScope != null) {
228                                                 this.javadoc.resolve(classScope);
229                                         }
230                                         */
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);
234                                 }
235                         } finally {
236                                 initializationScope.initializedField = previousField;
237                                 initializationScope.lastVisibleFieldID = previousFieldID;
238                                 if (this.binding.constant == null)
239                                         this.binding.constant = Constant.NotAConstant;
240                         }
241                 }
242         }
243
244         public void traverse(ASTVisitor visitor, MethodScope scope) {
245
246                 if (visitor.visit(this, scope)) {
247                         this.type.traverse(visitor, scope);
248                         if (this.initialization != null)
249                                 this.initialization.traverse(visitor, scope);
250                 }
251                 visitor.endVisit(this, scope);
252         }
253 }