diff --git a/resources/bytecode/javFiles/Bug295.jav b/resources/bytecode/javFiles/Bug295.jav new file mode 100644 index 00000000..be4488af --- /dev/null +++ b/resources/bytecode/javFiles/Bug295.jav @@ -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; + } +} + diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java index 109d649c..03fa2023 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -1381,7 +1381,7 @@ public class Codegen { MethodVisitor mv = cw.visitMethod(constructor.access(), "", 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()) { diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index f2056e3a..2c7044d3 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -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); } diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index ce330b40..35e8f5f1 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -451,7 +451,7 @@ public class SyntaxTreeGenerator { protected static Block prepareBlock(Block constructorBlock, RefType superClass) { List 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(); signature.add(new Void(new NullToken())); statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset())); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index fde26cb7..548cbb1c 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -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); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java index c7a6c2a7..08cff88a 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java @@ -71,6 +71,8 @@ public interface StatementVisitor { void visit(SuperCall superCall); + void visit(ThisCall thisCall); + void visit(ExpressionReceiver expressionReceiver); void visit(UnaryExpr unaryExpr); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java index 14ec3977..ee4acc96 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java @@ -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 argTypes, Token offset) { + super(new Void(offset), new ExpressionReceiver(new This(offset)), "", argumentList, receiverType, argTypes, offset); + } + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java index 638d13d6..8b1175bb 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java @@ -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); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 22554417..acfaabab 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -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); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index 7967f0c4..64655dbe 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -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 diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 3811c59c..060d70ae 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -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> 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> 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> oneMethodConstraints = generateConstraint(thisCall, assumption, info, resolver); + methodConstraints.addAll(oneMethodConstraints); + } + constraintsSet.addOderConstraint(methodConstraints); + } + /* * METHOD CALL Section: */ diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 3d03e762..22898fd0 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -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");