removed Makefile; lifted repo/org.ibex.tool/src/ to src/
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / FieldDeclaration.java
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
new file mode 100644 (file)
index 0000000..7f001c3
--- /dev/null
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class FieldDeclaration extends AbstractVariableDeclaration {
+       public FieldBinding binding;
+       boolean hasBeenResolved = false;
+       public Javadoc javadoc;
+
+       //allows to retrieve both the "type" part of the declaration (part1)
+       //and also the part that decribe the name and the init and optionally
+       //some other dimension ! .... 
+       //public int[] a, b[] = X, c ;
+       //for b that would give for 
+       // - part1 : public int[]
+       // - part2 : b[] = X,
+
+       public int endPart1Position;
+       public int endPart2Position;
+
+       public FieldDeclaration() {
+               // for subtypes or conversion
+       }
+
+       public FieldDeclaration(
+               char[] name,
+               int sourceStart,
+               int sourceEnd) {
+
+               this.name = name;
+
+               //due to some declaration like 
+               // int x, y = 3, z , x ;
+               //the sourceStart and the sourceEnd is ONLY on  the name
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               MethodScope initializationScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
+                       if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
+                               initializationScope.problemReporter().unusedPrivateField(this);
+                       }
+               }
+               // cannot define static non-constant field inside nested class
+               if (this.binding != null
+                       && this.binding.isValidBinding()
+                       && this.binding.isStatic()
+                       && this.binding.constant == NotAConstant
+                       && this.binding.declaringClass.isNestedType()
+                       && this.binding.declaringClass.isClass()
+                       && !this.binding.declaringClass.isStatic()) {
+                       initializationScope.problemReporter().unexpectedStaticModifierForField(
+                               (SourceTypeBinding) this.binding.declaringClass,
+                               this);
+               }
+
+               if (this.initialization != null) {
+                       flowInfo =
+                               this.initialization
+                                       .analyseCode(initializationScope, flowContext, flowInfo)
+                                       .unconditionalInits();
+                       flowInfo.markAsDefinitelyAssigned(this.binding);
+               }
+               return flowInfo;
+       }
+
+       /**
+        * Code generation for a field declaration:
+        *         standard assignment to a field 
+        *
+        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+        * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+               if ((this.bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               // do not generate initialization code if final and static (constant is then
+               // recorded inside the field itself).
+               int pc = codeStream.position;
+               boolean isStatic;
+               if (this.initialization != null
+                       && !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
+                       // non-static field, need receiver
+                       if (!isStatic)
+                               codeStream.aload_0();
+                       // generate initialization value
+                       this.initialization.generateCode(currentScope, codeStream, true);
+                       // store into field
+                       if (isStatic) {
+                               codeStream.putstatic(this.binding);
+                       } else {
+                               codeStream.putfield(this.binding);
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public TypeBinding getTypeBinding(Scope scope) {
+
+               return this.type.getTypeBinding(scope);
+       }
+
+       public boolean isField() {
+
+               return true;
+       }
+
+       public boolean isStatic() {
+
+               if (this.binding != null)
+                       return this.binding.isStatic();
+               return (this.modifiers & AccStatic) != 0;
+       }
+       
+       public void resolve(MethodScope initializationScope) {
+
+               // the two <constant = Constant.NotAConstant> could be regrouped into
+               // a single line but it is clearer to have two lines while the reason of their
+               // existence is not at all the same. See comment for the second one.
+
+               //--------------------------------------------------------
+               if (!this.hasBeenResolved && this.binding != null && this.binding.isValidBinding()) {
+
+                       this.hasBeenResolved = true;
+
+                       // check if field is hiding some variable - issue is that field binding already got inserted in scope
+                       // thus must lookup separately in super type and outer context
+                       ClassScope classScope = initializationScope.enclosingClassScope();
+                       
+                       if (classScope != null) {
+                               SourceTypeBinding declaringType = classScope.enclosingSourceType();
+                               boolean checkLocal = true;
+                               if (declaringType.superclass != null) {
+                                       Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this,  false /*do not resolve hidden field*/);
+                                       if (existingVariable != null && existingVariable.isValidBinding()){
+                                               initializationScope.problemReporter().fieldHiding(this, existingVariable);
+                                               checkLocal = false; // already found a matching field
+                                       }
+                               }
+                               if (checkLocal) {
+                                       Scope outerScope = classScope.parent;
+                                       // only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
+                                       // from outer scope. Subsequent static contexts are detected for free.
+                                       Binding existingVariable = outerScope.getBinding(this.name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+                                       if (existingVariable != null && existingVariable.isValidBinding()
+                                                       && (!(existingVariable instanceof FieldBinding)
+                                                                       || ((FieldBinding) existingVariable).isStatic() 
+                                                                       || !declaringType.isStatic())) {
+                                               initializationScope.problemReporter().fieldHiding(this, existingVariable);
+                                       }
+                               }
+                       }
+                       
+                       this.type.resolvedType = this.binding.type; // update binding for type reference
+
+                       FieldBinding previousField = initializationScope.initializedField;
+                       int previousFieldID = initializationScope.lastVisibleFieldID;
+                       try {
+                               initializationScope.initializedField = this.binding;
+                               initializationScope.lastVisibleFieldID = this.binding.id;
+
+                               if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
+                                       initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
+                               }
+                               // the resolution of the initialization hasn't been done
+                               if (this.initialization == null) {
+                                       this.binding.constant = Constant.NotAConstant;
+                               } else {
+                                       // break dead-lock cycles by forcing constant to NotAConstant
+                                       this.binding.constant = Constant.NotAConstant;
+                                       
+                                       TypeBinding typeBinding = this.binding.type;
+                                       TypeBinding initializationTypeBinding;
+                                       
+                                       if (this.initialization instanceof ArrayInitializer) {
+
+                                               if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
+                                                       ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
+                                                       this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+                                               }
+                                       } else if ((initializationTypeBinding = this.initialization.resolveType(initializationScope)) != null) {
+
+                                               if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
+                                                       || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
+
+                                                       this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+
+                                               }       else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
+                                                       this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+
+                                               } else {
+                                                       initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
+                                               }
+                                               if (this.binding.isFinal()){ // cast from constant actual type to variable type
+                                                       this.binding.constant =
+                                                               this.initialization.constant.castTo(
+                                                                       (this.binding.type.id << 4) + this.initialization.constant.typeID());
+                                               }
+                                       } else {
+                                               this.binding.constant = NotAConstant;
+                                       }
+                               }
+                               // Resolve Javadoc comment if one is present
+                               if (this.javadoc != null) {
+                                       /*
+                                       if (classScope != null) {
+                                               this.javadoc.resolve(classScope);
+                                       }
+                                       */
+                                       this.javadoc.resolve(initializationScope);
+                               } else if (this.binding != null && this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
+                                       initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+                               }
+                       } finally {
+                               initializationScope.initializedField = previousField;
+                               initializationScope.lastVisibleFieldID = previousFieldID;
+                               if (this.binding.constant == null)
+                                       this.binding.constant = Constant.NotAConstant;
+                       }
+               }
+       }
+
+       public void traverse(ASTVisitor visitor, MethodScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       this.type.traverse(visitor, scope);
+                       if (this.initialization != null)
+                               this.initialization.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}