List of usage examples for org.eclipse.jdt.internal.compiler.lookup MethodBinding canBeSeenBy
public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope)
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
public MethodBinding findExactMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordTypeReferences(argumentTypes); MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope); if (exactMethod != null && exactMethod.typeVariables == Binding.NO_TYPE_VARIABLES && !exactMethod.isBridge()) { // in >= 1.5 mode, ensure the exactMatch did not match raw types if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) for (int i = argumentTypes.length; --i >= 0;) if (isPossibleSubtypeOfRawType(argumentTypes[i])) return null; // must find both methods for this case: <S extends A> void foo() {} and <N extends B> N foo() { return null; } // or find an inherited method when the exact match is to a bridge method unitScope.recordTypeReferences(exactMethod.thrownExceptions); if (exactMethod.isAbstract() && exactMethod.thrownExceptions != Binding.NO_EXCEPTIONS) return null; // may need to merge exceptions with interface method // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) { if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, TypeConstants.GETCLASS) && exactMethod.returnType.isParameterizedType()/*1.5*/) { return environment().createGetClassMethod(receiverType, exactMethod, this); }//from w w w . jav a 2 s .c o m // targeting a generic method could find an exact match with variable return type if (invocationSite.genericTypeArguments() != null) { exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite); } return exactMethod; } } return null; }
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite, boolean inStaticContext) { ReferenceBinding currentType = receiverType; boolean receiverTypeIsInterface = receiverType.isInterface(); ObjectVector found = new ObjectVector(3); CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordTypeReferences(argumentTypes); if (receiverTypeIsInterface) { unitScope.recordTypeReference(receiverType); MethodBinding[] receiverMethods = receiverType.getMethods(selector, argumentTypes.length); if (receiverMethods.length > 0) found.addAll(receiverMethods); findMethodInSuperInterfaces(receiverType, selector, found, invocationSite); currentType = getJavaLangObject(); }// w w w. j a v a2 s . c o m // superclass lookup long complianceLevel = compilerOptions().complianceLevel; boolean isCompliant14 = complianceLevel >= ClassFileConstants.JDK1_4; boolean isCompliant15 = complianceLevel >= ClassFileConstants.JDK1_5; ReferenceBinding classHierarchyStart = currentType; MethodVerifier verifier = environment().methodVerifier(); while (currentType != null) { unitScope.recordTypeReference(currentType); currentType = (ReferenceBinding) currentType.capture(this, invocationSite == null ? 0 : invocationSite.sourceEnd()); MethodBinding[] currentMethods = currentType.getMethods(selector, argumentTypes.length); int currentLength = currentMethods.length; if (currentLength > 0) { if (isCompliant14 && (receiverTypeIsInterface || found.size > 0)) { nextMethod: for (int i = 0, l = currentLength; i < l; i++) { // currentLength can be modified inside the loop MethodBinding currentMethod = currentMethods[i]; if (currentMethod == null) continue nextMethod; if (receiverTypeIsInterface && !currentMethod.isPublic()) { // only public methods from Object are visible to interface receiverTypes currentLength--; currentMethods[i] = null; continue nextMethod; } // if 1.4 compliant, must filter out redundant protected methods from superclasses // 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; // BUT we can also ignore any overridden method since we already know the better match (fixes 80028) for (int j = 0, max = found.size; j < max; j++) { MethodBinding matchingMethod = (MethodBinding) found.elementAt(j); MethodBinding matchingOriginal = matchingMethod.original(); MethodBinding currentOriginal = matchingOriginal .findOriginalInheritedMethod(currentMethod); if (currentOriginal != null && verifier.isParameterSubsignature(matchingOriginal, currentOriginal)) { if (isCompliant15) { if (matchingMethod.isBridge() && !currentMethod.isBridge()) continue nextMethod; // keep inherited methods to find concrete method over a bridge method } currentLength--; currentMethods[i] = null; continue nextMethod; } } } } if (currentLength > 0) { // append currentMethods, filtering out null entries if (currentMethods.length == currentLength) { 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; MethodBinding problemMethod = null; boolean searchForDefaultAbstractMethod = isCompliant14 && !receiverTypeIsInterface && (receiverType.isAbstract() || receiverType.isTypeVariable()); if (foundSize > 0) { // argument type compatibility check for (int i = 0; i < foundSize; i++) { MethodBinding methodBinding = (MethodBinding) found.elementAt(i); MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) { if (foundSize == 1 && compatibleMethod.canBeSeenBy(receiverType, invocationSite, this)) { // return the single visible match now if (searchForDefaultAbstractMethod) return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, compatibleMethod); unitScope.recordTypeReferences(compatibleMethod.thrownExceptions); return compatibleMethod; } if (candidatesCount == 0) candidates = new MethodBinding[foundSize]; candidates[candidatesCount++] = compatibleMethod; } else if (problemMethod == null) { problemMethod = compatibleMethod; } } } } // no match was found if (candidatesCount == 0) { if (problemMethod != null) { switch (problemMethod.problemId()) { case ProblemReasons.TypeArgumentsForRawGenericMethod: case ProblemReasons.TypeParameterArityMismatch: return problemMethod; } } // abstract classes may get a match in interfaces; for non abstract // classes, reduces secondary errors since missing interface method // error is already reported MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); if (interfaceMethod != null) return interfaceMethod; if (found.size == 0) return null; if (problemMethod != null) return problemMethod; // still no match; try to find a close match when the parameter // order is wrong or missing some parameters // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=69471 // bad guesses are foo(), when argument types have been supplied // and foo(X, Y), when the argument types are (int, float, Y) // so answer the method with the most argType matches and least parameter type mismatches int bestArgMatches = -1; MethodBinding bestGuess = (MethodBinding) found.elementAt(0); // if no good match so just use the first one found 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; int argMatches = 0; next: for (int a = 0; a < argLength; a++) { TypeBinding arg = argumentTypes[a]; for (int p = a == 0 ? 0 : a - 1; p < paramLength && p < a + 1; p++) { // look one slot before & after to see if the type matches if (params[p] == arg) { argMatches++; continue next; } } } if (argMatches < bestArgMatches) continue nextMethod; if (argMatches == bestArgMatches) { int diff1 = paramLength < argLength ? 2 * (argLength - paramLength) : paramLength - argLength; int bestLength = bestGuess.parameters.length; int diff2 = bestLength < argLength ? 2 * (argLength - bestLength) : bestLength - argLength; if (diff1 >= diff2) continue nextMethod; } bestArgMatches = argMatches; bestGuess = methodBinding; } return new ProblemMethodBinding(bestGuess, bestGuess.selector, argumentTypes, ProblemReasons.NotFound); } // tiebreak using visibility check int visiblesCount = 0; if (receiverTypeIsInterface) { if (candidatesCount == 1) { unitScope.recordTypeReferences(candidates[0].thrownExceptions); return candidates[0]; } visiblesCount = candidatesCount; } else { 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++; } } switch (visiblesCount) { case 0: MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); if (interfaceMethod != null) return interfaceMethod; return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, ProblemReasons.NotVisible); case 1: if (searchForDefaultAbstractMethod) return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, candidates[0]); unitScope.recordTypeReferences(candidates[0].thrownExceptions); return candidates[0]; default: break; } } if (complianceLevel <= ClassFileConstants.JDK1_3) { ReferenceBinding declaringClass = candidates[0].declaringClass; return !declaringClass.isInterface() ? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite) : mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite); } // check for duplicate parameterized methods if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { for (int i = 0; i < visiblesCount; i++) { MethodBinding candidate = candidates[i]; if (candidate instanceof ParameterizedGenericMethodBinding) candidate = ((ParameterizedGenericMethodBinding) candidate).originalMethod; if (candidate.hasSubstitutedParameters()) { for (int j = i + 1; j < visiblesCount; j++) { MethodBinding otherCandidate = candidates[j]; if (otherCandidate.hasSubstitutedParameters()) { if (otherCandidate == candidate || (candidate.declaringClass == otherCandidate.declaringClass && candidate.areParametersEqual(otherCandidate))) { return new ProblemMethodBinding(candidates[i], candidates[i].selector, candidates[i].parameters, ProblemReasons.Ambiguous); } } } } } } if (inStaticContext) { MethodBinding[] staticCandidates = new MethodBinding[visiblesCount]; int staticCount = 0; for (int i = 0; i < visiblesCount; i++) if (candidates[i].isStatic()) staticCandidates[staticCount++] = candidates[i]; if (staticCount == 1) return staticCandidates[0]; if (staticCount > 1) return mostSpecificMethodBinding(staticCandidates, staticCount, argumentTypes, invocationSite, receiverType); } MethodBinding mostSpecificMethod = mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite, receiverType); if (searchForDefaultAbstractMethod) { // search interfaces for a better match if (mostSpecificMethod.isValidBinding()) // see if there is a better match in the interfaces - see AutoBoxingTest 99, LookupTest#81 return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, mostSpecificMethod); // see if there is a match in the interfaces - see LookupTest#84 MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); if (interfaceMethod != null && interfaceMethod.isValidBinding() /* else return the same error as before */) return interfaceMethod; } return mostSpecificMethod; }
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
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, Binding.NO_PARAMETERS, (ReferenceBinding) leafType, ProblemReasons.ReceiverTypeNotVisible); }//from w ww.j av a2 s . c o m ReferenceBinding object = getJavaLangObject(); MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes, null); if (methodBinding != null) { // handle the method clone() specially... cannot be protected or throw exceptions if (argumentTypes == Binding.NO_PARAMETERS) { switch (selector[0]) { case 'c': if (CharOperation.equals(selector, TypeConstants.CLONE)) { return environment().computeArrayClone(methodBinding); } break; case 'g': if (CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return environment().createGetClassMethod(receiverType, methodBinding, this); } break; } } if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) return methodBinding; } methodBinding = findMethod(object, selector, argumentTypes, invocationSite); if (methodBinding == null) return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); return methodBinding; }
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { boolean insideStaticContext = false; boolean insideConstructorCall = false; boolean insideTypeAnnotation = false; MethodBinding foundMethod = null;// w ww . j ava 2 s . co m MethodBinding foundProblem = null; boolean foundProblemVisible = false; Scope scope = this; int depth = 0; // in 1.4 mode (inherited visible shadows enclosing) CompilerOptions options; boolean inheritedHasPrecedence = (options = compilerOptions()).complianceLevel >= ClassFileConstants.JDK1_4; 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; insideTypeAnnotation = methodScope.insideTypeAnnotation; break; case CLASS_SCOPE: ClassScope classScope = (ClassScope) scope; ReferenceBinding receiverType = classScope.enclosingReceiverType(); if (!insideTypeAnnotation) { // retrieve an exact visible match (if possible) // compilationUnitScope().recordTypeReference(receiverType); not needed since receiver is the source type MethodBinding methodBinding = classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite); if (methodBinding == null) methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite); if (methodBinding != null) { // skip it if we did not find anything if (foundMethod == null) { if (methodBinding.isValidBinding()) { if (!methodBinding.isStatic() && (insideConstructorCall || insideStaticContext)) { if (foundProblem != null && foundProblem.problemId() != ProblemReasons.NotVisible) return foundProblem; // takes precedence return new ProblemMethodBinding(methodBinding, // closest match methodBinding.selector, methodBinding.parameters, insideConstructorCall ? ProblemReasons.NonStaticReferenceInConstructorInvocation : ProblemReasons.NonStaticReferenceInStaticContext); } if (inheritedHasPrecedence || receiverType == methodBinding.declaringClass || (receiverType.getMethods(selector)) != Binding.NO_METHODS) { // found a valid method in the 'immediate' scope (i.e. not inherited) // OR in 1.4 mode (inherited visible shadows enclosing) // OR the receiverType implemented a method with the correct name // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited) if (foundProblemVisible) { return foundProblem; } if (depth > 0) { invocationSite.setDepth(depth); invocationSite.setActualReceiverType(receiverType); } // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return environment().createGetClassMethod(receiverType, methodBinding, this); } return methodBinding; } if (foundProblem == null || foundProblem.problemId() == ProblemReasons.NotVisible) { if (foundProblem != null) foundProblem = null; // only remember the methodBinding if its the first one found // remember that private methods are visible if defined directly by an enclosing class if (depth > 0) { invocationSite.setDepth(depth); invocationSite.setActualReceiverType(receiverType); } foundMethod = methodBinding; } } else { // methodBinding is a problem method if (methodBinding.problemId() != ProblemReasons.NotVisible && methodBinding.problemId() != ProblemReasons.NotFound) return methodBinding; // return the error now if (foundProblem == null) { foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible } if (!foundProblemVisible && methodBinding.problemId() == ProblemReasons.NotFound) { MethodBinding closestMatch = ((ProblemMethodBinding) methodBinding).closestMatch; if (closestMatch != null && closestMatch.canBeSeenBy(receiverType, invocationSite, this)) { foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible foundProblemVisible = true; } } } } else { // found a valid method so check to see if this is a hiding case if (methodBinding.problemId() == ProblemReasons.Ambiguous || (foundMethod.declaringClass != methodBinding.declaringClass && (receiverType == methodBinding.declaringClass || receiverType.getMethods(selector) != Binding.NO_METHODS))) // ambiguous case -> must qualify the method (javac generates an ambiguous error instead) // otherwise 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 return new ProblemMethodBinding(methodBinding, // closest match selector, argumentTypes, ProblemReasons.InheritedNameHidesEnclosingName); } } } insideTypeAnnotation = false; 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 (insideStaticContext && options.sourceLevel >= ClassFileConstants.JDK1_5) { if (foundProblem != null) { if (foundProblem.declaringClass != null && foundProblem.declaringClass.id == TypeIds.T_JavaLangObject) return foundProblem; // static imports lose to methods from Object if (foundProblem.problemId() == ProblemReasons.NotFound && foundProblemVisible) { return foundProblem; // visible method selectors take precedence } } // at this point the scope is a compilation unit scope & need to check for imported static methods CompilationUnitScope unitScope = (CompilationUnitScope) scope; unitScope.faultInImports(); // field constants can cause static imports to be accessed before they're resolved ImportBinding[] imports = unitScope.imports; if (imports != null) { ObjectVector visible = null; boolean skipOnDemand = false; // set to true when matched static import of method name so stop looking for on demand methods for (int i = 0, length = imports.length; i < length; i++) { ImportBinding importBinding = imports[i]; if (importBinding.isStatic()) { Binding resolvedImport = importBinding.resolvedImport; MethodBinding possible = null; if (importBinding.onDemand) { if (!skipOnDemand && resolvedImport instanceof ReferenceBinding) // answers closest approximation, may not check argumentTypes or visibility possible = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite, true); } else { if (resolvedImport instanceof MethodBinding) { MethodBinding staticMethod = (MethodBinding) resolvedImport; if (CharOperation.equals(staticMethod.selector, selector)) // answers closest approximation, may not check argumentTypes or visibility possible = findMethod(staticMethod.declaringClass, selector, argumentTypes, invocationSite, true); } else if (resolvedImport instanceof FieldBinding) { // check to see if there are also methods with the same name FieldBinding staticField = (FieldBinding) resolvedImport; if (CharOperation.equals(staticField.name, selector)) { // must find the importRef's type again since the field can be from an inherited type char[][] importName = importBinding.reference.tokens; TypeBinding referencedType = getType(importName, importName.length - 1); if (referencedType != null) // answers closest approximation, may not check argumentTypes or visibility possible = findMethod((ReferenceBinding) referencedType, selector, argumentTypes, invocationSite, true); } } } if (possible != null && possible != foundProblem) { if (!possible.isValidBinding()) { if (foundProblem == null) foundProblem = possible; // answer as error case match } else if (possible.isStatic()) { MethodBinding compatibleMethod = computeCompatibleMethod(possible, argumentTypes, invocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) { if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) { if (visible == null || !visible.contains(compatibleMethod)) { ImportReference importReference = importBinding.reference; if (importReference != null) { importReference.bits |= ASTNode.Used; } if (!skipOnDemand && !importBinding.onDemand) { visible = null; // forget previous matches from on demand imports skipOnDemand = true; } if (visible == null) visible = new ObjectVector(3); visible.add(compatibleMethod); } } else if (foundProblem == null) { foundProblem = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, ProblemReasons.NotVisible); } } else if (foundProblem == null) { foundProblem = compatibleMethod; } } else if (foundProblem == null) { foundProblem = new ProblemMethodBinding(possible, selector, argumentTypes, ProblemReasons.NotFound); } } } } } if (visible != null) { MethodBinding[] temp = new MethodBinding[visible.size]; visible.copyInto(temp); foundMethod = mostSpecificMethodBinding(temp, temp.length, argumentTypes, invocationSite, null); } } } if (foundMethod != null) { invocationSite.setActualReceiverType(foundMethod.declaringClass); return foundMethod; } if (foundProblem != null) return foundProblem; return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); }