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

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

Introduction

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

Prototype

public final boolean areParameterErasuresEqual(MethodBinding method) 

Source Link

Usage

From source file:com.android.tools.lint.EcjParser.java

License:Apache License

/** Computes the super method, if any, given a method binding */
private static MethodBinding findSuperMethodBinding(@NonNull MethodBinding binding) {
    try {// ww w  .java  2  s.  c  o  m
        ReferenceBinding superclass = binding.declaringClass.superclass();
        while (superclass != null) {
            MethodBinding[] methods = superclass.getMethods(binding.selector, binding.parameters.length);
            for (MethodBinding method : methods) {
                if (method.areParameterErasuresEqual(binding)) {
                    return method;
                }
            }

            superclass = superclass.superclass();
        }
    } catch (Exception ignore) {
        // Work around ECJ bugs; see https://code.google.com/p/android/issues/detail?id=172268
    }

    return null;
}

From source file:com.android.tools.lint.psi.EcjPsiBinaryClass.java

License:Apache License

@NonNull
private PsiMethod[] findMethods(@Nullable String name, boolean includeInherited, boolean includeConstructors) {
    if (mBinding instanceof ReferenceBinding) {
        ReferenceBinding cls = (ReferenceBinding) mBinding;
        if (includeInherited) {
            List<EcjPsiBinaryMethod> result = null;
            while (cls != null) {
                MethodBinding[] methods = name != null ? cls.getMethods(name.toCharArray()) : cls.methods();
                if (methods != null) {
                    int count = methods.length;
                    if (count > 0) {
                        if (result == null) {
                            result = Lists.newArrayListWithExpectedSize(count);
                        }/*ww w.  j  a v  a2 s.c om*/
                        for (MethodBinding method : methods) {
                            if ((method.modifiers & Modifier.PRIVATE) != 0 && cls != mBinding) {
                                // Ignore parent methods that are private
                                continue;
                            }

                            if (includeConstructors || !method.isConstructor()) {
                                // See if this method looks like it's masked
                                boolean masked = false;
                                for (PsiMethod m : result) {
                                    MethodBinding mb = ((EcjPsiBinaryMethod) m).getBinding();
                                    if (mb.areParameterErasuresEqual(method)) {
                                        masked = true;
                                        break;
                                    }
                                }
                                if (masked) {
                                    continue;
                                }
                                result.add(new EcjPsiBinaryMethod(mManager, method));
                            }
                        }
                    }
                }
                cls = cls.superclass();
            }

            return result != null ? result.toArray(PsiMethod.EMPTY_ARRAY) : PsiMethod.EMPTY_ARRAY;
        } else {
            MethodBinding[] methods = name != null ? cls.getMethods(name.toCharArray()) : cls.methods();
            if (methods != null) {
                int count = methods.length;
                List<EcjPsiBinaryMethod> result = Lists.newArrayListWithExpectedSize(count);
                for (MethodBinding method : methods) {
                    if (includeConstructors || !method.isConstructor()) {
                        result.add(new EcjPsiBinaryMethod(mManager, method));
                    }
                }
                return result.toArray(PsiMethod.EMPTY_ARRAY);
            }
        }
    }

    return PsiMethod.EMPTY_ARRAY;
}

From source file:com.android.tools.lint.psi.EcjPsiManager.java

License:Apache License

/** Computes the super method, if any, given a method binding */
@SuppressWarnings("SameParameterValue")
@Nullable//  ww  w  .jav a 2  s  . com
static MethodBinding findSuperMethodBinding(@NonNull MethodBinding binding, boolean allowStatic,
        boolean allowPrivate) {
    if (binding.isConstructor()) {
        return null;
    }
    if (!allowPrivate && binding.isPrivate()) {
        return null;
    }
    if (!allowStatic && binding.isStatic()) {
        return null;
    }
    try {
        ReferenceBinding superclass = binding.declaringClass.superclass();
        while (superclass != null) {
            MethodBinding[] methods = superclass.getMethods(binding.selector, binding.parameters.length);
            for (MethodBinding method : methods) {
                if (method.isStatic() != binding.isStatic()) {
                    continue;
                }
                if (method.areParameterErasuresEqual(binding)) {
                    if (method.isPrivate()) {
                        if (method.declaringClass.outermostEnclosingType() == binding.declaringClass
                                .outermostEnclosingType()) {
                            return method;
                        } else {
                            return null;
                        }
                    } else {
                        return method;
                    }
                }
            }

            // TODO: Check interfaces too!

            superclass = superclass.superclass();
        }
    } catch (Exception ignore) {
        // Work around ECJ bugs; see https://code.google.com/p/android/issues/detail?id=172268
    }

    return null;
}

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

