diff --git a/resources/bytecode/javFiles/TXGenerics.jav b/resources/bytecode/javFiles/TXGenerics.jav new file mode 100644 index 00000000..8dd7ab76 --- /dev/null +++ b/resources/bytecode/javFiles/TXGenerics.jav @@ -0,0 +1,11 @@ +import java.lang.String; + +class TXGenerics { + a; + b; + + test() { + var c = new Cycle(); + c.m(a, b); + } +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index 7582865d..5b631250 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -19,6 +19,7 @@ import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.statement.Statement; import de.dhbwstuttgart.syntaxtree.type.WildcardType; +import de.dhbwstuttgart.target.tree.type.TargetRefType; import de.dhbwstuttgart.util.Pair; import javassist.bytecode.SignatureAttribute; import org.antlr.v4.runtime.Token; @@ -207,7 +208,8 @@ public class ASTFactory { } return new GenericDeclarationList(gtvs, new NullToken()); } else { - return createGenerics(signature); + var res = createGenerics(signature); + return res; } } @@ -220,8 +222,31 @@ public class ASTFactory { final Stack bound = new Stack<>(); final Stack classTypes = new Stack<>(); + // All hail the mighty visitor pattern + final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {}; + char wildcard = '='; + @Override + public SignatureVisitor visitSuperclass() { + return doNothing; + } + + @Override + public SignatureVisitor visitParameterType() { + return doNothing; + } + + @Override + public SignatureVisitor visitReturnType() { + return doNothing; + } + + @Override + public SignatureVisitor visitExceptionType() { + return doNothing; + } + @Override public void visitFormalTypeParameter(String name) { bounds = new ArrayList<>(); @@ -231,7 +256,11 @@ public class ASTFactory { @Override public void visitTypeVariable(String name) { var refType = new GenericRefType(name, new NullToken()); - pushType(refType); + if (classTypes.isEmpty()) { + ((List) gtvs.get(gtvs.size() - 1).getBounds()).add(refType); + } else { + pushType(refType); + } } @Override @@ -257,13 +286,13 @@ public class ASTFactory { return this; } - boolean equals(RefTypeOrTPHOrWildcardOrGeneric a, RefTypeOrTPHOrWildcardOrGeneric b) { + boolean equals(RefTypeOrTPHOrWildcardOrGeneric a, RefTypeOrTPHOrWildcardOrGeneric b) { if (b instanceof SuperWildcardType wc) return equals(a, wc.getInnerType()); else if (b instanceof ExtendsWildcardType wc) return equals(a, wc.getInnerType()); return a == b; - } + } @Override public void visitEnd() { diff --git a/src/main/java/de/dhbwstuttgart/util/Pair.java b/src/main/java/de/dhbwstuttgart/util/Pair.java index 3046afda..8bd5bf94 100644 --- a/src/main/java/de/dhbwstuttgart/util/Pair.java +++ b/src/main/java/de/dhbwstuttgart/util/Pair.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.util; +import java.util.Objects; import java.util.Optional; public class Pair { @@ -22,4 +23,17 @@ public class Pair { public String toString() { return "(" + key.toString() + "," + value.toString() + ")\n"; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Pair pair = (Pair) o; + return Objects.equals(key, pair.key) && Objects.equals(value, pair.value); + } + + @Override + public int hashCode() { + return Objects.hash(key, value); + } } diff --git a/src/test/java/GenericsParserTest.java b/src/test/java/GenericsParserTest.java index 6e711415..f35e51ed 100644 --- a/src/test/java/GenericsParserTest.java +++ b/src/test/java/GenericsParserTest.java @@ -1,4 +1,5 @@ import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; import de.dhbwstuttgart.syntaxtree.GenericTypeVar; @@ -57,6 +58,24 @@ public class GenericsParserTest { ); } + @Test + public void testMethodTypeVars() { + var signature = ";D:TB;>()V"; + var generics = ASTFactory.createGenerics(signature); + assertEquals(generics, new GenericDeclarationList( + List.of( + new GenericTypeVar("A", List.of(new GenericRefType("B", new NullToken())), new NullToken(), new NullToken()), + new GenericTypeVar("B", List.of(new RefType(new JavaClassName("ClassA"), new NullToken())), new NullToken(), new NullToken()), + new GenericTypeVar("C", List.of(new RefType(new JavaClassName("ClassB"), + List.of(new GenericRefType("A", new NullToken())), + new NullToken())), new NullToken(), new NullToken() + ), + new GenericTypeVar("D", List.of(new GenericRefType("B", new NullToken())), new NullToken(), new NullToken()) + ), + new NullToken() + )); + } + @Test public void testMethodComplex() { var signature = ";>;>;U:LClassC;>()V"; diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java index 34d1370f..a5c56828 100644 --- a/src/test/java/targetast/TestComplete.java +++ b/src/test/java/targetast/TestComplete.java @@ -575,6 +575,11 @@ public class TestComplete { assertEquals(fstArgm2, m2.getGenericReturnType()); } + @Test + public void testTXGenerics() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "TXGenerics.jav"); + var instance = classFiles.get("TXGenerics").getDeclaredConstructor().newInstance(); + } @Test public void typedIdTest() throws Exception {