Skip to content

Commit

Permalink
Use target class for candidate retrieval but not for method matching
Browse files Browse the repository at this point in the history
Closes gh-32181
See gh-21843
  • Loading branch information
jhoeller committed Feb 1, 2024
1 parent 521fbfd commit 1a783f4
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private static Method resolveBridgeMethod(Method bridgeMethod, Class<?> targetCl
ReflectionUtils.doWithMethods(targetClass, candidateMethods::add, filter);
if (!candidateMethods.isEmpty()) {
bridgedMethod = (candidateMethods.size() == 1 ? candidateMethods.get(0) :
searchCandidates(candidateMethods, bridgeMethod, targetClass));
searchCandidates(candidateMethods, bridgeMethod));
}
if (bridgedMethod == null) {
// A bridge method was passed in but we couldn't find the bridged method.
Expand Down Expand Up @@ -141,14 +141,14 @@ private static boolean isBridgedCandidateFor(Method candidateMethod, Method brid
* @return the bridged method, or {@code null} if none found
*/
@Nullable
private static Method searchCandidates(List<Method> candidateMethods, Method bridgeMethod, Class<?> targetClass) {
private static Method searchCandidates(List<Method> candidateMethods, Method bridgeMethod) {
if (candidateMethods.isEmpty()) {
return null;
}
Method previousMethod = null;
boolean sameSig = true;
for (Method candidateMethod : candidateMethods) {
if (isBridgeMethodFor(bridgeMethod, candidateMethod, targetClass)) {
if (isBridgeMethodFor(bridgeMethod, candidateMethod, bridgeMethod.getDeclaringClass())) {
return candidateMethod;
}
else if (previousMethod != null) {
Expand All @@ -164,12 +164,12 @@ else if (previousMethod != null) {
* Determines whether the bridge {@link Method} is the bridge for the
* supplied candidate {@link Method}.
*/
static boolean isBridgeMethodFor(Method bridgeMethod, Method candidateMethod, Class<?> targetClass) {
if (isResolvedTypeMatch(candidateMethod, bridgeMethod, targetClass)) {
static boolean isBridgeMethodFor(Method bridgeMethod, Method candidateMethod, Class<?> declaringClass) {
if (isResolvedTypeMatch(candidateMethod, bridgeMethod, declaringClass)) {
return true;
}
Method method = findGenericDeclaration(bridgeMethod);
return (method != null && isResolvedTypeMatch(method, candidateMethod, targetClass));
return (method != null && isResolvedTypeMatch(method, candidateMethod, declaringClass));
}

/**
Expand All @@ -178,14 +178,14 @@ static boolean isBridgeMethodFor(Method bridgeMethod, Method candidateMethod, Cl
* are equal after resolving all types against the declaringType, otherwise
* returns {@code false}.
*/
private static boolean isResolvedTypeMatch(Method genericMethod, Method candidateMethod, Class<?> targetClass) {
private static boolean isResolvedTypeMatch(Method genericMethod, Method candidateMethod, Class<?> declaringClass) {
Type[] genericParameters = genericMethod.getGenericParameterTypes();
if (genericParameters.length != candidateMethod.getParameterCount()) {
return false;
}
Class<?>[] candidateParameters = candidateMethod.getParameterTypes();
for (int i = 0; i < candidateParameters.length; i++) {
ResolvableType genericParameter = ResolvableType.forMethodParameter(genericMethod, i, targetClass);
ResolvableType genericParameter = ResolvableType.forMethodParameter(genericMethod, i, declaringClass);
Class<?> candidateParameter = candidateParameters[i];
if (candidateParameter.isArray()) {
// An array type: compare the component type.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@ void findBridgedMethodFromOriginalMethodNotInHierarchy() throws Exception {
assertThat(mostSpecificMethod).isSameAs(originalMethod);
}

@Test
void findBridgedMethodInHierarchyWithBoundedGenerics() throws Exception {
Method originalMethod = Bar.class.getDeclaredMethod("someMethod", Object.class, Object.class);
assertThat(originalMethod.isBridge()).isFalse();
Method bridgedMethod = BridgeMethodResolver.getMostSpecificMethod(originalMethod, SubBar.class);
assertThat(bridgedMethod.isBridge()).isFalse();
assertThat(bridgedMethod.getName()).isEqualTo("someMethod");
assertThat(bridgedMethod.getParameterCount()).isEqualTo(2);
assertThat(bridgedMethod.getParameterTypes()[0]).isEqualTo(CharSequence.class);
}

@Test
void isBridgeMethodFor() throws Exception {
Method bridged = MyBar.class.getDeclaredMethod("someMethod", String.class, Object.class);
Expand Down Expand Up @@ -377,8 +388,15 @@ void someMethod(T theArg, Map<?, ?> m) {
}


public abstract static class InterBar<T> extends Bar<T> {
public abstract static class InterBar<T extends CharSequence> extends Bar<T> {

@Override
void someMethod(T theArg, Object otherArg) {
}
}


public abstract static class SubBar<T extends StringBuffer> extends InterBar<T> {
}


Expand Down

0 comments on commit 1a783f4

Please sign in to comment.