Example usage for org.eclipse.jdt.internal.compiler.lookup MethodBinding isPublic

List of usage examples for org.eclipse.jdt.internal.compiler.lookup MethodBinding isPublic

Introduction

In this page you can find the example usage for org.eclipse.jdt.internal.compiler.lookup MethodBinding isPublic.

Prototype

public final boolean isPublic() 

Source Link

Usage

From source file:com.google.gwt.dev.javac.JdtUtil.java

License:Apache License

public static String formatBinding(MethodBinding methodBinding) {
    String accessModifier = null;
    if (methodBinding.isProtected()) {
        accessModifier = "protected";
    } else if (methodBinding.isPrivate()) {
        accessModifier = "private";
    } else if (methodBinding.isPublic()) {
        accessModifier = "public";
    }/*from  w  w  w . jav  a  2s .c  o m*/
    return Joiner.on(" ").skipNulls().join(accessModifier, methodBinding.isStatic() ? "static" : null,
            getSourceName(methodBinding.declaringClass) + "." + formatMethodSignature(methodBinding));
}

From source file:com.google.gwt.dev.javac.Shared.java

License:Open Source License

public static int bindingToModifierBits(MethodBinding binding) {
    int bits = 0;
    bits |= (binding.isPublic() ? MOD_PUBLIC : 0);
    bits |= (binding.isPrivate() ? MOD_PRIVATE : 0);
    bits |= (binding.isProtected() ? MOD_PROTECTED : 0);
    bits |= (binding.isStatic() ? MOD_STATIC : 0);
    bits |= (binding.isFinal() ? MOD_FINAL : 0);
    bits |= (binding.isNative() ? MOD_NATIVE : 0);
    bits |= (binding.isAbstract() ? MOD_ABSTRACT : 0);
    return bits;/*from  ww  w . jav  a2s  .co  m*/
}

From source file:com.google.gwt.dev.jjs.ast.AccessModifier.java

License:Apache License

public static AccessModifier fromMethodBinding(MethodBinding methodBinding) {
    if (methodBinding.isPublic()) {
        return PUBLIC;
    } else if (methodBinding.isProtected()) {
        return PROTECTED;
    } else if (methodBinding.isPrivate()) {
        return PRIVATE;
    }/*ww w  .ja  v  a  2  s  .co  m*/
    assert methodBinding.isDefault();
    return DEFAULT;
}

From source file:com.google.gwt.dev.jjs.impl.BuildTypeMap.java

License:Apache License

private void processExternalMethod(MethodBinding binding, JDeclaredType type) {
    if (binding.isPrivate()
            || (type.getName().startsWith("java.") && !binding.isPublic() && !binding.isProtected())) {
        return;/*from www. j  a  v a2 s.  co  m*/
    }
    if (binding.isConstructor()) {
        processConstructor(binding, null, type.getSourceInfo());
    } else {
        createMethod(binding, type.getSourceInfo());
    }
}

From source file:com.redhat.ceylon.eclipse.core.model.mirror.JDTMethod.java

License:Open Source License

public JDTMethod(JDTClass enclosingClass, MethodBinding method) {
    this.enclosingClass = enclosingClass;
    bindingRef = new WeakReference<MethodBinding>(method);
    name = new String(method.selector);
    readableName = new String(method.readableName());
    isStatic = method.isStatic();/*from   www  . j  a  v  a2 s. c  o m*/
    isPublic = method.isPublic();
    isConstructor = method.isConstructor();
    isStaticInit = method.selector == TypeConstants.CLINIT; // TODO : check if it is right
    isAbstract = method.isAbstract();
    isFinal = method.isFinal();
    isProtected = method.isProtected();
    isDefaultAccess = method.isDefault();
    isDeclaredVoid = method.returnType.id == TypeIds.T_void;
    isVariadic = method.isVarargs();
    isDefault = method.getDefaultValue() != null;
    bindingKey = method.computeUniqueKey();
    if (method instanceof ProblemMethodBinding) {
        annotations = new HashMap<>();
        parameters = Collections.emptyList();
        returnType = JDTType.UNKNOWN_TYPE;
        typeParameters = Collections.emptyList();
        isOverriding = false;
        isOverloading = false;
    }
}

