diff --git a/pom.xml b/pom.xml index 78e5bf45..3236c59c 100644 --- a/pom.xml +++ b/pom.xml @@ -17,10 +17,11 @@ http://maven.apache.org/maven-v4_0_0.xsd"> 4.11 test + org.antlr antlr4 - 4.8-1 + 4.11.1 commons-io @@ -53,12 +54,14 @@ http://maven.apache.org/maven-v4_0_0.xsd"> 3.8.0 --enable-preview - + 19 + 19 + org.antlr antlr4-maven-plugin - 4.8-1 + 4.11.1 antlr diff --git a/resources/bytecode/javFiles/Generics2.jav b/resources/bytecode/javFiles/Generics2.jav index 52d5caa2..762890bd 100644 --- a/resources/bytecode/javFiles/Generics2.jav +++ b/resources/bytecode/javFiles/Generics2.jav @@ -1,3 +1,6 @@ +import java.lang.String; +import java.lang.Integer; + class Generics2{ B m1(B b){ return b; diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index b2e9048f..a1359be4 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -17,7 +17,11 @@ 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 + */ public class ASTToTargetAST { public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change @@ -608,16 +612,37 @@ public class ASTToTargetAST { }).collect(Collectors.toSet()); } + public List convert(GenericTypeVar typeVar) { + var ret = new ArrayList(); + for (var bound : typeVar.getBounds()) { + ret.add(new TargetGeneric(typeVar.getName(), convert(bound))); + } + return ret; + } + public TargetClass convert(ClassOrInterface input) { currentClass = input; - var generics = sigma.generics(input); + Set generics = new HashSet<>(); + var genericsIter = input.getGenerics().iterator(); + if (genericsIter.hasNext()) { + // Add empty set of generics to cache so that it doesn't try to calculate it later + sigma.computedGenericsOfClasses.put(input, new HashSet<>()); + while (genericsIter.hasNext()) { + var next = genericsIter.next(); + generics.addAll(convert(next)); + } + } else { + // Generate generics only if there are no user defined ones + generics = convert(sigma.generics(input)); + } + TargetBlock fieldInitializer = null; if (input.getfieldInitializations().isPresent()) fieldInitializer = convert(input.getfieldInitializations().get().block); TargetBlock finalFieldInitializer = fieldInitializer; return new TargetClass(input.getModifiers(), input.getClassName().toString(), convert(input.getSuperClass()), - convert(generics), + generics, input.getSuperInterfaces().stream().map(this::convert).toList(), input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList(), input.getFieldDecl().stream().map(this::convert).toList(), @@ -630,6 +655,20 @@ public class ASTToTargetAST { .map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList(); } + private Set collectMethodGenerics(Set> generics, Method input) { + var convertedGenerics = new HashSet<>(convert(generics)); + outer: + for (GenericTypeVar typeVar : input.getGenerics()) { + for (var classGeneric : currentClass.getGenerics()) { + if (classGeneric.equals(typeVar)) { + continue outer; + } + } + convertedGenerics.addAll(convert(typeVar)); + } + return convertedGenerics; + } + private List convert(Constructor input, TargetBlock fieldInitializer) { sigma = all.get(0); List result = new ArrayList<>(); @@ -640,7 +679,8 @@ public class ASTToTargetAST { var generics = sigma.generics(currentClass, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { - result.add(new TargetConstructor(input.modifier, convert(generics), params, convert(input.block), fieldInitializer)); + var convertedGenerics = collectMethodGenerics(generics, input); + result.add(new TargetConstructor(input.modifier, convertedGenerics, params, convert(input.block), fieldInitializer)); parameterSet.add(params); } } @@ -658,9 +698,10 @@ public class ASTToTargetAST { var generics = sigma.generics(currentClass, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { + var convertedGenerics = collectMethodGenerics(generics, input); result.add(new TargetMethod( input.modifier, - input.name, convert(generics), params, + input.name, convertedGenerics, params, convert(input.getReturnType()), convert(input.block) )); diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index a8994318..fd75bd11 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -33,7 +33,7 @@ public class ASTToTypedTargetAST { @Test public void overloading() throws Exception { - var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Overloading.jav").toFile(); + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Overloading.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(); var converter = new ASTToTargetAST(resultSet); @@ -55,7 +55,7 @@ public class ASTToTypedTargetAST { @Test public void tphsAndGenerics() throws Exception { - var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Tph2.jav").toFile(); + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Tph2.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(); var converter = new ASTToTargetAST(resultSet); @@ -66,7 +66,7 @@ public class ASTToTypedTargetAST { @Test public void cycles() throws Exception { - var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Cycle.jav").toFile(); + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(); var converter = new ASTToTargetAST(resultSet); @@ -77,7 +77,7 @@ public class ASTToTypedTargetAST { @Test public void infimum() throws Exception { - var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Infimum.jav").toFile(); + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Infimum.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(); var converter = new ASTToTargetAST(resultSet); @@ -85,4 +85,26 @@ public class ASTToTypedTargetAST { var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); } + + @Test + public void definedGenerics() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics.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()); + } + + @Test + public void definedGenerics2() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics2.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var generics2 = 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 8bc767b8..104ff7d0 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -42,7 +42,7 @@ public class TestCodegen { } public static Map> generateClassFiles(String filename, IByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException { - var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/", filename).toFile(); + var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/", filename).toFile(); var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile())); var resultSet = compiler.typeInference(); var sourceFile = compiler.sourceFiles.get(file); diff --git a/src/test/java/targetast/TestGenerics.java b/src/test/java/targetast/TestGenerics.java index 4e80d3f2..d3b45ca3 100644 --- a/src/test/java/targetast/TestGenerics.java +++ b/src/test/java/targetast/TestGenerics.java @@ -22,7 +22,7 @@ import java.util.List; public class TestGenerics { - private static final String rootDirectory = System.getProperty("user.dir") + "/src/test/resources/insertGenericsJav/"; + private static final String rootDirectory = System.getProperty("user.dir") + "/resources/insertGenericsJav/"; private static final String bytecodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/"; private record Result(List genericsResults, ClassOrInterface clazz) { @@ -226,7 +226,6 @@ public class TestGenerics { @Ignore("This doesn't work properly") public void testThreeArgs() throws Exception { var result = computeGenerics("TestThreeArgs.jav"); - } @Test