1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.flow.*;
17 import net.sourceforge.phpdt.internal.compiler.lookup.*;
19 public class FieldDeclaration extends AbstractVariableDeclaration {
20 public FieldBinding binding;
21 boolean hasBeenResolved = false;
23 //allows to retrieve both the "type" part of the declaration (part1)
24 //and also the part that decribe the name and the init and optionally
25 //some other dimension ! ....
26 //public int[] a, b[] = X, c ;
27 //for b that would give for
28 // - part1 : public int[]
31 public int endPart1Position;
32 public int endPart2Position;
34 public FieldDeclaration() {
37 public FieldDeclaration(
38 Expression initialization,
43 this.initialization = initialization;
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 // cannot define static non-constant field inside nested class
60 && binding.isValidBinding()
62 && binding.constant == NotAConstant
63 && binding.declaringClass.isNestedType()
64 && binding.declaringClass.isClass()
65 && !binding.declaringClass.isStatic()) {
66 initializationScope.problemReporter().unexpectedStaticModifierForField(
67 (SourceTypeBinding) binding.declaringClass,
71 if (initialization != null) {
74 .analyseCode(initializationScope, flowContext, flowInfo)
75 .unconditionalInits();
76 flowInfo.markAsDefinitelyAssigned(binding);
78 flowInfo.markAsDefinitelyNotAssigned(binding);
79 // clear the bit in case it was already set (from enclosing info)
85 * Code generation for a field declaration:
86 * i.e. normal assignment to a field
88 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
89 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
91 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
93 if ((bits & IsReachableMASK) == 0) {
96 // do not generate initialization code if final and static (constant is then
97 // recorded inside the field itself).
98 int pc = codeStream.position;
100 if (initialization != null
101 && !((isStatic = binding.isStatic()) && binding.constant != NotAConstant)) {
102 // non-static field, need receiver
104 codeStream.aload_0();
105 // generate initialization value
106 initialization.generateCode(currentScope, codeStream, true);
109 codeStream.putstatic(binding);
111 codeStream.putfield(binding);
114 codeStream.recordPositionsFrom(pc, this.sourceStart);
117 public TypeBinding getTypeBinding(Scope scope) {
119 return type.getTypeBinding(scope);
122 public boolean isField() {
127 public boolean isStatic() {
130 return binding.isStatic();
131 return (modifiers & AccStatic) != 0;
134 public String name() {
136 return String.valueOf(name);
139 public void resolve(MethodScope initializationScope) {
141 // the two <constant = Constant.NotAConstant> could be regrouped into
142 // a single line but it is clearer to have two lines while the reason of their
143 // existence is not at all the same. See comment for the second one.
145 //--------------------------------------------------------
146 if (!this.hasBeenResolved && binding != null && this.binding.isValidBinding()) {
148 this.hasBeenResolved = true;
150 if (isTypeUseDeprecated(this.binding.type, initializationScope))
151 initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
153 this.type.binding = this.binding.type; // update binding for type reference
155 // the resolution of the initialization hasn't been done
156 if (this.initialization == null) {
157 this.binding.constant = Constant.NotAConstant;
159 int previous = initializationScope.fieldDeclarationIndex;
161 initializationScope.fieldDeclarationIndex = this.binding.id;
163 // break dead-lock cycles by forcing constant to NotAConstant
164 this.binding.constant = Constant.NotAConstant;
166 TypeBinding typeBinding = this.binding.type;
167 TypeBinding initializationTypeBinding;
169 if (initialization instanceof ArrayInitializer) {
171 if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
172 ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
173 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
175 } else if ((initializationTypeBinding = initialization.resolveType(initializationScope)) != null) {
177 if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
178 || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
180 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
182 } else if (initializationScope.areTypesCompatible(initializationTypeBinding, typeBinding)) {
183 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
186 initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
188 if (this.binding.isFinal()){ // cast from constant actual type to variable type
189 this.binding.constant =
190 this.initialization.constant.castTo(
191 (this.binding.type.id << 4) + this.initialization.constant.typeID());
194 this.binding.constant = NotAConstant;
197 initializationScope.fieldDeclarationIndex = previous;
198 if (this.binding.constant == null)
199 this.binding.constant = Constant.NotAConstant;
205 public void traverse(IAbstractSyntaxTreeVisitor visitor, MethodScope scope) {
207 if (visitor.visit(this, scope)) {
208 type.traverse(visitor, scope);
209 if (initialization != null)
210 initialization.traverse(visitor, scope);
212 visitor.endVisit(this, scope);