*******************************************************************************/
package net.sourceforge.phpdt.internal.compiler.lookup;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
import net.sourceforge.phpdt.internal.compiler.flow.UnconditionalFlowInfo;
import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
-import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
-import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedNameReference;
-import net.sourceforge.phpeclipse.internal.compiler.ast.SingleNameReference;
-import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
/**
- * Particular block scope used for methods, constructors or clinits, representing
- * its outermost blockscope. Note also that such a scope will be provided to enclose
- * field initializers subscopes as well.
+ * Particular block scope used for methods, constructors or clinits,
+ * representing its outermost blockscope. Note also that such a scope will be
+ * provided to enclose field initializers subscopes as well.
*/
public class MethodScope extends BlockScope {
public ReferenceContext referenceContext;
+
public boolean isStatic; // method modifier or initializer one
- //fields used during name resolution
- public static final int NotInFieldDecl = -1; //must be a negative value
- public boolean isConstructorCall = false;
- public int fieldDeclarationIndex = NotInFieldDecl;
+ // fields used during name resolution
+ public static final int NotInFieldDecl = -1; // must be a negative value
+
+ public boolean isConstructorCall = false;
+
+ public FieldBinding initializedField; // the field being initialized
+
+ public int fieldDeclarationIndex = NotInFieldDecl;
// flow analysis
public int analysisIndex; // for setting flow-analysis id
+
public boolean isPropagatingInnerClassEmulation;
// for local variables table attributes
public int lastIndex = 0;
+
public long[] definiteInits = new long[4];
+
public long[][] extraDefiniteInits = new long[4][];
// inner-emulation
public SyntheticArgumentBinding[] extraSyntheticArguments;
-
- public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
+
+ public MethodScope(ClassScope parent, ReferenceContext context,
+ boolean isStatic) {
super(METHOD_SCOPE, parent);
locals = new LocalVariableBinding[5];
this.startIndex = 0;
}
- /* Spec : 8.4.3 & 9.4
+ /*
+ * Spec : 8.4.3 & 9.4
*/
private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) {
-
+
int modifiers = methodBinding.modifiers;
if ((modifiers & AccAlternateModifierProblem) != 0)
problemReporter().duplicateModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
if (((ConstructorDeclaration) referenceContext).isDefaultConstructor) {
if (methodBinding.declaringClass.isPublic())
int realModifiers = modifiers & AccJustFlag;
// check for abnormal modifiers
- int unexpectedModifiers =
- ~(AccPublic | AccPrivate | AccProtected);// | AccStrictfp);
+ int unexpectedModifiers = ~(AccPublic | AccPrivate | AccProtected);// |
+ // AccStrictfp);
if ((realModifiers & unexpectedModifiers) != 0)
problemReporter().illegalModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
-// else if (
-// (((AbstractMethodDeclaration) referenceContext).modifiers & AccStrictfp) != 0)
-// // must check the parse node explicitly
-// problemReporter().illegalModifierForMethod(
-// methodBinding.declaringClass,
-// (AbstractMethodDeclaration) referenceContext);
-
- // check for incompatible modifiers in the visibility bits, isolate the visibility bits
- int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
+ // else if (
+ // (((AbstractMethodDeclaration) referenceContext).modifiers &
+ // AccStrictfp) != 0)
+ // // must check the parse node explicitly
+ // problemReporter().illegalModifierForMethod(
+ // methodBinding.declaringClass,
+ // (AbstractMethodDeclaration) referenceContext);
+
+ // check for incompatible modifiers in the visibility bits, isolate the
+ // visibility bits
+ int accessorBits = realModifiers
+ & (AccPublic | AccProtected | AccPrivate);
if ((accessorBits & (accessorBits - 1)) != 0) {
problemReporter().illegalVisibilityModifierCombinationForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
// need to keep the less restrictive
if ((accessorBits & AccPublic) != 0) {
modifiers ^= AccPrivate;
}
- // if the receiver's declaring class is a private nested type, then make sure the receiver is not private (causes problems for inner type emulation)
+ // if the receiver's declaring class is a private nested type, then make
+ // sure the receiver is not private (causes problems for inner type
+ // emulation)
if (methodBinding.declaringClass.isPrivate())
if ((modifiers & AccPrivate) != 0)
modifiers ^= AccPrivate;
methodBinding.modifiers = modifiers;
}
-
- /* Spec : 8.4.3 & 9.4
+
+ /*
+ * Spec : 8.4.3 & 9.4
*/
private void checkAndSetModifiersForMethod(MethodBinding methodBinding) {
-
+
int modifiers = methodBinding.modifiers;
if ((modifiers & AccAlternateModifierProblem) != 0)
problemReporter().duplicateModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
// after this point, tests on the 16 bits reserved.
int realModifiers = modifiers & AccJustFlag;
if (methodBinding.declaringClass.isInterface()) {
if ((realModifiers & ~(AccPublic | AccAbstract)) != 0)
problemReporter().illegalModifierForInterfaceMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
return;
}
// check for abnormal modifiers
- int unexpectedModifiers =
- ~(
- AccPublic
- | AccPrivate
- | AccProtected
- | AccAbstract
- | AccStatic
- | AccFinal);
-// | AccSynchronized
-// | AccNative
-// | AccStrictfp);
+ int unexpectedModifiers = ~(AccPublic | AccPrivate | AccProtected
+ | AccAbstract | AccStatic | AccFinal);
+ // | AccSynchronized
+ // | AccNative
+ // | AccStrictfp);
if ((realModifiers & unexpectedModifiers) != 0)
problemReporter().illegalModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
- // check for incompatible modifiers in the visibility bits, isolate the visibility bits
- int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
+ // check for incompatible modifiers in the visibility bits, isolate the
+ // visibility bits
+ int accessorBits = realModifiers
+ & (AccPublic | AccProtected | AccPrivate);
if ((accessorBits & (accessorBits - 1)) != 0) {
problemReporter().illegalVisibilityModifierCombinationForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
// need to keep the less restrictive
if ((accessorBits & AccPublic) != 0) {
// check for modifiers incompatible with abstract modifier
if ((modifiers & AccAbstract) != 0) {
- int incompatibleWithAbstract =
- AccPrivate | AccStatic | AccFinal;// | AccSynchronized | AccNative | AccStrictfp;
+ int incompatibleWithAbstract = AccPrivate | AccStatic | AccFinal;// |
+ // AccSynchronized
+ // |
+ // AccNative
+ // |
+ // AccStrictfp;
if ((modifiers & incompatibleWithAbstract) != 0)
problemReporter().illegalAbstractModifierCombinationForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
if (!methodBinding.declaringClass.isAbstract())
problemReporter().abstractMethodInAbstractClass(
- (SourceTypeBinding) methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ (SourceTypeBinding) methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
}
- /* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final)
- // methods from a final class are final : 8.4.3.3
- if (methodBinding.declaringClass.isFinal())
- modifiers |= AccFinal;
- */
+ /*
+ * DISABLED for backward compatibility with javac (if enabled should
+ * also mark private methods as final) // methods from a final class are
+ * final : 8.4.3.3 if (methodBinding.declaringClass.isFinal()) modifiers |=
+ * AccFinal;
+ */
// native methods cannot also be tagged as strictfp
-// if ((modifiers & AccNative) != 0 && (modifiers & AccStrictfp) != 0)
-// problemReporter().nativeMethodsCannotBeStrictfp(
-// methodBinding.declaringClass,
-// (AbstractMethodDeclaration) referenceContext);
-
- // static members are only authorized in a static member or top level type
+ // if ((modifiers & AccNative) != 0 && (modifiers & AccStrictfp) != 0)
+ // problemReporter().nativeMethodsCannotBeStrictfp(
+ // methodBinding.declaringClass,
+ // (AbstractMethodDeclaration) referenceContext);
+ // static members are only authorized in a static member or top level
+ // type
if (((realModifiers & AccStatic) != 0)
- && methodBinding.declaringClass.isNestedType()
- && !methodBinding.declaringClass.isStatic())
+ && methodBinding.declaringClass.isNestedType()
+ && !methodBinding.declaringClass.isStatic())
problemReporter().unexpectedStaticModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ methodBinding.declaringClass,
+ (AbstractMethodDeclaration) referenceContext);
methodBinding.modifiers = modifiers;
}
-
- /* Compute variable positions in scopes given an initial position offset
+
+ /*
+ * Compute variable positions in scopes given an initial position offset
* ignoring unused local variables.
*
- * Deal with arguments here, locals and subscopes are processed in BlockScope method
+ * Deal with arguments here, locals and subscopes are processed in
+ * BlockScope method
*/
-// public void computeLocalVariablePositions(int initOffset, CodeStream codeStream) {
-//
-// boolean isReportingUnusedArgument = false;
-//
-// if (referenceContext instanceof AbstractMethodDeclaration) {
-// AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration)referenceContext;
-// MethodBinding method = methodDecl.binding;
-// CompilerOptions options = compilationUnitScope().environment.options;
-// if (!(method.isAbstract()
-// || (method.isImplementing() && !options.reportUnusedParameterWhenImplementingAbstract)
-// || (method.isOverriding() && !method.isImplementing() && !options.reportUnusedParameterWhenOverridingConcrete)
-// || method.isMain())) {
-// isReportingUnusedArgument = true;
-// }
-// }
-// this.offset = initOffset;
-// this.maxOffset = initOffset;
-//
-// // manage arguments
-// int ilocal = 0, maxLocals = this.localIndex;
-// while (ilocal < maxLocals) {
-// LocalVariableBinding local = locals[ilocal];
-// if (local == null || !local.isArgument) break; // done with arguments
-//
-// // do not report fake used variable
-// if (isReportingUnusedArgument
-// && local.useFlag == LocalVariableBinding.UNUSED
-// && ((local.declaration.bits & AstNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
-// this.problemReporter().unusedArgument(local.declaration);
-// }
-//
-// // record user-defined argument for attribute generation
-// codeStream.record(local);
-//
-// // assign variable position
-// local.resolvedPosition = this.offset;
-//
-// if ((local.type == LongBinding) || (local.type == DoubleBinding)) {
-// this.offset += 2;
-// } else {
-// this.offset++;
-// }
-// // check for too many arguments/local variables
-// if (this.offset > 0xFF) { // no more than 255 words of arguments
-// this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration);
-// }
-// ilocal++;
-// }
-//
-// // sneak in extra argument before other local variables
-// if (extraSyntheticArguments != null) {
-// for (int iarg = 0, maxArguments = extraSyntheticArguments.length; iarg < maxArguments; iarg++){
-// SyntheticArgumentBinding argument = extraSyntheticArguments[iarg];
-// argument.resolvedPosition = this.offset;
-// if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
-// this.offset += 2;
-// } else {
-// this.offset++;
-// }
-// if (this.offset > 0xFF) { // no more than 255 words of arguments
-// this.problemReporter().noMoreAvailableSpaceForArgument(argument, (AstNode)this.referenceContext);
-// }
-// }
-// }
-// this.computeLocalVariablePositions(ilocal, this.offset, codeStream);
-// }
-
- /* Error management:
- * keep null for all the errors that prevent the method to be created
- * otherwise return a correct method binding (but without the element
- * that caused the problem) : ie : Incorrect thrown exception
+ // public void computeLocalVariablePositions(int initOffset, CodeStream
+ // codeStream) {
+ //
+ // boolean isReportingUnusedArgument = false;
+ //
+ // if (referenceContext instanceof AbstractMethodDeclaration) {
+ // AbstractMethodDeclaration methodDecl =
+ // (AbstractMethodDeclaration)referenceContext;
+ // MethodBinding method = methodDecl.binding;
+ // CompilerOptions options = compilationUnitScope().environment.options;
+ // if (!(method.isAbstract()
+ // || (method.isImplementing() &&
+ // !options.reportUnusedParameterWhenImplementingAbstract)
+ // || (method.isOverriding() && !method.isImplementing() &&
+ // !options.reportUnusedParameterWhenOverridingConcrete)
+ // || method.isMain())) {
+ // isReportingUnusedArgument = true;
+ // }
+ // }
+ // this.offset = initOffset;
+ // this.maxOffset = initOffset;
+ //
+ // // manage arguments
+ // int ilocal = 0, maxLocals = this.localIndex;
+ // while (ilocal < maxLocals) {
+ // LocalVariableBinding local = locals[ilocal];
+ // if (local == null || !local.isArgument) break; // done with arguments
+ //
+ // // do not report fake used variable
+ // if (isReportingUnusedArgument
+ // && local.useFlag == LocalVariableBinding.UNUSED
+ // && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachableMASK) !=
+ // 0)) { // declaration is reachable
+ // this.problemReporter().unusedArgument(local.declaration);
+ // }
+ //
+ // // record user-defined argument for attribute generation
+ // codeStream.record(local);
+ //
+ // // assign variable position
+ // local.resolvedPosition = this.offset;
+ //
+ // if ((local.type == LongBinding) || (local.type == DoubleBinding)) {
+ // this.offset += 2;
+ // } else {
+ // this.offset++;
+ // }
+ // // check for too many arguments/local variables
+ // if (this.offset > 0xFF) { // no more than 255 words of arguments
+ // this.problemReporter().noMoreAvailableSpaceForArgument(local,
+ // local.declaration);
+ // }
+ // ilocal++;
+ // }
+ //
+ // // sneak in extra argument before other local variables
+ // if (extraSyntheticArguments != null) {
+ // for (int iarg = 0, maxArguments = extraSyntheticArguments.length; iarg <
+ // maxArguments; iarg++){
+ // SyntheticArgumentBinding argument = extraSyntheticArguments[iarg];
+ // argument.resolvedPosition = this.offset;
+ // if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
+ // this.offset += 2;
+ // } else {
+ // this.offset++;
+ // }
+ // if (this.offset > 0xFF) { // no more than 255 words of arguments
+ // this.problemReporter().noMoreAvailableSpaceForArgument(argument,
+ // (ASTNode)this.referenceContext);
+ // }
+ // }
+ // }
+ // this.computeLocalVariablePositions(ilocal, this.offset, codeStream);
+ // }
+ /*
+ * Error management: keep null for all the errors that prevent the method to
+ * be created otherwise return a correct method binding (but without the
+ * element that caused the problem) : ie : Incorrect thrown exception
*/
MethodBinding createMethod(AbstractMethodDeclaration method) {
SourceTypeBinding declaringClass = referenceType().binding;
int modifiers = method.modifiers | AccUnresolved;
if (method.isConstructor()) {
- method.binding = new MethodBinding(modifiers, null, null, declaringClass);
+ method.binding = new MethodBinding(modifiers, null, null,
+ declaringClass);
checkAndSetModifiersForConstructor(method.binding);
} else {
if (declaringClass.isInterface())
modifiers |= AccPublic | AccAbstract;
- method.binding =
- new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
+ method.binding = new MethodBinding(modifiers, method.selector,
+ null, null, null, declaringClass);
checkAndSetModifiersForMethod(method.binding);
}
return method.binding;
}
- /* Overridden to detect the error case inside an explicit constructor call:
-
- class X {
- int i;
- X myX;
- X(X x) {
- this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors
- }
- }
- */
- public FieldBinding findField(
- TypeBinding receiverType,
- char[] fieldName,
- InvocationSite invocationSite) {
+ /*
+ * Overridden to detect the error case inside an explicit constructor call:
+ *
+ * class X { int i; X myX; X(X x) { this(i, myX.i, x.i); // same for super
+ * calls... only the first 2 field accesses are errors } }
+ */
+ public FieldBinding findField(TypeBinding receiverType, char[] fieldName,
+ InvocationSite invocationSite) {
- FieldBinding field = super.findField(receiverType, fieldName, invocationSite);
+ FieldBinding field = super.findField(receiverType, fieldName,
+ invocationSite);
if (field == null)
return null;
if (!field.isValidBinding())
return field;
if (invocationSite instanceof SingleNameReference)
- return new ProblemFieldBinding(
- field.declaringClass,
- fieldName,
- NonStaticReferenceInConstructorInvocation);
+ return new ProblemFieldBinding(field.declaringClass, fieldName,
+ NonStaticReferenceInConstructorInvocation);
if (invocationSite instanceof QualifiedNameReference) {
// look to see if the field is the first binding
QualifiedNameReference name = (QualifiedNameReference) invocationSite;
if (name.binding == null)
- // only true when the field is the fieldbinding at the beginning of name's tokens
- return new ProblemFieldBinding(
- field.declaringClass,
- fieldName,
- NonStaticReferenceInConstructorInvocation);
+ // only true when the field is the fieldbinding at the beginning
+ // of name's tokens
+ return new ProblemFieldBinding(field.declaringClass, fieldName,
+ NonStaticReferenceInConstructorInvocation);
}
return field;
}
public boolean isInsideInitializerOrConstructor() {
return (referenceContext instanceof TypeDeclaration)
- || (referenceContext instanceof ConstructorDeclaration);
+ || (referenceContext instanceof ConstructorDeclaration);
}
- /* Answer the problem reporter to use for raising new problems.
- *
+ /*
+ * Answer the problem reporter to use for raising new problems.
+ *
* Note that as a side-effect, this updates the current reference context
- * (unit, type or method) in case the problem handler decides it is necessary
- * to abort.
+ * (unit, type or method) in case the problem handler decides it is
+ * necessary to abort.
*/
public ProblemReporter problemReporter() {
public final int recordInitializationStates(FlowInfo flowInfo) {
- if (!flowInfo.isReachable()) return -1;
+ if (!flowInfo.isReachable())
+ return -1;
- UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInits();
+ UnconditionalFlowInfo unconditionalFlowInfo = flowInfo
+ .unconditionalInits();
long[] extraInits = unconditionalFlowInfo.extraDefiniteInits;
long inits = unconditionalFlowInfo.definiteInits;
- checkNextEntry : for (int i = lastIndex; --i >= 0;) {
+ checkNextEntry: for (int i = lastIndex; --i >= 0;) {
if (definiteInits[i] == inits) {
long[] otherInits = extraDefiniteInits[i];
if ((extraInits != null) && (otherInits != null)) {
// add a new entry
if (definiteInits.length == lastIndex) {
// need a resize
- System.arraycopy(
- definiteInits,
- 0,
- (definiteInits = new long[lastIndex + 20]),
- 0,
- lastIndex);
- System.arraycopy(
- extraDefiniteInits,
- 0,
- (extraDefiniteInits = new long[lastIndex + 20][]),
- 0,
- lastIndex);
+ System.arraycopy(definiteInits, 0,
+ (definiteInits = new long[lastIndex + 20]), 0, lastIndex);
+ System.arraycopy(extraDefiniteInits, 0,
+ (extraDefiniteInits = new long[lastIndex + 20][]), 0,
+ lastIndex);
}
definiteInits[lastIndex] = inits;
if (extraInits != null) {
extraDefiniteInits[lastIndex] = new long[extraInits.length];
- System.arraycopy(
- extraInits,
- 0,
- extraDefiniteInits[lastIndex],
- 0,
- extraInits.length);
+ System.arraycopy(extraInits, 0, extraDefiniteInits[lastIndex], 0,
+ extraInits.length);
}
return lastIndex++;
}
- /* Answer the reference type of this scope.
- *
- * It is the nearest enclosing type of this scope.
- */
+ /*
+ * Answer the reference type of this scope.
+ *
+ * It is the nearest enclosing type of this scope.
+ */
public TypeDeclaration referenceType() {
return (TypeDeclaration) ((ClassScope) parent).referenceContext;
s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$
s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$
s += newLine + "isConstructorCall = " + isConstructorCall; //$NON-NLS-1$
+ s += newLine + "initializedField = " + initializedField; //$NON-NLS-1$
s += newLine + "fieldDeclarationIndex = " + fieldDeclarationIndex; //$NON-NLS-1$
s += newLine + "referenceContext = " + referenceContext; //$NON-NLS-1$
return s;