From source file:lombok.eclipse.agent.PatchDelegate.java

License:Open Source License

private static void addAllMethodBindings0(List<BindingTuple> list, TypeBinding binding, Set<String> banList,
        char[] fieldName, ASTNode responsible) throws DelegateRecursion {
    if (binding instanceof SourceTypeBinding)
        ((SourceTypeBinding) binding).scope.environment().globalOptions.storeAnnotations = true;
    if (binding == null)
        return;/*from w w w .j av  a2s  .  c  om*/

    TypeBinding inner;

    if (binding instanceof ParameterizedTypeBinding) {
        inner = ((ParameterizedTypeBinding) binding).genericType();
    } else {
        inner = binding;
    }

    if (inner instanceof SourceTypeBinding) {
        ClassScope cs = ((SourceTypeBinding) inner).scope;
        if (cs != null) {
            try {
                Reflection.classScopeBuildFieldsAndMethodsMethod.invoke(cs);
            } catch (Exception e) {
                // See 'Reflection' class for why we ignore this exception.
            }
        }
    }

    if (binding instanceof ReferenceBinding) {
        ReferenceBinding rb = (ReferenceBinding) binding;
        MethodBinding[] availableMethods = rb.availableMethods();
        FieldBinding[] availableFields = rb.availableFields();
        failIfContainsAnnotation(binding, availableMethods);
        failIfContainsAnnotation(binding, availableFields);

        MethodBinding[] parameterizedSigs = availableMethods;
        MethodBinding[] baseSigs = parameterizedSigs;
        if (binding instanceof ParameterizedTypeBinding) {
            baseSigs = ((ParameterizedTypeBinding) binding).genericType().availableMethods();
            if (baseSigs.length != parameterizedSigs.length) {
                // The last known state of eclipse source says this can't happen, so we rely on it,
                // but if this invariant is broken, better to go with 'arg0' naming instead of crashing.
                baseSigs = parameterizedSigs;
            }
        }
        for (int i = 0; i < parameterizedSigs.length; i++) {
            MethodBinding mb = parameterizedSigs[i];
            String sig = printSig(mb);
            if (mb.isStatic())
                continue;
            if (mb.isBridge())
                continue;
            if (mb.isConstructor())
                continue;
            if (mb.isDefaultAbstract())
                continue;
            if (!mb.isPublic())
                continue;
            if (mb.isSynthetic())
                continue;
            if (!banList.add(sig))
                continue; // If add returns false, it was already in there.
            BindingTuple pair = new BindingTuple(mb, baseSigs[i], fieldName, responsible);
            list.add(pair);
        }
        addAllMethodBindings0(list, rb.superclass(), banList, fieldName, responsible);
        ReferenceBinding[] interfaces = rb.superInterfaces();
        if (interfaces != null) {
            for (ReferenceBinding iface : interfaces)
                addAllMethodBindings0(list, iface, banList, fieldName, responsible);
        }
    }
}

From source file:lombok.eclipse.agent.PatchExtensionMethod.java

License:Open Source License

private static List<MethodBinding> getApplicableExtensionMethodsDefinedInProvider(EclipseNode typeNode,
        ReferenceBinding extensionMethodProviderBinding, TypeBinding receiverType) {

    List<MethodBinding> extensionMethods = new ArrayList<MethodBinding>();
    CompilationUnitScope cuScope = ((CompilationUnitDeclaration) typeNode.top().get()).scope;
    for (MethodBinding method : extensionMethodProviderBinding.methods()) {
        if (!method.isStatic())
            continue;
        if (!method.isPublic())
            continue;
        if (method.parameters == null || method.parameters.length == 0)
            continue;
        TypeBinding firstArgType = method.parameters[0];
        if (receiverType.isProvablyDistinct(firstArgType)
                && !receiverType.isCompatibleWith(firstArgType.erasure()))
            continue;
        TypeBinding[] argumentTypes = Arrays.copyOfRange(method.parameters, 1, method.parameters.length);
        if ((receiverType instanceof ReferenceBinding) && ((ReferenceBinding) receiverType)
                .getExactMethod(method.selector, argumentTypes, cuScope) != null)
            continue;
        extensionMethods.add(method);/* w  w w  . j ava2  s  . c  om*/
    }
    return extensionMethods;
}

