Fix #300 and also call private methods correctly
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m35s
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m35s
This commit is contained in:
parent
1c63321b30
commit
786e0a7a23
17
resources/bytecode/javFiles/Bug300.jav
Normal file
17
resources/bytecode/javFiles/Bug300.jav
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import java.lang.String;
|
||||||
|
|
||||||
|
class Base {
|
||||||
|
toString() {
|
||||||
|
return "Base";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Bug300 extends Base {
|
||||||
|
public m() {
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return "Derived";
|
||||||
|
}
|
||||||
|
}
|
@ -1045,7 +1045,12 @@ public class Codegen {
|
|||||||
if (call.owner() instanceof TargetFunNType) // Decay FunN
|
if (call.owner() instanceof TargetFunNType) // Decay FunN
|
||||||
descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
||||||
|
|
||||||
mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC : call.name().equals("<init>") ? INVOKESPECIAL : INVOKEVIRTUAL, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
|
int insn = INVOKEVIRTUAL;
|
||||||
|
if (call.isInterface()) insn = INVOKEINTERFACE;
|
||||||
|
else if (call.isStatic()) insn = INVOKESTATIC;
|
||||||
|
else if (call.name().equals("<init>") || call.expr() instanceof TargetSuper || call.isPrivate()) insn = INVOKESPECIAL;
|
||||||
|
|
||||||
|
mv.visitMethodInsn(insn, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
|
||||||
|
|
||||||
if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
|
if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
|
||||||
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
|
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
|
||||||
|
@ -131,6 +131,7 @@ public class JavaTXCompiler {
|
|||||||
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
|
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
|
||||||
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
||||||
ClassOrInterface objectClass = ASTFactory.createClass(classLoader.loadClass(new JavaClassName("java.lang.Object").toString()));
|
ClassOrInterface objectClass = ASTFactory.createClass(classLoader.loadClass(new JavaClassName("java.lang.Object").toString()));
|
||||||
|
allClasses.add(objectClass);
|
||||||
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
||||||
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) {
|
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) {
|
||||||
var importedClasses = new ArrayList<ClassOrInterface>();
|
var importedClasses = new ArrayList<ClassOrInterface>();
|
||||||
|
@ -1028,7 +1028,7 @@ public class StatementGenerator {
|
|||||||
case PrimaryThisContext primthis:
|
case PrimaryThisContext primthis:
|
||||||
return new This(primthis.getStart());
|
return new This(primthis.getStart());
|
||||||
case PrimarySuperContext primsuper:
|
case PrimarySuperContext primsuper:
|
||||||
throw new NotImplementedException();
|
return new Super(primsuper.getStart());
|
||||||
case PrimaryLiteralContext primliteral:
|
case PrimaryLiteralContext primliteral:
|
||||||
return convert(primliteral.literal());
|
return convert(primliteral.literal());
|
||||||
case PrimaryIdentifierContext primidentifier:
|
case PrimaryIdentifierContext primidentifier:
|
||||||
|
@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement;
|
|||||||
import de.dhbwstuttgart.parser.NullToken;
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
@ -10,8 +11,12 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
|||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
|
||||||
public class Super extends Expression
|
public class Super extends Expression {
|
||||||
{
|
|
||||||
|
public Super(Token offset) {
|
||||||
|
super(TypePlaceholder.fresh(offset), offset);
|
||||||
|
}
|
||||||
|
|
||||||
public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
|
public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
|
||||||
{
|
{
|
||||||
super(type, offset);
|
super(type, offset);
|
||||||
|
@ -8,9 +8,8 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
|
|||||||
|
|
||||||
public class This extends Expression
|
public class This extends Expression
|
||||||
{
|
{
|
||||||
public This(Token offset)
|
public This(Token offset) {
|
||||||
{
|
super(TypePlaceholder.fresh(offset), offset);
|
||||||
super(TypePlaceholder.fresh(offset),offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArgumentList arglist;
|
public ArgumentList arglist;
|
||||||
|
@ -199,6 +199,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
Method foundMethod = null;
|
Method foundMethod = null;
|
||||||
var isStatic = false;
|
var isStatic = false;
|
||||||
var isInterface = true;
|
var isInterface = true;
|
||||||
|
var isPrivate = false;
|
||||||
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
|
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
|
||||||
|
|
||||||
var receiverClass = converter.currentClass;
|
var receiverClass = converter.currentClass;
|
||||||
@ -214,10 +215,11 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
returnType = converter.convert(foundMethod.getReturnType());
|
returnType = converter.convert(foundMethod.getReturnType());
|
||||||
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
|
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
|
||||||
isStatic = Modifier.isStatic(foundMethod.modifier);
|
isStatic = Modifier.isStatic(foundMethod.modifier);
|
||||||
|
isPrivate = Modifier.isPrivate(foundMethod.modifier);
|
||||||
isInterface = receiverClass.isInterface();
|
isInterface = receiverClass.isInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface);
|
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -288,7 +290,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
var type = converter.convert(superCall.getType());
|
var type = converter.convert(superCall.getType());
|
||||||
var parameters = superCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
|
var parameters = superCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
|
||||||
|
|
||||||
result = new TargetMethodCall(type, type, parameters, new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aSuper, superCall.name, false, false);
|
result = new TargetMethodCall(type, type, parameters, new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aSuper, superCall.name, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -297,7 +299,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
var type = converter.convert(thisCall.getType());
|
var type = converter.convert(thisCall.getType());
|
||||||
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
|
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
|
||||||
|
|
||||||
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false);
|
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package de.dhbwstuttgart.target.tree.expression;
|
package de.dhbwstuttgart.target.tree.expression;
|
||||||
|
|
||||||
import de.dhbwstuttgart.target.tree.MethodParameter;
|
|
||||||
import de.dhbwstuttgart.target.tree.TargetMethod;
|
import de.dhbwstuttgart.target.tree.TargetMethod;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression {
|
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) implements TargetStatementExpression {
|
||||||
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) {
|
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) {
|
||||||
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface);
|
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface, isPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,14 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation {
|
|||||||
public ClassOrInterface getCurrentClass() {
|
public ClassOrInterface getCurrentClass() {
|
||||||
return currentClass;
|
return currentClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClassOrInterface getSuperClass() {
|
||||||
|
for (var clazz : getAvailableClasses()) {
|
||||||
|
if (clazz.getClassName().equals(currentClass.getSuperClass().getName()))
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public TypeScope getCurrentTypeScope() {
|
public TypeScope getCurrentTypeScope() {
|
||||||
return methodContext;
|
return methodContext;
|
||||||
}
|
}
|
||||||
|
@ -499,7 +499,13 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(Super aSuper) {
|
public void visit(Super aSuper) {
|
||||||
throw new NotImplementedException();
|
var superClass = info.getSuperClass();
|
||||||
|
var params = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
|
||||||
|
for (var gtv : superClass.getGenerics()) {
|
||||||
|
params.add(new GenericRefType(gtv.getName(), aSuper.getOffset()));
|
||||||
|
}
|
||||||
|
var superType = new RefType(superClass.getClassName(), params, aSuper.getOffset());
|
||||||
|
constraintsSet.addUndConstraint(new Pair(aSuper.getType(), superType, PairOperator.EQUALSDOT, loc(aSuper.getOffset())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -559,19 +565,15 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(SuperCall superCall) {
|
public void visit(SuperCall superCall) {
|
||||||
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
|
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
|
||||||
for (var clazz : info.getAvailableClasses()) {
|
var clazz = info.getSuperClass();
|
||||||
if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) {
|
for (var ctor : clazz.getConstructors()) {
|
||||||
for (var ctor : clazz.getConstructors()) {
|
var params = convertParams(ctor.getParameterList(), info);
|
||||||
var params = convertParams(ctor.getParameterList(), info);
|
if (params.size() != superCall.arglist.getArguments().size()) continue;
|
||||||
if (params.size() != superCall.arglist.getArguments().size()) continue;
|
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited);
|
||||||
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited);
|
|
||||||
|
|
||||||
GenericsResolver resolver = getResolverInstance();
|
GenericsResolver resolver = getResolverInstance();
|
||||||
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
|
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
|
||||||
methodConstraints.addAll(oneMethodConstraints);
|
methodConstraints.addAll(oneMethodConstraints);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
constraintsSet.addOderConstraint(methodConstraints);
|
constraintsSet.addOderConstraint(methodConstraints);
|
||||||
}
|
}
|
||||||
|
@ -980,4 +980,11 @@ public class TestComplete {
|
|||||||
var clazz = classFiles.get("Bug298");
|
var clazz = classFiles.get("Bug298");
|
||||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
public void testBug300() throws Exception {
|
||||||
|
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug300.jav");
|
||||||
|
var clazz = classFiles.get("Bug300");
|
||||||
|
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
assertEquals(clazz.getDeclaredMethod("m").invoke(instance), "Base");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ public class TestCodegen {
|
|||||||
@Test
|
@Test
|
||||||
public void testMethodCall() throws Exception {
|
public void testMethodCall() throws Exception {
|
||||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("HelloWorld"));
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("HelloWorld"));
|
||||||
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false))));
|
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false, false))));
|
||||||
|
|
||||||
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
||||||
clazz.getDeclaredMethod("helloWorld").invoke(null);
|
clazz.getDeclaredMethod("helloWorld").invoke(null);
|
||||||
@ -271,8 +271,8 @@ public class TestCodegen {
|
|||||||
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
|
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
|
||||||
|
|
||||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("CGLambda"));
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("CGLambda"));
|
||||||
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false))));
|
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false, false))));
|
||||||
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true))))));
|
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true, false))))));
|
||||||
var clazz = generateClass(targetClass, classLoader);
|
var clazz = generateClass(targetClass, classLoader);
|
||||||
var instance = clazz.getConstructor().newInstance();
|
var instance = clazz.getConstructor().newInstance();
|
||||||
assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20);
|
assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20);
|
||||||
|
Loading…
Reference in New Issue
Block a user