forked from JavaTX/JavaCompilerCore
Add interfaces
This commit is contained in:
parent
628f1631e8
commit
892ba5fff0
33
resources/bytecode/javFiles/Interfaces.jav
Normal file
33
resources/bytecode/javFiles/Interfaces.jav
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
void method1();
|
||||||
|
default method2() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
void method3();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface C {
|
||||||
|
Integer myInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassX implements A {
|
||||||
|
}
|
||||||
|
|
||||||
|
record ClassY(Integer myInt) implements C {}
|
||||||
|
|
||||||
|
public class Interfaces implements A, B {
|
||||||
|
public void method1() {
|
||||||
|
}
|
||||||
|
public void method3() {
|
||||||
|
var intf = new Interfaces();
|
||||||
|
intf = new ClassX();
|
||||||
|
intf.method1();
|
||||||
|
|
||||||
|
C c = new ClassY(10);
|
||||||
|
c.myInt();
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import de.dhbwstuttgart.target.tree.type.*;
|
|||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.lang.invoke.*;
|
import java.lang.invoke.*;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
@ -1345,45 +1346,61 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateMethod(TargetMethod method) {
|
private void generateMethod(TargetMethod method) {
|
||||||
|
var access = method.access() | ACC_PUBLIC;
|
||||||
|
if (method.block() == null)
|
||||||
|
access |= ACC_ABSTRACT;
|
||||||
|
|
||||||
// TODO The older codegen has set ACC_PUBLIC for all methods, good for testing but bad for everything else
|
// TODO The older codegen has set ACC_PUBLIC for all methods, good for testing but bad for everything else
|
||||||
MethodVisitor mv = cw.visitMethod(method.access() | ACC_PUBLIC, method.name(), method.getDescriptor(), method.getSignature(), null);
|
MethodVisitor mv = cw.visitMethod(access, method.name(), method.getDescriptor(), method.getSignature(), null);
|
||||||
if (method.txSignature() != null) {
|
if (method.txSignature() != null) {
|
||||||
mv.visitAttribute(new JavaTXSignatureAttribute(method.getTXSignature()));
|
mv.visitAttribute(new JavaTXSignatureAttribute(method.getTXSignature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
mv.visitCode();
|
if (method.block() != null) {
|
||||||
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
|
mv.visitCode();
|
||||||
for (var param : method.signature().parameters()) {
|
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
|
||||||
bindLocalVariables(state, param.pattern(), 1, 0);
|
for (var param : method.signature().parameters()) {
|
||||||
|
bindLocalVariables(state, param.pattern(), 1, 0);
|
||||||
|
}
|
||||||
|
generate(state, method.block());
|
||||||
|
if (method.signature().returnType() == null)
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
}
|
}
|
||||||
generate(state, method.block());
|
|
||||||
if (method.signature().returnType() == null)
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String generateSignature(TargetStructure clazz, Set<TargetGeneric> generics) {
|
private static String generateSignature(TargetStructure clazz, Set<TargetGeneric> generics) {
|
||||||
String ret = "";
|
String ret = "";
|
||||||
if (generics.size() > 0) {
|
if (!generics.isEmpty()) {
|
||||||
ret += "<";
|
ret += "<";
|
||||||
for (var generic : generics) {
|
for (var generic : generics) {
|
||||||
ret += generic.name() + ":" + generic.bound().toDescriptor();
|
ret += generic.name() + ":" + generic.bound().toDescriptor();
|
||||||
}
|
}
|
||||||
ret += ">";
|
ret += ">";
|
||||||
}
|
}
|
||||||
ret += clazz.superType().toDescriptor();
|
if (clazz.superType() != null)
|
||||||
|
ret += clazz.superType().toDescriptor();
|
||||||
|
for (var intf : clazz.implementingInterfaces()) {
|
||||||
|
ret += intf.toSignature();
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret.isEmpty() ? null : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] generate() {
|
public byte[] generate() {
|
||||||
var access = clazz.modifiers();
|
var access = clazz.modifiers();
|
||||||
if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
|
if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
|
||||||
access |= ACC_PUBLIC;
|
access |= ACC_PUBLIC;
|
||||||
|
if (!(clazz instanceof TargetInterface))
|
||||||
|
access |= ACC_SUPER;
|
||||||
|
|
||||||
cw.visit(V1_8, access | ACC_SUPER, clazz.qualifiedName().toString().replaceAll("\\.", "/"), generateSignature(clazz, clazz.generics()), clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object", clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new));
|
var signature = generateSignature(clazz, clazz.generics());
|
||||||
if (clazz.txGenerics() != null)
|
var interfaces = clazz.implementingInterfaces().stream().map(TargetType::getInternalName).toArray(String[]::new);
|
||||||
|
var superType = clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object";
|
||||||
|
|
||||||
|
cw.visit(V1_8, access, clazz.qualifiedName().toString().replaceAll("\\.", "/"), signature, superType, interfaces);
|
||||||
|
if (clazz.txGenerics() != null && signature != null)
|
||||||
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
|
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
|
||||||
|
|
||||||
clazz.fields().forEach(this::generateField);
|
clazz.fields().forEach(this::generateField);
|
||||||
|
@ -40,8 +40,9 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
|||||||
|
|
||||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
|
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
|
||||||
super(offset);
|
super(offset);
|
||||||
if (isInterface && !Modifier.isInterface(modifiers))
|
if (isInterface) {
|
||||||
modifiers += Modifier.INTERFACE;
|
modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT;
|
||||||
|
}
|
||||||
this.modifiers = modifiers;
|
this.modifiers = modifiers;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.fields = fielddecl;
|
this.fields = fielddecl;
|
||||||
@ -72,6 +73,10 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
|||||||
this.constructors = new ArrayList<>(cl.constructors);
|
this.constructors = new ArrayList<>(cl.constructors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInterface() {
|
||||||
|
return (Modifier.INTERFACE & this.getModifiers()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Gets if it is added
|
// Gets if it is added
|
||||||
public Boolean areMethodsAdded() {
|
public Boolean areMethodsAdded() {
|
||||||
return methodAdded;
|
return methodAdded;
|
||||||
|
@ -113,7 +113,7 @@ public class OutputGenerator implements ASTVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ClassOrInterface classOrInterface) {
|
public void visit(ClassOrInterface classOrInterface) {
|
||||||
if ((Modifier.INTERFACE & classOrInterface.getModifiers()) == 1) {
|
if (classOrInterface.isInterface()) {
|
||||||
out.append("interface ");
|
out.append("interface ");
|
||||||
} else {
|
} else {
|
||||||
out.append("class ");
|
out.append("class ");
|
||||||
|
@ -146,6 +146,8 @@ public class ASTToTargetAST {
|
|||||||
|
|
||||||
if (input instanceof Record)
|
if (input instanceof Record)
|
||||||
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
|
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
|
||||||
|
else if (input.isInterface())
|
||||||
|
return new TargetInterface(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, methods, superInterfaces);
|
||||||
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
|
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,6 +358,7 @@ public class ASTToTargetAST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected TargetBlock convert(Block block) {
|
protected TargetBlock convert(Block block) {
|
||||||
|
if (block == null) return null;
|
||||||
return new TargetBlock(block.statements.stream().map(this::convert).toList());
|
return new TargetBlock(block.statements.stream().map(this::convert).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,153 +262,154 @@ public abstract class GenerateGenerics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
method.block.accept(new TracingStatementVisitor() {
|
if (method.block != null)
|
||||||
|
method.block.accept(new TracingStatementVisitor() {
|
||||||
|
|
||||||
private RefTypeOrTPHOrWildcardOrGeneric superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
|
private RefTypeOrTPHOrWildcardOrGeneric superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MethodCall methodCall) {
|
public void visit(MethodCall methodCall) {
|
||||||
//Anfang es werden Paare von TPHs gespeichert, die bei den Generated Generics ueber die Methodengrenzen hinweg
|
//Anfang es werden Paare von TPHs gespeichert, die bei den Generated Generics ueber die Methodengrenzen hinweg
|
||||||
//betrachtet werden muessen
|
//betrachtet werden muessen
|
||||||
//Definition 7.2 (Family of generated generics). T1 <. R1 <.^∗ R2 <. T2
|
//Definition 7.2 (Family of generated generics). T1 <. R1 <.^∗ R2 <. T2
|
||||||
Set<TPH> T1s =
|
Set<TPH> T1s =
|
||||||
methodCall.getArgumentList()
|
methodCall.getArgumentList()
|
||||||
.getArguments()
|
.getArguments()
|
||||||
.stream()
|
.stream()
|
||||||
.map(TypableStatement::getType)
|
.map(TypableStatement::getType)
|
||||||
.collect(Collectors.toCollection(HashSet::new))
|
.collect(Collectors.toCollection(HashSet::new))
|
||||||
.stream().filter(TypePlaceholder.class::isInstance)
|
.stream().filter(TypePlaceholder.class::isInstance)
|
||||||
.map(TypePlaceholder.class::cast)
|
.map(TypePlaceholder.class::cast)
|
||||||
.map(TPH::new)
|
.map(TPH::new)
|
||||||
.collect(Collectors.toCollection(HashSet::new));
|
.collect(Collectors.toCollection(HashSet::new));
|
||||||
Set<TPH> T2s = new HashSet<>();
|
Set<TPH> T2s = new HashSet<>();
|
||||||
findTphs(superType, T2s);
|
findTphs(superType, T2s);
|
||||||
|
|
||||||
System.out.println("T1s: " + T1s + " T2s: " + T2s);
|
System.out.println("T1s: " + T1s + " T2s: " + T2s);
|
||||||
//Ende
|
//Ende
|
||||||
|
|
||||||
superType = methodCall.receiverType;
|
superType = methodCall.receiverType;
|
||||||
methodCall.receiver.accept(this);
|
methodCall.receiver.accept(this);
|
||||||
for (int i = 0; i < methodCall.arglist.getArguments().size(); i++) {
|
for (int i = 0; i < methodCall.arglist.getArguments().size(); i++) {
|
||||||
superType = methodCall.arglist.getArguments().get(i).getType();
|
superType = methodCall.arglist.getArguments().get(i).getType();
|
||||||
methodCall.arglist.getArguments().get(i).accept(this);
|
methodCall.arglist.getArguments().get(i).accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
|
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
|
||||||
if (expressionReceiver.expr instanceof This) {
|
if (expressionReceiver.expr instanceof This) {
|
||||||
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.getArgumentList());
|
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.getArgumentList());
|
||||||
if (optMethod.isEmpty()) return;
|
if (optMethod.isEmpty()) return;
|
||||||
var method2 = optMethod.get();
|
var method2 = optMethod.get();
|
||||||
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
|
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
|
||||||
var generics = family(owner, method2);
|
var generics = family(owner, method2);
|
||||||
|
|
||||||
// transitive and
|
// transitive and
|
||||||
var all = transitiveClosure(generics);
|
var all = transitiveClosure(generics);
|
||||||
// reflexive
|
// reflexive
|
||||||
var toAdd = new HashSet<Pair>();
|
var toAdd = new HashSet<Pair>();
|
||||||
for (var generic : all) {
|
for (var generic : all) {
|
||||||
toAdd.add(new PairLT(generic.left, generic.left));
|
toAdd.add(new PairLT(generic.left, generic.left));
|
||||||
}
|
}
|
||||||
all.addAll(toAdd);
|
all.addAll(toAdd);
|
||||||
|
|
||||||
HashSet<PairLT> newPairs = new HashSet<>();
|
HashSet<PairLT> newPairs = new HashSet<>();
|
||||||
|
|
||||||
// Loop from hell
|
// Loop from hell
|
||||||
outer:
|
outer:
|
||||||
for (var R1 : typeVariables) {
|
for (var R1 : typeVariables) {
|
||||||
if (typeVariablesOfClass.contains(R1)) continue;
|
if (typeVariablesOfClass.contains(R1)) continue;
|
||||||
for (var generic : all)
|
for (var generic : all)
|
||||||
if (generic instanceof PairLT ptph) {
|
if (generic instanceof PairLT ptph) {
|
||||||
for (var pair : simplifiedConstraints) {
|
for (var pair : simplifiedConstraints) {
|
||||||
if (!(pair.left.equals(R1) && pair.right.equals(ptph.left)))
|
if (!(pair.left.equals(R1) && pair.right.equals(ptph.left)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (var R2 : typeVariables) {
|
for (var R2 : typeVariables) {
|
||||||
for (var pair2 : simplifiedConstraints) {
|
for (var pair2 : simplifiedConstraints) {
|
||||||
|
|
||||||
if (!(pair2.right.equals(R2) && pair2.left.equals(ptph.right)))
|
if (!(pair2.right.equals(R2) && pair2.left.equals(ptph.right)))
|
||||||
continue;
|
continue;
|
||||||
if (R1.equals(R2)) continue;
|
if (R1.equals(R2)) continue;
|
||||||
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
|
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
|
||||||
|
|
||||||
var newPair = new PairLT(R1, R2);
|
var newPair = new PairLT(R1, R2);
|
||||||
System.out.println("New pair: " + newPair);
|
System.out.println("New pair: " + newPair);
|
||||||
newPairs.add(newPair);
|
newPairs.add(newPair);
|
||||||
|
|
||||||
if (!containsRelation(result, newPair))
|
if (!containsRelation(result, newPair))
|
||||||
addToPairs(result, newPair);
|
addToPairs(result, newPair);
|
||||||
continue outer;
|
continue outer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
simplifiedConstraints.addAll(newPairs);
|
||||||
}
|
}
|
||||||
simplifiedConstraints.addAll(newPairs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(LambdaExpression lambdaExpression) {
|
public void visit(LambdaExpression lambdaExpression) {
|
||||||
superType = new Void(new NullToken());
|
superType = new Void(new NullToken());
|
||||||
lambdaExpression.methodBody.accept(this);
|
lambdaExpression.methodBody.accept(this);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(Assign assign) {
|
|
||||||
superType = assign.rightSide.getType();
|
|
||||||
assign.rightSide.accept(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(BinaryExpr binary) {
|
|
||||||
superType = new Void(new NullToken());
|
|
||||||
binary.lexpr.accept(this);
|
|
||||||
superType = new Void(new NullToken());
|
|
||||||
binary.rexpr.accept(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(Block block) {
|
|
||||||
for (var expr : block.statements) {
|
|
||||||
superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
|
|
||||||
expr.accept(this);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IfStmt ifStmt) {
|
public void visit(Assign assign) {
|
||||||
superType = new Void(new NullToken());
|
superType = assign.rightSide.getType();
|
||||||
ifStmt.expr.accept(this);
|
assign.rightSide.accept(this);
|
||||||
superType = new Void(new NullToken());
|
|
||||||
ifStmt.then_block.accept(this);
|
|
||||||
superType = new Void(new NullToken());
|
|
||||||
if (ifStmt.else_block != null)
|
|
||||||
ifStmt.else_block.accept(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(Return aReturn) {
|
|
||||||
superType = aReturn.getType();
|
|
||||||
aReturn.retexpr.accept(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(WhileStmt whileStmt) {
|
|
||||||
superType = new Void(new NullToken());
|
|
||||||
whileStmt.expr.accept(this);
|
|
||||||
superType = new Void(new NullToken());
|
|
||||||
whileStmt.loopBlock.accept(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(ArgumentList arglist) {
|
|
||||||
for (int i = 0; i < arglist.getArguments().size(); i++) {
|
|
||||||
superType = arglist.getArguments().get(i).getType();
|
|
||||||
arglist.getArguments().get(i).accept(this);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
@Override
|
||||||
|
public void visit(BinaryExpr binary) {
|
||||||
|
superType = new Void(new NullToken());
|
||||||
|
binary.lexpr.accept(this);
|
||||||
|
superType = new Void(new NullToken());
|
||||||
|
binary.rexpr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Block block) {
|
||||||
|
for (var expr : block.statements) {
|
||||||
|
superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
|
||||||
|
expr.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IfStmt ifStmt) {
|
||||||
|
superType = new Void(new NullToken());
|
||||||
|
ifStmt.expr.accept(this);
|
||||||
|
superType = new Void(new NullToken());
|
||||||
|
ifStmt.then_block.accept(this);
|
||||||
|
superType = new Void(new NullToken());
|
||||||
|
if (ifStmt.else_block != null)
|
||||||
|
ifStmt.else_block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Return aReturn) {
|
||||||
|
superType = aReturn.getType();
|
||||||
|
aReturn.retexpr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStmt whileStmt) {
|
||||||
|
superType = new Void(new NullToken());
|
||||||
|
whileStmt.expr.accept(this);
|
||||||
|
superType = new Void(new NullToken());
|
||||||
|
whileStmt.loopBlock.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ArgumentList arglist) {
|
||||||
|
for (int i = 0; i < arglist.getArguments().size(); i++) {
|
||||||
|
superType = arglist.getArguments().get(i).getType();
|
||||||
|
arglist.getArguments().get(i).accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var closure = transitiveClosure(simplifiedConstraints);
|
var closure = transitiveClosure(simplifiedConstraints);
|
||||||
// Type variables with bounds that are also type variables of the class
|
// Type variables with bounds that are also type variables of the class
|
||||||
@ -493,18 +494,19 @@ public abstract class GenerateGenerics {
|
|||||||
typeVariables.addAll(findTypeVariables(arg.getType()));
|
typeVariables.addAll(findTypeVariables(arg.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
method.block.accept(new TracingStatementVisitor() {
|
if (method.block != null)
|
||||||
@Override
|
method.block.accept(new TracingStatementVisitor() {
|
||||||
public void visit(LocalVarDecl localVarDecl) {
|
@Override
|
||||||
typeVariables.addAll(findTypeVariables(localVarDecl.getType()));
|
public void visit(LocalVarDecl localVarDecl) {
|
||||||
}
|
typeVariables.addAll(findTypeVariables(localVarDecl.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MethodCall methodCall) {
|
public void visit(MethodCall methodCall) {
|
||||||
super.visit(methodCall);
|
super.visit(methodCall);
|
||||||
typeVariables.addAll(findTypeVariables(methodCall.getType()));
|
typeVariables.addAll(findTypeVariables(methodCall.getType()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> javaTypeVariablesOfClass);
|
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> javaTypeVariablesOfClass);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package de.dhbwstuttgart.target.tree;
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
@ -1,6 +1,24 @@
|
|||||||
package de.dhbwstuttgart.target.tree;
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
import java.util.List;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
public record TargetInterface(String name, List<TargetMethod> methods, List<TargetInterface> extendedInterfaces) {
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces) implements TargetStructure {
|
||||||
|
@Override
|
||||||
|
public TargetType superType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TargetConstructor> constructors() {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TargetField> fields() {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,6 @@ import java.util.Set;
|
|||||||
public record TargetRecord(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetType> implementingInterfaces, List<TargetConstructor> constructors, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
|
public record TargetRecord(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetType> implementingInterfaces, List<TargetConstructor> constructors, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
|
||||||
|
|
||||||
public static final TargetType RECORD = new TargetRefType("java.lang.Record");
|
public static final TargetType RECORD = new TargetRefType("java.lang.Record");
|
||||||
|
|
||||||
@Override
|
|
||||||
public TargetType superType() {
|
public TargetType superType() {
|
||||||
return RECORD;
|
return RECORD;
|
||||||
}
|
}
|
||||||
|
@ -713,4 +713,12 @@ public class TestComplete {
|
|||||||
assertEquals(m1.invoke(instance, pt), 30);
|
assertEquals(m1.invoke(instance, pt), 30);
|
||||||
assertEquals(m2.invoke(instance, 10), 10);
|
assertEquals(m2.invoke(instance, 10), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterfaces() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Interfaces.jav");
|
||||||
|
var clazz = classFiles.get("Interfaces");
|
||||||
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
System.out.println(Arrays.toString(clazz.getInterfaces()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user