X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/BlockScope.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/BlockScope.java index 51f82b0..a3b1d92 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/BlockScope.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/BlockScope.java @@ -1,25 +1,22 @@ /******************************************************************************* - * 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; -import net.sourceforge.phpdt.internal.compiler.ast.Argument; -import net.sourceforge.phpdt.internal.compiler.ast.AstNode; -import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration; -import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration; -import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream; -import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions; -import net.sourceforge.phpdt.internal.compiler.impl.Constant; +import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; + +import net.sourceforge.phpdt.core.compiler.CharOperation; import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; -import net.sourceforge.phpdt.internal.compiler.util.CharOperation; +import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; public class BlockScope extends Scope { @@ -30,10 +27,13 @@ public class BlockScope extends Scope { public int offset; // for variable allocation throughout scopes public int maxOffset; // for variable allocation throughout scopes - // finally scopes must be shifted behind respective try scope + // finally scopes must be shifted behind respective try&catch scope(s) so as to avoid + // collisions of secret variables (return address, save value). public BlockScope[] shiftScopes; public final static VariableBinding[] EmulationPathToImplicitThis = {}; + public final static VariableBinding[] NoEnclosingInstanceInConstructorCall = {}; + public final static VariableBinding[] NoEnclosingInstanceInStaticContext = {}; public Scope[] subscopes = new Scope[1]; // need access from code assist public int scopeIndex = 0; // need access from code assist @@ -100,8 +100,8 @@ public class BlockScope extends Scope { } while ((scope = scope.parent) instanceof BlockScope); ClassScope localTypeScope = new ClassScope(this, localType); - localTypeScope.buildLocalTypeBinding(enclosingSourceType()); addSubscope(localTypeScope); + localTypeScope.buildLocalTypeBinding(enclosingSourceType()); } /* Insert a local variable into a given scope, updating its position @@ -140,7 +140,7 @@ public class BlockScope extends Scope { /* Answer true if the receiver is suitable for assigning final blank fields. * - * i.e. is inside an initializer, a constructor or a clinit + * in other words, it is inside an initializer, a constructor or a clinit */ public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) { @@ -151,9 +151,8 @@ public class BlockScope extends Scope { if (methodScope.isStatic != binding.isStatic()) return false; return methodScope.isInsideInitializer() // inside initializer - || ((AbstractMethodDeclaration) methodScope.referenceContext) - .isInitializationMethod(); - // inside constructor or clinit + || ((AbstractMethodDeclaration) methodScope.referenceContext) + .isInitializationMethod(); // inside constructor or clinit } String basicToString(int tab) { String newLine = "\n"; //$NON-NLS-1$ @@ -187,100 +186,88 @@ public class BlockScope extends Scope { /* Compute variable positions in scopes given an initial position offset * ignoring unused local variables. * - * Special treatment to have Try secret return address variables located at non - * colliding positions. Return addresses are not allocated initially, but gathered - * and allocated behind all other variables. + * No argument is expected here (ilocal is the first non-argument local of the outermost scope) + * Arguments are managed by the MethodScope method */ - public void computeLocalVariablePositions( - int initOffset, - CodeStream codeStream) { - - this.offset = initOffset; - this.maxOffset = initOffset; - - // local variable init - int ilocal = 0, maxLocals = 0, localsLength = locals.length; - while ((maxLocals < localsLength) && (locals[maxLocals] != null)) - maxLocals++; - boolean hasMoreVariables = maxLocals > 0; - - // scope init - int iscope = 0, maxScopes = 0, subscopesLength = subscopes.length; - while ((maxScopes < subscopesLength) && (subscopes[maxScopes] != null)) - maxScopes++; - boolean hasMoreScopes = maxScopes > 0; - - // iterate scopes and variables in parallel - while (hasMoreVariables || hasMoreScopes) { - if (hasMoreScopes - && (!hasMoreVariables || (subscopes[iscope].startIndex() <= ilocal))) { - // consider subscope first - if (subscopes[iscope] instanceof BlockScope) { - BlockScope subscope = (BlockScope) subscopes[iscope]; - int subOffset = subscope.shiftScopes == null ? this.offset : subscope.maxShiftedOffset(); - subscope.computeLocalVariablePositions(subOffset, codeStream); - if (subscope.maxOffset > this.maxOffset) - this.maxOffset = subscope.maxOffset; - } - hasMoreScopes = ++iscope < maxScopes; - } else { - // consider variable first - LocalVariableBinding local = locals[ilocal]; - - // check if variable is actually used, and may force it to be preserved - boolean generatesLocal = - (local.used && (local.constant == Constant.NotAConstant)) || local.isArgument; - if (!local.used - && (local.declaration != null) // unused (and non secret) local - && ((local.declaration.bits & AstNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable - if (local.isArgument) // method argument - this.problemReporter().unusedArgument(local.declaration); - else if (!(local.declaration instanceof Argument)) // do not report unused catch arguments - this.problemReporter().unusedLocalVariable(local.declaration); - } - if (!generatesLocal) { - if (local.declaration != null - && environment().options.preserveAllLocalVariables) { - generatesLocal = true; // force it to be preserved in the generated code - local.used = true; - } - } - if (generatesLocal) { - - if (local.declaration != null) { - codeStream.record(local); - // record user local variables for attribute generation - } - // allocate variable position - local.resolvedPosition = this.offset; - - // check for too many arguments/local variables - if (local.isArgument) { - if (this.offset > 0xFF) { // no more than 255 words of arguments - this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration); - } - } else { - if (this.offset > 0xFFFF) { // no more than 65535 words of locals - this.problemReporter().noMoreAvailableSpaceForLocal( - local, local.declaration == null ? (AstNode)this.methodScope().referenceContext : local.declaration); - } - } - - // increment offset - if ((local.type == LongBinding) || (local.type == DoubleBinding)) { - this.offset += 2; - } else { - this.offset++; - } - } else { - local.resolvedPosition = -1; // not generated - } - hasMoreVariables = ++ilocal < maxLocals; - } - } - if (this.offset > this.maxOffset) - this.maxOffset = this.offset; - } +// void computeLocalVariablePositions(int ilocal, int initOffset, CodeStream codeStream) { +// +// this.offset = initOffset; +// this.maxOffset = initOffset; +// +// // local variable init +// int maxLocals = this.localIndex; +// boolean hasMoreVariables = ilocal < maxLocals; +// +// // scope init +// int iscope = 0, maxScopes = this.scopeIndex; +// boolean hasMoreScopes = maxScopes > 0; +// +// // iterate scopes and variables in parallel +// while (hasMoreVariables || hasMoreScopes) { +// if (hasMoreScopes +// && (!hasMoreVariables || (subscopes[iscope].startIndex() <= ilocal))) { +// // consider subscope first +// if (subscopes[iscope] instanceof BlockScope) { +// BlockScope subscope = (BlockScope) subscopes[iscope]; +// int subOffset = subscope.shiftScopes == null ? this.offset : subscope.maxShiftedOffset(); +// subscope.computeLocalVariablePositions(0, subOffset, codeStream); +// if (subscope.maxOffset > this.maxOffset) +// this.maxOffset = subscope.maxOffset; +// } +// hasMoreScopes = ++iscope < maxScopes; +// } else { +// +// // consider variable first +// LocalVariableBinding local = locals[ilocal]; // if no local at all, will be locals[ilocal]==null +// +// // check if variable is actually used, and may force it to be preserved +// boolean generateCurrentLocalVar = (local.useFlag == LocalVariableBinding.USED && (local.constant == Constant.NotAConstant)); +// +// // do not report fake used variable +// if (local.useFlag == LocalVariableBinding.UNUSED +// && (local.declaration != null) // unused (and non secret) local +// && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable +// +// if (!(local.declaration instanceof Argument)) // do not report unused catch arguments +// this.problemReporter().unusedLocalVariable(local.declaration); +// } +// +// // could be optimized out, but does need to preserve unread variables ? +//// if (!generateCurrentLocalVar) { +//// if (local.declaration != null && environment().options.preserveAllLocalVariables) { +//// generateCurrentLocalVar = true; // force it to be preserved in the generated code +//// local.useFlag = LocalVariableBinding.USED; +//// } +//// } +// +// // allocate variable +// if (generateCurrentLocalVar) { +// +// if (local.declaration != null) { +// codeStream.record(local); // record user-defined local variables for attribute generation +// } +// // assign variable position +// local.resolvedPosition = this.offset; +// +// if ((local.type == LongBinding) || (local.type == DoubleBinding)) { +// this.offset += 2; +// } else { +// this.offset++; +// } +// if (this.offset > 0xFFFF) { // no more than 65535 words of locals +// this.problemReporter().noMoreAvailableSpaceForLocal( +// local, +// local.declaration == null ? (ASTNode)this.methodScope().referenceContext : local.declaration); +// } +// } else { +// local.resolvedPosition = -1; // not generated +// } +// hasMoreVariables = ++ilocal < maxLocals; +// } +// } +// if (this.offset > this.maxOffset) +// this.maxOffset = this.offset; +// } /* Answer true if the variable name already exists within the receiver's scope. */ @@ -322,57 +309,6 @@ public class BlockScope extends Scope { } } - /* - * Record the suitable binding denoting a synthetic field or constructor argument, - * mapping to a given actual enclosing instance type in the scope context. - * Skip it if the enclosingType is actually the current scope's enclosing type. - */ - - public void emulateOuterAccess( - ReferenceBinding targetEnclosingType, - boolean useDirectReference) { - - ReferenceBinding currentType = enclosingSourceType(); - if (currentType.isNestedType() - && currentType != targetEnclosingType){ - /*&& !targetEnclosingType.isSuperclassOf(currentType)*/ - - if (useDirectReference) { - // the target enclosing type is not in scope, we directly refer it - // must also add a synthetic field if we're not inside a constructor - NestedTypeBinding currentNestedType = (NestedTypeBinding) currentType; - if (methodScope().isInsideInitializerOrConstructor()) - currentNestedType.addSyntheticArgument(targetEnclosingType); - else - currentNestedType.addSyntheticArgumentAndField(targetEnclosingType); - - } else { // indirect reference sequence - int depth = 0; - - // saturate all the way up until reaching compatible enclosing type - while (currentType.isLocalType()){ - NestedTypeBinding currentNestedType = (NestedTypeBinding) currentType; - currentType = currentNestedType.enclosingType; - - if (depth == 0){ - if (methodScope().isInsideInitializerOrConstructor()) { - // must also add a synthetic field if we're not inside a constructor - currentNestedType.addSyntheticArgument(currentType); - } else { - currentNestedType.addSyntheticArgumentAndField(currentType); - } - } else if (currentNestedType == targetEnclosingType - || targetEnclosingType.isSuperclassOf(currentNestedType)) { - break; - } else { - currentNestedType.addSyntheticArgumentAndField(currentType); - } - depth++; - } - } - } - } - /* Note that it must never produce a direct access to the targetEnclosingType, * but instead a field sequence (this$2.this$1.this$0) so as to handle such a test case: * @@ -484,7 +420,7 @@ public class BlockScope extends Scope { if (!((ReferenceBinding) binding).canBeSeenBy(this)) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), - binding, + (ReferenceBinding)binding, NotVisible); break foundType; } @@ -503,7 +439,7 @@ public class BlockScope extends Scope { char[] nextName = compoundName[currentIndex++]; invocationSite.setFieldIndex(currentIndex); invocationSite.setActualReceiverType(typeBinding); - if ((binding = findField(typeBinding, nextName, invocationSite)) != null) { + if ((mask & FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite)) != null) { if (!binding.isValidBinding()) return new ProblemFieldBinding( ((FieldBinding) binding).declaringClass, @@ -511,11 +447,19 @@ public class BlockScope extends Scope { binding.problemId()); break; // binding is now a field } - if ((binding = findMemberType(nextName, typeBinding)) == null) - return new ProblemBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - typeBinding, - NotFound); + if ((binding = findMemberType(nextName, typeBinding)) == null) { + if ((mask & FIELD) != 0) { + return new ProblemBinding( + CharOperation.subarray(compoundName, 0, currentIndex), + typeBinding, + NotFound); + } else { + return new ProblemReferenceBinding( + CharOperation.subarray(compoundName, 0, currentIndex), + typeBinding, + NotFound); + } + } if (!binding.isValidBinding()) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), @@ -580,7 +524,7 @@ public class BlockScope extends Scope { if (!((ReferenceBinding) binding).canBeSeenBy(this)) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), - binding, + (ReferenceBinding)binding, NotVisible); break foundType; } @@ -743,27 +687,27 @@ public class BlockScope extends Scope { NonStaticReferenceInStaticContext); } } - if (enclosingType == fieldBinding.declaringClass - || environment().options.complianceLevel >= CompilerOptions.JDK1_4){ - // found a valid field in the 'immediate' scope (ie. not inherited) - // OR in 1.4 mode (inherited shadows enclosing) - if (foundField == null) { - if (depth > 0){ - invocationSite.setDepth(depth); - invocationSite.setActualReceiverType(enclosingType); - } - // return the fieldBinding if it is not declared in a superclass of the scope's binding (i.e. "inherited") - return insideProblem == null ? fieldBinding : insideProblem; - } - if (foundField.isValidBinding()) - // if a valid field was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited) - if (foundField.declaringClass != fieldBinding.declaringClass) - // ie. have we found the same field - do not trust field identity yet - return new ProblemFieldBinding( - fieldBinding.declaringClass, - name, - InheritedNameHidesEnclosingName); - } +// if (enclosingType == fieldBinding.declaringClass +// || environment().options.complianceLevel >= CompilerOptions.JDK1_4){ +// // found a valid field in the 'immediate' scope (ie. not inherited) +// // OR in 1.4 mode (inherited shadows enclosing) +// if (foundField == null) { +// if (depth > 0){ +// invocationSite.setDepth(depth); +// invocationSite.setActualReceiverType(enclosingType); +// } +// // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited) +// return insideProblem == null ? fieldBinding : insideProblem; +// } +// if (foundField.isValidBinding()) +// // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited) +// if (foundField.declaringClass != fieldBinding.declaringClass) +// // ie. have we found the same field - do not trust field identity yet +// return new ProblemFieldBinding( +// fieldBinding.declaringClass, +// name, +// InheritedNameHidesEnclosingName); +// } } if (foundField == null @@ -824,86 +768,6 @@ public class BlockScope extends Scope { else return new ProblemBinding(name, enclosingSourceType(), NotFound); } - - /* - * This retrieves the argument that maps to an enclosing instance of the suitable type, - * if not found then answers nil -- do not create one - * - * #implicitThis : the implicit this will be ok - * #((arg) this$n) : available as a constructor arg - * #((arg) this$n access$m... access$p) : available as as a constructor arg + a sequence of synthetic accessors to synthetic fields - * #((fieldDescr) this$n access#m... access$p) : available as a first synthetic field + a sequence of synthetic accessors to synthetic fields - * nil : not found - * - */ - public Object[] getCompatibleEmulationPath(ReferenceBinding targetEnclosingType) { - - MethodScope currentMethodScope = this.methodScope(); - SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType(); - - // identity check - if (!currentMethodScope.isStatic - && !currentMethodScope.isConstructorCall - && (sourceType == targetEnclosingType - || targetEnclosingType.isSuperclassOf(sourceType))) { - return EmulationPathToImplicitThis; // implicit this is good enough - } - if (!sourceType.isNestedType() - || sourceType.isStatic()) { // no emulation from within non-inner types - return null; - } - boolean insideConstructor = - currentMethodScope.isInsideInitializerOrConstructor(); - // use synthetic constructor arguments if possible - if (insideConstructor) { - SyntheticArgumentBinding syntheticArg; - if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, this, false)) != null) { - return new Object[] { syntheticArg }; - } - } - - // use a direct synthetic field then - if (!currentMethodScope.isStatic) { - FieldBinding syntheticField; - if ((syntheticField = sourceType.getSyntheticField(targetEnclosingType, this, false)) != null) { - return new Object[] { syntheticField }; - } - // could be reached through a sequence of enclosing instance link (nested members) - Object[] path = new Object[2]; // probably at least 2 of them - ReferenceBinding currentType = sourceType.enclosingType(); - if (insideConstructor) { - path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument((SourceTypeBinding) currentType, this, false); - } else { - path[0] = - sourceType.getSyntheticField((SourceTypeBinding) currentType, this, false); - } - if (path[0] != null) { // keep accumulating - int count = 1; - ReferenceBinding currentEnclosingType; - while ((currentEnclosingType = currentType.enclosingType()) != null) { - //done? - if (currentType == targetEnclosingType - || targetEnclosingType.isSuperclassOf(currentType)) - break; - syntheticField = ((NestedTypeBinding) currentType).getSyntheticField((SourceTypeBinding) currentEnclosingType, this, false); - if (syntheticField == null) - break; - // append inside the path - if (count == path.length) { - System.arraycopy(path, 0, (path = new Object[count + 1]), 0, count); - } - // private access emulation is necessary since synthetic field is private - path[count++] = ((SourceTypeBinding) syntheticField.declaringClass).addSyntheticMethod(syntheticField, true); - currentType = currentEnclosingType; - } - if (currentType == targetEnclosingType - || targetEnclosingType.isSuperclassOf(currentType)) { - return path; - } - } - } - return null; - } /* API * @@ -922,18 +786,18 @@ public class BlockScope extends Scope { compilationUnitScope().recordTypeReference(receiverType); compilationUnitScope().recordTypeReferences(argumentTypes); MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes); - if (methodBinding != null) + if (methodBinding != null) { if (methodBinding.canBeSeenBy(invocationSite, this)) return methodBinding; - + } MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName); - if (methods == NoMethods) + if (methods == NoMethods) { return new ProblemMethodBinding( ConstructorDeclaration.ConstantPoolName, argumentTypes, NotFound); - + } MethodBinding[] compatible = new MethodBinding[methods.length]; int compatibleIndex = 0; for (int i = 0, length = methods.length; i < length; i++) @@ -957,8 +821,9 @@ public class BlockScope extends Scope { return visible[0]; if (visibleIndex == 0) return new ProblemMethodBinding( + compatible[0], ConstructorDeclaration.ConstantPoolName, - argumentTypes, + compatible[0].parameters, NotVisible); return mostSpecificClassMethodBinding(visible, visibleIndex); } @@ -967,9 +832,9 @@ public class BlockScope extends Scope { * This retrieves the argument that maps to an enclosing instance of the suitable type, * if not found then answers nil -- do not create one * - * #implicitThis : the implicit this will be ok - * #((arg) this$n) : available as a constructor arg - * #((arg) this$n ... this$p) : available as as a constructor arg + a sequence of fields + * #implicitThis : the implicit this will be ok + * #((arg) this$n) : available as a constructor arg + * #((arg) this$n ... this$p) : available as as a constructor arg + a sequence of fields * #((fieldDescr) this$n ... this$p) : available as a sequence of fields * nil : not found * @@ -1012,80 +877,108 @@ public class BlockScope extends Scope { * This retrieves the argument that maps to an enclosing instance of the suitable type, * if not found then answers nil -- do not create one * - * #implicitThis : the implicit this will be ok + * #implicitThis : the implicit this will be ok * #((arg) this$n) : available as a constructor arg * #((arg) this$n access$m... access$p) : available as as a constructor arg + a sequence of synthetic accessors to synthetic fields * #((fieldDescr) this$n access#m... access$p) : available as a first synthetic field + a sequence of synthetic accessors to synthetic fields - * nil : not found - * - * EXACT MATCH VERSION - no type compatibility is performed + * nil : not found + * jls 15.9.2 */ - public Object[] getExactEmulationPath(ReferenceBinding targetEnclosingType) { - + public Object[] getEmulationPath( + ReferenceBinding targetEnclosingType, + boolean onlyExactMatch, + boolean ignoreEnclosingArgInConstructorCall) { + //TODO: (philippe) investigate why exactly test76 fails if ignoreEnclosingArgInConstructorCall is always false MethodScope currentMethodScope = this.methodScope(); SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType(); // identity check if (!currentMethodScope.isStatic - && !currentMethodScope.isConstructorCall - && (sourceType == targetEnclosingType)) { + && (!currentMethodScope.isConstructorCall || ignoreEnclosingArgInConstructorCall) + && (sourceType == targetEnclosingType + || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType)))) { + if (currentMethodScope.isConstructorCall) { + return NoEnclosingInstanceInConstructorCall; + } + if (currentMethodScope.isStatic){ + return NoEnclosingInstanceInStaticContext; + } return EmulationPathToImplicitThis; // implicit this is good enough } - if (!sourceType.isNestedType() - || sourceType.isStatic()) { // no emulation from within non-inner types + if (!sourceType.isNestedType() || sourceType.isStatic()) { // no emulation from within non-inner types + if (currentMethodScope.isConstructorCall) { + return NoEnclosingInstanceInConstructorCall; + } + if (currentMethodScope.isStatic){ + return NoEnclosingInstanceInStaticContext; + } return null; } - - boolean insideConstructor = - currentMethodScope.isInsideInitializerOrConstructor(); + boolean insideConstructor = currentMethodScope.isInsideInitializerOrConstructor(); // use synthetic constructor arguments if possible if (insideConstructor) { SyntheticArgumentBinding syntheticArg; - if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, this, true)) != null) { + if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, onlyExactMatch)) != null) { return new Object[] { syntheticArg }; } } + // use a direct synthetic field then - if (!currentMethodScope.isStatic) { - FieldBinding syntheticField; - if ((syntheticField = sourceType.getSyntheticField(targetEnclosingType, this, true)) != null) { - return new Object[] { syntheticField }; + if (currentMethodScope.isStatic) { + return NoEnclosingInstanceInStaticContext; + } + FieldBinding syntheticField = sourceType.getSyntheticField(targetEnclosingType, onlyExactMatch); + if (syntheticField != null) { + if (currentMethodScope.isConstructorCall){ + return NoEnclosingInstanceInConstructorCall; } - // could be reached through a sequence of enclosing instance link (nested members) - Object[] path = new Object[2]; // probably at least 2 of them - ReferenceBinding currentType = sourceType.enclosingType(); - if (insideConstructor) { - path[0] = - ((NestedTypeBinding) sourceType).getSyntheticArgument((SourceTypeBinding) currentType, this, true); - } else { - path[0] = - sourceType.getSyntheticField((SourceTypeBinding) currentType, this, true); + return new Object[] { syntheticField }; + } + // could be reached through a sequence of enclosing instance link (nested members) + Object[] path = new Object[2]; // probably at least 2 of them + ReferenceBinding currentType = sourceType.enclosingType(); + if (insideConstructor) { + path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument((SourceTypeBinding) currentType, onlyExactMatch); + } else { + if (currentMethodScope.isConstructorCall){ + return NoEnclosingInstanceInConstructorCall; } - if (path[0] != null) { // keep accumulating - int count = 1; - ReferenceBinding currentEnclosingType; - while ((currentEnclosingType = currentType.enclosingType()) != null) { - //done? - if (currentType == targetEnclosingType) - break; - syntheticField = - ((NestedTypeBinding) currentType).getSyntheticField( - (SourceTypeBinding) currentEnclosingType, - this, - true); - if (syntheticField == null) - break; - // append inside the path - if (count == path.length) { - System.arraycopy(path, 0, (path = new Object[count + 1]), 0, count); + path[0] = sourceType.getSyntheticField((SourceTypeBinding) currentType, onlyExactMatch); + } + if (path[0] != null) { // keep accumulating + + int count = 1; + ReferenceBinding currentEnclosingType; + while ((currentEnclosingType = currentType.enclosingType()) != null) { + + //done? + if (currentType == targetEnclosingType + || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType))) break; + + if (currentMethodScope != null) { + currentMethodScope = currentMethodScope.enclosingMethodScope(); + if (currentMethodScope != null && currentMethodScope.isConstructorCall){ + return NoEnclosingInstanceInConstructorCall; + } + if (currentMethodScope != null && currentMethodScope.isStatic){ + return NoEnclosingInstanceInStaticContext; } - // private access emulation is necessary since synthetic field is private - path[count++] = ((SourceTypeBinding) syntheticField.declaringClass).addSyntheticMethod(syntheticField, true); - currentType = currentEnclosingType; } - if (currentType == targetEnclosingType) { - return path; + + syntheticField = ((NestedTypeBinding) currentType).getSyntheticField((SourceTypeBinding) currentEnclosingType, onlyExactMatch); + if (syntheticField == null) break; + + // append inside the path + if (count == path.length) { + System.arraycopy(path, 0, (path = new Object[count + 1]), 0, count); } + // private access emulation is necessary since synthetic field is private + path[count++] = ((SourceTypeBinding) syntheticField.declaringClass).addSyntheticMethod(syntheticField, true); + currentType = currentEnclosingType; + } + if (currentType == targetEnclosingType + || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType))) { + return path; } } return null; @@ -1202,15 +1095,15 @@ public class BlockScope extends Scope { return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound); } // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead) - fuzzyProblem = new ProblemMethodBinding(selector, argumentTypes, InheritedNameHidesEnclosingName); + fuzzyProblem = new ProblemMethodBinding(selector, methodBinding.parameters, InheritedNameHidesEnclosingName); } else if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) { // using instead of for visibility check does grant all access to innerclass fuzzyProblem = new ProblemMethodBinding( + methodBinding, selector, - argumentTypes, - methodBinding.declaringClass, + methodBinding.parameters, NotVisible); } } @@ -1230,33 +1123,33 @@ public class BlockScope extends Scope { } } - if (receiverType == methodBinding.declaringClass - || (receiverType.getMethods(selector)) != NoMethods - || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= CompilerOptions.JDK1_4)){ - // found a valid method in the 'immediate' scope (ie. not inherited) - // OR the receiverType implemented a method with the correct name - // OR in 1.4 mode (inherited visible shadows enclosing) - if (foundMethod == null) { - if (depth > 0){ - invocationSite.setDepth(depth); - invocationSite.setActualReceiverType(receiverType); - } - // return the methodBinding if it is not declared in a superclass of the scope's binding (i.e. "inherited") - if (fuzzyProblem != null) - return fuzzyProblem; - if (insideProblem != null) - return insideProblem; - return methodBinding; - } - // if a method was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited) - // NOTE: Unlike fields, a non visible method hides a visible method - if (foundMethod.declaringClass != methodBinding.declaringClass) - // ie. have we found the same method - do not trust field identity yet - return new ProblemMethodBinding( - methodBinding.selector, - methodBinding.parameters, - InheritedNameHidesEnclosingName); - } +// if (receiverType == methodBinding.declaringClass +// || (receiverType.getMethods(selector)) != NoMethods +// || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= CompilerOptions.JDK1_4)){ +// // found a valid method in the 'immediate' scope (ie. not inherited) +// // OR the receiverType implemented a method with the correct name +// // OR in 1.4 mode (inherited visible shadows enclosing) +// if (foundMethod == null) { +// if (depth > 0){ +// invocationSite.setDepth(depth); +// invocationSite.setActualReceiverType(receiverType); +// } +// // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited) +// if (fuzzyProblem != null) +// return fuzzyProblem; +// if (insideProblem != null) +// return insideProblem; +// return methodBinding; +// } +// // if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited) +// // NOTE: Unlike fields, a non visible method hides a visible method +// if (foundMethod.declaringClass != methodBinding.declaringClass) +// // ie. have we found the same method - do not trust field identity yet +// return new ProblemMethodBinding( +// methodBinding.selector, +// methodBinding.parameters, +// InheritedNameHidesEnclosingName); +// } } if (foundMethod == null @@ -1327,8 +1220,7 @@ public class BlockScope extends Scope { ReferenceBinding currentType = (ReferenceBinding) receiverType; if (!currentType.canBeSeenBy(this)) - return new ProblemMethodBinding(selector, argumentTypes, NotVisible); - // *** Need a new problem id - TypeNotVisible? + return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible); // retrieve an exact visible match (if possible) MethodBinding methodBinding = @@ -1350,9 +1242,9 @@ public class BlockScope extends Scope { NotFound); if (!methodBinding.canBeSeenBy(currentType, invocationSite, this)) return new ProblemMethodBinding( + methodBinding, selector, - argumentTypes, - methodBinding.declaringClass, + methodBinding.parameters, NotVisible); } return methodBinding; @@ -1384,25 +1276,10 @@ public class BlockScope extends Scope { * Code responsible to request some more emulation work inside the invocation type, so as to supply * correct synthetic arguments to any allocation of the target type. */ - public void propagateInnerEmulation( - ReferenceBinding targetType, - boolean isEnclosingInstanceSupplied, - boolean useDirectReference) { - - // perform some emulation work in case there is some and we are inside a local type only - // propage emulation of the enclosing instances - ReferenceBinding[] syntheticArgumentTypes; - if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) - != null) { - for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { - ReferenceBinding syntheticArgType = syntheticArgumentTypes[i]; - // need to filter out the one that could match a supplied enclosing instance - if (!(isEnclosingInstanceSupplied - && (syntheticArgType == targetType.enclosingType()))) { - this.emulateOuterAccess(syntheticArgType, useDirectReference); - } - } - } + public void propagateInnerEmulation(ReferenceBinding targetType, boolean isEnclosingInstanceSupplied) { + + // no need to propagate enclosing instances, they got eagerly allocated already. + SyntheticArgumentBinding[] syntheticArguments; if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) { for (int i = 0, max = syntheticArguments.length; i < max; i++) { @@ -1418,7 +1295,7 @@ public class BlockScope extends Scope { /* Answer the reference type of this scope. * - * i.e. the nearest enclosing type of this scope. + * It is the nearest enclosing type of this scope. */ public TypeDeclaration referenceType() { @@ -1442,4 +1319,4 @@ public class BlockScope extends Scope { s += ((BlockScope) subscopes[i]).toString(tab + 1) + "\n"; //$NON-NLS-1$ return s; } -} \ No newline at end of file +}