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