< prev index next >

test/java/lang/reflect/DefaultMethodMembers/FilterNotMostSpecific.java

Print this page

        

@@ -34,13 +34,12 @@
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 import static org.testng.Assert.*;

@@ -53,11 +52,11 @@
         MethodDesc[] expectedMethods = iface.getAnnotationsByType(MethodDesc.class);
 
         for (MethodDesc expected : expectedMethods) {
             if (expected.isGetMethodReturn()) {
                 try {
-                    Method m = iface.getMethod(expected.name());
+                    Method m = iface.getMethod(expected.name(), expected.parameterTypes());
                     if (!assertMatch(expected, m))
                         fail(failMsg(expected, m, iface));
                     else
                         match = true;
                 } catch (NoSuchMethodException e) {

@@ -70,30 +69,22 @@
 
     @Test(dataProvider="getCases")
     public void testGetMethods(Class<?> iface) {
         List<Method> foundMethods = filterObjectMethods(iface.getMethods());
         MethodDesc[] expectedMethods = iface.getAnnotationsByType(MethodDesc.class);
-        Set<Method> used = new HashSet<>();
 
         for (MethodDesc expected : expectedMethods) {
             boolean found = false;
-
             for (Method m : foundMethods) {
-                if (used.contains(m))
-                    continue;
-
-                if(expected.name().equals(m.getName()) &&
-                    expected.declaringClass() ==m.getDeclaringClass()) {
-
+                if (assertMatch(expected, m)) {
                     found = true;
-                    assertMatch(expected, m);
-                    used.add(m);
                     break;
                 }
             }
-            if (! found)
-                fail("On: "+ iface +"\nDid not find " + toMethodString(expected) + " among " + foundMethods);
+            if (!found)
+                fail("On: "+ iface +"\nDid not find " + toMethodString(expected) +
+                     " among " + foundMethods);
         }
         assertEquals(foundMethods.size(), expectedMethods.length,
                 "\non: " + iface +
                 "\nexpected: " + toMethodStrings(expectedMethods) +
                 "\nfound: " + foundMethods + "\n");

@@ -102,10 +93,15 @@
     private boolean assertMatch(MethodDesc expected, Method m) {
         if (!expected.name().equals(m.getName()))
             return false;
         if (expected.declaringClass() != m.getDeclaringClass())
             return false;
+        if (!Arrays.equals(expected.parameterTypes(), m.getParameterTypes()))
+            return false;
+        if (expected.returnType() != NotSpecified.class &&
+            expected.returnType() != m.getReturnType())
+            return false;
 
         if (expected.kind() == MethodKind.ABSTRACT)
             assertTrue(Modifier.isAbstract(m.getModifiers()), m + " should be ABSTRACT");
         else if (expected.kind() == MethodKind.CONCRETE)
             assertTrue(!Modifier.isAbstract(m.getModifiers()) && !m.isDefault(), m + " should be CONCRETE");

@@ -126,12 +122,17 @@
             filter(m -> (m.getDeclaringClass() != java.lang.Object.class)).
             collect(Collectors.toList());
     }
 
     private String toMethodString(MethodDesc m) {
-        return m.declaringClass().getSimpleName().toString() + "." +
-            m.name() + "()";
+        return (m.returnType() != NotSpecified.class
+                ? m.returnType().getSimpleName() + " "
+                : "") +
+               m.declaringClass().getSimpleName().toString() + "." +
+               m.name() + Stream.of(m.parameterTypes())
+                                .map(cl -> cl.getSimpleName())
+                                .collect(Collectors.joining(", ", "(", ")"));
     }
 
     private List<String> toMethodStrings(MethodDesc[] m) {
         return Arrays.stream(m).
             map(this::toMethodString)

@@ -140,15 +141,20 @@
 
     @Retention(RetentionPolicy.RUNTIME)
     @Repeatable(MethodDescs.class)
     public @interface MethodDesc {
         String name();
+        Class<?> returnType() default NotSpecified.class;
+        Class<?>[] parameterTypes() default {};
         Class<?> declaringClass();
         MethodKind kind() default MethodKind.ABSTRACT;
         boolean isGetMethodReturn() default false;
     }
 
+    // special type marking a not-specified return type in @MethodDesc
+    interface NotSpecified {}
+
     @Retention(RetentionPolicy.RUNTIME)
     public @interface MethodDescs {
         MethodDesc[] value();
     }
 

@@ -170,44 +176,38 @@
             isGetMethodReturn=true)
     interface P1 extends Jbis {}
 
     @MethodDesc(name="nonDefault", declaringClass=Jbis.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=I.class)
     interface P2 extends Jbis, Jprim {}
 
     @MethodDesc(name="nonDefault", declaringClass=Jbis.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=I.class)
     interface P3 extends Jbis, Jprim, I {}
 
-    @MethodDesc(name="nonDefault", declaringClass=I.class,
+    @MethodDesc(name="nonDefault", declaringClass=J.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=J.class)
     interface P4 extends I, J {}
 
     @MethodDesc(name="nonDefault", declaringClass=J.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=I.class)
     interface P5 extends J, I {}
 
     @MethodDesc(name="nonDefault", declaringClass=J.class,
             isGetMethodReturn=true)
     interface K1 extends J {}
 
     @MethodDesc(name="nonDefault", declaringClass=K1M.class,
             isGetMethodReturn=true)
     interface K1M extends J { void nonDefault(); }
 
-    @MethodDesc(name="nonDefault", declaringClass=I.class,
+    @MethodDesc(name="nonDefault", declaringClass=J.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=J.class)
     interface K2 extends I, J {}
 
     @MethodDesc(name="nonDefault", declaringClass=J.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=I.class)
     interface K2O extends J, I {}
 
     @MethodDesc(name="nonDefault", declaringClass=K2M.class,
             isGetMethodReturn=true)
     interface K2M extends J, I { void nonDefault(); }

@@ -242,25 +242,22 @@
             isGetMethodReturn=true)
     interface N1DN extends M { default void isDefault() {} void nonDefault(); }
 
     @MethodDesc(name="isDefault", declaringClass=M.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
     @MethodDesc(name="nonDefault", declaringClass=M.class,
             isGetMethodReturn=true)
     interface N2 extends M, L {}
 
     @MethodDesc(name="isDefault", declaringClass=M.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class,
+    @MethodDesc(name="nonDefault", declaringClass=M.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
     interface N22 extends L, M {}
 
     @MethodDesc(name="isDefault", declaringClass=N2D.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
     @MethodDesc(name="nonDefault", declaringClass=M.class,
             isGetMethodReturn=true)
     interface N2D extends M, L { default void isDefault() {}}
 
     @MethodDesc(name="isDefault", declaringClass=M.class,

@@ -275,52 +272,40 @@
             isGetMethodReturn=true)
     interface N2DN extends M, L { default void isDefault() {} void nonDefault(); }
 
     @MethodDesc(name="isDefault", declaringClass=N2DN.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface O1 extends L, M, N2DN {}
 
     @MethodDesc(name="isDefault", declaringClass=N2DN.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface O2 extends M, N2DN, L {}
 
     @MethodDesc(name="isDefault", declaringClass=N2DN.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
     @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
     interface O3 extends N2DN, L, M {}
 
     @MethodDesc(name="isDefault", declaringClass=N2DN.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     abstract class C1 implements L, M, N2DN {}
 
     @MethodDesc(name="isDefault", declaringClass=N2DN.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     abstract class C2 implements M, N2DN, L {}
 
     @MethodDesc(name="isDefault", declaringClass=N2DN.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
     @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
     abstract class C3 implements N2DN, L, M {}
 
     @MethodDesc(name="isDefault", declaringClass=N2DN.class,

@@ -343,92 +328,58 @@
 
     // reabstraction
 
     @MethodDesc(name="isDefault", declaringClass=R1.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface R1 extends L, M, N2DN { void isDefault(); }
 
     @MethodDesc(name="isDefault", declaringClass=R2.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface R2 extends M, N2DN, L { void isDefault(); }
 
     @MethodDesc(name="isDefault", declaringClass=R3.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
     @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
     interface R3 extends N2DN, L, M { void isDefault(); }
 
-    // this one is strange but logical, getMethod finds N2DN first, which is
-    // default but not the most specific
-    @MethodDesc(name="isDefault", declaringClass=N2DN.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="isDefault", declaringClass=R1.class)
-    @MethodDesc(name="nonDefault", declaringClass=L.class,
+    @MethodDesc(name="isDefault", declaringClass=R1.class,
+            isGetMethodReturn=true)
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface R4 extends L, M, N2DN, R1 {}
 
-    // this one is strange but logical, getMethod finds N2DN first, which is
-    // default but not the most specific
-    @MethodDesc(name="isDefault", declaringClass=N2DN.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="isDefault", declaringClass=R2.class)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class,
+    @MethodDesc(name="isDefault", declaringClass=R2.class,
+            isGetMethodReturn=true)
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface R5 extends M, N2DN, R2, L {}
 
-    // this one is strange but logical, getMethod finds N2DN first, which is
-    // default but not the most specific
-    @MethodDesc(name="isDefault", declaringClass=N2DN.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="isDefault", declaringClass=R3.class)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
+    @MethodDesc(name="isDefault", declaringClass=R3.class,
+            isGetMethodReturn=true)
     @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
     interface R6 extends N2DN, R3, L, M {}
 
-    // the following three finds the "right" one
     @MethodDesc(name="isDefault", declaringClass=R1.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="isDefault", declaringClass=N2DN.class,
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="nonDefault", declaringClass=L.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface R7 extends L, M, R1, N2DN {}
 
     @MethodDesc(name="isDefault", declaringClass=R2.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="isDefault", declaringClass=N2DN.class,
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class,
+    @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=N2DN.class)
     interface R8 extends M, R2, N2DN, L {}
 
     @MethodDesc(name="isDefault", declaringClass=R3.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="isDefault", declaringClass=N2DN.class,
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="nonDefault", declaringClass=L.class)
-    @MethodDesc(name="nonDefault", declaringClass=M.class)
     @MethodDesc(name="nonDefault", declaringClass=N2DN.class,
             isGetMethodReturn=true)
     interface R9 extends R3, N2DN, L, M {}
 
     // More reabstraction

@@ -443,55 +394,44 @@
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
     interface Z32 extends Z2, Z1 {}
 
     interface Z3 extends Z2, Z1 { void z(); }
 
-    @MethodDesc(name="z", declaringClass=Z2.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="z", declaringClass=Z3.class)
+    @MethodDesc(name="z", declaringClass=Z3.class,
+            isGetMethodReturn = true)
     interface Z41 extends Z1, Z2, Z3 { }
 
-    @MethodDesc(name="z", declaringClass=Z2.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="z", declaringClass=Z3.class)
+    @MethodDesc(name="z", declaringClass=Z3.class,
+            isGetMethodReturn = true)
     interface Z42 extends Z2, Z3, Z1 { }
 
     @MethodDesc(name="z", declaringClass=Z3.class,
-            isGetMethodReturn=true)
-    @MethodDesc(name="z", declaringClass=Z2.class,
-            kind=MethodKind.DEFAULT)
+            isGetMethodReturn = true)
     interface Z43 extends Z3, Z1, Z2 { }
 
-    @MethodDesc(name="z", declaringClass=Z2.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="z", declaringClass=Z3.class)
+    @MethodDesc(name="z", declaringClass=Z3.class,
+            isGetMethodReturn = true)
     abstract class ZC41 implements Z1, Z2, Z3 { }
 
-    @MethodDesc(name="z", declaringClass=Z2.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="z", declaringClass=Z3.class)
+    @MethodDesc(name="z", declaringClass=Z3.class,
+            isGetMethodReturn = true)
     abstract class ZC42 implements Z2, Z3, Z1 { }
 
     @MethodDesc(name="z", declaringClass=Z3.class,
-            isGetMethodReturn=true)
-    @MethodDesc(name="z", declaringClass=Z2.class,
-            kind=MethodKind.DEFAULT)
+            isGetMethodReturn = true)
     abstract class ZC43 implements Z3, Z1, Z2 { }
 
     // More reabstraction + concretization
     interface X1 { default void x() {} }
     interface X2 extends X1 { void x(); }
 
-    @MethodDesc(name="x", declaringClass=X1.class,
-            kind=MethodKind.DEFAULT, isGetMethodReturn=true)
-    @MethodDesc(name="x", declaringClass=X2.class)
+    @MethodDesc(name="x", declaringClass=X2.class,
+            isGetMethodReturn=true)
     interface X31 extends X1, X2 {}
 
     @MethodDesc(name="x", declaringClass=X2.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="x", declaringClass=X1.class,
-            kind=MethodKind.DEFAULT)
     interface X32 extends X2, X1 {}
 
     @MethodDesc(name="x", declaringClass=X3.class,
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
     interface X3 extends X2, X1 { default void x() {} }

@@ -522,89 +462,111 @@
             kind=MethodKind.DEFAULT, isGetMethodReturn=true)
     abstract class XC43 implements X3, X1, X2 { }
 
     interface K extends I, J { void nonDefault(); }
 
-    @MethodDesc(name="nonDefault", declaringClass=I.class,
+    @MethodDesc(name="nonDefault", declaringClass=K.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=J.class)
-    @MethodDesc(name="nonDefault", declaringClass=K.class)
     abstract class ZZ1 implements I, J, K {}
 
-    @MethodDesc(name="nonDefault", declaringClass=I.class,
+    @MethodDesc(name="nonDefault", declaringClass=K.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=J.class)
-    @MethodDesc(name="nonDefault", declaringClass=K.class)
     abstract class ZZ2 extends ZZ1 implements K, I, J {}
 
-    @MethodDesc(name="nonDefault", declaringClass=I.class,
+    @MethodDesc(name="nonDefault", declaringClass=K.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="nonDefault", declaringClass=J.class)
-    @MethodDesc(name="nonDefault", declaringClass=K.class)
     abstract class ZZ3 extends ZZ2 implements J, K, I {}
 
-    // bridges
-    interface B1A { Object m(); }
-    interface B1B extends B1A { Map m(); }
-
-    @MethodDesc(name="m", declaringClass=B1C.class,
-            isGetMethodReturn=true)
-    @MethodDesc(name="m", declaringClass=B1C.class,
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="m", declaringClass=B1C.class,
-            kind=MethodKind.DEFAULT)
-    interface B1C extends B1B { HashMap m(); }
-
-    @MethodDesc(name="m", declaringClass=B2.class,
-            isGetMethodReturn=true)
-    @MethodDesc(name="m", declaringClass=B2.class,
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="m", declaringClass=B2.class,
-            kind=MethodKind.DEFAULT)
-    interface B2 extends B1C { HashMap m(); }
-
-    @MethodDesc(name="m", declaringClass=B2.class, //HahsMap
-            isGetMethodReturn=true)
-    @MethodDesc(name="m", declaringClass=B2.class, //Map
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="m", declaringClass=B2.class, //Object
-            kind=MethodKind.DEFAULT)
-    interface B3A extends B2, B1A {}
-
-    // this one is funny since HashMap isn't a bridge thus not a default
-    @MethodDesc(name="m", declaringClass=B2.class, //HashMap
-            isGetMethodReturn=true)
-    @MethodDesc(name="m", declaringClass=B2.class, //Map
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="m", declaringClass=B2.class, //Object
-            kind=MethodKind.DEFAULT)
-    @MethodDesc(name="m", declaringClass=B1C.class) //HashMap
-    interface B3B extends B2, B1C {}
+    // bridges...
+
+    interface B1 { Object m(); }
+    interface B2A extends B1 { Map m(); }
+    interface B2B extends B1 { HashMap m(); }
+
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B3A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Map.class, declaringClass=B3A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=HashMap.class, declaringClass=B3A.class,
+            isGetMethodReturn=true)
+    interface B3A extends B2A { HashMap m(); }
+
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class,
+            isGetMethodReturn=true)
+    interface B4A extends B3A { HashMap m(); }
+
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class,
+            isGetMethodReturn=true)
+    interface B5A2 extends B4A, B1 {}
+
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class,
+            isGetMethodReturn=true)
+    interface B5A4A extends B4A, B3A {}
+
+    // ... + most specific return type for getMethod from two unrelated interfaces
+
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B2A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B2B.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Map.class, declaringClass=B2A.class)
+    @MethodDesc(name="m", returnType=HashMap.class, declaringClass=B2B.class,
+            isGetMethodReturn=true)
+    interface B3AB extends B2A, B2B {}
+
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B2A.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Object.class, declaringClass=B2B.class,
+            kind = MethodKind.DEFAULT)
+    @MethodDesc(name="m", returnType=Map.class, declaringClass=B2A.class)
+    @MethodDesc(name="m", returnType=HashMap.class, declaringClass=B2B.class,
+            isGetMethodReturn=true)
+    interface B3BA extends B2B, B2A {}
 
     // same name different params type
     interface A1 { void m(); void m(int i); void m(int i, int j); }
     interface A2A extends A1 { void m(); void m(int i); void m(int i, int j); }
     interface A2B extends A1 { void m(); void m(int i); default void m(int i, int j) {} }
 
-    @MethodDesc(name="m", declaringClass=A1.class,
+    @MethodDesc(name="m", parameterTypes = {}, declaringClass=A2A.class,
+            isGetMethodReturn=true)
+    @MethodDesc(name="m", parameterTypes = {int.class}, declaringClass=A2A.class,
+            isGetMethodReturn=true)
+    @MethodDesc(name="m", parameterTypes = {int.class, int.class}, declaringClass=A2A.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="m", declaringClass=A1.class)
-    @MethodDesc(name="m", declaringClass=A1.class)
-    @MethodDesc(name="m", declaringClass=A2A.class)
-    @MethodDesc(name="m", declaringClass=A2A.class)
-    @MethodDesc(name="m", declaringClass=A2A.class)
     interface A3A extends A1, A2A {}
 
-    @MethodDesc(name="m", declaringClass=A1.class,
+    @MethodDesc(name="m", parameterTypes = {}, declaringClass=A2B.class,
+            isGetMethodReturn=true)
+    @MethodDesc(name="m", parameterTypes = {int.class}, declaringClass=A2B.class,
             isGetMethodReturn=true)
-    @MethodDesc(name="m", declaringClass=A1.class)
-    @MethodDesc(name="m", declaringClass=A2B.class)
-    @MethodDesc(name="m", declaringClass=A2B.class)
-    @MethodDesc(name="m", declaringClass=A2B.class,
-            kind=MethodKind.DEFAULT)
+    @MethodDesc(name="m", parameterTypes = {int.class, int.class}, declaringClass=A2B.class,
+            kind = MethodKind.DEFAULT, isGetMethodReturn=true)
     interface A3B extends A1, A2B {}
 
+    // method in directly implemented interface overrides interface method
+    // inherited by superclass
+
+    interface E { void m(); }
+    interface F extends E { void m(); }
+    abstract class G implements E {}
+
+    @MethodDesc(name="m", declaringClass=F.class, isGetMethodReturn=true)
+    abstract class H extends G implements F {}
+
     @DataProvider
     public Object[][] getCases() { return CASES; }
     public static final Class<?>[][] CASES =  {
         { K1.class },
         { K1M.class },

@@ -678,14 +640,18 @@
 
         { XC41.class },
         { XC42.class },
         { XC43.class },
 
-        { B1C.class },
-        { B2.class },
         { B3A.class },
-        { B3B.class },
+        { B4A.class },
+        { B5A2.class },
+        { B5A4A.class },
+        { B3AB.class },
+        { B3BA.class },
 
         { A3A.class },
         { A3B.class },
+
+        { H.class },
     };
 }
< prev index next >