Set version 1.1.9
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / FieldDeclaration.java
1 /***********************************************************************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made
3  * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
4  * http://www.eclipse.org/legal/cpl-v10.html
5  * 
6  * Contributors: IBM Corporation - initial API and implementation
7  **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.compiler.ast;
9
10 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
11 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
12 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
13 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
14 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
15 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
16 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
17 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
21
22 public class FieldDeclaration extends AbstractVariableDeclaration {
23   public FieldBinding binding;
24
25   boolean hasBeenResolved = false;
26
27   //allows to retrieve both the "type" part of the declaration (part1)
28   //and also the part that decribe the name and the init and optionally
29   //some other dimension ! ....
30   //public int[] a, b[] = X, c ;
31   //for b that would give for
32   // - part1 : public int[]
33   // - part2 : b[] = X,
34
35   public int endPart1Position;
36
37   public int endPart2Position;
38
39   public FieldDeclaration() {
40   }
41
42   public FieldDeclaration(char[] name, int sourceStart, 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 FieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
54
55     this.initialization = initialization;
56     this.name = name;
57
58     //due to some declaration like
59     // int x, y = 3, z , x ;
60     //the sourceStart and the sourceEnd is ONLY on the name
61     this.sourceStart = sourceStart;
62     this.sourceEnd = sourceEnd;
63   }
64
65   public FlowInfo analyseCode(MethodScope initializationScope, FlowContext flowContext, FlowInfo flowInfo) {
66
67     if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
68       if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
69         initializationScope.problemReporter().unusedPrivateField(this);
70       }
71     }
72     // cannot define static non-constant field inside nested class
73     if (binding != null && binding.isValidBinding() && binding.isStatic() && binding.constant == NotAConstant
74         && binding.declaringClass.isNestedType() && binding.declaringClass.isClass() && !binding.declaringClass.isStatic()) {
75       initializationScope.problemReporter().unexpectedStaticModifierForField((SourceTypeBinding) binding.declaringClass, this);
76     }
77
78     if (initialization != null) {
79       flowInfo = initialization.analyseCode(initializationScope, flowContext, flowInfo).unconditionalInits();
80       flowInfo.markAsDefinitelyAssigned(binding);
81     }
82     return flowInfo;
83   }
84
85   /**
86    * Code generation for a field declaration: standard assignment to a field
87    * 
88    * @param currentScope
89    *          net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
90    * @param codeStream
91    *          net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
92    */
93   //    public void generateCode(BlockScope currentScope, CodeStream codeStream) {
94   //
95   //            if ((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 (initialization != null
103   //                    && !((isStatic = binding.isStatic()) && binding.constant != NotAConstant)) {
104   //                    // non-static field, need receiver
105   //                    if (!isStatic)
106   //                            codeStream.aload_0();
107   //                    // generate initialization value
108   //                    initialization.generateCode(currentScope, codeStream, true);
109   //                    // store into field
110   //                    if (isStatic) {
111   //                            codeStream.putstatic(binding);
112   //                    } else {
113   //                            codeStream.putfield(binding);
114   //                    }
115   //            }
116   //            codeStream.recordPositionsFrom(pc, this.sourceStart);
117   //    }
118   public TypeBinding getTypeBinding(Scope scope) {
119
120     return type.getTypeBinding(scope);
121   }
122
123   public boolean isField() {
124
125     return true;
126   }
127
128   public boolean isStatic() {
129
130     if (binding != null)
131       return binding.isStatic();
132     return (modifiers & AccStatic) != 0;
133   }
134
135   public String name() {
136
137     return String.valueOf(name);
138   }
139
140   public void resolve(MethodScope initializationScope) {
141
142     // the two <constant = Constant.NotAConstant> could be regrouped into
143     // a single line but it is clearer to have two lines while the reason of their
144     // existence is not at all the same. See comment for the second one.
145
146     //--------------------------------------------------------
147     if (!this.hasBeenResolved && binding != null && this.binding.isValidBinding()) {
148
149       this.hasBeenResolved = true;
150
151       if (isTypeUseDeprecated(this.binding.type, initializationScope))
152         initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
153
154       this.type.resolvedType = this.binding.type; // update binding for type reference
155
156       // the resolution of the initialization hasn't been done
157       if (this.initialization == null) {
158         this.binding.constant = Constant.NotAConstant;
159       } else {
160         int previous = initializationScope.fieldDeclarationIndex;
161         try {
162           initializationScope.fieldDeclarationIndex = this.binding.id;
163
164           // break dead-lock cycles by forcing constant to NotAConstant
165           this.binding.constant = Constant.NotAConstant;
166
167           TypeBinding typeBinding = this.binding.type;
168           TypeBinding initializationTypeBinding;
169
170           if (initialization instanceof ArrayInitializer) {
171
172             if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
173               ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
174               this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
175             }
176           } else if ((initializationTypeBinding = initialization.resolveType(initializationScope)) != null) {
177
178             if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
179                 || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
180
181               this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
182
183             } else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
184               this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
185
186             } else {
187               initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
188             }
189             if (this.binding.isFinal()) { // cast from constant actual type to variable type
190               this.binding.constant = this.initialization.constant.castTo((this.binding.type.id << 4)
191                   + this.initialization.constant.typeID());
192             }
193           } else {
194             this.binding.constant = NotAConstant;
195           }
196         } finally {
197           initializationScope.fieldDeclarationIndex = previous;
198           if (this.binding.constant == null)
199             this.binding.constant = Constant.NotAConstant;
200         }
201       }
202     }
203   }
204
205   public void traverse(ASTVisitor visitor, MethodScope scope) {
206
207     if (visitor.visit(this, scope)) {
208       type.traverse(visitor, scope);
209       if (initialization != null)
210         initialization.traverse(visitor, scope);
211     }
212     visitor.endVisit(this, scope);
213   }
214
215   /*
216    * (non-Javadoc)
217    * 
218    * @see java.lang.Object#equals(java.lang.Object)
219    */
220   public boolean equals(Object obj) {
221     if (obj instanceof FieldDeclaration) {
222       char[] objName = ((FieldDeclaration) obj).name;
223       if (name.length != objName.length) {
224         return false;
225       }
226       for (int i = 0; i < objName.length; i++) {
227         if (name[i] != objName[i]) {
228           return false;
229         }
230       }
231       return true;
232     }
233     return super.equals(obj);
234   }
235 }