List of usage examples for org.eclipse.jdt.internal.compiler.lookup MethodBinding isValidBinding
public final boolean isValidBinding()
From source file:com.codenvy.ide.ext.java.server.internal.core.search.matching.MethodLocator.java
License:Open Source License
protected int matchMethod(MethodBinding method, boolean skipImpossibleArg) { if (!matchesName(this.pattern.selector, method.selector)) return IMPOSSIBLE_MATCH; int level = ACCURATE_MATCH; // look at return type only if declaring type is not specified if (this.pattern.declaringSimpleName == null) { // TODO (frederic) use this call to refine accuracy on return type // int newLevel = resolveLevelForType(this.pattern.returnSimpleName, this.pattern.returnQualification, this.pattern.returnTypeArguments, 0, method.returnType); int newLevel = resolveLevelForType(this.pattern.returnSimpleName, this.pattern.returnQualification, method.returnType);//from w w w .j a va 2s . c om if (level > newLevel) { if (newLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH; level = newLevel; // can only be downgraded } } // parameter types int parameterCount = this.pattern.parameterSimpleNames == null ? -1 : this.pattern.parameterSimpleNames.length; if (parameterCount > -1) { // global verification if (method.parameters == null) return INACCURATE_MATCH; if (parameterCount != method.parameters.length) return IMPOSSIBLE_MATCH; if (!method.isValidBinding() && ((ProblemMethodBinding) method).problemId() == ProblemReasons.Ambiguous) { // return inaccurate match for ambiguous call (bug 80890) return INACCURATE_MATCH; } boolean foundTypeVariable = false; // verify each parameter for (int i = 0; i < parameterCount; i++) { TypeBinding argType = method.parameters[i]; int newLevel = IMPOSSIBLE_MATCH; if (argType.isMemberType()) { // only compare source name for member type (bug 41018) newLevel = CharOperation.match(this.pattern.parameterSimpleNames[i], argType.sourceName(), this.isCaseSensitive) ? ACCURATE_MATCH : IMPOSSIBLE_MATCH; } else { // TODO (frederic) use this call to refine accuracy on parameter types // newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], this.pattern.parametersTypeArguments[i], 0, argType); newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], argType); } if (level > newLevel) { if (newLevel == IMPOSSIBLE_MATCH) { if (skipImpossibleArg) { // Do not consider match as impossible while finding declarations and source level >= 1.5 // (see bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763) newLevel = level; } else if (argType.isTypeVariable()) { newLevel = level; foundTypeVariable = true; } else { return IMPOSSIBLE_MATCH; } } level = newLevel; // can only be downgraded } } if (foundTypeVariable) { if (!method.isStatic() && !method.isPrivate()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=123836, No point in textually comparing type variables, captures etc with concrete types. MethodBinding focusMethodBinding = this.matchLocator.getMethodBinding(this.pattern); if (focusMethodBinding != null) { if (matchOverriddenMethod(focusMethodBinding.declaringClass, focusMethodBinding, method)) { return ACCURATE_MATCH; } } } return IMPOSSIBLE_MATCH; } } return level; }
From source file:org.eclipse.che.jdt.internal.core.search.indexing.SourceIndexer.java
License:Open Source License
public void indexResolvedDocument() { try {/*from ww w .j a va2 s. co m*/ if (DEBUG) System.out.println(new String(this.cud.compilationResult.fileName) + ':'); for (int i = 0, length = this.cud.functionalExpressionsCount; i < length; i++) { FunctionalExpression expression = this.cud.functionalExpressions[i]; if (expression instanceof LambdaExpression) { LambdaExpression lambdaExpression = (LambdaExpression) expression; if (lambdaExpression.binding != null && lambdaExpression.binding.isValidBinding()) { final char[] superinterface = lambdaExpression.resolvedType.sourceName(); if (DEBUG) { System.out.println('\t' + new String(superinterface) + '.' + new String(lambdaExpression.descriptor.selector) + "-> {}"); //$NON-NLS-1$ } SourceIndexer.this.addIndexEntry(IIndexConstants.METHOD_DECL, MethodPattern.createIndexKey(lambdaExpression.descriptor.selector, lambdaExpression.descriptor.parameters.length)); addClassDeclaration(0, // most entries are blank, that is fine, since lambda type/method cannot be searched. CharOperation.NO_CHAR, // package name ONE_ZERO, ONE_ZERO_CHAR, // enclosing types. CharOperation.NO_CHAR, // super class new char[][] { superinterface }, CharOperation.NO_CHAR_CHAR, true); // not primary. } else { if (DEBUG) System.out.println("\tnull/bad binding in lambda"); //$NON-NLS-1$ } } else { ReferenceExpression referenceExpression = (ReferenceExpression) expression; if (referenceExpression.isArrayConstructorReference()) continue; MethodBinding binding = referenceExpression.getMethodBinding(); if (binding != null && binding.isValidBinding()) { if (DEBUG) { System.out .println('\t' + new String(referenceExpression.resolvedType.sourceName()) + "::" //$NON-NLS-1$ + new String(referenceExpression.descriptor.selector) + " == " + new String(binding.declaringClass.sourceName()) + '.' + //$NON-NLS-1$ new String(binding.selector)); } if (referenceExpression.isMethodReference()) SourceIndexer.this.addMethodReference(binding.selector, binding.parameters.length); else SourceIndexer.this.addConstructorReference(binding.declaringClass.sourceName(), binding.parameters.length); } else { if (DEBUG) System.out.println("\tnull/bad binding in reference expression"); //$NON-NLS-1$ } } } } catch (Exception e) { if (JobManager.VERBOSE) { e.printStackTrace(); } } }
From source file:org.eclipse.che.jdt.internal.core.search.matching.MethodLocator.java
License:Open Source License
protected int resolveLevel(ReferenceExpression referenceExpression) { MethodBinding method = referenceExpression.getMethodBinding(); if (method == null || !method.isValidBinding()) return INACCURATE_MATCH; int methodLevel = matchMethod(method, false); if (methodLevel == IMPOSSIBLE_MATCH) { if (method != method.original()) methodLevel = matchMethod(method.original(), false); if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH; method = method.original();/* w ww. jav a 2s . com*/ } // receiver type if (this.pattern.declaringSimpleName == null && this.pattern.declaringQualification == null) return methodLevel; // since any declaring class will do int declaringLevel = resolveLevelForType(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass); return (methodLevel & MATCH_LEVEL_MASK) > (declaringLevel & MATCH_LEVEL_MASK) ? declaringLevel : methodLevel; // return the weaker match }
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
/** * Internal use only//from ww w .j a v a 2 s .c om * Given a method, returns null if arguments cannot be converted to parameters. * Will answer a substituted method in case the method was generic and type inference got triggered; * in case the method was originally compatible, then simply answer it back. */ protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite) { TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments(); TypeBinding[] parameters = method.parameters; TypeVariableBinding[] typeVariables = method.typeVariables; if (parameters == arguments && (method.returnType.tagBits & TagBits.HasTypeVariable) == 0 && genericTypeArguments == null && typeVariables == Binding.NO_TYPE_VARIABLES) return method; int argLength = arguments.length; int paramLength = parameters.length; boolean isVarArgs = method.isVarargs(); if (argLength != paramLength) if (!isVarArgs || argLength < paramLength - 1) return null; // incompatible // https://bugs.eclipse.org/bugs/show_bug.cgi?id=330435, inference should kick in only at source 1.5+ if (typeVariables != Binding.NO_TYPE_VARIABLES && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // generic method TypeBinding[] newArgs = null; for (int i = 0; i < argLength; i++) { TypeBinding param = i < paramLength ? parameters[i] : parameters[paramLength - 1]; if (arguments[i].isBaseType() != param.isBaseType()) { if (newArgs == null) { newArgs = new TypeBinding[argLength]; System.arraycopy(arguments, 0, newArgs, 0, argLength); } newArgs[i] = environment().computeBoxingType(arguments[i]); } } if (newArgs != null) arguments = newArgs; method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite); if (method == null) return null; // incompatible if (!method.isValidBinding()) return method; // bound check issue is taking precedence } else if (genericTypeArguments != null && compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) { if (method instanceof ParameterizedGenericMethodBinding) { if (!((ParameterizedGenericMethodBinding) method).wasInferred) // attempt to invoke generic method of raw type with type hints <String>foo() return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.TypeArgumentsForRawGenericMethod); } else if (!method.isOverriding() || !isOverriddenMethodGeneric(method)) { return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.TypeParameterArityMismatch); } } if (parameterCompatibilityLevel(method, arguments) > NOT_COMPATIBLE) { if ((method.tagBits & TagBits.AnnotationPolymorphicSignature) != 0) { // generate polymorphic method return this.environment().createPolymorphicMethod(method, arguments); } return method; } // if method is generic and type arguments have been supplied, only then answer a problem // of ParameterizedMethodTypeMismatch, else a non-generic method was invoked using type arguments // in which case this problem category will be bogus if (genericTypeArguments != null && typeVariables != Binding.NO_TYPE_VARIABLES) return new ProblemMethodBinding(method, method.selector, arguments, ProblemReasons.ParameterizedMethodTypeMismatch); return null; // incompatible }
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
protected MethodBinding findDefaultAbstractMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite, ReferenceBinding classHierarchyStart, ObjectVector found, MethodBinding concreteMatch) { int startFoundSize = found.size; ReferenceBinding currentType = classHierarchyStart; while (currentType != null) { findMethodInSuperInterfaces(currentType, selector, found, invocationSite); currentType = currentType.superclass(); }//from ww w. j a v a 2 s. co m MethodBinding[] candidates = null; int candidatesCount = 0; MethodBinding problemMethod = null; int foundSize = found.size; if (foundSize > startFoundSize) { // argument type compatibility check for (int i = startFoundSize; i < foundSize; i++) { MethodBinding methodBinding = (MethodBinding) found.elementAt(i); MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) { if (concreteMatch != null && environment().methodVerifier() .areMethodsCompatible(concreteMatch, compatibleMethod)) continue; // can skip this method since concreteMatch overrides it if (candidatesCount == 0) { candidates = new MethodBinding[foundSize - startFoundSize + 1]; if (concreteMatch != null) candidates[candidatesCount++] = concreteMatch; } candidates[candidatesCount++] = compatibleMethod; } else if (problemMethod == null) { problemMethod = compatibleMethod; } } } } if (candidatesCount < 2) { if (concreteMatch == null) { if (candidatesCount == 0) return problemMethod; // can be null concreteMatch = candidates[0]; } compilationUnitScope().recordTypeReferences(concreteMatch.thrownExceptions); return concreteMatch; } // no need to check for visibility - interface methods are public if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite, receiverType); return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite); }
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(); }//from w w w . j av a2 s . c om // 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 getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; try {//from www . ja v a2 s . c o m env.missingClassFileLocation = invocationSite; unitScope.recordTypeReference(receiverType); unitScope.recordTypeReferences(argumentTypes); MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes); if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) { // targeting a non generic constructor with type arguments ? if (invocationSite.genericTypeArguments() != null) methodBinding = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite); return methodBinding; } MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT, argumentTypes.length); if (methods == Binding.NO_METHODS) return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound); MethodBinding[] compatible = new MethodBinding[methods.length]; int compatibleIndex = 0; MethodBinding problemMethod = null; for (int i = 0, length = methods.length; i < length; i++) { MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) compatible[compatibleIndex++] = compatibleMethod; else if (problemMethod == null) problemMethod = compatibleMethod; } } if (compatibleIndex == 0) { if (problemMethod == null) return new ProblemMethodBinding(methods[0], TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound); return problemMethod; } // 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], TypeConstants.INIT, compatible[0].parameters, ProblemReasons.NotVisible); // all of visible are from the same declaringClass, even before 1.4 we can call this method instead of mostSpecificClassMethodBinding return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite, receiverType); } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } }
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;//from w ww . jav a2s.c om 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); }
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; try {//ww w . j a v a 2 s. co m env.missingClassFileLocation = invocationSite; switch (receiverType.kind()) { case Binding.BASE_TYPE: return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); case Binding.ARRAY_TYPE: unitScope.recordTypeReference(receiverType); return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite); } unitScope.recordTypeReference(receiverType); ReferenceBinding currentType = (ReferenceBinding) receiverType; if (!currentType.canBeSeenBy(this)) return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.ReceiverTypeNotVisible); // retrieve an exact visible match (if possible) MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite); if (methodBinding != null) return methodBinding; methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite); // GROOVY start: give it one more chance as the ast transform may have introduced it // is this the right approach? Requires ast transforms running before this is done if (methodBinding == null) { methodBinding = oneLastLook(currentType, selector, argumentTypes, invocationSite); } // GROOVY end if (methodBinding == null) return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); if (!methodBinding.isValidBinding()) return methodBinding; // 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; } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } }
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, final InvocationSite invocationSite, ReferenceBinding receiverType) { int[] compatibilityLevels = new int[visibleSize]; for (int i = 0; i < visibleSize; i++) compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes); InvocationSite tieBreakInvocationSite = new InvocationSite() { public TypeBinding[] genericTypeArguments() { return null; } // ignore genericTypeArgs public boolean isSuperAccess() { return invocationSite.isSuperAccess(); }//from w w w .j av a2 s .c o m public boolean isTypeAccess() { return invocationSite.isTypeAccess(); } public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */} public void setDepth(int depth) { /* ignore */} public void setFieldIndex(int depth) { /* ignore */} public int sourceStart() { return invocationSite.sourceStart(); } public int sourceEnd() { return invocationSite.sourceStart(); } public TypeBinding expectedType() { return invocationSite.expectedType(); } }; MethodBinding[] moreSpecific = new MethodBinding[visibleSize]; int count = 0; for (int level = 0, max = VARARGS_COMPATIBLE; level <= max; level++) { nextVisible: for (int i = 0; i < visibleSize; i++) { if (compatibilityLevels[i] != level) continue nextVisible; max = level; // do not examine further categories, will either return mostSpecific or report ambiguous case MethodBinding current = visible[i]; MethodBinding original = current.original(); MethodBinding tiebreakMethod = current.tiebreakMethod(); for (int j = 0; j < visibleSize; j++) { if (i == j || compatibilityLevels[j] != level) continue; MethodBinding next = visible[j]; if (original == next.original()) { // parameterized superclasses & interfaces may be walked twice from different paths so skip next from now on compatibilityLevels[j] = -1; continue; } MethodBinding methodToTest = next; if (next instanceof ParameterizedGenericMethodBinding) { ParameterizedGenericMethodBinding pNext = (ParameterizedGenericMethodBinding) next; if (pNext.isRaw && !pNext.isStatic()) { // hold onto the raw substituted method } else { methodToTest = pNext.originalMethod; } } MethodBinding acceptable = computeCompatibleMethod(methodToTest, tiebreakMethod.parameters, tieBreakInvocationSite); /* There are 4 choices to consider with current & next : foo(B) & foo(A) where B extends A 1. the 2 methods are equal (both accept each others parameters) -> want to continue 2. current has more specific parameters than next (so acceptable is a valid method) -> want to continue 3. current has less specific parameters than next (so acceptable is null) -> go on to next 4. current and next are not compatible with each other (so acceptable is null) -> go on to next */ if (acceptable == null || !acceptable.isValidBinding()) continue nextVisible; if (!isAcceptableMethod(tiebreakMethod, acceptable)) continue nextVisible; // pick a concrete method over a bridge method when parameters are equal since the return type of the concrete method is more specific if (current.isBridge() && !next.isBridge()) if (tiebreakMethod.areParametersEqual(acceptable)) continue nextVisible; // skip current so acceptable wins over this bridge method } moreSpecific[i] = current; count++; } } if (count == 1) { for (int i = 0; i < visibleSize; i++) { if (moreSpecific[i] != null) { compilationUnitScope().recordTypeReferences(visible[i].thrownExceptions); return visible[i]; } } } else if (count == 0) { return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous); } // found several methods that are mutually acceptable -> must be equal // so now with the first acceptable method, find the 'correct' inherited method for each other acceptable method AND // see if they are equal after substitution of type variables (do the type variables have to be equal to be considered an override???) if (receiverType != null) receiverType = receiverType instanceof CaptureBinding ? receiverType : (ReferenceBinding) receiverType.erasure(); nextSpecific: for (int i = 0; i < visibleSize; i++) { MethodBinding current = moreSpecific[i]; if (current != null) { ReferenceBinding[] mostSpecificExceptions = null; MethodBinding original = current.original(); boolean shouldIntersectExceptions = original.declaringClass.isAbstract() && original.thrownExceptions != Binding.NO_EXCEPTIONS; // only needed when selecting from interface methods for (int j = 0; j < visibleSize; j++) { MethodBinding next = moreSpecific[j]; if (next == null || i == j) continue; MethodBinding original2 = next.original(); if (original.declaringClass == original2.declaringClass) break nextSpecific; // duplicates thru substitution if (!original.isAbstract()) { if (original2.isAbstract()) continue; // only compare current against other concrete methods original2 = original.findOriginalInheritedMethod(original2); if (original2 == null) continue nextSpecific; // current's declaringClass is not a subtype of next's declaringClass if (current.hasSubstitutedParameters() || original.typeVariables != Binding.NO_TYPE_VARIABLES) { if (!environment().methodVerifier().isParameterSubsignature(original, original2)) continue nextSpecific; // current does not override next } } else if (receiverType != null) { // should not be null if original isAbstract, but be safe TypeBinding superType = receiverType .findSuperTypeOriginatingFrom(original.declaringClass.erasure()); if (original.declaringClass == superType || !(superType instanceof ReferenceBinding)) { // keep original } else { // must find inherited method with the same substituted variables MethodBinding[] superMethods = ((ReferenceBinding) superType) .getMethods(original.selector, argumentTypes.length); for (int m = 0, l = superMethods.length; m < l; m++) { if (superMethods[m].original() == original) { original = superMethods[m]; break; } } } superType = receiverType.findSuperTypeOriginatingFrom(original2.declaringClass.erasure()); if (original2.declaringClass == superType || !(superType instanceof ReferenceBinding)) { // keep original2 } else { // must find inherited method with the same substituted variables MethodBinding[] superMethods = ((ReferenceBinding) superType) .getMethods(original2.selector, argumentTypes.length); for (int m = 0, l = superMethods.length; m < l; m++) { if (superMethods[m].original() == original2) { original2 = superMethods[m]; break; } } } if (original.typeVariables != Binding.NO_TYPE_VARIABLES) original2 = original.computeSubstitutedMethod(original2, environment()); if (original2 == null || !original.areParameterErasuresEqual(original2)) continue nextSpecific; // current does not override next if (original.returnType != original2.returnType) { if (next.original().typeVariables != Binding.NO_TYPE_VARIABLES) { if (original.returnType.erasure() .findSuperTypeOriginatingFrom(original2.returnType.erasure()) == null) continue nextSpecific; } else if (!current.returnType.isCompatibleWith(next.returnType)) { continue nextSpecific; } // continue with original 15.12.2.5 } if (shouldIntersectExceptions && original2.declaringClass.isInterface()) { if (current.thrownExceptions != next.thrownExceptions) { if (next.thrownExceptions == Binding.NO_EXCEPTIONS) { mostSpecificExceptions = Binding.NO_EXCEPTIONS; } else { if (mostSpecificExceptions == null) { mostSpecificExceptions = current.thrownExceptions; } int mostSpecificLength = mostSpecificExceptions.length; int nextLength = next.thrownExceptions.length; SimpleSet temp = new SimpleSet(mostSpecificLength); boolean changed = false; nextException: for (int t = 0; t < mostSpecificLength; t++) { ReferenceBinding exception = mostSpecificExceptions[t]; for (int s = 0; s < nextLength; s++) { ReferenceBinding nextException = next.thrownExceptions[s]; if (exception.isCompatibleWith(nextException)) { temp.add(exception); continue nextException; } else if (nextException.isCompatibleWith(exception)) { temp.add(nextException); changed = true; continue nextException; } else { changed = true; } } } if (changed) { mostSpecificExceptions = temp.elementSize == 0 ? Binding.NO_EXCEPTIONS : new ReferenceBinding[temp.elementSize]; temp.asArray(mostSpecificExceptions); } } } } } } if (mostSpecificExceptions != null && mostSpecificExceptions != current.thrownExceptions) { return new MostSpecificExceptionMethodBinding(current, mostSpecificExceptions); } return current; } } // if all moreSpecific methods are equal then see if duplicates exist because of substitution return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous); }