License:Open Source License

protected boolean canOverridingMethodDifferInErasure(MethodBinding overridingMethod,
        MethodBinding inheritedMethod) {
    if (overridingMethod.areParameterErasuresEqual(inheritedMethod))
        return false; // no further change in signature is possible due to parameterization.
    if (overridingMethod.declaringClass.isRawType())
        return false; // no parameterization is happening anyways.
    return true;/*from  w  w  w . j a  va  2 s.  c om*/
}

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

License:Open Source License

void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod,
        MethodBinding[] allInheritedMethods) {
    if (currentMethod.isVarargs() != inheritedMethod.isVarargs())
        problemReporter(currentMethod).varargsConflict(currentMethod, inheritedMethod, this.type);

    // so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod
    MethodBinding originalInherited = inheritedMethod.original();
    if (originalInherited.returnType != currentMethod.returnType)
        if (!isAcceptableReturnTypeOverride(currentMethod, inheritedMethod))
            problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited,
                    this.type);

    MethodBinding bridge = this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original());
    if (bridge != null) {
        for (int i = 0, l = allInheritedMethods == null ? 0 : allInheritedMethods.length; i < l; i++) {
            if (allInheritedMethods[i] != null
                    && detectInheritedNameClash(originalInherited, allInheritedMethods[i].original()))
                return;
        }//from   w  w  w. j a  v  a  2 s  . co m
        // See if the new bridge clashes with any of the user methods of the class. For this check
        // we should check for "method descriptor clash" and not just "method signature clash". Really
        // what we are checking is whether there is a contention for the method dispatch table slot.
        // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=293615.
        MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(bridge.selector);
        for (int i = current.length - 1; i >= 0; --i) {
            final MethodBinding thisMethod = current[i];
            if (thisMethod.areParameterErasuresEqual(bridge)
                    && thisMethod.returnType.erasure() == bridge.returnType.erasure()) {
                // use inherited method for problem reporting.
                problemReporter(thisMethod).methodNameClash(thisMethod,
                        inheritedMethod.declaringClass.isRawType() ? inheritedMethod
                                : inheritedMethod.original(),
                        ProblemSeverities.Error);
                return;
            }
        }
    }
}

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

License:Open Source License

boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) {
    if (!inherited.areParameterErasuresEqual(otherInherited))
        return false;
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=322001
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=323693
    // When reporting a name clash between two inherited methods, we should not look for a
    // signature clash, but instead should be looking for method descriptor clash. 
    if (inherited.returnType.erasure() != otherInherited.returnType.erasure())
        return false;
    // skip it if otherInherited is defined by a subtype of inherited's declaringClass or vice versa.
    // avoid being order sensitive and check with the roles reversed also.
    if (inherited.declaringClass.erasure() != otherInherited.declaringClass.erasure()) {
        if (inherited.declaringClass.findSuperTypeOriginatingFrom(otherInherited.declaringClass) != null)
            return false;
        if (otherInherited.declaringClass.findSuperTypeOriginatingFrom(inherited.declaringClass) != null)
            return false;
    }//from  w  w w .ja va  2 s.  c  o m

    problemReporter().inheritedMethodsHaveNameClash(this.type, inherited, otherInherited);
    return true;
}

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

License:Open Source License

