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

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

Introduction

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

Prototype

public final boolean areParametersEqual(MethodBinding method) 

Source Link

Usage

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  .  ja  v  a 2 s .  com

    // 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

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. ja va  2  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);
}

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

License:Open Source License

private void addDefaultAbstractMethods() {
    if ((this.tagBits & TagBits.KnowsDefaultAbstractMethods) != 0)
        return;//  w  ww. j  a va 2  s .  co m

    this.tagBits |= TagBits.KnowsDefaultAbstractMethods;
    if (isClass() && isAbstract()) {
        if (this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_2)
            return; // no longer added for post 1.2 targets

        ReferenceBinding[] itsInterfaces = superInterfaces();
        if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
            MethodBinding[] defaultAbstracts = null;
            int defaultAbstractsCount = 0;
            ReferenceBinding[] interfacesToVisit = itsInterfaces;
            int nextPosition = interfacesToVisit.length;
            for (int i = 0; i < nextPosition; i++) {
                ReferenceBinding superType = interfacesToVisit[i];
                if (superType.isValidBinding()) {
                    MethodBinding[] superMethods = superType.methods();
                    nextAbstractMethod: for (int m = superMethods.length; --m >= 0;) {
                        MethodBinding method = superMethods[m];
                        // explicitly implemented ?
                        if (implementsMethod(method))
                            continue nextAbstractMethod;
                        if (defaultAbstractsCount == 0) {
                            defaultAbstracts = new MethodBinding[5];
                        } else {
                            // already added as default abstract ?
                            for (int k = 0; k < defaultAbstractsCount; k++) {
                                MethodBinding alreadyAdded = defaultAbstracts[k];
                                if (CharOperation.equals(alreadyAdded.selector, method.selector)
                                        && alreadyAdded.areParametersEqual(method))
                                    continue nextAbstractMethod;
                            }
                        }
                        MethodBinding defaultAbstract = new MethodBinding(
                                method.modifiers | ExtraCompilerModifiers.AccDefaultAbstract
                                        | ClassFileConstants.AccSynthetic,
                                method.selector, method.returnType, method.parameters, method.thrownExceptions,
                                this);
                        if (defaultAbstractsCount == defaultAbstracts.length)
                            System.arraycopy(defaultAbstracts, 0,
                                    defaultAbstracts = new MethodBinding[2 * defaultAbstractsCount], 0,
                                    defaultAbstractsCount);
                        defaultAbstracts[defaultAbstractsCount++] = defaultAbstract;
                    }

                    if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) {
                        int itsLength = itsInterfaces.length;
                        if (nextPosition + itsLength >= interfacesToVisit.length)
                            System.arraycopy(interfacesToVisit, 0,
                                    interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0,
                                    nextPosition);
                        nextInterface: for (int a = 0; a < itsLength; a++) {
                            ReferenceBinding next = itsInterfaces[a];
                            for (int b = 0; b < nextPosition; b++)
                                if (next == interfacesToVisit[b])
                                    continue nextInterface;
                            interfacesToVisit[nextPosition++] = next;
                        }
                    }
                }
            }
            if (defaultAbstractsCount > 0) {
                int length = this.methods.length;
                System.arraycopy(this.methods, 0,
                        this.methods = new MethodBinding[length + defaultAbstractsCount], 0, length);
                System.arraycopy(defaultAbstracts, 0, this.methods, length, defaultAbstractsCount);
                // re-sort methods
                length = length + defaultAbstractsCount;
                if (length > 1)
                    ReferenceBinding.sortMethods(this.methods, 0, length);
                // this.tagBits |= TagBits.AreMethodsSorted; -- already set in #methods()
            }
        }
    }
}

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

License:Open Source License

