Add user defined generics to methods

This commit is contained in:
Victorious3 2023-01-10 16:06:57 +01:00
parent 229c6c523d
commit 7aa7f94110
4 changed files with 70 additions and 5 deletions

View File

@ -1,3 +1,6 @@
import java.lang.String;
import java.lang.Integer;
class Generics2<B extends String>{
<B extends Integer> B m1(B b){
return b;

View File

@ -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<TargetGeneric> convert(GenericTypeVar typeVar) {
var ret = new ArrayList<TargetGeneric>();
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<TargetGeneric> 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<TargetGeneric> collectMethodGenerics(Set<ResultPair<?, ?>> 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<TargetConstructor> convert(Constructor input, TargetBlock fieldInitializer) {
sigma = all.get(0);
List<TargetConstructor> result = new ArrayList<>();
@ -640,7 +679,8 @@ public class ASTToTargetAST {
var generics = sigma.generics(currentClass, input);
List<MethodParameter> 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<MethodParameter> 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)
));

View File

@ -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());
}
}

View File

@ -226,7 +226,6 @@ public class TestGenerics {
@Ignore("This doesn't work properly")
public void testThreeArgs() throws Exception {
var result = computeGenerics("TestThreeArgs.jav");
}
@Test