+/***********************************************************************************************************************************
+ * 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);
+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() {
}
- /**
- * 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$
+ 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);
}
- buff.append(vars[i].toStringExpression());
}
- return buff.toString();
+ // 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;
}
/**
- * Get the image of a variable.
- * @return the image that represents a php variable
+ * 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 ImageDescriptor getImage() {
- return PHPUiImages.DESC_VAR;
+ // 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 Object getParent() {
- return parent;
+ public boolean isField() {
+
+ return true;
}
- public Position getPosition() {
- return position;
+ public boolean isStatic() {
+
+ if (binding != null)
+ return binding.isStatic();
+ return (modifiers & AccStatic) != 0;
}
- /**
- * Get the variables from outside (parameters, globals ...)
- * @return the variables from outside
- */
- public List getOutsideVariable() {
- return new ArrayList();
+ public String name() {
+
+ return String.valueOf(name);
}
- /**
- * get the modified variables.
- * @return the variables from we change value
- */
- public List getModifiedVariable() {
- return new ArrayList();
+ 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;
+ }
+ }
+ }
}
- /**
- * Get the variables used.
- * @return the variables used
+ 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 List getUsedVariable() {
- return new ArrayList();
+ 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