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 7ec902b..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 @@ -1,13 +1,13 @@ /******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * 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 v0.5 + * 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-v05.html + * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation - ******************************************************************************/ + *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.lookup; import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration; @@ -21,35 +21,42 @@ import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext; import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; /** - * 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 needToCompactLocalVariables; + public boolean isStatic; // method modifier or initializer one - //fields used in the TC process (no real meaning) - public static final int NotInFieldDecl = -1; //must be a negative value - public boolean isConstructorCall = false; //modified on the fly by the TC + // 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; - //modified on the fly by the TC + // 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][]; - public MethodScope( - ClassScope parent, - ReferenceContext context, - boolean isStatic) { + // inner-emulation + public SyntheticArgumentBinding[] extraSyntheticArguments; + + public MethodScope(ClassScope parent, ReferenceContext context, + boolean isStatic) { super(METHOD_SCOPE, parent); locals = new LocalVariableBinding[5]; @@ -58,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()) @@ -79,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) { @@ -111,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; @@ -136,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) { @@ -179,44 +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; } - - /* 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 + + /* + * 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 + */ + // 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) { @@ -226,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); } @@ -240,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()) @@ -267,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; } @@ -292,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() { @@ -315,13 +405,14 @@ public class MethodScope extends BlockScope { public final int recordInitializationStates(FlowInfo flowInfo) { - if ((flowInfo == FlowInfo.DeadEnd) || (flowInfo.isFakeReachable())) { + 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)) { @@ -345,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. - * - * i.e. 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; @@ -393,8 +474,10 @@ 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; } -} \ No newline at end of file +}