boolean detectNameClash(MethodBinding current, MethodBinding inherited, boolean treatAsSynthetic) {
    MethodBinding methodToCheck = inherited;
    MethodBinding original = methodToCheck.original(); // can be the same as inherited
    if (!current.areParameterErasuresEqual(original))
        return false;
    int severity = ProblemSeverities.Error;
    if (this.environment.globalOptions.complianceLevel == ClassFileConstants.JDK1_6) {
        // for 1.6 return types also need to be checked
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317719
        if (current.returnType.erasure() != original.returnType.erasure())
            severity = ProblemSeverities.Warning;
    }/* w w w .j  ava  2s  .  co  m*/
    if (!treatAsSynthetic) {
        // For a user method, see if current class overrides the inherited method. If it does,
        // then any grievance we may have ought to be against the current class's method and
        // NOT against any super implementations. https://bugs.eclipse.org/bugs/show_bug.cgi?id=293615

        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=315978 : we now defer this rather expensive
        // check to just before reporting (the incorrect) name clash. In the event there is no name
        // clash to report to begin with (the common case), no penalty needs to be paid.  
        MethodBinding[] currentNamesakes = (MethodBinding[]) this.currentMethods.get(inherited.selector);
        if (currentNamesakes.length > 1) { // we know it ought to at least one and that current is NOT the override
            for (int i = 0, length = currentNamesakes.length; i < length; i++) {
                MethodBinding currentMethod = currentNamesakes[i];
                if (currentMethod != current && doesMethodOverride(currentMethod, inherited)) {
                    methodToCheck = currentMethod;
                    break;
                }
            }
        }
    }
    original = methodToCheck.original(); // can be the same as inherited
    if (!current.areParameterErasuresEqual(original))
        return false;
    original = inherited.original(); // For error reporting use, inherited.original()
    problemReporter(current).methodNameClash(current,
            inherited.declaringClass.isRawType() ? inherited : original, severity);
    if (severity == ProblemSeverities.Warning)
        return false;
    return true;
}

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

License:Open Source License

boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod) {
    if (!areParametersEqual(method, substituteMethod)) {
        // method can still override substituteMethod in cases like :
        // <U extends Number> void c(U u) {}
        // @Override void c(Number n) {}
        // but method cannot have a "generic-enabled" parameter type
        if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod))
            return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method);

        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=279836
        if (method.declaringClass.isRawType() && substituteMethod.declaringClass.isRawType())
            if (method.hasSubstitutedParameters() && substituteMethod.hasSubstitutedParameters())
                return areMethodsCompatible(method, substituteMethod);

        return false;
    }//w  w w  . ja v a  2  s .  c  o m

    if (substituteMethod instanceof ParameterizedGenericMethodBinding) {
        if (method.typeVariables != Binding.NO_TYPE_VARIABLES)
            return !((ParameterizedGenericMethodBinding) substituteMethod).isRaw;
        // since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does
        return !hasGenericParameter(method);
    }

    // if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod()
    return method.typeVariables == Binding.NO_TYPE_VARIABLES;
}

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();
        }/*ww w  . ja v a  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

public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge,
        MethodBinding targetMethod) {/*from ww w.j  a va  2  s . co  m*/
    if (isInterface())
        return null; // only classes & enums get bridge methods
    // targetMethod may be inherited
    if (inheritedMethodToBridge.returnType.erasure() == targetMethod.returnType.erasure()
            && inheritedMethodToBridge.areParameterErasuresEqual(targetMethod)) {
        return null; // do not need bridge method
    }
    if (this.synthetics == null)
        this.synthetics = new HashMap[MAX_SYNTHETICS];
    if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) {
        this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);
    } else {
        // check to see if there is another equivalent inheritedMethod already added
        Iterator synthMethods = this.synthetics[SourceTypeBinding.METHOD_EMUL].keySet().iterator();
        while (synthMethods.hasNext()) {
            Object synthetic = synthMethods.next();
            if (synthetic instanceof MethodBinding) {
                MethodBinding method = (MethodBinding) synthetic;
                if (CharOperation.equals(inheritedMethodToBridge.selector, method.selector)
                        && inheritedMethodToBridge.returnType.erasure() == method.returnType.erasure()
                        && inheritedMethodToBridge.areParameterErasuresEqual(method)) {
                    return null;
                }
            }
        }
    }

    SyntheticMethodBinding accessMethod = null;
    SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL]
            .get(inheritedMethodToBridge);
    if (accessors == null) {
        accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this);
        this.synthetics[SourceTypeBinding.METHOD_EMUL].put(inheritedMethodToBridge,
                accessors = new SyntheticMethodBinding[2]);
        accessors[1] = accessMethod;
    } else {
        if ((accessMethod = accessors[1]) == null) {
            accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this);
            accessors[1] = accessMethod;
        }
    }
    return accessMethod;
}