Просмотр исходного кода

draft: new: CGAdapter: if not ambiguous, delegate to even incompatible method

Mariusz Sieroń 6 лет назад
Родитель
Сommit
dc19999aa6

+ 22 - 0
assira.drafts/src/main/java/net/ranides/assira/reflection/asm/cg/CGAdapter.java

@@ -125,6 +125,10 @@ public class CGAdapter implements IClassGenerator {
         IMethod target = query.filter(r -> r.declares(method.arguments())).first()
         IMethod target = query.filter(r -> r.declares(method.arguments())).first()
                 .or(() -> query.filter(r -> r.matches(method.arguments())).first())
                 .or(() -> query.filter(r -> r.matches(method.arguments())).first())
                 .or(() -> query.filter(r -> method.matches(r.arguments())).first())
                 .or(() -> query.filter(r -> method.matches(r.arguments())).first())
+                .or(() -> {
+                    List<IMethod> out = query.filter(r -> possible(method, r)).list();
+                    return Optional.ofNullable(out.size()==1 ? out.get(0) : null);
+                })
                 .orElseThrow(() -> new IllegalArgumentException("Not found method for: " + method));
                 .orElseThrow(() -> new IllegalArgumentException("Not found method for: " + method));
 
 
         List<IClass<?>> oargs = target.arguments().types().list();
         List<IClass<?>> oargs = target.arguments().types().list();
@@ -150,6 +154,24 @@ public class CGAdapter implements IClassGenerator {
         m.end();
         m.end();
     }
     }
 
 
+    private boolean possible(IMethod m1, IMethod m2) {
+        if(m1.arguments().count() != m2.arguments().count()) {
+            return false;
+        }
+        List<IClass<?>> args1 = m1.arguments().types().list();
+        List<IClass<?>> args2 = m2.arguments().types().list();
+        for(int i=0,n=args1.size(); i<n; i++) {
+            if(!possible(args1.get(i), args2.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean possible(IClass<?> c1, IClass<?> c2) {
+        return (!IAttribute.PRIMITIVE.match(c1) && !IAttribute.PRIMITIVE.match(c2)) || c1.isEquivalent(c2);
+    }
+
     private void scanInner(IClass<?> type) {
     private void scanInner(IClass<?> type) {
         addInner(type);
         addInner(type);
 
 

+ 11 - 2
assira.drafts/src/test/java/net/ranides/assira/reflection/AdapterTest.java

@@ -6,6 +6,8 @@ import net.ranides.assira.reflection.adapter.model0.Image0;
 import net.ranides.assira.reflection.adapter.model0.Screen0;
 import net.ranides.assira.reflection.adapter.model0.Screen0;
 import net.ranides.assira.reflection.adapter.model1.Screen1;
 import net.ranides.assira.reflection.adapter.model1.Screen1;
 import net.ranides.assira.reflection.adapter.model2.Image2;
 import net.ranides.assira.reflection.adapter.model2.Image2;
+import net.ranides.assira.reflection.adapter.model2.Image2class;
+import net.ranides.assira.reflection.adapter.model2.Image2error;
 import net.ranides.assira.reflection.adapter.model2.Screen2;
 import net.ranides.assira.reflection.adapter.model2.Screen2;
 import net.ranides.assira.reflection.adapter.model3.Image3;
 import net.ranides.assira.reflection.adapter.model3.Image3;
 import net.ranides.assira.reflection.adapter.model3.Screen3;
 import net.ranides.assira.reflection.adapter.model3.Screen3;
@@ -16,7 +18,7 @@ import org.objectweb.asm.util.ASMifier;
 import java.io.IOException;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Arrays;
 
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
 
 
 public class AdapterTest {
 public class AdapterTest {
 
 
@@ -47,7 +49,14 @@ public class AdapterTest {
         assertEquals("640x480 false", screen2.width()+"x"+screen2.height()+" "+screen2.isWide());
         assertEquals("640x480 false", screen2.width()+"x"+screen2.height()+" "+screen2.isWide());
 
 
         assertEquals(new Image0("first", 4, 5), screen2.put("first",4,5));
         assertEquals(new Image0("first", 4, 5), screen2.put("first",4,5));
-        assertEquals(new Image0("second", 7, 8), screen2.put(new Image0("second",7,8)));
+        assertEquals(new Image0("second", 7, 8), screen2.put(new Image2class("second",7,8)));
+
+        try {
+            assertEquals(new Image0("second", 7, 8), screen2.put(new Image2error()));
+            fail("ClassCastException expected");
+        } catch(ClassCastException ex) {
+            assertTrue(true);
+        }
 
 
         screen2.add("far",420,150);
         screen2.add("far",420,150);
 //        screen2.add(new Image0("last",2,3)); // declaration requires more specific object
 //        screen2.add(new Image0("last",2,3)); // declaration requires more specific object

+ 15 - 0
assira.drafts/src/test/java/net/ranides/assira/reflection/adapter/model2/Image2class.java

@@ -0,0 +1,15 @@
+package net.ranides.assira.reflection.adapter.model2;
+
+import net.ranides.assira.reflection.adapter.model0.Image0;
+
+public class Image2class extends Image0 implements Image2mix {
+
+    public Image2class(String id, int x, int y) {
+        super(id, x, y);
+    }
+
+    @Override
+    public String uid() {
+        return getId()+"-"+getX()+getY();
+    }
+}

+ 9 - 0
assira.drafts/src/test/java/net/ranides/assira/reflection/adapter/model2/Image2error.java

@@ -0,0 +1,9 @@
+package net.ranides.assira.reflection.adapter.model2;
+
+public class Image2error implements Image2mix {
+
+    @Override
+    public String uid() {
+        return "mix";
+    }
+}

+ 7 - 0
assira.drafts/src/test/java/net/ranides/assira/reflection/adapter/model2/Image2mix.java

@@ -0,0 +1,7 @@
+package net.ranides.assira.reflection.adapter.model2;
+
+public interface Image2mix {
+
+    String uid();
+
+}

+ 1 - 1
assira.drafts/src/test/java/net/ranides/assira/reflection/adapter/model2/Screen2.java

@@ -8,7 +8,7 @@ public interface Screen2 {
 
 
     Object put(String id, int x, int y);
     Object put(String id, int x, int y);
 
 
-    Object put(Object image);
+    Object put(Image2mix image);
 
 
     void add(String id, int x, int y);
     void add(String id, int x, int y);