From d9bb0037b85a90ce5a1309160f35535f012e68f0 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 17 Jan 2023 11:58:59 +0100 Subject: [PATCH 1/4] Improve genericcs tests --- resources/bytecode/javFiles/Generics3.jav | 7 ++++ .../java/targetast/ASTToTypedTargetAST.java | 41 +++++++++++++++++++ src/test/java/targetast/TestCodegen.java | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 resources/bytecode/javFiles/Generics3.jav diff --git a/resources/bytecode/javFiles/Generics3.jav b/resources/bytecode/javFiles/Generics3.jav new file mode 100644 index 000000000..fb354d430 --- /dev/null +++ b/resources/bytecode/javFiles/Generics3.jav @@ -0,0 +1,7 @@ +import java.lang.String; +import java.lang.Integer; +import java.util.List; + +class Generics3> { + +} \ No newline at end of file diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index fd75bd114..0d26fde5f 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -1,5 +1,6 @@ package targetast; +import com.google.common.reflect.TypeToken; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.environment.ByteArrayClassLoader; import de.dhbwstuttgart.parser.NullToken; @@ -9,12 +10,14 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.tree.TargetClass; import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Ignore; import org.junit.Test; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Vector; import static org.junit.Assert.*; @@ -86,6 +89,21 @@ public class ASTToTypedTargetAST { var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } + @Test + public void gen() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Gen.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var generics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); + var m = generics.getDeclaredMethod("m", Vector.class); + var mReturnType = m.getGenericReturnType(); + assertEquals(mReturnType, m.getParameters()[0].getParameterizedType()); + assertEquals(mReturnType, new TypeToken>(){}.getType()); + } + @Test public void definedGenerics() throws Exception { var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics.jav").toFile(); @@ -95,6 +113,13 @@ public class ASTToTypedTargetAST { var classes = compiler.sourceFiles.get(file).getClasses(); var generics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); + var B = generics.getTypeParameters()[0]; + var mt1 = generics.getDeclaredMethod("mt1", Object.class); + var constructor = generics.getDeclaredConstructor(Object.class); + + assertEquals(B, mt1.getGenericReturnType()); + assertEquals(B, mt1.getParameters()[0].getParameterizedType()); + assertEquals(B, constructor.getParameters()[0].getParameterizedType()); } @Test @@ -106,5 +131,21 @@ public class ASTToTypedTargetAST { var classes = compiler.sourceFiles.get(file).getClasses(); var generics2 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); + assertEquals(generics2.getTypeParameters()[0].getBounds()[0], String.class); + var m = generics2.getDeclaredMethod("m1", Object.class); + assertEquals(m.getTypeParameters()[0].getBounds()[0], Integer.class); + var param = m.getTypeParameters()[0]; + } + + @Test + @Ignore("Not implemented") + public void definedGenerics3() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics3.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var generics3 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } } diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index 104ff7d07..c1c2a5ee7 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -330,7 +330,7 @@ public class TestCodegen { } @Test - @Ignore("The lambda class is not generated because we don'T call ASTToTargetAST") + @Ignore("The lambda class is not generated because we don't call ASTToTargetAST") public void testLambda() throws Exception { var classLoader = new ByteArrayClassLoader(); //var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class")); From 43e8837308a246f8c4c7ebb984d73dbc38b42563 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 17 Jan 2023 12:42:20 +0100 Subject: [PATCH 2/4] Simplify tests by adding BoundsChain --- .../dhbwstuttgart/target/generate/Bound.java | 14 -- .../target/generate/BoundsList.java | 44 ++++++ .../target/generate/GenericsResult.java | 10 +- src/test/java/targetast/TestGenerics.java | 144 +++++++++--------- 4 files changed, 123 insertions(+), 89 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java diff --git a/src/main/java/de/dhbwstuttgart/target/generate/Bound.java b/src/main/java/de/dhbwstuttgart/target/generate/Bound.java index 3b53e864e..1b39df6c4 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/Bound.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/Bound.java @@ -7,18 +7,4 @@ import java.util.List; public record Bound(boolean isOnMethod, RefTypeOrTPHOrWildcardOrGeneric bound) { - public static boolean chainEquals(List left, List right) { - if (left.size() != right.size()) return false; - for (var i = 0; i < left.size(); i++) { - var l = left.get(i); - var r = right.get(i); - if (l.isOnMethod != r.isOnMethod) return false; - if (i == left.size() - 1) { - if (!(l.bound instanceof TypePlaceholder)) { - if (!(l.bound.equals(r.bound))) return false; - } - } - } - return true; - } } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java b/src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java new file mode 100644 index 000000000..b92394d62 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java @@ -0,0 +1,44 @@ +package de.dhbwstuttgart.target.generate; + +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +import java.util.AbstractList; +import java.util.List; + +public class BoundsList extends AbstractList { + private final List bounds; + + public BoundsList(List bounds) { + this.bounds = bounds; + } + public BoundsList(Bound... bounds) { + this.bounds = List.of(bounds); + } + + @Override + public Bound get(int index) { + return bounds.get(index); + } + + @Override + public int size() { + return bounds.size(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof BoundsList right)) return false; + if (size() != right.size()) return false; + for (var i = 0; i < size(); i++) { + var l = get(i); + var r = right.get(i); + if (l.isOnMethod() != r.isOnMethod()) return false; + if (i == size() - 1) { + if (!(l.bound() instanceof TypePlaceholder)) { + if (!(l.bound().equals(r.bound()))) return false; + } + } + } + return true; + } +} diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java b/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java index 29922d852..df7a555fb 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java @@ -11,7 +11,7 @@ import java.util.*; public class GenericsResult { final ASTToTargetAST.Sigma sigma; - public GenericsResult(ASTToTargetAST.Sigma sigma) { + GenericsResult(ASTToTargetAST.Sigma sigma) { this.sigma = sigma; } @@ -23,11 +23,11 @@ public class GenericsResult { return this.sigma.computedGenericsOfMethods.getOrDefault(method, Set.of()); } - public List getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) { + public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) { return getBounds(type, clazz, null); } - public List getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz, Method method) { + public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz, Method method) { type = resolve(type); if (type instanceof TypePlaceholder) { var methodGenerics = get(method); @@ -55,9 +55,9 @@ public class GenericsResult { } bound.ifPresent(result::add); } while (bound.isPresent()); - return result; + return new BoundsList(result); } - return List.of(); + return new BoundsList(List.of()); } public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) { diff --git a/src/test/java/targetast/TestGenerics.java b/src/test/java/targetast/TestGenerics.java index d3b45ca30..8dea939b7 100644 --- a/src/test/java/targetast/TestGenerics.java +++ b/src/test/java/targetast/TestGenerics.java @@ -8,6 +8,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.generate.Bound; +import de.dhbwstuttgart.target.generate.BoundsList; import de.dhbwstuttgart.target.generate.GenericsResult; import org.junit.Ignore; import org.junit.Test; @@ -57,12 +58,13 @@ public class TestGenerics { var ECK1 = generics.getBounds(otherMethod.getParameterList().getParameterAt(0).getType(), result.clazz, anyMethod); var ECK2 = generics.getBounds(otherMethod.getReturnType(), result.clazz, anyMethod); - var ECKChain = List.of(new Bound(false, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(ECK1, ECK2) && Bound.chainEquals(ECK2, ECKChain)); + var ECKChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + assertEquals(ECK1, ECK2); + assertEquals(ECK2, ECKChain); var M = generics.getBounds(a.getType(), result.clazz); - var MChain = List.of(new Bound(false, TypePlaceholder.of("ECK")), new Bound(false, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(M, MChain)); + var MChain = new BoundsList(new Bound(false, TypePlaceholder.of("ECK")), new Bound(false, ASTToTargetAST.OBJECT)); + assertEquals(M, MChain); } @Test @@ -75,8 +77,8 @@ public class TestGenerics { assertEquals(0, generics.get(fReturn).size()); var N = generics.getBounds(fReturn.getReturnType(), result.clazz); - var NChain = List.of(new Bound(false, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(N, NChain)); + var NChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + assertEquals(N, NChain); } @Test @@ -91,18 +93,18 @@ public class TestGenerics { assertEquals(2, generics.get(main).size()); var N = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); - var NChain = List.of(new Bound(true, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(N, NChain)); + var NChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(N, NChain); var Q = generics.getBounds(m.getReturnType(), result.clazz, m); - var QChain = List.of(new Bound(true, TypePlaceholder.of("N")), new Bound(true, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(Q, QChain)); + var QChain = new BoundsList(new Bound(true, TypePlaceholder.of("N")), new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(Q, QChain); var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); - assertTrue(Bound.chainEquals(R, NChain)); + assertEquals(R, NChain); var Q2 = generics.getBounds(main.getReturnType(), result.clazz, main); - assertTrue(Bound.chainEquals(Q2, NChain)); + assertEquals(Q2, NChain); } @Test @@ -120,26 +122,26 @@ public class TestGenerics { assertEquals(2, generics.get(m).size()); var R = generics.getBounds(a.getType(), result.clazz); - var RChain = List.of(new Bound(false, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(R, RChain)); + var RChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + assertEquals(R, RChain); var O = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); - var OChain = List.of(new Bound(true, TypePlaceholder.of("AB")), new Bound(true, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(O, OChain)); + var OChain = new BoundsList(new Bound(true, TypePlaceholder.of("AB")), new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(O, OChain); var AB = generics.getBounds(id.getReturnType(), result.clazz, id); - assertTrue(Bound.chainEquals(AB, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(AB, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); var S = generics.getBounds(setA.getParameterList().getParameterAt(0).getType(), result.clazz, setA); - var SChain = List.of(new Bound(true, TypePlaceholder.of("R")), new Bound(false, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(S, SChain)); - assertTrue(Bound.chainEquals(generics.getBounds(setA.getReturnType(), result.clazz, setA), RChain)); + var SChain = new BoundsList(new Bound(true, TypePlaceholder.of("R")), new Bound(false, ASTToTargetAST.OBJECT)); + assertEquals(S, SChain); + assertEquals(generics.getBounds(setA.getReturnType(), result.clazz, setA), RChain); var X = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); var Y = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); - var XChain = List.of(new Bound(true, ASTToTargetAST.OBJECT)); - var YChain = List.of(new Bound(true, TypePlaceholder.of("Y")), new Bound(true, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(X, XChain)); - assertTrue(Bound.chainEquals(Y, YChain)); + var XChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); + var YChain = new BoundsList(new Bound(true, TypePlaceholder.of("Y")), new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(X, XChain); + assertEquals(Y, YChain); } @Test @@ -164,28 +166,28 @@ public class TestGenerics { assertEquals(3, generics.get(main).size()); var M = generics.getBounds(a.getType(), result.clazz); - assertTrue(Bound.chainEquals(M, List.of(new Bound(false, ASTToTargetAST.OBJECT)))); + assertEquals(M, new BoundsList(new Bound(false, ASTToTargetAST.OBJECT))); var O = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); - var OChain = List.of(new Bound(true, TypePlaceholder.of("P")), new Bound(true, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(O, OChain)); + var OChain = new BoundsList(new Bound(true, TypePlaceholder.of("P")), new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(O, OChain); var AK = generics.getBounds(id.getReturnType(), result.clazz, id); - var AKChain = List.of(new Bound(true, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(AK, AKChain)); + var AKChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(AK, AKChain); // TODO Shouldn't AK and AK2 be the same and on the class? var AK2 = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); var Y = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); - assertTrue(Bound.chainEquals(AK2, AKChain)); - assertTrue(Bound.chainEquals(Y, AKChain)); + assertEquals(AK2, AKChain); + assertEquals(Y, AKChain); var AF = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); var AG= generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); var AK3 = generics.getBounds(main.getReturnType(), result.clazz, main); - var AFChain = List.of(new Bound(true, TypePlaceholder.of("AG")), new Bound(true, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(AF, AFChain)); - assertTrue(Bound.chainEquals(AG, AKChain)); - assertTrue(Bound.chainEquals(AK3, AKChain)); + var AFChain = new BoundsList(new Bound(true, TypePlaceholder.of("AG")), new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(AF, AFChain); + assertEquals(AG, AKChain); + assertEquals(AK3, AKChain); } @Test @@ -197,7 +199,7 @@ public class TestGenerics { assertEquals(1, generics.get(anyMethod).size()); var M = generics.getBounds(anyMethod.getReturnType(), result.clazz, anyMethod); - assertTrue(Bound.chainEquals(M, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(M, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); } @Test @@ -211,15 +213,16 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var M = generics.getBounds(a.getType(), result.clazz); var DYX = generics.getBounds(b.getType(), result.clazz); - var MChain = List.of(new Bound(false, TypePlaceholder.of("DYX")), new Bound(false, ASTToTargetAST.OBJECT)); - var DYXChain = List.of(new Bound(false, ASTToTargetAST.OBJECT)); - assertTrue(Bound.chainEquals(M, MChain)); + var MChain = new BoundsList(new Bound(false, TypePlaceholder.of("DYX")), new Bound(false, ASTToTargetAST.OBJECT)); + var DYXChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + assertEquals(M, MChain); var Q = generics.getBounds(anyMethod.getReturnType(), result.clazz, anyMethod); - assertTrue(Bound.chainEquals(Q, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(Q, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); var DYX2 = generics.getBounds(otherMethod.getReturnType(), result.clazz, otherMethod); - assertTrue(Bound.chainEquals(DYX, DYX2) && Bound.chainEquals(DYX2, DYXChain)); + assertEquals(DYX, DYX2); + assertEquals(DYX2, DYXChain); } @Test @@ -238,18 +241,18 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var U = generics.getBounds(id2.getParameterList().getParameterAt(0).getType(), result.clazz, id2); var FPT = generics.getBounds(id2.getReturnType(), result.clazz, id2); - assertTrue(Bound.chainEquals(U, List.of(new Bound(true, TypePlaceholder.of("FPT")), new Bound(false, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(FPT, List.of(new Bound(false, ASTToTargetAST.OBJECT)))); + assertEquals(U, new BoundsList(new Bound(true, TypePlaceholder.of("FPT")), new Bound(false, ASTToTargetAST.OBJECT))); + assertEquals(FPT, new BoundsList(new Bound(false, ASTToTargetAST.OBJECT))); var AA = generics.getBounds(m.getReturnType(), result.clazz, m); var AC = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); - assertTrue(Bound.chainEquals(AA, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(AC, List.of(new Bound(true, TypePlaceholder.of("AD")), new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(AA, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(AC, new BoundsList(new Bound(true, TypePlaceholder.of("AD")), new Bound(true, ASTToTargetAST.OBJECT))); var AH = generics.getBounds(m2.getReturnType(), result.clazz, m2); var AL = generics.getBounds(m2.getParameterList().getParameterAt(0).getType(), result.clazz, m2); - assertTrue(Bound.chainEquals(AH, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(AH, AL)); + assertEquals(AH, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(AH, AL); } @Test @@ -264,33 +267,34 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var AO = generics.getBounds(a.getType(), result.clazz); - var AOBound = List.of( + var AOBound = new BoundsList( new Bound(false, TypePlaceholder.of("Y")), new Bound(false, TypePlaceholder.of("AK")), new Bound(false, TypePlaceholder.of("AE")), new Bound(false, ASTToTargetAST.OBJECT) ); - assertTrue(Bound.chainEquals(AO, AOBound)); + assertEquals(AO, AOBound); var S = generics.getBounds(setA.getParameterList().getParameterAt(0).getType(), result.clazz, setA); - var SChain = new ArrayList(); - SChain.add(new Bound(true, TypePlaceholder.of("AO"))); - SChain.addAll(AOBound); - assertTrue(Bound.chainEquals(S, SChain)); + var c = new ArrayList(); + c.add(new Bound(true, TypePlaceholder.of("AO"))); + c.addAll(AOBound); + var SChain = new BoundsList(c); + assertEquals(S, SChain); var Y = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); - var YChain = List.of(new Bound(true, TypePlaceholder.of("AE")), new Bound(false, ASTToTargetAST.OBJECT)); + var YChain = new BoundsList(new Bound(true, TypePlaceholder.of("AE")), new Bound(false, ASTToTargetAST.OBJECT)); var AE = generics.getBounds(m.getReturnType(), result.clazz, m); - assertTrue(Bound.chainEquals(Y, YChain)); - assertTrue(Bound.chainEquals(AE, List.of(new Bound(false, ASTToTargetAST.OBJECT)))); + assertEquals(Y, YChain); + assertEquals(AE, new BoundsList(new Bound(false, ASTToTargetAST.OBJECT))); // TODO main seems to change between runs /*var AE2 = generics.getBounds(main.getReturnType(), result.clazz, main); var AF = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); var AG = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); - assertTrue(Bound.chainEquals(AE, AE2)); - assertTrue(Bound.chainEquals(AF, List.of(new Bound(true, TypePlaceholder.of("AK")), new Bound(true, TypePlaceholder.of("AE")), new Bound(false, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(AG, SChain));*/ + assertEquals(AE, AE2)); + assertEquals(AF, new BoundsList(new Bound(true, TypePlaceholder.of("AK")), new Bound(true, TypePlaceholder.of("AE")), new Bound(false, ASTToTargetAST.OBJECT)))); + assertEquals(AG, SChain));*/ } @Test @@ -308,15 +312,15 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var Q = generics.getBounds(id.getReturnType(), result.clazz, id); var N = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); - assertTrue(Bound.chainEquals(Q, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(N, List.of(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(Q, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(N, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); var Q2 = generics.getBounds(main.getReturnType(), result.clazz, main); var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); var S = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); - assertTrue(Bound.chainEquals(Q2, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(R, List.of(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(S, List.of(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(Q2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(R, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(S, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); } @Test @@ -330,8 +334,8 @@ public class TestGenerics { var S = generics.getBounds(((RefType) par1).getParaList().get(0), result.clazz, m); var ACM = generics.getBounds(((RefType) par2).getParaList().get(0), result.clazz, m); - assertTrue(Bound.chainEquals(S, List.of(new Bound(true, TypePlaceholder.of("V")), new Bound(true, TypePlaceholder.of("ACM")), new Bound(true, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(ACM, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(S, new BoundsList(new Bound(true, TypePlaceholder.of("V")), new Bound(true, TypePlaceholder.of("ACM")), new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(ACM, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); } @Test @@ -344,14 +348,14 @@ public class TestGenerics { var par1 = generics.resolve(add.getParameterList().getParameterAt(0).getType()); var ACK = generics.getBounds(((RefType) par1).getParaList().get(0), result.clazz, add); var O = generics.getBounds(add.getParameterList().getParameterAt(1).getType(), result.clazz, add); - assertTrue(Bound.chainEquals(ACK, List.of(new Bound(true, ASTToTargetAST.OBJECT)))); - assertTrue(Bound.chainEquals(O, List.of(new Bound(true, TypePlaceholder.of("ACK")), new Bound(true, ASTToTargetAST.OBJECT)))); + assertEquals(ACK, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(O, new BoundsList(new Bound(true, TypePlaceholder.of("ACK")), new Bound(true, ASTToTargetAST.OBJECT))); var par2 = generics.resolve(main.getParameterList().getParameterAt(0).getType()); var ACK2 = generics.getBounds(((RefType) par2).getParaList().get(0), result.clazz, add); var V = generics.getBounds(add.getParameterList().getParameterAt(1).getType(), result.clazz, add); - assertTrue(Bound.chainEquals(ACK2, ACK)); - assertTrue(Bound.chainEquals(V, O)); + assertEquals(ACK2, ACK); + assertEquals(V, O); } @Test From abe7553c379d1b51b55055ae1281f8bed22e7f41 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 17 Jan 2023 15:57:41 +0100 Subject: [PATCH 3/4] Add missing object bounds --- resources/bytecode/javFiles/Generics4.jav | 12 +++++++++ .../target/generate/ASTToTargetAST.java | 27 +++++++++++++++---- .../java/targetast/ASTToTypedTargetAST.java | 15 +++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 resources/bytecode/javFiles/Generics4.jav diff --git a/resources/bytecode/javFiles/Generics4.jav b/resources/bytecode/javFiles/Generics4.jav new file mode 100644 index 000000000..e66bd3a0a --- /dev/null +++ b/resources/bytecode/javFiles/Generics4.jav @@ -0,0 +1,12 @@ +import java.lang.String; +import java.lang.Integer; + +class Generics4 { + C m1(C b){ + return b; + } + + m2(x) { + return m1(); + } +} \ No newline at end of file diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index a1359be4e..3b34c459b 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -17,7 +17,6 @@ import de.dhbwstuttgart.typeinference.result.*; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.stream.StreamSupport; /** * @author dholle @@ -453,11 +452,14 @@ public class ASTToTargetAST { eliminateInfima(input); } - RefTypeOrTPHOrWildcardOrGeneric getType(TypePlaceholder tph) { - if (equality.containsKey(tph)) { - return getType(equality.get(tph)); + RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) { + if (type instanceof TypePlaceholder tph) { + if (equality.containsKey(tph)) { + return getType(equality.get(tph)); + } + return concreteTypes.getOrDefault(tph, tph); } - return concreteTypes.getOrDefault(tph, tph); + return type; } TargetType getTargetType(TypePlaceholder tph) { @@ -655,6 +657,10 @@ public class ASTToTargetAST { .map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList(); } + private boolean hasGeneric(Set generics, GenericRefType type) { + return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName())); + } + private Set collectMethodGenerics(Set> generics, Method input) { var convertedGenerics = new HashSet<>(convert(generics)); outer: @@ -666,6 +672,17 @@ public class ASTToTargetAST { } convertedGenerics.addAll(convert(typeVar)); } + var returnType = sigma.getType(input.getReturnType()); + if ((returnType instanceof GenericRefType refType) && !hasGeneric(convertedGenerics, refType)) { + convertedGenerics.add(new TargetGeneric(refType.getParsedName(), convert(OBJECT))); + } + for (var param : input.getParameterList()) { + var type = sigma.getType(param.getType()); + if (type instanceof GenericRefType refType && !hasGeneric(convertedGenerics, refType)) { + convertedGenerics.add(new TargetGeneric(refType.getParsedName(), convert(OBJECT))); + } + } + return convertedGenerics; } diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index 0d26fde5f..6d5a08c02 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -148,4 +148,19 @@ public class ASTToTypedTargetAST { var generics3 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } + + @Test + public void definedGenerics4() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics4.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var generics4 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); + + //var instance = generics4.getDeclaredConstructor().newInstance(); + //var method = generics4.getDeclaredMethod("m2", Object.class); + //method.invoke(instance, new Object()); + } } From db089bea60f3463d7ae2758391cb53b4cca8041a Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 17 Jan 2023 16:05:15 +0100 Subject: [PATCH 4/4] Forgot x here --- resources/bytecode/javFiles/Generics4.jav | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/bytecode/javFiles/Generics4.jav b/resources/bytecode/javFiles/Generics4.jav index e66bd3a0a..50b0b3e23 100644 --- a/resources/bytecode/javFiles/Generics4.jav +++ b/resources/bytecode/javFiles/Generics4.jav @@ -7,6 +7,6 @@ class Generics4 { } m2(x) { - return m1(); + return m1(x); } } \ No newline at end of file