1) Moved net.sourceforge.phpeclipse.ui\src\net\sourceforge\phpdt back to net.sourcefo...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / FieldDeclaration.java
index b41df20..7268571 100644 (file)
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.compiler.ast;
 
-import net.sourceforge.phpdt.internal.compiler.parser.Outlineable;
-import net.sourceforge.phpdt.internal.ui.PHPUiImages;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.text.Position;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * A Field declaration.
- * This is a variable declaration for a php class
- * In fact it's an array of VariableUsage, since a field could contains
- * several var :
- * var $toto,$tata;
- * @author Matthieu Casanova
- */
-public class FieldDeclaration extends Statement implements Outlineable {
-
-  /** The variables. */
-  public VariableDeclaration[] vars;
-
-  private Object parent;
-  private Position position;
-
-  /**
-   * Create a new field.
-   * @param vars the array of variables.
-   * @param sourceStart the starting offset
-   * @param sourceEnd   the ending offset
-   */
-  public FieldDeclaration(final VariableDeclaration[] vars,
-                          final int sourceStart,
-                          final int sourceEnd,
-                          final Object parent) {
-    super(sourceStart, sourceEnd);
-    this.vars = vars;
-    this.parent = parent;
-    position = new Position(sourceStart, sourceEnd);
-  }
-
-  /**
-   * Return the object into String.
-   * @param tab how many tabs (not used here
-   * @return a String
-   */
-  public String toString(final int tab) {
-    final StringBuffer buff = new StringBuffer(tabString(tab));
-    buff.append("var ");//$NON-NLS-1$
-    for (int i = 0; i < vars.length; i++) {
-      if (i != 0) {
-        buff.append(",");//$NON-NLS-1$
-      }
-      buff.append(vars[i].toStringExpression());
-    }
-    return buff.toString();
-  }
-
-  /**
-   * Get the image of a variable.
-   * @return the image that represents a php variable
-   */
-  public ImageDescriptor getImage() {
-    return PHPUiImages.DESC_VAR;
-  }
-
-  public Object getParent() {
-    return parent;
-  }
-
-  public Position getPosition() {
-    return position;
-  }
-
-  /**
-   * Get the variables from outside (parameters, globals ...)
-   */
-  public void getOutsideVariable(final List list) {
-  }
-
-  /**
-   * get the modified variables.
-   */
-  public void getModifiedVariable(final List list) {
-  }
-
-  /**
-   * Get the variables used.
-   */
-  public void getUsedVariable(final List list) {
-  }
-}
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class FieldDeclaration extends AbstractVariableDeclaration {
+       public FieldBinding binding;
+
+       boolean hasBeenResolved = false;
+
+       // 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() {
+       }
+
+       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 FieldDeclaration(Expression initialization, char[] name,
+                       int sourceStart, int sourceEnd) {
+
+               this.initialization = initialization;
+               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 (binding != null && binding.isValidBinding() && binding.isStatic()
+                               && binding.constant == NotAConstant
+                               && binding.declaringClass.isNestedType()
+                               && binding.declaringClass.isClass()
+                               && !binding.declaringClass.isStatic()) {
+                       initializationScope.problemReporter()
+                                       .unexpectedStaticModifierForField(
+                                                       (SourceTypeBinding) binding.declaringClass, this);
+               }
+
+               if (initialization != null) {
+                       flowInfo = initialization.analyseCode(initializationScope,
+                                       flowContext, flowInfo).unconditionalInits();
+                       flowInfo.markAsDefinitelyAssigned(binding);
+               }
+               return flowInfo;
+       }
+
+       /**
+        * Code generation for a field declaration: standard assignment to a field
+        * 
+        * @param currentScope
+        *            net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
+        * @param codeStream
+        *            net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
+        */
+       // public void generateCode(BlockScope currentScope, CodeStream codeStream)
+       // {
+       //
+       // if ((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 (initialization != null
+       // && !((isStatic = binding.isStatic()) && binding.constant !=
+       // NotAConstant)) {
+       // // non-static field, need receiver
+       // if (!isStatic)
+       // codeStream.aload_0();
+       // // generate initialization value
+       // initialization.generateCode(currentScope, codeStream, true);
+       // // store into field
+       // if (isStatic) {
+       // codeStream.putstatic(binding);
+       // } else {
+       // codeStream.putfield(binding);
+       // }
+       // }
+       // codeStream.recordPositionsFrom(pc, this.sourceStart);
+       // }
+       public TypeBinding getTypeBinding(Scope scope) {
+
+               return type.getTypeBinding(scope);
+       }
+
+       public boolean isField() {
+
+               return true;
+       }
+
+       public boolean isStatic() {
+
+               if (binding != null)
+                       return binding.isStatic();
+               return (modifiers & AccStatic) != 0;
+       }
+
+       public String name() {
+
+               return String.valueOf(name);
+       }
+
+       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 && binding != null
+                               && this.binding.isValidBinding()) {
+
+                       this.hasBeenResolved = true;
+
+                       if (isTypeUseDeprecated(this.binding.type, initializationScope))
+                               initializationScope.problemReporter().deprecatedType(
+                                               this.binding.type, this.type);
+
+                       this.type.resolvedType = this.binding.type; // update binding for
+                                                                                                               // type reference
+
+                       // the resolution of the initialization hasn't been done
+                       if (this.initialization == null) {
+                               this.binding.constant = Constant.NotAConstant;
+                       } else {
+                               int previous = initializationScope.fieldDeclarationIndex;
+                               try {
+                                       initializationScope.fieldDeclarationIndex = this.binding.id;
+
+                                       // break dead-lock cycles by forcing constant to
+                                       // NotAConstant
+                                       this.binding.constant = Constant.NotAConstant;
+
+                                       TypeBinding typeBinding = this.binding.type;
+                                       TypeBinding initializationTypeBinding;
+
+                                       if (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 = 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;
+                                       }
+                               } finally {
+                                       initializationScope.fieldDeclarationIndex = previous;
+                                       if (this.binding.constant == null)
+                                               this.binding.constant = Constant.NotAConstant;
+                               }
+                       }
+               }
+       }
+
+       public void traverse(ASTVisitor visitor, MethodScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       type.traverse(visitor, scope);
+                       if (initialization != null)
+                               initialization.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               if (obj instanceof FieldDeclaration) {
+                       char[] objName = ((FieldDeclaration) obj).name;
+                       if (name.length != objName.length) {
+                               return false;
+                       }
+                       for (int i = 0; i < objName.length; i++) {
+                               if (name[i] != objName[i]) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               return super.equals(obj);
+       }
+}
\ No newline at end of file