提交 9c088c27 编写于 作者: T Tim Van Holder

[JENKINS-62723] Further fix for Util.isOverridden

This handles the remaining case (override provided by default implementation of an interface).
上级 ccc0e347
......@@ -1443,6 +1443,8 @@ public class Util {
*/
public static boolean isOverridden(@NonNull Class<?> base, @NonNull Class<?> derived, @NonNull String methodName, @NonNull Class<?>... types) {
// If derived is not a subclass or implementor of base, it can't override any method
// Technically this should also be triggered when base == derived, because it can't override its own method, but
// the unit tests explicitly test for that as working.
if (!base.isAssignableFrom(derived)) {
throw new IllegalArgumentException("The specified derived class (" + derived.getCanonicalName() + ") does not derive from the specified base class (" + base.getCanonicalName() + ").");
}
......@@ -1474,13 +1476,24 @@ public class Util {
}
return res;
} catch (NoSuchMethodException e) {
// If the base is an interface, the implementation may come from a default implementation on a derived
// interface. So look at interfaces too.
if (base != null && Modifier.isInterface(base.getModifiers())) {
for (Class<?> iface : clazz.getInterfaces()) {
if (base.equals(iface) || !base.isAssignableFrom(iface)) {
continue;
}
final Method defaultImpl = Util.getMethod(iface, base, methodName, types);
if (defaultImpl != null) {
return defaultImpl;
}
}
}
// Method not found in clazz, let's search in superclasses
Class<?> superclass = clazz.getSuperclass();
// TODO: When base is an interface, it's _possible_ that the class may implement a subinterface of base
// which provides a default implementation. Such a case is not currently detected as an override.
if (superclass != null) {
// if the superclass doesn't derive from base anymore, stop looking
if (base != null && !base.isAssignableFrom(superclass)) {
// if the superclass doesn't derive from base anymore (or IS base), stop looking
if (base != null && (base.equals(superclass) || !base.isAssignableFrom(superclass))) {
return null;
}
return getMethod(superclass, base, methodName, types);
......
......@@ -139,9 +139,8 @@ public class IsOverriddenTest {
errors.checkSucceeds(() -> {assertThat("I1 does not override I1.bar", Util.isOverridden(I1.class, I1.class, "bar"), is(false)); return null;});
errors.checkSucceeds(() -> {assertThat("I2 overrides I1.bar", Util.isOverridden(I1.class, I2.class, "bar"), is(true)); return null;});
errors.checkSucceeds(() -> {assertThat("C1 does not override I1.bar", Util.isOverridden(I1.class, C1.class, "bar"), is(false)); return null;});
// TODO: Not currently handled by isOverridden()
//errors.checkSucceeds(() -> {assertThat("C2 overrides I1.bar (via I2)", Util.isOverridden(I1.class, C2.class, "bar"), is(true)); return null;});
//errors.checkSucceeds(() -> {assertThat("C3 overrides I1.bar (via I2)", Util.isOverridden(I1.class, C3.class, "bar"), is(true)); return null;});
errors.checkSucceeds(() -> {assertThat("C2 overrides I1.bar (via I2)", Util.isOverridden(I1.class, C2.class, "bar"), is(true)); return null;});
errors.checkSucceeds(() -> {assertThat("C3 overrides I1.bar (via I2)", Util.isOverridden(I1.class, C3.class, "bar"), is(true)); return null;});
errors.checkSucceeds(() -> {assertThat("C4 overrides I1.bar", Util.isOverridden(I1.class, C4.class, "bar"), is(true)); return null;});
}
private interface I1 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册