Implement ThisCall (fix #295)
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
This commit is contained in:
parent
c07d4d36e9
commit
0acfe6c0d4
18
resources/bytecode/javFiles/Bug295.jav
Normal file
18
resources/bytecode/javFiles/Bug295.jav
Normal 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;
|
||||
}
|
||||
}
|
||||
|
@ -1381,7 +1381,7 @@ public class Codegen {
|
||||
MethodVisitor mv = cw.visitMethod(constructor.access(), "<init>", constructor.getDescriptor(), constructor.getSignature(), null);
|
||||
if (constructor.txGenerics() != null)
|
||||
mv.visitAttribute(new JavaTXSignatureAttribute(constructor.getTXSignature()));
|
||||
|
||||
|
||||
mv.visitCode();
|
||||
var state = new State(null, mv, 1);
|
||||
for (var param : constructor.parameters()) {
|
||||
|
@ -717,6 +717,8 @@ public class StatementGenerator {
|
||||
MethodCall ret;
|
||||
if (expr.SUPER() != null) {
|
||||
ret = new SuperCall(argumentList, TypePlaceholder.fresh(offset), signature, offset);
|
||||
} else if(expr.THIS() != null) {
|
||||
ret = new ThisCall(argumentList, TypePlaceholder.fresh(offset), signature, offset);
|
||||
} else {
|
||||
ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset);
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ public class SyntaxTreeGenerator {
|
||||
|
||||
protected static Block prepareBlock(Block constructorBlock, RefType superClass) {
|
||||
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>();
|
||||
signature.add(new Void(new NullToken()));
|
||||
statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset()));
|
||||
|
@ -286,6 +286,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
this.visit((MethodCall) superCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ThisCall thisCall) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Switch switchStmt) {
|
||||
switchStmt.getSwitch().accept(this);
|
||||
|
@ -71,6 +71,8 @@ public interface StatementVisitor {
|
||||
|
||||
void visit(SuperCall superCall);
|
||||
|
||||
void visit(ThisCall thisCall);
|
||||
|
||||
void visit(ExpressionReceiver expressionReceiver);
|
||||
|
||||
void visit(UnaryExpr unaryExpr);
|
||||
|
@ -1,20 +1,24 @@
|
||||
package de.dhbwstuttgart.syntaxtree.statement;
|
||||
|
||||
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 ThisCall(Receiver receiver, ArgumentList arglist, int offset)
|
||||
{
|
||||
// TODO What is this?
|
||||
super(null, null, null, null, null, null, null);
|
||||
|
||||
}
|
||||
|
||||
public ArgumentList arglist;
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(StatementVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -382,6 +382,13 @@ public class OutputGenerator implements ASTVisitor {
|
||||
out.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ThisCall thisCall) {
|
||||
out.append("this(");
|
||||
thisCall.arglist.accept(this);
|
||||
out.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ExpressionReceiver receiver) {
|
||||
receiver.expr.accept(this);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
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);
|
||||
}
|
||||
|
||||
@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
|
||||
public void visit(ExpressionReceiver expressionReceiver) {
|
||||
result = converter.convert(expressionReceiver.expr);
|
||||
|
@ -1,12 +1,18 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
|
||||
// This visitor walks the entire tree, individual methods may be overridden
|
||||
public abstract class TracingStatementVisitor implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(ThisCall thisCall) {
|
||||
visit((MethodCall) thisCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MethodCall methodCall) {
|
||||
methodCall.receiver.accept(this);
|
||||
@ -155,7 +161,7 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(SuperCall superCall) {
|
||||
|
||||
visit((MethodCall) superCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -564,7 +564,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
for (var ctor : clazz.getConstructors()) {
|
||||
var params = convertParams(ctor.getParameterList(), info);
|
||||
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();
|
||||
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
|
||||
@ -576,6 +576,21 @@ public class TYPEStmt implements StatementVisitor {
|
||||
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:
|
||||
*/
|
||||
|
@ -941,6 +941,16 @@ public class TestComplete {
|
||||
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
|
||||
public void testBug296() throws Exception {
|
||||
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug296.jav");
|
||||
|
Loading…
Reference in New Issue
Block a user