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
6 * Contributors: IBM Corporation - initial API and implementation
7 **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.compiler.ast;
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;
22 public class FieldDeclaration extends AbstractVariableDeclaration {
23 public FieldBinding binding;
25 boolean hasBeenResolved = false;
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[]
35 public int endPart1Position;
37 public int endPart2Position;
39 public FieldDeclaration() {
42 public FieldDeclaration(char[] name, int sourceStart, int sourceEnd) {
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 FieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
55 this.initialization = initialization;
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;
65 public FlowInfo analyseCode(MethodScope initializationScope, FlowContext flowContext, FlowInfo flowInfo) {
67 if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
68 if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
69 initializationScope.problemReporter().unusedPrivateField(this);
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);
78 if (initialization != null) {
79 flowInfo = initialization.analyseCode(initializationScope, flowContext, flowInfo).unconditionalInits();
80 flowInfo.markAsDefinitelyAssigned(binding);
86 * Code generation for a field declaration: standard assignment to a field
89 * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
91 * net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
93 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
95 // if ((bits & IsReachableMASK) == 0) {
98 // // do not generate initialization code if final and static (constant is then
99 // // recorded inside the field itself).
100 // int pc = codeStream.position;
102 // if (initialization != null
103 // && !((isStatic = binding.isStatic()) && binding.constant != NotAConstant)) {
104 // // non-static field, need receiver
106 // codeStream.aload_0();
107 // // generate initialization value
108 // initialization.generateCode(currentScope, codeStream, true);
109 // // store into field
111 // codeStream.putstatic(binding);
113 // codeStream.putfield(binding);
116 // codeStream.recordPositionsFrom(pc, this.sourceStart);
118 public TypeBinding getTypeBinding(Scope scope) {
120 return type.getTypeBinding(scope);
123 public boolean isField() {
128 public boolean isStatic() {
131 return binding.isStatic();
132 return (modifiers & AccStatic) != 0;
135 public String name() {
137 return String.valueOf(name);
140 public void resolve(MethodScope initializationScope) {
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.
146 //--------------------------------------------------------
147 if (!this.hasBeenResolved && binding != null && this.binding.isValidBinding()) {
149 this.hasBeenResolved = true;
151 if (isTypeUseDeprecated(this.binding.type, initializationScope))
152 initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
154 this.type.resolvedType = this.binding.type; // update binding for type reference
156 // the resolution of the initialization hasn't been done
157 if (this.initialization == null) {
158 this.binding.constant = Constant.NotAConstant;
160 int previous = initializationScope.fieldDeclarationIndex;
162 initializationScope.fieldDeclarationIndex = this.binding.id;
164 // break dead-lock cycles by forcing constant to NotAConstant
165 this.binding.constant = Constant.NotAConstant;
167 TypeBinding typeBinding = this.binding.type;
168 TypeBinding initializationTypeBinding;
170 if (initialization instanceof ArrayInitializer) {
172 if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
173 ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
174 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
176 } else if ((initializationTypeBinding = initialization.resolveType(initializationScope)) != null) {
178 if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
179 || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
181 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
183 } else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
184 this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
187 initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
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());
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(ASTVisitor 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);
218 * @see java.lang.Object#equals(java.lang.Object)
220 public boolean equals(Object obj) {
221 if (obj instanceof FieldDeclaration) {
222 char[] objName = ((FieldDeclaration) obj).name;
223 if (name.length != objName.length) {
226 for (int i = 0; i < objName.length; i++) {
227 if (name[i] != objName[i]) {
233 return super.equals(obj);