From 7aa7f941103ca6d103cbcb718783d98ea64089dd Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 10 Jan 2023 16:06:57 +0100 Subject: [PATCH] Add user defined generics to methods --- resources/bytecode/javFiles/Generics2.jav | 3 ++ .../target/generate/ASTToTargetAST.java | 49 +++++++++++++++++-- .../java/targetast/ASTToTypedTargetAST.java | 22 +++++++++ src/test/java/targetast/TestGenerics.java | 1 - 4 files changed, 70 insertions(+), 5 deletions(-) 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 6fc382db..fd75bd11 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -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/TestGenerics.java b/src/test/java/targetast/TestGenerics.java index c782f579..d3b45ca3 100644 --- a/src/test/java/targetast/TestGenerics.java +++ b/src/test/java/targetast/TestGenerics.java @@ -226,7 +226,6 @@ public class TestGenerics { @Ignore("This doesn't work properly") public void testThreeArgs() throws Exception { var result = computeGenerics("TestThreeArgs.jav"); - } @Test