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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.internal.compiler.ast;
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;
25 public class FieldDeclaration extends AbstractVariableDeclaration {
26 public FieldBinding binding;
27 boolean hasBeenResolved = false;
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[]
37 public int endPart1Position;
38 public int endPart2Position;
40 public FieldDeclaration() {
42 public FieldDeclaration(
49 //due to some declaration like
50 // int x, y = 3, z , x ;
51 //the sourceStart and the sourceEnd is ONLY on the name
52 this.sourceStart = sourceStart;
53 this.sourceEnd = sourceEnd;
55 public FieldDeclaration(
56 Expression initialization,
61 this.initialization = initialization;
64 //due to some declaration like
65 // int x, y = 3, z , x ;
66 //the sourceStart and the sourceEnd is ONLY on the name
67 this.sourceStart = sourceStart;
68 this.sourceEnd = sourceEnd;
71 public FlowInfo analyseCode(
72 MethodScope initializationScope,
73 FlowContext flowContext,
76 if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
77 if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
78 initializationScope.problemReporter().unusedPrivateField(this);
81 // cannot define static non-constant field inside nested class
83 && binding.isValidBinding()
85 && binding.constant == NotAConstant
86 && binding.declaringClass.isNestedType()
87 && binding.declaringClass.isClass()
88 && !binding.declaringClass.isStatic()) {
89 initializationScope.problemReporter().unexpectedStaticModifierForField(
90 (SourceTypeBinding) binding.declaringClass,
94 if (initialization != null) {
97 .analyseCode(initializationScope, flowContext, flowInfo)
98 .unconditionalInits();
99 flowInfo.markAsDefinitelyAssigned(binding);
105 * Code generation for a field declaration:
106 * standard assignment to a field
108 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
109 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
111 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
113 // if ((bits & IsReachableMASK) == 0) {
116 // // do not generate initialization code if final and static (constant is then
117 // // recorded inside the field itself).
118 // int pc = codeStream.position;
120 // if (initialization != null
121 // && !((isStatic = binding.isStatic()) && binding.constant != NotAConstant)) {
122 // // non-static field, need receiver
124 // codeStream.aload_0();
125 // // generate initialization value
126 // initialization.generateCode(currentScope, codeStream, true);
127 // // store into field
129 // codeStream.putstatic(binding);
131 // codeStream.putfield(binding);
134 // codeStream.recordPositionsFrom(pc, this.sourceStart);
137 public TypeBinding getTypeBinding(Scope scope) {
139 return type.getTypeBinding(scope);
142 public boolean isField() {
147 public boolean isStatic() {
150 return binding.isStatic();
151 return (modifiers & AccStatic) != 0;
154 public String name() {
156 return String.valueOf(name);
159 public void resolve(MethodScope initializationScope) {
161 // the two <constant = Constant.NotAConstant> could be regrouped into
162 // a single line but it is clearer to have two lines while the reason of their
163 // existence is not at all the same. See comment for the second one.
165 //--------------------------------------------------------
166 if (!this.hasBeenResolved && binding != null && this.binding.isValidBinding()) {
168 this.hasBeenResolved = true;
170 if (isTypeUseDeprecated(this.binding.type, initializationScope))
171 initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
173 this.type.resolvedType = this.binding.type; // update binding for type reference
175 // the resolution of the initialization hasn't been done
176 if (this.initialization == null) {
177 this.binding.constant = Constant.NotAConstant;
179 int previous = initializationScope.fieldDeclarationIndex;
181 initializationScope.fieldDeclarationIndex = this.binding.id;
183 // break dead-lock cycles by forcing constant to NotAConstant
184 this.binding.constant = Constant.NotAConstant;
186 TypeBinding typeBinding = this.binding.type;
187 TypeBinding initializationTypeBinding;
189 if (initialization instanceof ArrayInitializer) {
191 if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
192 ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
193 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
195 } else if ((initializationTypeBinding = initialization.resolveType(initializationScope)) != null) {
197 if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
198 || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
200 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
202 } else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
203 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
206 initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
208 if (this.binding.isFinal()){ // cast from constant actual type to variable type
209 this.binding.constant =
210 this.initialization.constant.castTo(
211 (this.binding.type.id << 4) + this.initialization.constant.typeID());
214 this.binding.constant = NotAConstant;
217 initializationScope.fieldDeclarationIndex = previous;
218 if (this.binding.constant == null)
219 this.binding.constant = Constant.NotAConstant;
225 public void traverse(IAbstractSyntaxTreeVisitor visitor, MethodScope scope) {
227 if (visitor.visit(this, scope)) {
228 type.traverse(visitor, scope);
229 if (initialization != null)
230 initialization.traverse(visitor, scope);
232 visitor.endVisit(this, scope);