X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/MethodScope.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/MethodScope.java index 4fe05b4..5059768 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/MethodScope.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/MethodScope.java @@ -10,44 +10,53 @@ *******************************************************************************/ 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.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]; @@ -56,15 +65,16 @@ public class MethodScope extends BlockScope { 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()) @@ -77,25 +87,28 @@ public class MethodScope extends BlockScope { 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) { @@ -109,23 +122,26 @@ public class MethodScope extends BlockScope { 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; @@ -134,34 +150,30 @@ public class MethodScope extends BlockScope { 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) { @@ -177,116 +189,130 @@ public class MethodScope extends BlockScope { // 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) { @@ -296,13 +322,14 @@ public class MethodScope extends BlockScope { 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); } @@ -310,22 +337,17 @@ public class MethodScope extends BlockScope { 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()) @@ -337,19 +359,16 @@ public class MethodScope extends BlockScope { 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; } @@ -362,14 +381,15 @@ public class MethodScope extends BlockScope { 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() { @@ -385,12 +405,14 @@ public class MethodScope extends BlockScope { 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)) { @@ -414,36 +436,26 @@ public class MethodScope extends BlockScope { // 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; @@ -462,6 +474,7 @@ public class MethodScope extends BlockScope { 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;