public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes,
        CompilationUnitScope refScope) {
    // sender from refScope calls recordTypeReference(this)
    int argCount = argumentTypes.length;
    boolean foundNothing = true;

    if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
        long range;
        if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
            nextMethod: for (int imethod = (int) range, end = (int) (range >> 32); imethod <= end; imethod++) {
                MethodBinding method = this.methods[imethod];
                foundNothing = false; // inner type lookups must know that a method with this name exists
                if (method.parameters.length == argCount) {
                    TypeBinding[] toMatch = method.parameters;
                    for (int iarg = 0; iarg < argCount; iarg++)
                        if (toMatch[iarg] != argumentTypes[iarg])
                            continue nextMethod;
                    return method;
                }/*from w  w w  .  ja va2s. c om*/
            }
        }
    } else {
        // lazily sort methods
        if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
            int length = this.methods.length;
            if (length > 1)
                ReferenceBinding.sortMethods(this.methods, 0, length);
            this.tagBits |= TagBits.AreMethodsSorted;
        }

        long range;
        if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
            // check unresolved method
            int start = (int) range, end = (int) (range >> 32);
            for (int imethod = start; imethod <= end; imethod++) {
                MethodBinding method = this.methods[imethod];
                if (resolveTypesFor(method) == null || method.returnType == null) {
                    methods();
                    return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed
                }
            }
            // check dup collisions
            boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
            for (int i = start; i <= end; i++) {
                MethodBinding method1 = this.methods[i];
                for (int j = end; j > i; j--) {
                    MethodBinding method2 = this.methods[j];
                    boolean paramsMatch = isSource15 ? method1.areParameterErasuresEqual(method2)
                            : method1.areParametersEqual(method2);
                    if (paramsMatch) {
                        methods();
                        return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed
                    }
                }
            }
            nextMethod: for (int imethod = start; imethod <= end; imethod++) {
                MethodBinding method = this.methods[imethod];
                TypeBinding[] toMatch = method.parameters;
                if (toMatch.length == argCount) {
                    for (int iarg = 0; iarg < argCount; iarg++)
                        if (toMatch[iarg] != argumentTypes[iarg])
                            continue nextMethod;
                    return method;
                }
            }
        }
    }

    if (foundNothing) {
        if (isInterface()) {
            if (this.superInterfaces.length == 1) {
                if (refScope != null)
                    refScope.recordTypeReference(this.superInterfaces[0]);
                return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
            }
        } else if (this.superclass != null) {
            if (refScope != null)
                refScope.recordTypeReference(this.superclass);
            return this.superclass.getExactMethod(selector, argumentTypes, refScope);
        }
    }
    return null;
}

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

License:Open Source License

public MethodBinding[] getMethods(char[] selector) {
    if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
        long range;
        if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
            int start = (int) range, end = (int) (range >> 32);
            int length = end - start + 1;
            MethodBinding[] result;//ww  w.  j  ava2s . com
            System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
            return result;
        } else {
            return Binding.NO_METHODS;
        }
    }
    // lazily sort methods
    if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
        int length = this.methods.length;
        if (length > 1)
            ReferenceBinding.sortMethods(this.methods, 0, length);
        this.tagBits |= TagBits.AreMethodsSorted;
    }
    MethodBinding[] result;
    long range;
    if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
        int start = (int) range, end = (int) (range >> 32);
        for (int i = start; i <= end; i++) {
            MethodBinding method = this.methods[i];
            if (resolveTypesFor(method) == null || method.returnType == null) {
                methods();
                return getMethods(selector); // try again since the problem methods have been removed
            }
        }
        int length = end - start + 1;
        System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
    } else {
        return Binding.NO_METHODS;
    }
    boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
    for (int i = 0, length = result.length - 1; i < length; i++) {
        MethodBinding method = result[i];
        for (int j = length; j > i; j--) {
            boolean paramsMatch = isSource15 ? method.areParameterErasuresEqual(result[j])
                    : method.areParametersEqual(result[j]);
            if (paramsMatch) {
                methods();
                return getMethods(selector); // try again since the duplicate methods have been removed
            }
        }
    }
    return result;
}

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

