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,
54 int sourceStart, int sourceEnd) {
56 this.initialization = initialization;
59 // due to some declaration like
60 // int x, y = 3, z , x ;
61 // the sourceStart and the sourceEnd is ONLY on the name
62 this.sourceStart = sourceStart;
63 this.sourceEnd = sourceEnd;
66 public FlowInfo analyseCode(MethodScope initializationScope,
67 FlowContext flowContext, FlowInfo flowInfo) {
69 if (this.binding != null && this.binding.isPrivate()
70 && !this.binding.isPrivateUsed()) {
71 if (!initializationScope.referenceCompilationUnit().compilationResult
73 initializationScope.problemReporter().unusedPrivateField(this);
76 // cannot define static non-constant field inside nested class
77 if (binding != null && binding.isValidBinding() && binding.isStatic()
78 && binding.constant == NotAConstant
79 && binding.declaringClass.isNestedType()
80 && binding.declaringClass.isClass()
81 && !binding.declaringClass.isStatic()) {
82 initializationScope.problemReporter()
83 .unexpectedStaticModifierForField(
84 (SourceTypeBinding) binding.declaringClass, this);
87 if (initialization != null) {
88 flowInfo = initialization.analyseCode(initializationScope,
89 flowContext, flowInfo).unconditionalInits();
90 flowInfo.markAsDefinitelyAssigned(binding);
96 * Code generation for a field declaration: standard assignment to a field
99 * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
101 * net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
103 // public void generateCode(BlockScope currentScope, CodeStream codeStream)
106 // if ((bits & IsReachableMASK) == 0) {
109 // // do not generate initialization code if final and static (constant is
111 // // recorded inside the field itself).
112 // int pc = codeStream.position;
114 // if (initialization != null
115 // && !((isStatic = binding.isStatic()) && binding.constant !=
117 // // non-static field, need receiver
119 // codeStream.aload_0();
120 // // generate initialization value
121 // initialization.generateCode(currentScope, codeStream, true);
122 // // store into field
124 // codeStream.putstatic(binding);
126 // codeStream.putfield(binding);
129 // codeStream.recordPositionsFrom(pc, this.sourceStart);
131 public TypeBinding getTypeBinding(Scope scope) {
133 return type.getTypeBinding(scope);
136 public boolean isField() {
141 public boolean isStatic() {
144 return binding.isStatic();
145 return (modifiers & AccStatic) != 0;
148 public String name() {
150 return String.valueOf(name);
153 public void resolve(MethodScope initializationScope) {
155 // the two <constant = Constant.NotAConstant> could be regrouped into
156 // a single line but it is clearer to have two lines while the reason of
158 // existence is not at all the same. See comment for the second one.
160 // --------------------------------------------------------
161 if (!this.hasBeenResolved && binding != null
162 && this.binding.isValidBinding()) {
164 this.hasBeenResolved = true;
166 if (isTypeUseDeprecated(this.binding.type, initializationScope))
167 initializationScope.problemReporter().deprecatedType(
168 this.binding.type, this.type);
170 this.type.resolvedType = this.binding.type; // update binding for
173 // the resolution of the initialization hasn't been done
174 if (this.initialization == null) {
175 this.binding.constant = Constant.NotAConstant;
177 int previous = initializationScope.fieldDeclarationIndex;
179 initializationScope.fieldDeclarationIndex = this.binding.id;
181 // break dead-lock cycles by forcing constant to
183 this.binding.constant = Constant.NotAConstant;
185 TypeBinding typeBinding = this.binding.type;
186 TypeBinding initializationTypeBinding;
188 if (initialization instanceof ArrayInitializer) {
190 if ((initializationTypeBinding = this.initialization
191 .resolveTypeExpecting(initializationScope,
192 typeBinding)) != null) {
193 ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
194 this.initialization.implicitWidening(typeBinding,
195 initializationTypeBinding);
197 } else if ((initializationTypeBinding = initialization
198 .resolveType(initializationScope)) != null) {
200 if (this.initialization
201 .isConstantValueOfTypeAssignableToType(
202 initializationTypeBinding, typeBinding)
203 || (typeBinding.isBaseType() && BaseTypeBinding
204 .isWidening(typeBinding.id,
205 initializationTypeBinding.id))) {
207 this.initialization.implicitWidening(typeBinding,
208 initializationTypeBinding);
210 } else if (initializationTypeBinding
211 .isCompatibleWith(typeBinding)) {
212 this.initialization.implicitWidening(typeBinding,
213 initializationTypeBinding);
216 initializationScope.problemReporter()
218 initializationTypeBinding,
221 if (this.binding.isFinal()) { // cast from constant
224 this.binding.constant = this.initialization.constant
225 .castTo((this.binding.type.id << 4)
226 + this.initialization.constant
230 this.binding.constant = NotAConstant;
233 initializationScope.fieldDeclarationIndex = previous;
234 if (this.binding.constant == null)
235 this.binding.constant = Constant.NotAConstant;
241 public void traverse(ASTVisitor visitor, MethodScope scope) {
243 if (visitor.visit(this, scope)) {
244 type.traverse(visitor, scope);
245 if (initialization != null)
246 initialization.traverse(visitor, scope);
248 visitor.endVisit(this, scope);
254 * @see java.lang.Object#equals(java.lang.Object)
256 public boolean equals(Object obj) {
257 if (obj instanceof FieldDeclaration) {
258 char[] objName = ((FieldDeclaration) obj).name;
259 if (name.length != objName.length) {
262 for (int i = 0; i < objName.length; i++) {
263 if (name[i] != objName[i]) {
269 return super.equals(obj);