From source file:lombok.eclipse.handlers.HandleBoundSetter.java

License:Open Source License

@Override
public void handle(final AnnotationValues<BoundSetter> annotation, final Annotation ast,
        final EclipseNode annotationNode) {
    BoundSetter annotationInstance = annotation.getInstance();
    new BoundSetterHandler<EclipseType, EclipseField, EclipseNode, ASTNode>(annotationNode, ast) {

        @Override/*from   ww w.  j  a va2s . com*/
        protected EclipseType typeOf(EclipseNode node, ASTNode ast) {
            return EclipseType.typeOf(node, ast);
        }

        @Override
        protected EclipseField fieldOf(EclipseNode node, ASTNode ast) {
            return EclipseField.fieldOf(node, ast);
        }

        @Override
        protected boolean hasMethodIncludingSupertypes(final EclipseType type, final String methodName,
                final lombok.ast.TypeRef... argumentTypes) {
            return hasMethod(type.get().binding, methodName, type.editor().build(As.list(argumentTypes)));
        }

        private boolean hasMethod(final TypeBinding binding, final String methodName,
                List<ASTNode> argumentTypes) {
            if (binding instanceof ReferenceBinding) {
                ReferenceBinding rb = (ReferenceBinding) binding;
                MethodBinding[] availableMethods = rb.availableMethods();
                for (MethodBinding method : Each.elementIn(availableMethods)) {
                    if (method.isAbstract())
                        continue;
                    if (!method.isPublic())
                        continue;
                    if (!methodName.equals(As.string(method.selector)))
                        continue;
                    if (argumentTypes.size() != As.list(method.parameters).size())
                        continue;
                    // TODO check actual types..
                    return true;
                }
                ReferenceBinding superclass = rb.superclass();
                ensureAllClassScopeMethodWereBuild(superclass);
                return hasMethod(superclass, methodName, argumentTypes);
            }
            return false;
        }

    }.handle(annotationInstance.value(), annotationInstance.vetoable(),
            annotationInstance.throwVetoException());
}

From source file:org.eclipse.jdt.internal.compiler.lookup.MethodVerifier15.java

License:Open Source License

