Implement ThisCall (fix #295)

This commit is contained in:
Daniel Holle 2024-03-18 13:29:53 +01:00
parent c07d4d36e9
commit 0acfe6c0d4
12 changed files with 91 additions and 12 deletions

View File

@ -0,0 +1,18 @@
import java.lang.Integer;
public class Bug295 {
public Integer a;
public Integer b;
public Integer c;
public Bug295(a, b, c) {
this(a);
this.b = b;
this.c = c;
}
public Bug295(a) {
this.a = a;
}
}

View File

@ -717,6 +717,8 @@ public class StatementGenerator {
MethodCall ret; MethodCall ret;
if (expr.SUPER() != null) { if (expr.SUPER() != null) {
ret = new SuperCall(argumentList, TypePlaceholder.fresh(offset), signature, offset); ret = new SuperCall(argumentList, TypePlaceholder.fresh(offset), signature, offset);
} else if(expr.THIS() != null) {
ret = new ThisCall(argumentList, TypePlaceholder.fresh(offset), signature, offset);
} else { } else {
ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset); ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset);
} }

View File

@ -451,7 +451,7 @@ public class SyntaxTreeGenerator {
protected static Block prepareBlock(Block constructorBlock, RefType superClass) { protected static Block prepareBlock(Block constructorBlock, RefType superClass) {
List<Statement> statements = constructorBlock.getStatements(); List<Statement> statements = constructorBlock.getStatements();
if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall)) { if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall || statements.get(0) instanceof ThisCall)) {
var signature = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>(); var signature = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
signature.add(new Void(new NullToken())); signature.add(new Void(new NullToken()));
statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset())); statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset()));

View File

@ -286,6 +286,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
this.visit((MethodCall) superCall); this.visit((MethodCall) superCall);
} }
@Override
public void visit(ThisCall thisCall) {
}
@Override @Override
public void visit(Switch switchStmt) { public void visit(Switch switchStmt) {
switchStmt.getSwitch().accept(this); switchStmt.getSwitch().accept(this);

View File

@ -71,6 +71,8 @@ public interface StatementVisitor {
void visit(SuperCall superCall); void visit(SuperCall superCall);
void visit(ThisCall thisCall);
void visit(ExpressionReceiver expressionReceiver); void visit(ExpressionReceiver expressionReceiver);
void visit(UnaryExpr unaryExpr); void visit(UnaryExpr unaryExpr);

View File

@ -1,20 +1,24 @@
package de.dhbwstuttgart.syntaxtree.statement; package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.Constructor;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.Void;
import org.antlr.v4.runtime.Token;
import java.util.ArrayList;
public class ThisCall extends MethodCall public class ThisCall extends MethodCall
{ {
public ThisCall(Receiver receiver, ArgumentList arglist, int offset) public ThisCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset) {
{ super(new Void(offset), new ExpressionReceiver(new This(offset)), "<init>", argumentList, receiverType, argTypes, offset);
// TODO What is this?
super(null, null, null, null, null, null, null);
} }
public ArgumentList arglist; @Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
} }

View File

@ -382,6 +382,13 @@ public class OutputGenerator implements ASTVisitor {
out.append(")"); out.append(")");
} }
@Override
public void visit(ThisCall thisCall) {
out.append("this(");
thisCall.arglist.accept(this);
out.append(")");
}
@Override @Override
public void visit(ExpressionReceiver receiver) { public void visit(ExpressionReceiver receiver) {
receiver.expr.accept(this); receiver.expr.accept(this);

View File

@ -1,6 +1,7 @@
package de.dhbwstuttgart.target.generate; package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
@ -290,6 +291,15 @@ public class StatementToTargetExpression implements ASTVisitor {
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);
} }
@Override
public void visit(ThisCall thisCall) {
var aThis = converter.convert(new RefType(converter.currentClass.getClassName(), new NullToken()));
var type = converter.convert(thisCall.getType());
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);
}
@Override @Override
public void visit(ExpressionReceiver expressionReceiver) { public void visit(ExpressionReceiver expressionReceiver) {
result = converter.convert(expressionReceiver.expr); result = converter.convert(expressionReceiver.expr);

View File

@ -1,12 +1,18 @@
package de.dhbwstuttgart.target.generate; package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;
// This visitor walks the entire tree, individual methods may be overridden // This visitor walks the entire tree, individual methods may be overridden
public abstract class TracingStatementVisitor implements StatementVisitor { public abstract class TracingStatementVisitor implements StatementVisitor {
@Override
public void visit(ThisCall thisCall) {
visit((MethodCall) thisCall);
}
@Override @Override
public void visit(MethodCall methodCall) { public void visit(MethodCall methodCall) {
methodCall.receiver.accept(this); methodCall.receiver.accept(this);
@ -155,7 +161,7 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
@Override @Override
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
visit((MethodCall) superCall);
} }
@Override @Override

View File

@ -564,7 +564,7 @@ public class TYPEStmt implements StatementVisitor {
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(clazz, 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);
@ -576,6 +576,21 @@ public class TYPEStmt implements StatementVisitor {
constraintsSet.addOderConstraint(methodConstraints); constraintsSet.addOderConstraint(methodConstraints);
} }
@Override
public void visit(ThisCall thisCall) {
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
for (var ctor : info.getCurrentClass().getConstructors()) {
var params = convertParams(ctor.getParameterList(), info);
if (params.size() != thisCall.arglist.getArguments().size()) continue;
var assumption = new MethodAssumption(info.getCurrentClass(), new Void(new NullToken()), params, createTypeScope(info.getCurrentClass(), ctor), ctor.isInherited);
GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(thisCall, assumption, info, resolver);
methodConstraints.addAll(oneMethodConstraints);
}
constraintsSet.addOderConstraint(methodConstraints);
}
/* /*
* METHOD CALL Section: * METHOD CALL Section:
*/ */

View File

@ -941,6 +941,16 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
} }
@Test
public void testBug295() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug295.jav");
var clazz = classFiles.get("Bug295");
var instance = clazz.getDeclaredConstructor(Integer.class, Integer.class, Integer.class).newInstance(1, 2, 3);
assertEquals(clazz.getDeclaredField("a").get(instance), 1);
assertEquals(clazz.getDeclaredField("b").get(instance), 2);
assertEquals(clazz.getDeclaredField("c").get(instance), 3);
}
@Test @Test
public void testBug296() throws Exception { public void testBug296() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug296.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug296.jav");