List of usage examples for org.eclipse.jdt.internal.compiler.lookup MethodBinding areParameterErasuresEqual
public final boolean areParameterErasuresEqual(MethodBinding method)
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; }