void checkMethods() {
    boolean mustImplementAbstractMethods = mustImplementAbstractMethods();
    boolean skipInheritedMethods = mustImplementAbstractMethods && canSkipInheritedMethods(); // have a single concrete superclass so only check overridden methods
    boolean isOrEnclosedByPrivateType = this.type.isOrEnclosedByPrivateType();
    char[][] methodSelectors = this.inheritedMethods.keyTable;
    nextSelector: for (int s = methodSelectors.length; --s >= 0;) {
        if (methodSelectors[s] == null)
            continue nextSelector;

        MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]);
        MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s];

        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
        // inherited methods of super classes are too. current != null case handled below.
        if (current == null && !isOrEnclosedByPrivateType) {
            int length = inherited.length;
            for (int i = 0; i < length; i++) {
                inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
            }/*ww w. jav a  2  s  .c  om*/
        }
        if (current == null && this.type.isPublic()) {
            int length = inherited.length;
            for (int i = 0; i < length; i++) {
                MethodBinding inheritedMethod = inherited[i];
                if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic())
                    this.type.addSyntheticBridgeMethod(inheritedMethod.original());
            }
        }

        if (current == null && skipInheritedMethods)
            continue nextSelector;

        if (inherited.length == 1 && current == null) { // handle the common case
            if (mustImplementAbstractMethods && inherited[0].isAbstract())
                checkAbstractMethod(inherited[0]);
            continue nextSelector;
        }

        int index = -1;
        int inheritedLength = inherited.length;
        MethodBinding[] matchingInherited = new MethodBinding[inheritedLength];
        MethodBinding[] foundMatch = new MethodBinding[inheritedLength]; // null is no match, otherwise value is matching currentMethod
        if (current != null) {
            for (int i = 0, length1 = current.length; i < length1; i++) {
                MethodBinding currentMethod = current[i];
                MethodBinding[] nonMatchingInherited = null;
                for (int j = 0; j < inheritedLength; j++) {
                    MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod);
                    if (inheritedMethod != null) {
                        if (foundMatch[j] == null
                                && isSubstituteParameterSubsignature(currentMethod, inheritedMethod)) {
                            matchingInherited[++index] = inheritedMethod;
                            foundMatch[j] = currentMethod;
                        } else {
                            // best place to check each currentMethod against each non-matching inheritedMethod
                            checkForNameClash(currentMethod, inheritedMethod);
                            if (inheritedLength > 1) {
                                if (nonMatchingInherited == null)
                                    nonMatchingInherited = new MethodBinding[inheritedLength];
                                nonMatchingInherited[j] = inheritedMethod;
                            }
                        }
                    }
                }
                if (index >= 0) {
                    // see addtional comments in https://bugs.eclipse.org/bugs/show_bug.cgi?id=122881
                    // if (index > 0 && currentMethod.declaringClass.isInterface()) // only check when inherited methods are from interfaces
                    //   checkInheritedReturnTypes(matchingInherited, index + 1);
                    checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1,
                            nonMatchingInherited); // pass in the length of matching
                    while (index >= 0)
                        matchingInherited[index--] = null; // clear the contents of the matching methods
                }
            }
        }

        // skip tracks which inherited methods have matched other inherited methods
        // either because they match the same currentMethod or match each other
        boolean[] skip = new boolean[inheritedLength];
        for (int i = 0; i < inheritedLength; i++) {
            MethodBinding matchMethod = foundMatch[i];
            if (matchMethod == null && current != null && this.type.isPublic()) { // current == null case handled already.
                MethodBinding inheritedMethod = inherited[i];
                if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic()) {
                    this.type.addSyntheticBridgeMethod(inheritedMethod.original());
                }
            }
            // https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
            // inherited methods of super classes are too. current == null case handled already.
            if (!isOrEnclosedByPrivateType && matchMethod == null && current != null) {
                inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
            }
            if (skip[i])
                continue;
            MethodBinding inheritedMethod = inherited[i];
            if (matchMethod == null)
                matchingInherited[++index] = inheritedMethod;
            for (int j = i + 1; j < inheritedLength; j++) {
                MethodBinding otherInheritedMethod = inherited[j];
                if (matchMethod == foundMatch[j] && matchMethod != null)
                    continue; // both inherited methods matched the same currentMethod
                if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod))
                    continue;
                // Skip the otherInheritedMethod if it is completely replaced by inheritedMethod
                // This elimination used to happen rather eagerly in computeInheritedMethods step
                // itself earlier. (https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358)
                if (inheritedMethod.declaringClass != otherInheritedMethod.declaringClass) {
                    if (otherInheritedMethod.declaringClass.isInterface()) {
                        if (isInterfaceMethodImplemented(otherInheritedMethod, inheritedMethod,
                                otherInheritedMethod.declaringClass)) {
                            skip[j] = true;
                            continue;
                        }
                    } else if (areMethodsCompatible(inheritedMethod, otherInheritedMethod)) {
                        skip[j] = true;
                        continue;
                    }
                }
                otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod);
                if (otherInheritedMethod != null) {
                    if (isSubstituteParameterSubsignature(inheritedMethod, otherInheritedMethod)) {
                        if (index == -1)
                            matchingInherited[++index] = inheritedMethod;
                        if (foundMatch[j] == null)
                            matchingInherited[++index] = otherInheritedMethod;
                        skip[j] = true;
                    } else if (matchMethod == null && foundMatch[j] == null) {
                        checkInheritedMethods(inheritedMethod, otherInheritedMethod);
                    }
                }
            }
            if (index == -1)
                continue;

            if (index > 0)
                checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
            else if (mustImplementAbstractMethods && matchingInherited[0].isAbstract() && matchMethod == null)
                checkAbstractMethod(matchingInherited[0]);
            while (index >= 0)
                matchingInherited[index--] = null; // clear the previous contents of the matching methods
        }
    }
}

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  ww.  java 2  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;
}