]> source.dussan.org Git - javassist.git/commitdiff
Fix MemberResolver.lookupMethod bug when super class has more precise match 466/head
authorshifujun <shifujun@foxmail.com>
Fri, 8 Dec 2023 06:48:28 +0000 (14:48 +0800)
committershifujun <shifujun@foxmail.com>
Fri, 8 Dec 2023 09:18:27 +0000 (17:18 +0800)
When onlyExact=false and super class have a more precise match,
it should not return with current class's maybe result.

New added testSuperCall reveals the problem.

src/main/javassist/compiler/MemberResolver.java
src/test/javassist/JvstTest5.java
src/test/javassist/SuperCallCase.java [new file with mode: 0644]

index c01974df1aac3a14f28cd1391493464442595502..dd271368954dde829949482ae0ddf69c4560f93a 100644 (file)
@@ -130,9 +130,7 @@ public class MemberResolver implements TokenId {
 
         if (onlyExact)
             maybe = null;
-        else
-            if (maybe != null)
-                return maybe;
+        //else maybe super class has more precise match
 
         int mod = clazz.getModifiers();
         boolean isIntf = Modifier.isInterface(mod);
@@ -143,8 +141,11 @@ public class MemberResolver implements TokenId {
                 if (pclazz != null) {
                     Method r = lookupMethod(pclazz, methodName, argTypes,
                                             argDims, argClassNames, onlyExact);
-                    if (r != null)
-                        return r;
+                    if (r != null) {
+                        if (maybe == null || maybe.notmatch > r.notmatch) {
+                            maybe = r;
+                        }
+                    }
                 }
             }
         }
@@ -156,8 +157,11 @@ public class MemberResolver implements TokenId {
                 Method r = lookupMethod(intf, methodName,
                         argTypes, argDims, argClassNames,
                         onlyExact);
-                if (r != null)
-                    return r;
+                if (r != null) {
+                    if (maybe == null || maybe.notmatch > r.notmatch) {
+                        maybe = r;
+                    }
+                }
             }
 
             if (isIntf) {
@@ -166,8 +170,11 @@ public class MemberResolver implements TokenId {
                 if (pclazz != null) {
                     Method r = lookupMethod(pclazz, methodName, argTypes,
                                             argDims, argClassNames, onlyExact);
-                    if (r != null)
-                        return r;
+                    if (r != null) {
+                        if (maybe == null || maybe.notmatch > r.notmatch) {
+                            maybe = r;
+                        }
+                    }
                 }
             }
         }
index f1c5683711c1870df46b4caa2ad057e527d7d43d..561181c3beb354481c2dc92b93ad8c1d69dd9444 100644 (file)
@@ -4,6 +4,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
 import java.lang.reflect.TypeVariable;
 
 import javassist.bytecode.AccessFlag;
@@ -166,7 +167,7 @@ public class JvstTest5 extends JvstTestRoot {
         CtClass cc = sloader.makeClass("test5.JIRA256");
         ClassFile ccFile = cc.getClassFile();
         ConstPool constpool = ccFile.getConstPool();
-         
+
         AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
         javassist.bytecode.annotation.Annotation entityAnno
             = new javassist.bytecode.annotation.Annotation("test5.Entity", constpool);
@@ -181,7 +182,7 @@ public class JvstTest5 extends JvstTestRoot {
         assertTrue(o.getClass().getName().equals("test5.JIRA256"));
 
         java.lang.annotation.Annotation[] annotations = o.getClass().getDeclaredAnnotations();
-        assertEquals(1, annotations.length); 
+        assertEquals(1, annotations.length);
     }
 
     public void testJIRA250() throws Exception {
@@ -625,4 +626,24 @@ public class JvstTest5 extends JvstTestRoot {
         assertEquals(1, attr.size());
         assertNull(attr.parameterName(0));
     }
+
+    public void testSuperCall() throws Exception {
+        String javacResult = new BearKeeper().javacResult();
+        assertEquals("Man feed(Bear)", javacResult);
+
+        CtClass cc = sloader.get("javassist.BearKeeper");
+        CtMethod cm = CtMethod.make(
+                "public String javassistResult() {return super.feed(new javassist.Bear());}",
+                cc);
+        cc.addMethod(cm);
+        cc.setModifiers(Modifier.PUBLIC);
+        cc.writeFile();
+        Object obj = make(cc.getName());
+        Method m = obj.getClass().getMethod("javassistResult");
+        Object javassistResult = m.invoke(obj);
+
+        //before this fix
+        //expected:<Man feed(Bear)> but was:<Keeper feed(Animal)>
+        assertEquals(javacResult, javassistResult);
+    }
 }
diff --git a/src/test/javassist/SuperCallCase.java b/src/test/javassist/SuperCallCase.java
new file mode 100644 (file)
index 0000000..8d5ea9e
--- /dev/null
@@ -0,0 +1,38 @@
+package javassist;
+
+class Animal {
+}
+
+class Bear extends Animal {
+}
+
+
+/**
+ * Base class has a method with precise type.
+ */
+class Man {
+    String feed(Bear bear) {
+        return "Man feed(Bear)";
+    }
+}
+
+/**
+ * Derived class has a method which has same name with base class's and more imprecise type.
+ */
+class Keeper extends Man {
+    String feed(Animal animal) {
+        return "Keeper feed(Animal)";
+    }
+}
+
+/**
+ * Derived class has a method which call super method with precise type.
+ */
+class BearKeeper extends Keeper {
+    public BearKeeper() {
+    }
+
+    String javacResult() {
+        return super.feed(new Bear());
+    }
+}