License:Open Source License

public MethodBinding[] methods() {
    if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
        return this.methods;

    // lazily sort methods
    if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
        int length = this.methods.length;
        if (length > 1)
            ReferenceBinding.sortMethods(this.methods, 0, length);
        this.tagBits |= TagBits.AreMethodsSorted;
    }//from w  ww . j a v  a  2  s.  c o m

    int failed = 0;
    MethodBinding[] resolvedMethods = this.methods;
    try {
        for (int i = 0, length = this.methods.length; i < length; i++) {
            if (resolveTypesFor(this.methods[i]) == null) {
                // do not alter original method array until resolution is over, due to reentrance (143259)
                if (resolvedMethods == this.methods) {
                    System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length);
                }
                resolvedMethods[i] = null; // unable to resolve parameters
                failed++;
            }
        }

        // find & report collision cases
        boolean complyTo15OrAbove = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
        boolean compliance16 = this.scope.compilerOptions().complianceLevel == ClassFileConstants.JDK1_6;

        for (int i = 0, length = this.methods.length; i < length; i++) {
            int severity = ProblemSeverities.Error;
            MethodBinding method = resolvedMethods[i];
            if (method == null)
                continue;
            char[] selector = method.selector;
            AbstractMethodDeclaration methodDecl = null;
            nextSibling: for (int j = i + 1; j < length; j++) {
                MethodBinding method2 = resolvedMethods[j];
                if (method2 == null)
                    continue nextSibling;
                if (!CharOperation.equals(selector, method2.selector))
                    break nextSibling; // methods with same selector are contiguous

                if (complyTo15OrAbove) {
                    if (method.areParameterErasuresEqual(method2)) {
                        // we now ignore return types in 1.7 when detecting duplicates, just as we did before 1.5 
                        // Only in 1.6, we have to make sure even return types are different
                        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317719
                        if (compliance16 && method.returnType != null && method2.returnType != null) {
                            if (method.returnType.erasure() != method2.returnType.erasure()) {
                                // check to see if the erasure of either method is equal to the other
                                // if not, then change severity to WARNING
                                TypeBinding[] params1 = method.parameters;
                                TypeBinding[] params2 = method2.parameters;
                                int pLength = params1.length;
                                TypeVariableBinding[] vars = method.typeVariables;
                                TypeVariableBinding[] vars2 = method2.typeVariables;
                                boolean equalTypeVars = vars == vars2;
                                MethodBinding subMethod = method2;
                                if (!equalTypeVars) {
                                    MethodBinding temp = method.computeSubstitutedMethod(method2,
                                            this.scope.environment());
                                    if (temp != null) {
                                        equalTypeVars = true;
                                        subMethod = temp;
                                    }
                                }
                                boolean equalParams = method.areParametersEqual(subMethod);
                                if (equalParams && equalTypeVars) {
                                    // duplicates regardless of return types
                                } else if (vars != Binding.NO_TYPE_VARIABLES
                                        && vars2 != Binding.NO_TYPE_VARIABLES) {
                                    // both have type arguments. Erasure of signature of one cannot be equal to signature of other
                                    severity = ProblemSeverities.Warning;
                                } else if (pLength > 0) {
                                    int index = pLength;
                                    // is erasure of signature of m2 same as signature of m1?
                                    for (; --index >= 0;) {
                                        if (params1[index] != params2[index].erasure())
                                            break;
                                        if (params1[index] == params2[index]) {
                                            TypeBinding type = params1[index].leafComponentType();
                                            if (type instanceof SourceTypeBinding
                                                    && type.typeVariables() != Binding.NO_TYPE_VARIABLES) {
                                                index = pLength; // handle comparing identical source types like X<T>... its erasure is itself BUT we need to answer false
                                                break;
                                            }
                                        }
                                    }
                                    if (index >= 0 && index < pLength) {
                                        // is erasure of signature of m1 same as signature of m2?
                                        for (index = pLength; --index >= 0;)
                                            if (params1[index].erasure() != params2[index])
                                                break;

                                    }
                                    if (index >= 0) {
                                        // erasure of neither is equal to signature of other
                                        severity = ProblemSeverities.Warning;
                                    }
                                } else if (pLength != 0) {
                                    severity = ProblemSeverities.Warning;
                                } // pLength = 0 automatically makes erasure of arguments one equal to arguments of other.
                            }
                            // else return types also equal. All conditions satisfied
                            // to give error in 1.6 compliance as well.
                        }
                    } else {
                        continue nextSibling;
                    }
                } else if (!method.areParametersEqual(method2)) {
                    // prior to 1.5, parameters identical meant a collision case
                    continue nextSibling;
                }
                // otherwise duplicates / name clash
                boolean isEnumSpecialMethod = isEnum() && (CharOperation.equals(selector, TypeConstants.VALUEOF)
                        || CharOperation.equals(selector, TypeConstants.VALUES));
                // report duplicate
                boolean removeMethod2 = (severity == ProblemSeverities.Error) ? true : false; // do not remove if in 1.6 and just a warning given
                if (methodDecl == null) {
                    methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special
                    if (methodDecl != null && methodDecl.binding != null) { // ensure its a valid user defined method
                        boolean removeMethod = method.returnType == null && method2.returnType != null;
                        if (isEnumSpecialMethod) {
                            this.scope.problemReporter().duplicateEnumSpecialMethod(this, methodDecl);
                            // remove user defined methods & keep the synthetic
                            removeMethod = true;
                        } else {
                            this.scope.problemReporter().duplicateMethodInType(this, methodDecl,
                                    method.areParametersEqual(method2), severity);
                        }
                        if (removeMethod) {
                            removeMethod2 = false;
                            methodDecl.binding = null;
                            // do not alter original method array until resolution is over, due to reentrance (143259)
                            if (resolvedMethods == this.methods)
                                System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length],
                                        0, length);
                            resolvedMethods[i] = null;
                            failed++;
                        }
                    }
                }
                AbstractMethodDeclaration method2Decl = method2.sourceMethod();
                if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method
                    if (isEnumSpecialMethod) {
                        this.scope.problemReporter().duplicateEnumSpecialMethod(this, method2Decl);
                        removeMethod2 = true;
                    } else {
                        this.scope.problemReporter().duplicateMethodInType(this, method2Decl,
                                method.areParametersEqual(method2), severity);
                    }
                    if (removeMethod2) {
                        method2Decl.binding = null;
                        // do not alter original method array until resolution is over, due to reentrance (143259)
                        if (resolvedMethods == this.methods)
                            System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0,
                                    length);
                        resolvedMethods[j] = null;
                        failed++;
                    }
                }
            }
            if (method.returnType == null && resolvedMethods[i] != null) { // forget method with invalid return type... was kept to detect possible collisions
                methodDecl = method.sourceMethod();
                if (methodDecl != null)
                    methodDecl.binding = null;
                // do not alter original method array until resolution is over, due to reentrance (143259)
                if (resolvedMethods == this.methods)
                    System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length);
                resolvedMethods[i] = null;
                failed++;
            }
        }
    } finally {
        if (failed > 0) {
            int newSize = resolvedMethods.length - failed;
            if (newSize == 0) {
                this.methods = Binding.NO_METHODS;
            } else {
                MethodBinding[] newMethods = new MethodBinding[newSize];
                for (int i = 0, j = 0, length = resolvedMethods.length; i < length; i++)
                    if (resolvedMethods[i] != null)
                        newMethods[j++] = resolvedMethods[i];
                this.methods = newMethods;
            }
        }

        // handle forward references to potential default abstract methods
        addDefaultAbstractMethods();
        this.tagBits |= TagBits.AreMethodsComplete;
    }
    return this.methods;
}