X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Flookup%2FScope.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Flookup%2FScope.java;h=0000000000000000000000000000000000000000;hb=6f0cd02d46e011bd5599e1b7fefc6159cb811135;hp=bfbb0b55c82f4789cec0d39e3a0085f06d42a0c4;hpb=622d0e5a4b1b35b6918a516a79a0cc22272a919e;p=org.ibex.tool.git diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java deleted file mode 100644 index bfbb0b5..0000000 --- a/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ /dev/null @@ -1,2000 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.compiler.lookup; - -import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.internal.compiler.ast.*; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; -import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; -import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; -import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; -import org.eclipse.jdt.internal.compiler.util.ObjectVector; - -public abstract class Scope - implements BaseTypes, BindingIds, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds { - - public final static int BLOCK_SCOPE = 1; - public final static int METHOD_SCOPE = 2; - public final static int CLASS_SCOPE = 3; - public final static int COMPILATION_UNIT_SCOPE = 4; - - public int kind; - public Scope parent; - - protected Scope(int kind, Scope parent) { - this.kind = kind; - this.parent = parent; - } - - /* Answer an int describing the relationship between the given types. - * - * NotRelated - * EqualOrMoreSpecific : left is compatible with right - * MoreGeneric : right is compatible with left - */ - public static int compareTypes(TypeBinding left, TypeBinding right) { - if (left.isCompatibleWith(right)) - return EqualOrMoreSpecific; - if (right.isCompatibleWith(left)) - return MoreGeneric; - return NotRelated; - } - - // Internal use only - protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) { - if (parameters == arguments) - return true; - - int length = parameters.length; - if (length != arguments.length) - return false; - - for (int i = 0; i < length; i++) - if (parameters[i] != arguments[i]) - if (!arguments[i].isCompatibleWith(parameters[i])) - return false; - return true; - } - - public final ClassScope classScope() { - Scope scope = this; - do { - if (scope instanceof ClassScope) - return (ClassScope) scope; - scope = scope.parent; - } while (scope != null); - return null; - } - - /* Answer an int describing the relationship between the given type and unchecked exceptions. - * - * NotRelated - * EqualOrMoreSpecific : type is known for sure to be an unchecked exception type - * MoreGeneric : type is a supertype of an actual unchecked exception type - */ - public int compareUncheckedException(ReferenceBinding type) { - int comparison = compareTypes(type, getJavaLangRuntimeException()); - if (comparison != 0) return comparison; - return compareTypes(type, getJavaLangError()); - } - - public final CompilationUnitScope compilationUnitScope() { - Scope lastScope = null; - Scope scope = this; - do { - lastScope = scope; - scope = scope.parent; - } while (scope != null); - return (CompilationUnitScope) lastScope; - } - - public ArrayBinding createArray(TypeBinding type, int dimension) { - if (!type.isValidBinding()) - return new ArrayBinding(type, dimension); - return environment().createArrayType(type, dimension); - } - - public final ClassScope enclosingClassScope() { - Scope scope = this; - while ((scope = scope.parent) != null) { - if (scope instanceof ClassScope) return (ClassScope)scope; - } - return null; // may answer null if no type around - } - - public final MethodScope enclosingMethodScope() { - Scope scope = this; - while ((scope = scope.parent) != null) { - if (scope instanceof MethodScope) return (MethodScope)scope; - } - return null; // may answer null if no method around - } - - /* Answer the receiver's enclosing source type. - */ - public final SourceTypeBinding enclosingSourceType() { - Scope scope = this; - do { - if (scope instanceof ClassScope) - return ((ClassScope) scope).referenceContext.binding; - scope = scope.parent; - } while (scope != null); - return null; - } - public final LookupEnvironment environment() { - Scope scope, unitScope = this; - while ((scope = unitScope.parent) != null) - unitScope = scope; - return ((CompilationUnitScope) unitScope).environment; - } - - protected void faultInReceiverType(TypeBinding type) { - if (type.isArrayType()) - type = ((ArrayBinding) type).leafComponentType; - - // check on Begin bit, so as to be resilient with potential illformed binaries containing cycles (67769) - if (type instanceof BinaryTypeBinding && (type.tagBits & BeginHierarchyCheck) == 0) { - type.tagBits |= BeginHierarchyCheck; - // fault in the hierarchy of the type now so we can detect missing types instead of in storeDependencyInfo - BinaryTypeBinding binaryType = (BinaryTypeBinding) type; - ReferenceBinding enclosingType = binaryType.enclosingType(); - if (enclosingType != null) - faultInReceiverType(enclosingType); - ReferenceBinding superclass = binaryType.superclass(); - if (superclass != null) - faultInReceiverType(superclass); - ReferenceBinding[] interfaces = binaryType.superInterfaces(); - for (int i = 0, l = interfaces.length; i < l; i++) - faultInReceiverType(interfaces[i]); - type.tagBits |= EndHierarchyCheck; - } - } - - // abstract method lookup lookup (since maybe missing default abstract methods) - public MethodBinding findDefaultAbstractMethod( - ReferenceBinding receiverType, - char[] selector, - TypeBinding[] argumentTypes, - InvocationSite invocationSite, - ReferenceBinding classHierarchyStart, - MethodBinding matchingMethod, - ObjectVector found) { - - int startFoundSize = found.size; - ReferenceBinding currentType = classHierarchyStart; - while (currentType != null) { - matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod); - currentType = currentType.superclass(); - } - int foundSize = found.size; - if (foundSize == startFoundSize) { - if (matchingMethod != null) compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions); - return matchingMethod; // maybe null - } - MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize]; - int candidatesCount = 0; - // argument type compatibility check - for (int i = startFoundSize; i < foundSize; i++) { - MethodBinding methodBinding = (MethodBinding) found.elementAt(i); - if (areParametersAssignable(methodBinding.parameters, argumentTypes)) - candidates[candidatesCount++] = methodBinding; - } - if (candidatesCount == 1) { - compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions); - return candidates[0]; - } - if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters - int argLength = argumentTypes.length; - nextMethod : for (int i = 0; i < foundSize; i++) { - MethodBinding methodBinding = (MethodBinding) found.elementAt(i); - TypeBinding[] params = methodBinding.parameters; - int paramLength = params.length; - nextArg: for (int a = 0; a < argLength; a++) { - TypeBinding arg = argumentTypes[a]; - for (int p = 0; p < paramLength; p++) - if (params[p] == arg) - continue nextArg; - continue nextMethod; - } - return methodBinding; - } - return (MethodBinding) found.elementAt(0); // no good match so just use the first one found - } - // no need to check for visibility - interface methods are public - return mostSpecificInterfaceMethodBinding(candidates, candidatesCount); - } - - // Internal use only - public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) { - if ((enclosingType.tagBits & HasNoMemberTypes) != 0) - return null; // know it has no member types (nor inherited member types) - - SourceTypeBinding enclosingSourceType = enclosingSourceType(); - compilationUnitScope().recordReference(enclosingType.compoundName, typeName); - ReferenceBinding memberType = enclosingType.getMemberType(typeName); - if (memberType != null) { - compilationUnitScope().recordTypeReference(memberType); // to record supertypes - if (enclosingSourceType == null - ? memberType.canBeSeenBy(getCurrentPackage()) - : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) - return memberType; - return new ProblemReferenceBinding(typeName, memberType, NotVisible); - } - return null; - } - - // Internal use only - public MethodBinding findExactMethod( - ReferenceBinding receiverType, - char[] selector, - TypeBinding[] argumentTypes, - InvocationSite invocationSite) { - - faultInReceiverType(receiverType); - compilationUnitScope().recordTypeReference(receiverType); - compilationUnitScope().recordTypeReferences(argumentTypes); - MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes); - if (exactMethod != null) { - compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions); - if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) - return exactMethod; - } - return null; - } - - // Internal use only - /* Answer the field binding that corresponds to fieldName. - Start the lookup at the receiverType. - InvocationSite implements - isSuperAccess(); this is used to determine if the discovered field is visible. - Only fields defined by the receiverType or its supertypes are answered; - a field of an enclosing type will not be found using this API. - - If no visible field is discovered, null is answered. - */ - public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) { - if (receiverType.isBaseType()) return null; - if (receiverType.isArrayType()) { - TypeBinding leafType = receiverType.leafComponentType(); - if (leafType instanceof ReferenceBinding) { - if (!((ReferenceBinding) leafType).canBeSeenBy(this)) - return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible); - } - if (CharOperation.equals(fieldName, LENGTH)) - return ArrayBinding.ArrayLength; - return null; - } - - faultInReceiverType(receiverType); - compilationUnitScope().recordTypeReference(receiverType); - - ReferenceBinding currentType = (ReferenceBinding) receiverType; - if (!currentType.canBeSeenBy(this)) - return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible); - - FieldBinding field = currentType.getField(fieldName, true /*resolve*/); - if (field != null) { - if (field.canBeSeenBy(currentType, invocationSite, this)) - return field; - return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible); - } - // collect all superinterfaces of receiverType until the field is found in a supertype - ReferenceBinding[][] interfacesToVisit = null; - int lastPosition = -1; - FieldBinding visibleField = null; - boolean keepLooking = true; - boolean notVisible = false; - // we could hold onto the not visible field for extra error reporting - while (keepLooking) { - ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); - if (itsInterfaces != NoSuperInterfaces) { - if (interfacesToVisit == null) - interfacesToVisit = new ReferenceBinding[5][]; - if (++lastPosition == interfacesToVisit.length) - System.arraycopy( - interfacesToVisit, - 0, - interfacesToVisit = new ReferenceBinding[lastPosition * 2][], - 0, - lastPosition); - interfacesToVisit[lastPosition] = itsInterfaces; - } - if ((currentType = currentType.superclass()) == null) - break; - - if ((field = currentType.getField(fieldName, needResolve)) != null) { - keepLooking = false; - if (field.canBeSeenBy(receiverType, invocationSite, this)) { - if (visibleField == null) - visibleField = field; - else - return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous); - } else { - notVisible = true; - } - } - } - - // walk all visible interfaces to find ambiguous references - if (interfacesToVisit != null) { - ProblemFieldBinding ambiguous = null; - done : for (int i = 0; i <= lastPosition; i++) { - ReferenceBinding[] interfaces = interfacesToVisit[i]; - for (int j = 0, length = interfaces.length; j < length; j++) { - ReferenceBinding anInterface = interfaces[j]; - if ((anInterface.tagBits & InterfaceVisited) == 0) { - // if interface as not already been visited - anInterface.tagBits |= InterfaceVisited; - if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) { - if (visibleField == null) { - visibleField = field; - } else { - ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous); - break done; - } - } else { - ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); - if (itsInterfaces != NoSuperInterfaces) { - if (++lastPosition == interfacesToVisit.length) - System.arraycopy( - interfacesToVisit, - 0, - interfacesToVisit = new ReferenceBinding[lastPosition * 2][], - 0, - lastPosition); - interfacesToVisit[lastPosition] = itsInterfaces; - } - } - } - } - } - - // bit reinitialization - for (int i = 0; i <= lastPosition; i++) { - ReferenceBinding[] interfaces = interfacesToVisit[i]; - for (int j = 0, length = interfaces.length; j < length; j++) - interfaces[j].tagBits &= ~InterfaceVisited; - } - if (ambiguous != null) - return ambiguous; - } - - if (visibleField != null) - return visibleField; - if (notVisible) - return new ProblemFieldBinding(currentType, fieldName, NotVisible); - return null; - } - - // Internal use only - public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) { - if ((enclosingType.tagBits & HasNoMemberTypes) != 0) - return null; // know it has no member types (nor inherited member types) - - SourceTypeBinding enclosingSourceType = enclosingSourceType(); - PackageBinding currentPackage = getCurrentPackage(); - compilationUnitScope().recordReference(enclosingType.compoundName, typeName); - ReferenceBinding memberType = enclosingType.getMemberType(typeName); - if (memberType != null) { - compilationUnitScope().recordTypeReference(memberType); // to record supertypes - if (enclosingSourceType == null - ? memberType.canBeSeenBy(currentPackage) - : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) - return memberType; - return new ProblemReferenceBinding(typeName, memberType, NotVisible); - } - - // collect all superinterfaces of receiverType until the memberType is found in a supertype - ReferenceBinding currentType = enclosingType; - ReferenceBinding[][] interfacesToVisit = null; - int lastPosition = -1; - ReferenceBinding visibleMemberType = null; - boolean keepLooking = true; - ReferenceBinding notVisible = null; - // we could hold onto the not visible field for extra error reporting - while (keepLooking) { - ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); - if (itsInterfaces != NoSuperInterfaces) { - if (interfacesToVisit == null) - interfacesToVisit = new ReferenceBinding[5][]; - if (++lastPosition == interfacesToVisit.length) - System.arraycopy( - interfacesToVisit, - 0, - interfacesToVisit = new ReferenceBinding[lastPosition * 2][], - 0, - lastPosition); - interfacesToVisit[lastPosition] = itsInterfaces; - } - if ((currentType = currentType.superclass()) == null) - break; - - compilationUnitScope().recordReference(currentType.compoundName, typeName); - if ((memberType = currentType.getMemberType(typeName)) != null) { - compilationUnitScope().recordTypeReference(memberType); // to record supertypes - keepLooking = false; - if (enclosingSourceType == null - ? memberType.canBeSeenBy(currentPackage) - : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) { - if (visibleMemberType == null) - visibleMemberType = memberType; - else - return new ProblemReferenceBinding(typeName, Ambiguous); - } else { - notVisible = memberType; - } - } - } - // walk all visible interfaces to find ambiguous references - if (interfacesToVisit != null) { - ProblemReferenceBinding ambiguous = null; - done : for (int i = 0; i <= lastPosition; i++) { - ReferenceBinding[] interfaces = interfacesToVisit[i]; - for (int j = 0, length = interfaces.length; j < length; j++) { - ReferenceBinding anInterface = interfaces[j]; - if ((anInterface.tagBits & InterfaceVisited) == 0) { - // if interface as not already been visited - anInterface.tagBits |= InterfaceVisited; - compilationUnitScope().recordReference(anInterface.compoundName, typeName); - if ((memberType = anInterface.getMemberType(typeName)) != null) { - compilationUnitScope().recordTypeReference(memberType); // to record supertypes - if (visibleMemberType == null) { - visibleMemberType = memberType; - } else { - ambiguous = new ProblemReferenceBinding(typeName, Ambiguous); - break done; - } - } else { - ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); - if (itsInterfaces != NoSuperInterfaces) { - if (++lastPosition == interfacesToVisit.length) - System.arraycopy( - interfacesToVisit, - 0, - interfacesToVisit = new ReferenceBinding[lastPosition * 2][], - 0, - lastPosition); - interfacesToVisit[lastPosition] = itsInterfaces; - } - } - } - } - } - - // bit reinitialization - for (int i = 0; i <= lastPosition; i++) { - ReferenceBinding[] interfaces = interfacesToVisit[i]; - for (int j = 0, length = interfaces.length; j < length; j++) - interfaces[j].tagBits &= ~InterfaceVisited; - } - if (ambiguous != null) - return ambiguous; - } - if (visibleMemberType != null) - return visibleMemberType; - if (notVisible != null) - return new ProblemReferenceBinding(typeName, notVisible, NotVisible); - return null; - } - - // Internal use only - public MethodBinding findMethod( - ReferenceBinding receiverType, - char[] selector, - TypeBinding[] argumentTypes, - InvocationSite invocationSite) { - - ReferenceBinding currentType = receiverType; - MethodBinding matchingMethod = null; - ObjectVector found = new ObjectVector(); //TODO should rewrite to remove #matchingMethod since found is allocated anyway - - faultInReceiverType(receiverType); - compilationUnitScope().recordTypeReference(receiverType); - compilationUnitScope().recordTypeReferences(argumentTypes); - - if (currentType.isInterface()) { - MethodBinding[] currentMethods = currentType.getMethods(selector); - int currentLength = currentMethods.length; - if (currentLength == 1) { - matchingMethod = currentMethods[0]; - } else if (currentLength > 1) { - found.addAll(currentMethods); - } - matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod); - currentType = getJavaLangObject(); - } - - boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= ClassFileConstants.JDK1_4; - // superclass lookup - ReferenceBinding classHierarchyStart = currentType; - while (currentType != null) { - MethodBinding[] currentMethods = currentType.getMethods(selector); - int currentLength = currentMethods.length; - - /* - * if 1.4 compliant, must filter out redundant protected methods from superclasses - */ - if (isCompliant14){ - nextMethod: for (int i = 0; i < currentLength; i++){ - MethodBinding currentMethod = currentMethods[i]; - // protected method need to be checked only - default access is already dealt with in #canBeSeen implementation - // when checking that p.C -> q.B -> p.A cannot see default access members from A through B. - if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod; - if (matchingMethod != null){ - if (currentMethod.areParametersEqual(matchingMethod)){ - currentLength--; - currentMethods[i] = null; // discard this match - continue nextMethod; - } - } else { - for (int j = 0, max = found.size; j < max; j++) { - if (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){ - currentLength--; - currentMethods[i] = null; - continue nextMethod; - } - } - } - } - } - - if (currentLength == 1 && matchingMethod == null && found.size == 0) { - matchingMethod = currentMethods[0]; - } else if (currentLength > 0) { - if (matchingMethod != null) { - found.add(matchingMethod); - matchingMethod = null; - } - // append currentMethods, filtering out null entries - int maxMethod = currentMethods.length; - if (maxMethod == currentLength) { // no method was eliminated for 1.4 compliance (see above) - found.addAll(currentMethods); - } else { - for (int i = 0, max = currentMethods.length; i < max; i++) { - MethodBinding currentMethod = currentMethods[i]; - if (currentMethod != null) found.add(currentMethod); - } - } - } - currentType = currentType.superclass(); - } - - // if found several candidates, then eliminate those not matching argument types - int foundSize = found.size; - MethodBinding[] candidates = null; - int candidatesCount = 0; - boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ? - if (foundSize > 0) { - // argument type compatibility check - for (int i = 0; i < foundSize; i++) { - MethodBinding methodBinding = (MethodBinding) found.elementAt(i); - if (areParametersAssignable(methodBinding.parameters, argumentTypes)) { - switch (candidatesCount) { - case 0: - matchingMethod = methodBinding; // if only one match, reuse matchingMethod - checkedMatchingMethod = true; // matchingMethod is known to exist and match params here - break; - case 1: - candidates = new MethodBinding[foundSize]; // only lazily created if more than one match - candidates[0] = matchingMethod; // copy back - matchingMethod = null; - // fall through - default: - candidates[candidatesCount] = methodBinding; - } - candidatesCount++; - } - } - } - // if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod - if (matchingMethod != null) { - if (checkedMatchingMethod || areParametersAssignable(matchingMethod.parameters, argumentTypes)) { - // (if no default abstract) must explicitly look for one instead, which could be a better match - if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) { - // ignore matching method (to be consistent with multiple matches, none visible (matching method is then null) - MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found); - if (interfaceMethod != null) return interfaceMethod; - compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions); - return matchingMethod; - } - } - return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found); - } - - // no match was found, try to find a close match when the parameter order is wrong or missing some parameters - if (candidatesCount == 0) { - MethodBinding interfaceMethod = - findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found); - if (interfaceMethod != null) return interfaceMethod; - - int argLength = argumentTypes.length; - foundSize = found.size; - nextMethod : for (int i = 0; i < foundSize; i++) { - MethodBinding methodBinding = (MethodBinding) found.elementAt(i); - TypeBinding[] params = methodBinding.parameters; - int paramLength = params.length; - nextArg: for (int a = 0; a < argLength; a++) { - TypeBinding arg = argumentTypes[a]; - for (int p = 0; p < paramLength; p++) - if (params[p] == arg) - continue nextArg; - continue nextMethod; - } - return methodBinding; - } - return (MethodBinding) found.elementAt(0); // no good match so just use the first one found - } - - // tiebreak using visibility check - int visiblesCount = 0; - for (int i = 0; i < candidatesCount; i++) { - MethodBinding methodBinding = candidates[i]; - if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) { - if (visiblesCount != i) { - candidates[i] = null; - candidates[visiblesCount] = methodBinding; - } - visiblesCount++; - } - } - if (visiblesCount == 1) { - compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions); - return candidates[0]; - } - if (visiblesCount == 0) { - MethodBinding interfaceMethod = - findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found); - if (interfaceMethod != null) return interfaceMethod; - return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible); - } - if (isCompliant14) - return mostSpecificMethodBinding(candidates, visiblesCount); - return candidates[0].declaringClass.isClass() - ? mostSpecificClassMethodBinding(candidates, visiblesCount) - : mostSpecificInterfaceMethodBinding(candidates, visiblesCount); - } - - // Internal use only - public MethodBinding findMethodForArray( - ArrayBinding receiverType, - char[] selector, - TypeBinding[] argumentTypes, - InvocationSite invocationSite) { - - TypeBinding leafType = receiverType.leafComponentType(); - if (leafType instanceof ReferenceBinding) { - if (!((ReferenceBinding) leafType).canBeSeenBy(this)) - return new ProblemMethodBinding(selector, TypeConstants.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible); - } - - ReferenceBinding object = getJavaLangObject(); - MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes); - if (methodBinding != null) { - // handle the method clone() specially... cannot be protected or throw exceptions - if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE)) - return new UpdatedMethodBinding( - environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0 - (methodBinding.modifiers ^ AccProtected) | AccPublic, - CLONE, - methodBinding.returnType, - argumentTypes, - null, - object); - if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) - return methodBinding; - } - // answers closest approximation, may not check argumentTypes or visibility - methodBinding = findMethod(object, selector, argumentTypes, invocationSite); - if (methodBinding == null) - return new ProblemMethodBinding(selector, argumentTypes, NotFound); - if (methodBinding.isValidBinding()) { - if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) - return new ProblemMethodBinding( - methodBinding, - selector, - argumentTypes, - NotFound); - if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this)) - return new ProblemMethodBinding( - methodBinding, - selector, - methodBinding.parameters, - NotVisible); - } - return methodBinding; - } - - public MethodBinding findMethodInSuperInterfaces( - ReferenceBinding currentType, - char[] selector, - ObjectVector found, - MethodBinding matchingMethod) { - - ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); - if (itsInterfaces != NoSuperInterfaces) { - ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][]; - int lastPosition = -1; - if (++lastPosition == interfacesToVisit.length) - System.arraycopy( - interfacesToVisit, 0, - interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, - lastPosition); - interfacesToVisit[lastPosition] = itsInterfaces; - - for (int i = 0; i <= lastPosition; i++) { - ReferenceBinding[] interfaces = interfacesToVisit[i]; - for (int j = 0, length = interfaces.length; j < length; j++) { - currentType = interfaces[j]; - if ((currentType.tagBits & InterfaceVisited) == 0) { - // if interface as not already been visited - currentType.tagBits |= InterfaceVisited; - - MethodBinding[] currentMethods = currentType.getMethods(selector); - int currentLength = currentMethods.length; - if (currentLength == 1 && matchingMethod == null && found.size == 0) { - matchingMethod = currentMethods[0]; - } else if (currentLength > 0) { - if (matchingMethod != null) { - found.add(matchingMethod); - matchingMethod = null; - } - found.addAll(currentMethods); - } - itsInterfaces = currentType.superInterfaces(); - if (itsInterfaces != NoSuperInterfaces) { - if (++lastPosition == interfacesToVisit.length) - System.arraycopy( - interfacesToVisit, 0, - interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, - lastPosition); - interfacesToVisit[lastPosition] = itsInterfaces; - } - } - } - } - - // bit reinitialization - for (int i = 0; i <= lastPosition; i++) { - ReferenceBinding[] interfaces = interfacesToVisit[i]; - for (int j = 0, length = interfaces.length; j < length; j++) - interfaces[j].tagBits &= ~InterfaceVisited; - } - } - return matchingMethod; - } - - // Internal use only - public ReferenceBinding findType( - char[] typeName, - PackageBinding declarationPackage, - PackageBinding invocationPackage) { - - compilationUnitScope().recordReference(declarationPackage.compoundName, typeName); - ReferenceBinding typeBinding = declarationPackage.getType(typeName); - if (typeBinding == null) - return null; - - if (typeBinding.isValidBinding()) { - if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage)) - return new ProblemReferenceBinding(typeName, typeBinding, NotVisible); - } - return typeBinding; - } - - public LocalVariableBinding findVariable(char[] variable) { - - return null; - } - - public TypeBinding getBaseType(char[] name) { - // list should be optimized (with most often used first) - int length = name.length; - if (length > 2 && length < 8) { - switch (name[0]) { - case 'i' : - if (length == 3 && name[1] == 'n' && name[2] == 't') - return IntBinding; - break; - case 'v' : - if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd') - return VoidBinding; - break; - case 'b' : - if (length == 7 - && name[1] == 'o' - && name[2] == 'o' - && name[3] == 'l' - && name[4] == 'e' - && name[5] == 'a' - && name[6] == 'n') - return BooleanBinding; - if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e') - return ByteBinding; - break; - case 'c' : - if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r') - return CharBinding; - break; - case 'd' : - if (length == 6 - && name[1] == 'o' - && name[2] == 'u' - && name[3] == 'b' - && name[4] == 'l' - && name[5] == 'e') - return DoubleBinding; - break; - case 'f' : - if (length == 5 - && name[1] == 'l' - && name[2] == 'o' - && name[3] == 'a' - && name[4] == 't') - return FloatBinding; - break; - case 'l' : - if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') - return LongBinding; - break; - case 's' : - if (length == 5 - && name[1] == 'h' - && name[2] == 'o' - && name[3] == 'r' - && name[4] == 't') - return ShortBinding; - } - } - return null; - } - - /* API - * - * Answer the binding that corresponds to the argument name. - * flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE. - * Only bindings corresponding to the mask can be answered. - * - * For example, getBinding("foo", VARIABLE, site) will answer - * the binding for the field or local named "foo" (or an error binding if none exists). - * If a type named "foo" exists, it will not be detected (and an error binding will be answered) - * - * The VARIABLE mask has precedence over the TYPE mask. - * - * If the VARIABLE mask is not set, neither fields nor locals will be looked for. - * - * InvocationSite implements: - * isSuperAccess(); this is used to determine if the discovered field is visible. - * - * Limitations: cannot request FIELD independently of LOCAL, or vice versa - */ - public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) { - - try { - Binding binding = null; - FieldBinding problemField = null; - if ((mask & VARIABLE) != 0) { - boolean insideStaticContext = false; - boolean insideConstructorCall = false; - - FieldBinding foundField = null; - // can be a problem field which is answered if a valid field is not found - ProblemFieldBinding foundInsideProblem = null; - // inside Constructor call or inside static context - Scope scope = this; - int depth = 0; - int foundDepth = 0; - ReferenceBinding foundActualReceiverType = null; - done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found - switch (scope.kind) { - case METHOD_SCOPE : - MethodScope methodScope = (MethodScope) scope; - insideStaticContext |= methodScope.isStatic; - insideConstructorCall |= methodScope.isConstructorCall; - // Fall through... could duplicate the code below to save a cast - questionable optimization - case BLOCK_SCOPE : - LocalVariableBinding variableBinding = scope.findVariable(name); - // looks in this scope only - if (variableBinding != null) { - if (foundField != null && foundField.isValidBinding()) - return new ProblemFieldBinding( - foundField, // closest match - foundField.declaringClass, - name, - InheritedNameHidesEnclosingName); - if (depth > 0) - invocationSite.setDepth(depth); - return variableBinding; - } - break; - case CLASS_SCOPE : - ClassScope classScope = (ClassScope) scope; - SourceTypeBinding enclosingType = classScope.referenceContext.binding; - FieldBinding fieldBinding = - classScope.findField(enclosingType, name, invocationSite, needResolve); - // Use next line instead if willing to enable protected access accross inner types - // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite); - if (fieldBinding != null) { // skip it if we did not find anything - if (fieldBinding.problemId() == Ambiguous) { - if (foundField == null || foundField.problemId() == NotVisible) - // supercedes any potential InheritedNameHidesEnclosingName problem - return fieldBinding; - // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead) - return new ProblemFieldBinding( - foundField, // closest match - foundField.declaringClass, - name, - InheritedNameHidesEnclosingName); - } - - ProblemFieldBinding insideProblem = null; - if (fieldBinding.isValidBinding()) { - if (!fieldBinding.isStatic()) { - if (insideConstructorCall) { - insideProblem = - new ProblemFieldBinding( - fieldBinding, // closest match - fieldBinding.declaringClass, - name, - NonStaticReferenceInConstructorInvocation); - } else if (insideStaticContext) { - insideProblem = - new ProblemFieldBinding( - fieldBinding, // closest match - fieldBinding.declaringClass, - name, - NonStaticReferenceInStaticContext); - } - } - if (enclosingType == fieldBinding.declaringClass - || environment().options.complianceLevel >= ClassFileConstants.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( - foundField, // closest match - foundField.declaringClass, - name, - InheritedNameHidesEnclosingName); - } - } - - if (foundField == null - || (foundField.problemId() == NotVisible - && fieldBinding.problemId() != NotVisible)) { - // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is... - foundDepth = depth; - foundActualReceiverType = enclosingType; - foundInsideProblem = insideProblem; - foundField = fieldBinding; - } - } - depth++; - insideStaticContext |= enclosingType.isStatic(); - // 1EX5I8Z - accessing outer fields within a constructor call is permitted - // in order to do so, we change the flag as we exit from the type, not the method - // itself, because the class scope is used to retrieve the fields. - MethodScope enclosingMethodScope = scope.methodScope(); - insideConstructorCall = - enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall; - break; - case COMPILATION_UNIT_SCOPE : - break done; - } - scope = scope.parent; - } - - if (foundInsideProblem != null) - return foundInsideProblem; - if (foundField != null) { - if (foundField.isValidBinding()){ - if (foundDepth > 0){ - invocationSite.setDepth(foundDepth); - invocationSite.setActualReceiverType(foundActualReceiverType); - } - return foundField; - } - problemField = foundField; - } - } - - // We did not find a local or instance variable. - if ((mask & TYPE) != 0) { - if ((binding = getBaseType(name)) != null) - return binding; - binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE); - if (binding.isValidBinding() || mask == TYPE) - return binding; - // answer the problem type binding if we are only looking for a type - } else if ((mask & PACKAGE) != 0) { - compilationUnitScope().recordSimpleReference(name); - if ((binding = environment().getTopLevelPackage(name)) != null) - return binding; - } - if (problemField != null) return problemField; - return new ProblemBinding(name, enclosingSourceType(), NotFound); - - } catch (AbortCompilation e) { - e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); - throw e; - } - } - - public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) { - try { - faultInReceiverType(receiverType); - compilationUnitScope().recordTypeReference(receiverType); - compilationUnitScope().recordTypeReferences(argumentTypes); - MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes); - if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) - return methodBinding; - MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName); - 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++) - if (areParametersAssignable(methods[i].parameters, argumentTypes)) - compatible[compatibleIndex++] = methods[i]; - if (compatibleIndex == 0) - return new ProblemMethodBinding( - ConstructorDeclaration.ConstantPoolName, - argumentTypes, - NotFound); - // need a more descriptive error... cannot convert from X to Y - - MethodBinding[] visible = new MethodBinding[compatibleIndex]; - int visibleIndex = 0; - for (int i = 0; i < compatibleIndex; i++) { - MethodBinding method = compatible[i]; - if (method.canBeSeenBy(invocationSite, this)) - visible[visibleIndex++] = method; - } - if (visibleIndex == 1) return visible[0]; - if (visibleIndex == 0) - return new ProblemMethodBinding( - compatible[0], - ConstructorDeclaration.ConstantPoolName, - compatible[0].parameters, - NotVisible); - return mostSpecificClassMethodBinding(visible, visibleIndex); - } catch (AbortCompilation e) { - e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); - throw e; - } - } - - public final PackageBinding getCurrentPackage() { - Scope scope, unitScope = this; - while ((scope = unitScope.parent) != null) - unitScope = scope; - return ((CompilationUnitScope) unitScope).fPackage; - } - - /** - * Returns the modifiers of the innermost enclosing declaration. - * @return modifiers - */ - public int getDeclarationModifiers(){ - switch(this.kind){ - case Scope.BLOCK_SCOPE : - case Scope.METHOD_SCOPE : - MethodScope methodScope = methodScope(); - if (!methodScope.isInsideInitializer()){ - // check method modifiers to see if deprecated - MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding; - if (context != null) { - return context.modifiers; - } - } else { - SourceTypeBinding type = ((BlockScope)this).referenceType().binding; - - // inside field declaration ? check field modifier to see if deprecated - if (methodScope.initializedField != null) { - return methodScope.initializedField.modifiers; - } - if (type != null) { - return type.modifiers; - } - } - break; - case Scope.CLASS_SCOPE : - ReferenceBinding context = ((ClassScope)this).referenceType().binding; - if (context != null) { - return context.modifiers; - } - break; - } - return -1; - } - - public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) { - try { - FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/); - if (field != null) return field; - - return new ProblemFieldBinding( - receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null, - fieldName, - NotFound); - } catch (AbortCompilation e) { - e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); - throw e; - } - } - - /* API - * - * Answer the method binding that corresponds to selector, argumentTypes. - * Start the lookup at the enclosing type of the receiver. - * InvocationSite implements - * isSuperAccess(); this is used to determine if the discovered method is visible. - * setDepth(int); this is used to record the depth of the discovered method - * relative to the enclosing type of the receiver. (If the method is defined - * in the enclosing type of the receiver, the depth is 0; in the next enclosing - * type, the depth is 1; and so on - * - * If no visible method is discovered, an error binding is answered. - */ - public MethodBinding getImplicitMethod( - char[] selector, - TypeBinding[] argumentTypes, - InvocationSite invocationSite) { - - boolean insideStaticContext = false; - boolean insideConstructorCall = false; - MethodBinding foundMethod = null; - ProblemMethodBinding foundFuzzyProblem = null; - // the weird method lookup case (matches method name in scope, then arg types, then visibility) - ProblemMethodBinding foundInsideProblem = null; - // inside Constructor call or inside static context - Scope scope = this; - int depth = 0; - done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found - switch (scope.kind) { - case METHOD_SCOPE : - MethodScope methodScope = (MethodScope) scope; - insideStaticContext |= methodScope.isStatic; - insideConstructorCall |= methodScope.isConstructorCall; - break; - case CLASS_SCOPE : - ClassScope classScope = (ClassScope) scope; - SourceTypeBinding receiverType = classScope.referenceContext.binding; - boolean isExactMatch = true; - // retrieve an exact visible match (if possible) - MethodBinding methodBinding = - (foundMethod == null) - ? classScope.findExactMethod( - receiverType, - selector, - argumentTypes, - invocationSite) - : classScope.findExactMethod( - receiverType, - foundMethod.selector, - foundMethod.parameters, - invocationSite); - // ? findExactMethod(receiverType, selector, argumentTypes, invocationSite) - // : findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite); - if (methodBinding == null) { - // answers closest approximation, may not check argumentTypes or visibility - isExactMatch = false; - methodBinding = - classScope.findMethod(receiverType, selector, argumentTypes, invocationSite); - // methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite); - } - if (methodBinding != null) { // skip it if we did not find anything - if (methodBinding.problemId() == Ambiguous) { - if (foundMethod == null || foundMethod.problemId() == NotVisible) { - // supercedes any potential InheritedNameHidesEnclosingName problem - return methodBinding; - } - // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead) - return new ProblemMethodBinding( - methodBinding, // closest match - selector, - argumentTypes, - InheritedNameHidesEnclosingName); - } - ProblemMethodBinding fuzzyProblem = null; - ProblemMethodBinding insideProblem = null; - if (methodBinding.isValidBinding()) { - if (!isExactMatch) { - if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) { - if (foundMethod == null || foundMethod.problemId() == NotVisible){ - // inherited mismatch is reported directly, not looking at enclosing matches - 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, 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, - methodBinding.parameters, - NotVisible); - } - } - if (fuzzyProblem == null && !methodBinding.isStatic()) { - if (insideConstructorCall) { - insideProblem = - new ProblemMethodBinding( - methodBinding, // closest match - methodBinding.selector, - methodBinding.parameters, - NonStaticReferenceInConstructorInvocation); - } else if (insideStaticContext) { - insideProblem = - new ProblemMethodBinding( - methodBinding, // closest match - methodBinding.selector, - methodBinding.parameters, - NonStaticReferenceInStaticContext); - } - } - - if (receiverType == methodBinding.declaringClass - || (receiverType.getMethods(selector)) != NoMethods - || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.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, // closest match - methodBinding.selector, - methodBinding.parameters, - InheritedNameHidesEnclosingName); - } - } - - if (foundMethod == null - || (foundMethod.problemId() == NotVisible - && methodBinding.problemId() != NotVisible)) { - // only remember the methodBinding if its the first one found or the previous one was not visible & methodBinding is... - // remember that private methods are visible if defined directly by an enclosing class - if (depth > 0){ - invocationSite.setDepth(depth); - invocationSite.setActualReceiverType(receiverType); - } - foundFuzzyProblem = fuzzyProblem; - foundInsideProblem = insideProblem; - if (fuzzyProblem == null) - foundMethod = methodBinding; // only keep it if no error was found - } - } - depth++; - insideStaticContext |= receiverType.isStatic(); - // 1EX5I8Z - accessing outer fields within a constructor call is permitted - // in order to do so, we change the flag as we exit from the type, not the method - // itself, because the class scope is used to retrieve the fields. - MethodScope enclosingMethodScope = scope.methodScope(); - insideConstructorCall = - enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall; - break; - case COMPILATION_UNIT_SCOPE : - break done; - } - scope = scope.parent; - } - - if (foundFuzzyProblem != null) - return foundFuzzyProblem; - if (foundInsideProblem != null) - return foundInsideProblem; - if (foundMethod != null) - return foundMethod; - return new ProblemMethodBinding(selector, argumentTypes, NotFound); - } - - public final ReferenceBinding getJavaIoSerializable() { - compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE); - ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangAssertionError() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR); - ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR); - if (type != null) return type; - problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangClass() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS); - ReferenceBinding type = environment().getType(JAVA_LANG_CLASS); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangCloneable() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE); - ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangError() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR); - ReferenceBinding type = environment().getType(JAVA_LANG_ERROR); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangObject() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT); - ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangRuntimeException() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION); - ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangString() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING); - ReferenceBinding type = environment().getType(JAVA_LANG_STRING); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - public final ReferenceBinding getJavaLangThrowable() { - compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE); - ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE); - if (type != null) return type; - - problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation - } - - /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType. - */ - public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) { - ReferenceBinding memberType = findMemberType(typeName, enclosingType); - if (memberType != null) return memberType; - return new ProblemReferenceBinding(typeName, NotFound); - } - - public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { - try { - if (receiverType.isArrayType()) - return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite); - if (receiverType.isBaseType()) - return new ProblemMethodBinding(selector, argumentTypes, NotFound); - - ReferenceBinding currentType = (ReferenceBinding) receiverType; - if (!currentType.canBeSeenBy(this)) - return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible); - - // retrieve an exact visible match (if possible) - MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite); - if (methodBinding != null) return methodBinding; - - // answers closest approximation, may not check argumentTypes or visibility - methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite); - if (methodBinding == null) - return new ProblemMethodBinding(selector, argumentTypes, NotFound); - if (methodBinding.isValidBinding()) { - if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) - return new ProblemMethodBinding( - methodBinding, - selector, - argumentTypes, - NotFound); - if (!methodBinding.canBeSeenBy(currentType, invocationSite, this)) - return new ProblemMethodBinding( - methodBinding, - selector, - methodBinding.parameters, - NotVisible); - } - return methodBinding; - - } catch (AbortCompilation e) { - e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); - throw e; - } - } - - /* Answer the type binding that corresponds the given name, starting the lookup in the receiver. - * The name provided is a simple source name (e.g., "Object" , "Point", ...) - */ - // The return type of this method could be ReferenceBinding if we did not answer base types. - // NOTE: We could support looking for Base Types last in the search, however any code using - // this feature would be extraordinarily slow. Therefore we don't do this - public final TypeBinding getType(char[] name) { - // Would like to remove this test and require senders to specially handle base types - TypeBinding binding = getBaseType(name); - if (binding != null) return binding; - return (ReferenceBinding) getTypeOrPackage(name, TYPE); - } - - /* Answer the type binding corresponding to the compoundName. - * - * NOTE: If a problem binding is returned, senders should extract the compound name - * from the binding & not assume the problem applies to the entire compoundName. - */ - public final TypeBinding getType(char[][] compoundName) { - int typeNameLength = compoundName.length; - if (typeNameLength == 1) { - // Would like to remove this test and require senders to specially handle base types - TypeBinding binding = getBaseType(compoundName[0]); - if (binding != null) return binding; - } - - compilationUnitScope().recordQualifiedReference(compoundName); - Binding binding = - getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE); - if (binding == null) - return new ProblemReferenceBinding(compoundName[0], NotFound); - if (!binding.isValidBinding()) - return (ReferenceBinding) binding; - - int currentIndex = 1; - boolean checkVisibility = false; - if (binding instanceof PackageBinding) { - PackageBinding packageBinding = (PackageBinding) binding; - while (currentIndex < typeNameLength) { - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility - if (binding == null) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - NotFound); - if (!binding.isValidBinding()) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - binding.problemId()); - if (!(binding instanceof PackageBinding)) - break; - packageBinding = (PackageBinding) binding; - } - if (binding instanceof PackageBinding) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - NotFound); - checkVisibility = true; - } - - // binding is now a ReferenceBinding - ReferenceBinding typeBinding = (ReferenceBinding) binding; - compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes - if (checkVisibility) // handles the fall through case - if (!typeBinding.canBeSeenBy(this)) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - typeBinding, - NotVisible); - - while (currentIndex < typeNameLength) { - typeBinding = getMemberType(compoundName[currentIndex++], typeBinding); - if (!typeBinding.isValidBinding()) { - if (typeBinding instanceof ProblemReferenceBinding) { - ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding; - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - problemBinding.original, - typeBinding.problemId()); - } - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - typeBinding.problemId()); - } - } - return typeBinding; - } - - /* Internal use only - */ - final Binding getTypeOrPackage(char[] name, int mask) { - Scope scope = this; - ReferenceBinding foundType = null; - if ((mask & TYPE) == 0) { - Scope next = scope; - while ((next = scope.parent) != null) - scope = next; - } else { - done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found - switch (scope.kind) { - case METHOD_SCOPE : - case BLOCK_SCOPE : - ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only - if (localType != null) { - if (foundType != null && foundType != localType) - return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName); - return localType; - } - break; - case CLASS_SCOPE : - SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding; - // 6.5.5.1 - simple name favors member type over top-level type in same unit - ReferenceBinding memberType = findMemberType(name, sourceType); - if (memberType != null) { // skip it if we did not find anything - if (memberType.problemId() == Ambiguous) { - if (foundType == null || foundType.problemId() == NotVisible) - // supercedes any potential InheritedNameHidesEnclosingName problem - return memberType; - // make the user qualify the type, likely wants the first inherited type - return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName); - } - if (memberType.isValidBinding()) { - if (sourceType == memberType.enclosingType() - || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) { - // found a valid type in the 'immediate' scope (ie. not inherited) - // OR in 1.4 mode (inherited shadows enclosing) - if (foundType == null) - return memberType; - if (foundType.isValidBinding()) - // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited) - if (foundType != memberType) - return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName); - } - } - if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible)) - // only remember the memberType if its the first one found or the previous one was not visible & memberType is... - foundType = memberType; - } - if (CharOperation.equals(sourceType.sourceName, name)) { - if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible) - return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName); - return sourceType; - } - break; - case COMPILATION_UNIT_SCOPE : - break done; - } - scope = scope.parent; - } - if (foundType != null && foundType.problemId() != NotVisible) - return foundType; - } - - // at this point the scope is a compilation unit scope - CompilationUnitScope unitScope = (CompilationUnitScope) scope; - PackageBinding currentPackage = unitScope.fPackage; - // ask for the imports + name - if ((mask & TYPE) != 0) { - // check single type imports. - - ImportBinding[] imports = unitScope.imports; - if (imports != null) { - HashtableOfObject typeImports = unitScope.resolvedSingeTypeImports; - if (typeImports != null) { - ImportBinding typeImport = (ImportBinding) typeImports.get(name); - if (typeImport != null) { - ImportReference importReference = typeImport.reference; - if (importReference != null) importReference.used = true; - return typeImport.resolvedImport; // already know its visible - } - } else { - // walk all the imports since resolvedSingeTypeImports is not yet initialized - for (int i = 0, length = imports.length; i < length; i++) { - ImportBinding typeImport = imports[i]; - if (!typeImport.onDemand) { - if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) { - if (unitScope.resolveSingleTypeImport(typeImport) != null) { - ImportReference importReference = typeImport.reference; - if (importReference != null) importReference.used = true; - return typeImport.resolvedImport; // already know its visible - } - } - } - } - } - } - // check if the name is in the current package, skip it if its a sub-package - unitScope.recordReference(currentPackage.compoundName, name); - Binding binding = currentPackage.getTypeOrPackage(name); - if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package - - // check on demand imports - if (imports != null) { - boolean foundInImport = false; - ReferenceBinding type = null; - for (int i = 0, length = imports.length; i < length; i++) { - ImportBinding someImport = imports[i]; - if (someImport.onDemand) { - Binding resolvedImport = someImport.resolvedImport; - ReferenceBinding temp = resolvedImport instanceof PackageBinding - ? findType(name, (PackageBinding) resolvedImport, currentPackage) - : findDirectMemberType(name, (ReferenceBinding) resolvedImport); - if (temp != null) { - if (temp.isValidBinding()) { - ImportReference importReference = someImport.reference; - if (importReference != null) importReference.used = true; - if (foundInImport) - // Answer error binding -- import on demand conflict; name found in two import on demand packages. - return new ProblemReferenceBinding(name, Ambiguous); - type = temp; - foundInImport = true; - } else if (foundType == null) { - foundType = temp; - } - } - } - } - if (type != null) return type; - } - } - - unitScope.recordSimpleReference(name); - if ((mask & PACKAGE) != 0) { - PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name); - if (packageBinding != null) return packageBinding; - } - - // Answer error binding -- could not find name - if (foundType != null) return foundType; // problem type from above - return new ProblemReferenceBinding(name, NotFound); - } - - // Added for code assist... NOT Public API - public final Binding getTypeOrPackage(char[][] compoundName) { - int nameLength = compoundName.length; - if (nameLength == 1) { - TypeBinding binding = getBaseType(compoundName[0]); - if (binding != null) return binding; - } - Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE); - if (!binding.isValidBinding()) return binding; - - int currentIndex = 1; - boolean checkVisibility = false; - if (binding instanceof PackageBinding) { - PackageBinding packageBinding = (PackageBinding) binding; - - while (currentIndex < nameLength) { - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); - if (binding == null) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - NotFound); - if (!binding.isValidBinding()) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - binding.problemId()); - if (!(binding instanceof PackageBinding)) - break; - packageBinding = (PackageBinding) binding; - } - if (binding instanceof PackageBinding) return binding; - checkVisibility = true; - } - // binding is now a ReferenceBinding - ReferenceBinding typeBinding = (ReferenceBinding) binding; - if (checkVisibility) // handles the fall through case - if (!typeBinding.canBeSeenBy(this)) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - typeBinding, - NotVisible); - - while (currentIndex < nameLength) { - typeBinding = getMemberType(compoundName[currentIndex++], typeBinding); - // checks visibility - if (!typeBinding.isValidBinding()) - return new ProblemReferenceBinding( - CharOperation.subarray(compoundName, 0, currentIndex), - typeBinding.problemId()); - } - return typeBinding; - } - - /* Answer true if the scope is nested inside a given field declaration. - * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed - * e.g. during name resolution. - */ - public final boolean isDefinedInField(FieldBinding field) { - Scope scope = this; - do { - if (scope instanceof MethodScope) { - MethodScope methodScope = (MethodScope) scope; - if (methodScope.initializedField == field) return true; - } - scope = scope.parent; - } while (scope != null); - return false; - } - - /* Answer true if the scope is nested inside a given method declaration - */ - public final boolean isDefinedInMethod(MethodBinding method) { - Scope scope = this; - do { - if (scope instanceof MethodScope) { - ReferenceContext refContext = ((MethodScope) scope).referenceContext; - if (refContext instanceof AbstractMethodDeclaration - && ((AbstractMethodDeclaration)refContext).binding == method) { - return true; - } - } - scope = scope.parent; - } while (scope != null); - return false; - } - - /* Answer whether the type is defined in the same compilation unit as the receiver - */ - public final boolean isDefinedInSameUnit(ReferenceBinding type) { - // find the outer most enclosing type - ReferenceBinding enclosingType = type; - while ((type = enclosingType.enclosingType()) != null) - enclosingType = type; - - // find the compilation unit scope - Scope scope, unitScope = this; - while ((scope = unitScope.parent) != null) - unitScope = scope; - - // test that the enclosingType is not part of the compilation unit - SourceTypeBinding[] topLevelTypes = - ((CompilationUnitScope) unitScope).topLevelTypes; - for (int i = topLevelTypes.length; --i >= 0;) - if (topLevelTypes[i] == enclosingType) - return true; - return false; - } - - /* Answer true if the scope is nested inside a given type declaration - */ - public final boolean isDefinedInType(ReferenceBinding type) { - Scope scope = this; - do { - if (scope instanceof ClassScope) - if (((ClassScope) scope).referenceContext.binding == type){ - return true; - } - scope = scope.parent; - } while (scope != null); - return false; - } - - public boolean isInsideDeprecatedCode(){ - switch(this.kind){ - case Scope.BLOCK_SCOPE : - case Scope.METHOD_SCOPE : - MethodScope methodScope = methodScope(); - if (!methodScope.isInsideInitializer()){ - // check method modifiers to see if deprecated - MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding; - if (context != null && context.isViewedAsDeprecated()) { - return true; - } - } else { - SourceTypeBinding type = ((BlockScope)this).referenceType().binding; - // inside field declaration ? check field modifier to see if deprecated - if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated()) { - return true; - } - if (type != null && type.isViewedAsDeprecated()) { - return true; - } - } - break; - case Scope.CLASS_SCOPE : - ReferenceBinding context = ((ClassScope)this).referenceType().binding; - if (context != null && context.isViewedAsDeprecated()) { - return true; - } - break; - } - return false; - } - - public final MethodScope methodScope() { - Scope scope = this; - do { - if (scope instanceof MethodScope) - return (MethodScope) scope; - scope = scope.parent; - } while (scope != null); - return null; - } - - // Internal use only - /* All methods in visible are acceptable matches for the method in question... - * The methods defined by the receiver type appear before those defined by its - * superclass and so on. We want to find the one which matches best. - * - * Since the receiver type is a class, we know each method's declaring class is - * either the receiver type or one of its superclasses. It is an error if the best match - * is defined by a superclass, when a lesser match is defined by the receiver type - * or a closer superclass. - */ - protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) { - - MethodBinding method = null; - MethodBinding previous = null; - - nextVisible : for (int i = 0; i < visibleSize; i++) { - method = visible[i]; - - if (previous != null && method.declaringClass != previous.declaringClass) - break; // cannot answer a method farther up the hierarchy than the first method found - if (!method.isStatic()) previous = method; // no ambiguity for static methods - for (int j = 0; j < visibleSize; j++) { - if (i == j) continue; - MethodBinding next = visible[j]; - if (!areParametersAssignable(next.parameters, method.parameters)) - continue nextVisible; - } - compilationUnitScope().recordTypeReferences(method.thrownExceptions); - return method; - } - return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous); - } - - // Internal use only - /* All methods in visible are acceptable matches for the method in question... - * Since the receiver type is an interface, we ignore the possibility that 2 inherited - * but unrelated superinterfaces may define the same method in acceptable but - * not identical ways... we just take the best match that we find since any class which - * implements the receiver interface MUST implement all signatures for the method... - * in which case the best match is correct. - * - * NOTE: This is different than javac... in the following example, the message send of - * bar(X) in class Y is supposed to be ambiguous. But any class which implements the - * interface I MUST implement both signatures for bar. If this class was the receiver of - * the message send instead of the interface I, then no problem would be reported. - * - interface I1 { - void bar(J j); - } - interface I2 { - // void bar(J j); - void bar(Object o); - } - interface I extends I1, I2 {} - interface J {} - - class X implements J {} - - class Y extends X { - public void foo(I i, X x) { i.bar(x); } - } - */ - protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) { - MethodBinding method = null; - nextVisible : for (int i = 0; i < visibleSize; i++) { - method = visible[i]; - for (int j = 0; j < visibleSize; j++) { - if (i == j) continue; - MethodBinding next = visible[j]; - if (!areParametersAssignable(next.parameters, method.parameters)) - continue nextVisible; - } - compilationUnitScope().recordTypeReferences(method.thrownExceptions); - return method; - } - return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous); - } - - - // Internal use only - /* All methods in visible are acceptable matches for the method in question... - * Since 1.4, the inherited ambiguous case has been removed from mostSpecificClassMethodBinding - */ - protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize) { - MethodBinding method = null; - nextVisible : for (int i = 0; i < visibleSize; i++) { - method = visible[i]; - for (int j = 0; j < visibleSize; j++) { - if (i == j) continue; - MethodBinding next = visible[j]; - if (!areParametersAssignable(next.parameters, method.parameters)) - continue nextVisible; - } - compilationUnitScope().recordTypeReferences(method.thrownExceptions); - return method; - } - return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous); - } - - public final ClassScope outerMostClassScope() { - ClassScope lastClassScope = null; - Scope scope = this; - do { - if (scope instanceof ClassScope) - lastClassScope = (ClassScope) scope; - scope = scope.parent; - } while (scope != null); - return lastClassScope; // may answer null if no class around - } - - public final MethodScope outerMostMethodScope() { - MethodScope lastMethodScope = null; - Scope scope = this; - do { - if (scope instanceof MethodScope) - lastMethodScope = (MethodScope) scope; - scope = scope.parent; - } while (scope != null); - return lastMethodScope; // may answer null if no method around - } - - public abstract ProblemReporter problemReporter(); - - public final CompilationUnitDeclaration referenceCompilationUnit() { - Scope scope, unitScope = this; - while ((scope = unitScope.parent) != null) - unitScope = scope; - return ((CompilationUnitScope) unitScope).referenceContext; - } - // start position in this scope - for ordering scopes vs. variables - int startIndex() { - return 0; - } - - /** - * Returns the immediately enclosing switchCase statement (carried by closest blockScope), - */ - public CaseStatement switchCase() { - Scope scope = this; - do { - if (scope instanceof BlockScope) - return ((BlockScope) scope).switchCase; - scope = scope.parent; - } while (scope != null); - return null; - } -}