diff --git a/src/main/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java index 63dfed2..61134ab 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -15,30 +15,20 @@ public class ClassNode implements ASTNode, Visitable { public AccessModifierNode accessType; public String identifier; public List members = new ArrayList<>(); - public boolean hasConstructor; - public ClassNode() {} + public ClassNode(){ + + } public ClassNode(String accessType, String identifier){ this.accessType = new AccessModifierNode(accessType); this.identifier = identifier; - hasConstructor = false; } public void addMember(MemberNode member) { - if (member instanceof ConstructorNode) { - this.hasConstructor = true; - } members.add(member); } - public void ensureConstructor(){ - if(!hasConstructor) { - ConstructorNode constructor = new ConstructorNode(new AccessModifierNode("public"), identifier); - members.addFirst(constructor); - } - } - public List getMethods(){ List methods = new ArrayList<>(); for (MemberNode member : members) { diff --git a/src/main/java/ast/members/ConstructorNode.java b/src/main/java/ast/members/ConstructorNode.java index a70ac85..d6a40c2 100644 --- a/src/main/java/ast/members/ConstructorNode.java +++ b/src/main/java/ast/members/ConstructorNode.java @@ -13,11 +13,6 @@ public class ConstructorNode extends MethodNode { public List parameters = new ArrayList<>(); public BlockNode block; - public ConstructorNode(AccessModifierNode accessType, String identifier) { - this.accessType = accessType; - this.identifier = identifier; - } - public ConstructorNode(String accessType, String identifier, BlockNode block) { this.accessType = new AccessModifierNode(accessType); this.identifier = identifier; diff --git a/src/main/java/parser/astBuilder/ASTBuilder.java b/src/main/java/parser/astBuilder/ASTBuilder.java index b6d8283..7ee199b 100644 --- a/src/main/java/parser/astBuilder/ASTBuilder.java +++ b/src/main/java/parser/astBuilder/ASTBuilder.java @@ -44,11 +44,32 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitClassDeclaration(SimpleJavaParser.ClassDeclarationContext ctx) { - ClassNode classNode = new ClassNode(ctx.AccessModifier().getText(), ctx.Identifier().getText()); - for (SimpleJavaParser.MemberDeclarationContext member : ctx.memberDeclaration()) { - classNode.addMember((MemberNode) visit(member)); + ClassNode classNode; + if(ctx.AccessModifier() != null){ + classNode = new ClassNode(ctx.AccessModifier().getText(), ctx.Identifier().getText()); } - classNode.ensureConstructor(); + else{ + classNode = new ClassNode("public", ctx.Identifier().getText()); + } + + boolean hasConstructor = false; + + for (SimpleJavaParser.MemberDeclarationContext member : ctx.memberDeclaration()) { + MemberNode memberNode = (MemberNode) visit(member); + if(memberNode != null) { + if(memberNode instanceof ConstructorNode){ + hasConstructor = true; + } + classNode.addMember(memberNode); + } + } + + if(!hasConstructor){ + BlockNode blockNode = new BlockNode(); + blockNode.addStatement(new ReturnNode(null)); + classNode.members.addFirst(new ConstructorNode("public", ctx.Identifier().getText(), blockNode)); + } + return classNode; } @@ -72,29 +93,54 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { return mainMethod; } else { if(ctx.type() != null) { - MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement())); - if(ctx.parameterList() != null) { - for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { - methodNode.addParameter((ParameterNode) visit(parameter)); + if(ctx.AccessModifier() != null) { + MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement())); + if(ctx.parameterList() != null) { + for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { + methodNode.addParameter((ParameterNode) visit(parameter)); + } } + return methodNode; + } else { + MethodNode methodNode = new MethodNode("public", createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement())); + if(ctx.parameterList() != null) { + for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { + methodNode.addParameter((ParameterNode) visit(parameter)); + } + } + return methodNode; } - return methodNode; } else { - MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement())); - if(ctx.parameterList() != null) { - for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { - methodNode.addParameter((ParameterNode) visit(parameter)); + if(ctx.AccessModifier() != null) { + MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement())); + if(ctx.parameterList() != null) { + for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { + methodNode.addParameter((ParameterNode) visit(parameter)); + } } + methodNode.block.addStatement(new ReturnNode(null)); + return methodNode; + } else { + MethodNode methodNode = new MethodNode("public", null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement())); + if(ctx.parameterList() != null) { + for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { + methodNode.addParameter((ParameterNode) visit(parameter)); + } + } + methodNode.block.addStatement(new ReturnNode(null)); + return methodNode; } - methodNode.block.addStatement(new ReturnNode(null)); - return methodNode; } } } @Override public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) { - return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), createTypeNode(ctx.type().getText()), ctx.Identifier().getText()); + if(ctx.AccessModifier() != null) { + return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), createTypeNode(ctx.type().getText()), ctx.Identifier().getText()); + } else { + return new FieldNode(new AccessModifierNode("public"), createTypeNode(ctx.type().getText()), ctx.Identifier().getText()); + } } @Override @@ -184,10 +230,17 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { crement = (IStatementNode) visit(ctx.statementExpression(i)); } - BlockNode forBlock = (BlockNode) visit(ctx.blockStatement()); + BlockNode forBlock = new BlockNode(); + + BlockNode forStatements = (BlockNode) visit(ctx.blockStatement()); + if(forStatements != null) { + forBlock.addStatement((IStatementNode) forStatements); + } if(crement != null){ - forBlock.addStatement((crement)); + BlockNode forCrement = new BlockNode(); + forCrement.addStatement((crement)); + forBlock.addStatement(forCrement); } WhileNode While = new WhileNode(condition, forBlock); @@ -259,7 +312,12 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitMethodCall(SimpleJavaParser.MethodCallContext ctx) { - MethodCallNode methodCallStatementExpressionNode = new MethodCallNode((TargetNode) visit(ctx.target()), ctx.Identifier().getText()); + MethodCallNode methodCallStatementExpressionNode; + if(ctx.target() != null) { + methodCallStatementExpressionNode = new MethodCallNode((TargetNode) visit(ctx.target()), ctx.Identifier().getText()); + } else { + methodCallStatementExpressionNode = new MethodCallNode(null, ctx.Identifier().getText()); + } for(SimpleJavaParser.ChainedMethodContext chainedMethod : ctx.chainedMethod()) { methodCallStatementExpressionNode.addChainedMethod((ChainedMethodNode) visit(chainedMethod)); } diff --git a/src/main/java/parser/generated/SimpleJavaBaseListener.java b/src/main/java/parser/generated/SimpleJavaBaseListener.java index 5cc0d6c..eecc12f 100644 --- a/src/main/java/parser/generated/SimpleJavaBaseListener.java +++ b/src/main/java/parser/generated/SimpleJavaBaseListener.java @@ -1,4 +1,4 @@ -// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 +// Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 package parser.generated; import org.antlr.v4.runtime.ParserRuleContext; diff --git a/src/main/java/parser/generated/SimpleJavaBaseVisitor.java b/src/main/java/parser/generated/SimpleJavaBaseVisitor.java index 97b6b28..b3a6029 100644 --- a/src/main/java/parser/generated/SimpleJavaBaseVisitor.java +++ b/src/main/java/parser/generated/SimpleJavaBaseVisitor.java @@ -1,4 +1,4 @@ -// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 +// Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 package parser.generated; import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; diff --git a/src/main/java/parser/generated/SimpleJavaLexer.java b/src/main/java/parser/generated/SimpleJavaLexer.java index 51b5bfc..23296ee 100644 --- a/src/main/java/parser/generated/SimpleJavaLexer.java +++ b/src/main/java/parser/generated/SimpleJavaLexer.java @@ -1,4 +1,4 @@ -// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 +// Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 package parser.generated; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.CharStream; diff --git a/src/main/java/parser/generated/SimpleJavaListener.java b/src/main/java/parser/generated/SimpleJavaListener.java index 3e7bf6d..580bfe1 100644 --- a/src/main/java/parser/generated/SimpleJavaListener.java +++ b/src/main/java/parser/generated/SimpleJavaListener.java @@ -1,4 +1,4 @@ -// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 +// Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 package parser.generated; import org.antlr.v4.runtime.tree.ParseTreeListener; diff --git a/src/main/java/parser/generated/SimpleJavaParser.java b/src/main/java/parser/generated/SimpleJavaParser.java index cff16d5..3a80a6a 100644 --- a/src/main/java/parser/generated/SimpleJavaParser.java +++ b/src/main/java/parser/generated/SimpleJavaParser.java @@ -1,4 +1,4 @@ -// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 +// Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 package parser.generated; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.DFA; diff --git a/src/main/java/parser/generated/SimpleJavaVisitor.java b/src/main/java/parser/generated/SimpleJavaVisitor.java index 5d66eae..beefef9 100644 --- a/src/main/java/parser/generated/SimpleJavaVisitor.java +++ b/src/main/java/parser/generated/SimpleJavaVisitor.java @@ -1,4 +1,4 @@ -// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 +// Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 package parser.generated; import org.antlr.v4.runtime.tree.ParseTreeVisitor; diff --git a/src/test/java/parser/AstBuilderTest.java b/src/test/java/parser/AstBuilderTest.java index b5bec24..b163a2a 100644 --- a/src/test/java/parser/AstBuilderTest.java +++ b/src/test/java/parser/AstBuilderTest.java @@ -1,57 +1,405 @@ package parser; + +import ast.ASTNode; import ast.ClassNode; import ast.ProgramNode; +import ast.expressions.IExpressionNode; +import ast.expressions.unaryexpressions.MemberAccessNode; +import ast.expressions.unaryexpressions.UnaryNode; +import ast.members.ConstructorNode; +import ast.members.FieldNode; +import ast.members.MemberNode; +import ast.members.MethodNode; +import ast.parameters.ParameterNode; +import ast.statementexpressions.AssignNode; +import ast.statementexpressions.AssignableNode; +import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode; +import ast.statements.BlockNode; +import ast.statements.IStatementNode; +import ast.statements.ReturnNode; +import ast.type.AccessModifierNode; +import ast.type.EnumValueNode; +import ast.type.ValueNode; +import ast.type.type.BaseType; +import ast.type.type.ITypeNode; +import ast.type.type.TypeEnum; +import com.fasterxml.jackson.annotation.JsonFormat; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import parser.astBuilder.ASTBuilder; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; -import static org.junit.jupiter.api.Assertions.assertEquals; +import java.io.IOException; +import java.lang.reflect.Member; -public class AstBuilderTest { +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("Untyped Abstract Syntax Tree") +class AstBuilderTest { @Test - public void astBuilderTest() { - // ---------------- Leere Klasse nachgebaut ---------------- + @DisplayName("Empty Class Test") + public void emptyClassTest(){ + ClassNode emptyClass = Helper.generateEmptyClass("TestClass"); + ProgramNode expected = new ProgramNode(); + expected.addClass(emptyClass); - ProgramNode expectedASTEmptyClass = new ProgramNode(); + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/EmptyClass.java"); + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } - // public class Name {} - ClassNode nameClass = new ClassNode("public", "Name"); + @Test + @DisplayName("Multiple Empty Classes Test") + public void multipleEmptyClassesTest() { + ClassNode class1 = Helper.generateEmptyClass("TestClass1"); + ClassNode class2 = Helper.generateEmptyClass("TestClass2"); + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + expected.addClass(class2); - expectedASTEmptyClass.addClass(nameClass); + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/MultipleClasses.java"); + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + @Test + @DisplayName("Empty Class Test with Constructor") + public void emptyClassWithConstructorTest() { + ClassNode class1 = Helper.generateEmptyClass("TestClass"); + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); - // ---------------- Leere Klasse erzeugt ---------------- + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/EmptyClassWithConstructor.java"); + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } - // init - CharStream inputCharStream = CharStreams.fromString("public class Name {}"); - SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - tokenStream.fill(); + @Test + @DisplayName("Field Test") + public void fieldTest() { + ClassNode class1 = Helper.generateEmptyClass("TestClass"); + class1.addMember(new FieldNode(null, new BaseType(TypeEnum.INT), "a")); - /* Parser -> Parsetree */ - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTreeEmptyClass = parser.program(); // parse the input + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); - /* AST builder -> AST */ - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode actualASTEmptyClass = (ProgramNode) new ASTBuilder().visit(parseTreeEmptyClass); + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/Field.java"); + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + @Test + @DisplayName("Field Test with Accessmodifier") + public void fieldTestWithModifier() { + ClassNode class1 = Helper.generateEmptyClass("TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a")); - // ---------------- Vergleichen ---------------- + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); - String expectedASTasString = expectedASTEmptyClass.toString(); - String actualASTasString = new ASTBuilder().visit(parseTreeEmptyClass).toString(); + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/FieldWithAccessModifier.java"); + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } - // Wie vergleiche ich das? - assertEquals(expectedASTasString, actualASTasString); - assertEquals(expectedASTEmptyClass, actualASTEmptyClass); + @Test + @DisplayName("Commments Ignore Test") + public void commmentsIgnoreTest(){ + ClassNode class1 = Helper.generateEmptyClass("TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("private"), new BaseType(TypeEnum.INT), "a")); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/Comments.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Constructor Paramerter Test") + public void constructorParameterTest(){ + BlockNode block = new BlockNode(); + block.addStatement(new ReturnNode(null)); + ConstructorNode constructor = new ConstructorNode("public", "TestClass", block); + constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a")); + constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "b")); + + ClassNode class1 = new ClassNode("public", "TestClass"); + class1.addMember(constructor); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/ConstructorParameter.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("This Dot Test") + public void thisDotTest(){ + BlockNode block = new BlockNode(); + MemberAccessNode memberAccess = new MemberAccessNode(true); + memberAccess.addIdentifier("a"); + + AssignableNode assignable = new AssignableNode(memberAccess); + + ValueNode value = new ValueNode(EnumValueNode.INT_VALUE, "1"); + IExpressionNode expression = new UnaryNode(value); + + block.addStatement(new AssignNode(assignable, expression)); + block.addStatement(new ReturnNode(null)); + ConstructorNode constructor = new ConstructorNode("public", "TestClass", block); + + ClassNode class1 = new ClassNode("public", "TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a")); + class1.addMember(constructor); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/ThisDot.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Constructor This Dot Test") + public void constructorThisDotTest(){ + BlockNode block = new BlockNode(); + MemberAccessNode memberAccess = new MemberAccessNode(true); + memberAccess.addIdentifier("a"); + + AssignableNode assignable = new AssignableNode(memberAccess); + + IExpressionNode expression = new UnaryNode("a"); + + block.addStatement(new AssignNode(assignable, expression)); + block.addStatement(new ReturnNode(null)); + ConstructorNode constructor = new ConstructorNode("public", "TestClass", block); + constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a")); + + ClassNode class1 = new ClassNode("public", "TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("private"), new BaseType(TypeEnum.INT), "a")); + class1.addMember(constructor); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/ConstructorThisDot.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Void Methoden Test") + public void voidMethodenTest(){ + ClassNode class1 = Helper.generateEmptyClass("TestClass"); + BlockNode block = new BlockNode(); + block.addStatement(new ReturnNode(null)); + class1.addMember(new MethodNode("public", null, true, "test", block)); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/VoidMethod.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Constructor Method call Test") + public void constructorMethodCallTest(){ + BlockNode blockCon = new BlockNode(); + MemberAccessNode memberAccess = new MemberAccessNode(true); + memberAccess.addIdentifier("a"); + + AssignableNode assignable = new AssignableNode(memberAccess); + + IExpressionNode expression = new UnaryNode(new MethodCallNode(null, "testMethod")); + + blockCon.addStatement(new AssignNode(assignable, expression)); + blockCon.addStatement(new ReturnNode(null)); + ConstructorNode constructor = new ConstructorNode("public", "TestClass", blockCon); + + BlockNode blockMethod = new BlockNode(); + blockMethod.addStatement(new ReturnNode(new UnaryNode(new ValueNode(EnumValueNode.INT_VALUE, "1")))); + MethodNode method = new MethodNode("public", new BaseType(TypeEnum.INT), false, "testMethod", blockMethod); + + ClassNode class1 = new ClassNode("public", "TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a")); + class1.addMember(constructor); + class1.addMember(method); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/ConstructorMethodCall.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Constructor Method call Parameters Test") + public void constructorMethodCallParametersTest(){ + BlockNode blockCon = new BlockNode(); + MemberAccessNode memberAccess = new MemberAccessNode(true); + memberAccess.addIdentifier("a"); + + AssignableNode assignable = new AssignableNode(memberAccess); + + MethodCallNode methodCall = new MethodCallNode(null, "testMethod"); + methodCall.addExpression(new UnaryNode("a")); + IExpressionNode expression = new UnaryNode(methodCall); + + blockCon.addStatement(new AssignNode(assignable, expression)); + blockCon.addStatement(new ReturnNode(null)); + ConstructorNode constructor = new ConstructorNode("public", "TestClass", blockCon); + constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a")); + + BlockNode blockMethod = new BlockNode(); + blockMethod.addStatement(new ReturnNode(new UnaryNode("a"))); + MethodNode method = new MethodNode("public", new BaseType(TypeEnum.INT), false, "testMethod", blockMethod); + method.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a")); + + ClassNode class1 = new ClassNode("public", "TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a")); + class1.addMember(constructor); + class1.addMember(method); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/ConstructorMethodCallParameters.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Char Test") + public void charTest(){ + BlockNode blockCon = new BlockNode(); + MemberAccessNode memberAccess = new MemberAccessNode(true); + memberAccess.addIdentifier("a"); + + AssignableNode assignable = new AssignableNode(memberAccess); + + MethodCallNode methodCall = new MethodCallNode(null, "testMethod"); + methodCall.addExpression(new UnaryNode("a")); + IExpressionNode expression = new UnaryNode(methodCall); + + blockCon.addStatement(new AssignNode(assignable, expression)); + blockCon.addStatement(new ReturnNode(null)); + ConstructorNode constructor = new ConstructorNode("public", "TestClass", blockCon); + constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.CHAR), "a")); + + BlockNode blockMethod = new BlockNode(); + blockMethod.addStatement(new ReturnNode(new UnaryNode("a"))); + MethodNode method = new MethodNode("public", new BaseType(TypeEnum.CHAR), false, "testMethod", blockMethod); + method.addParameter(new ParameterNode(new BaseType(TypeEnum.CHAR), "a")); + + ClassNode class1 = new ClassNode("public", "TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.CHAR), "a")); + class1.addMember(constructor); + class1.addMember(method); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/Char.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Null Test") + public void nullTest(){ + BlockNode blockCon = new BlockNode(); + MemberAccessNode memberAccess = new MemberAccessNode(true); + memberAccess.addIdentifier("a"); + + AssignableNode assignable = new AssignableNode(memberAccess); + + blockCon.addStatement(new AssignNode(assignable, new UnaryNode(new ValueNode(EnumValueNode.NULL_VALUE, "null")))); + blockCon.addStatement(new ReturnNode(null)); + ConstructorNode constructor = new ConstructorNode("public", "TestClass", blockCon); + + ClassNode class1 = new ClassNode("public", "TestClass"); + class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a")); + class1.addMember(constructor); + + ProgramNode expected = new ProgramNode(); + expected.addClass(class1); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/Null.java"); + + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Self Reference Test") + public void selfReferneceTest(){ + + //assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Variable Compare Test") + public void variableCompareTest(){ + + //assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Variable Calculation Test") + public void variableCalculationTest(){ + + //assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Main Method Test") + public void mainMethodTest(){ + + //assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("While Test") + public void whileTest(){ + + //assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("Do While Test") + public void doWhileTest(){ + + //assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + @Test + @DisplayName("For Test") + public void forTest(){ + + //assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); + } + + //Noch nicht speziell Increment nur zum Development Testen per Debug + @Test + @DisplayName("Increment Test") + public void incrementTest(){ + ClassNode classNode = Helper.generateEmptyClass("TestClass"); + classNode.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a")); + + ProgramNode expected = new ProgramNode(); + expected.addClass(classNode); + + ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/Increment.java"); + assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected); } @@ -65,39 +413,4 @@ public class AstBuilderTest { - - - // ---------------- Alter CompilerInput nachgebaut ---------------- - // ProgramNode startNode = new ProgramNode(); - // public class CompilerInput {} - // ClassNode compilerInputClass = new ClassNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), "CompilerInput"); - // public int a; - // compilerInputClass.addMember(new FieldNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), new BaseTypeNode(EnumTypeNode.INT), "a")); - // public static int testMethod(char x) { return 0; } - /* compilerInputClass.addMember( - new MethodNode( - new AccessTypeNode(EnumAccessTypeNode.PUBLIC), - new BaseTypeNode(EnumTypeNode.INT), - "testMethod", - new ParameterListNode(List.of(new ParameterNode(new BaseTypeNode(EnumTypeNode.CHAR), "x"))), - List.of(new ReturnStatementNode(new LiteralNode(0))) - )); - - ClassNode testClass = new ClassNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), "Test"); - testClass.addMember( - new MethodNode( - new AccessTypeNode(EnumAccessTypeNode.PUBLIC), - new BaseTypeNode(EnumTypeNode.INT), - "testMethod", - new ParameterListNode(List.of(new ParameterNode(new BaseTypeNode(EnumTypeNode.CHAR), "x"), new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "a"))), - List.of(new ReturnStatementNode(new LiteralNode(0))) - ) - ); - - */ - - //compilerInputClass.addClass(testClass); - - // startNode.addClass(compilerInputClass); - // startNode.addClass(testClass); -} +} \ No newline at end of file diff --git a/src/test/java/parser/Helper.java b/src/test/java/parser/Helper.java new file mode 100644 index 0000000..a679c8a --- /dev/null +++ b/src/test/java/parser/Helper.java @@ -0,0 +1,47 @@ +package parser; + +import ast.ASTNode; +import ast.ClassNode; +import ast.ProgramNode; +import ast.members.ConstructorNode; +import ast.members.MemberNode; +import ast.statements.BlockNode; +import ast.statements.ReturnNode; +import ast.type.AccessModifierNode; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import parser.astBuilder.ASTBuilder; +import parser.generated.SimpleJavaLexer; +import parser.generated.SimpleJavaParser; + +import java.io.IOException; + +public class Helper { + public static ASTNode generateAST(String filePath) { + CharStream testFile = null; + try { + testFile = CharStreams.fromFileName(filePath); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(testFile); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + tokenStream.fill(); + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + ASTBuilder astBuilder = new ASTBuilder(); + + return astBuilder.visit(parseTree); + } + + public static ClassNode generateEmptyClass(String className) { + BlockNode blockNode = new BlockNode(); + blockNode.addStatement(new ReturnNode(null)); + MemberNode constructor = new ConstructorNode("public",className, blockNode); + ClassNode classNode = new ClassNode("public", className); + classNode.addMember(constructor); + return classNode; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/Char.java b/src/test/resources/input/javaCases/Char.java new file mode 100644 index 0000000..de9c21f --- /dev/null +++ b/src/test/resources/input/javaCases/Char.java @@ -0,0 +1,12 @@ +class TestClass{ + + char a; + + public TestClass(char a){ + this.a = testMethod(a); + } + + char testMethod(char a){ + return a; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/Comments.java b/src/test/resources/input/javaCases/Comments.java new file mode 100644 index 0000000..2af751c --- /dev/null +++ b/src/test/resources/input/javaCases/Comments.java @@ -0,0 +1,8 @@ +/* + + Mutliple Line Comment. Ignore + + */ +class TestClass{ + private int a; // Ignore +} diff --git a/src/test/resources/input/javaCases/ConstructorMethodCall.java b/src/test/resources/input/javaCases/ConstructorMethodCall.java new file mode 100644 index 0000000..172777c --- /dev/null +++ b/src/test/resources/input/javaCases/ConstructorMethodCall.java @@ -0,0 +1,12 @@ +class TestClass { + + int a; + + public TestClass(){ + this.a = testMethod(); + } + + int testMethod(){ + return 1; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/ConstructorMethodCallParameters.java b/src/test/resources/input/javaCases/ConstructorMethodCallParameters.java new file mode 100644 index 0000000..fe3b0fd --- /dev/null +++ b/src/test/resources/input/javaCases/ConstructorMethodCallParameters.java @@ -0,0 +1,12 @@ +class TestClass { + + int a; + + public TestClass(int a){ + this.a = testMethod(a); + } + + int testMethod(int a){ + return a; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/ConstructorParameter.java b/src/test/resources/input/javaCases/ConstructorParameter.java new file mode 100644 index 0000000..96e27a1 --- /dev/null +++ b/src/test/resources/input/javaCases/ConstructorParameter.java @@ -0,0 +1,5 @@ +class TestClass { + public TestClass(int a, int b){ + + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/ConstructorThisDot.java b/src/test/resources/input/javaCases/ConstructorThisDot.java new file mode 100644 index 0000000..d51452d --- /dev/null +++ b/src/test/resources/input/javaCases/ConstructorThisDot.java @@ -0,0 +1,8 @@ +class TestClass{ + + private int a; + + public TestClass(int a){ + this.a = a; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/DoWhile.java b/src/test/resources/input/javaCases/DoWhile.java new file mode 100644 index 0000000..65c25de --- /dev/null +++ b/src/test/resources/input/javaCases/DoWhile.java @@ -0,0 +1,10 @@ +class TestClass{ + + public TestClass(){ + int i = 0; + + do{ + i++ + }while(i < 10); + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/EmptyClass.java b/src/test/resources/input/javaCases/EmptyClass.java new file mode 100644 index 0000000..f2be03c --- /dev/null +++ b/src/test/resources/input/javaCases/EmptyClass.java @@ -0,0 +1 @@ +class TestClass {} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/EmptyClassWithConstructor.java b/src/test/resources/input/javaCases/EmptyClassWithConstructor.java new file mode 100644 index 0000000..0907f20 --- /dev/null +++ b/src/test/resources/input/javaCases/EmptyClassWithConstructor.java @@ -0,0 +1,5 @@ +public class TestClass { + public TestClass() { + + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/Field.java b/src/test/resources/input/javaCases/Field.java new file mode 100644 index 0000000..082ad8b --- /dev/null +++ b/src/test/resources/input/javaCases/Field.java @@ -0,0 +1,3 @@ +public class TestClass { + int a; +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/FieldWithAccessModifier.java b/src/test/resources/input/javaCases/FieldWithAccessModifier.java new file mode 100644 index 0000000..7cd041f --- /dev/null +++ b/src/test/resources/input/javaCases/FieldWithAccessModifier.java @@ -0,0 +1,3 @@ +public class TestClass { + public int a; +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/For.java b/src/test/resources/input/javaCases/For.java new file mode 100644 index 0000000..4bb8f8a --- /dev/null +++ b/src/test/resources/input/javaCases/For.java @@ -0,0 +1,8 @@ +class TestClass{ + + public TestClass(){ + for(int i = 0; i < 10; i++){ + int a; + } + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/Increment.java b/src/test/resources/input/javaCases/Increment.java new file mode 100644 index 0000000..9560a9b --- /dev/null +++ b/src/test/resources/input/javaCases/Increment.java @@ -0,0 +1,12 @@ +public class Increment { + + public int test; + + public void increment(int p) { + test = p++; + + for(int i = 1; i<=10, i++) { + int a = 5; + } + } +} diff --git a/src/test/resources/input/javaCases/MainMehod.java b/src/test/resources/input/javaCases/MainMehod.java new file mode 100644 index 0000000..df7c2e1 --- /dev/null +++ b/src/test/resources/input/javaCases/MainMehod.java @@ -0,0 +1,5 @@ +class TestClass{ + + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/MultipleClasses.java b/src/test/resources/input/javaCases/MultipleClasses.java new file mode 100644 index 0000000..a560484 --- /dev/null +++ b/src/test/resources/input/javaCases/MultipleClasses.java @@ -0,0 +1,3 @@ +class TestClass1 {} + +class TestClass2{} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/Null.java b/src/test/resources/input/javaCases/Null.java new file mode 100644 index 0000000..719b7a0 --- /dev/null +++ b/src/test/resources/input/javaCases/Null.java @@ -0,0 +1,8 @@ +class TestClass{ + + int a; + + public TestClass(){ + this.a = null; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/SelfReference.java b/src/test/resources/input/javaCases/SelfReference.java new file mode 100644 index 0000000..cbe6e25 --- /dev/null +++ b/src/test/resources/input/javaCases/SelfReference.java @@ -0,0 +1,18 @@ +class TestClass{ + + TestClass testClass; + + int testMethod1() { + return this.testMethod2() + } + + int testMethod2() { + return 1; + } + + int testMehtod3(){ + TestClass testClass1 = new TestClass(); + return testClass1.testClass.testMethod1(); + } + +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/ThisDot.java b/src/test/resources/input/javaCases/ThisDot.java new file mode 100644 index 0000000..866b39e --- /dev/null +++ b/src/test/resources/input/javaCases/ThisDot.java @@ -0,0 +1,8 @@ +class TestClass{ + + public int a; + + public TestClass() { + this.a = 1; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/VoidMethod.java b/src/test/resources/input/javaCases/VoidMethod.java new file mode 100644 index 0000000..d342243 --- /dev/null +++ b/src/test/resources/input/javaCases/VoidMethod.java @@ -0,0 +1,3 @@ +class TestClass{ + void test(){} +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/While.java b/src/test/resources/input/javaCases/While.java new file mode 100644 index 0000000..c06efdd --- /dev/null +++ b/src/test/resources/input/javaCases/While.java @@ -0,0 +1,10 @@ +class TestClass{ + + public TestClass(){ + int i = 10; + + while ( i > 0){ + i--; + } + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/variableCalculationTest.java b/src/test/resources/input/javaCases/variableCalculationTest.java new file mode 100644 index 0000000..7708811 --- /dev/null +++ b/src/test/resources/input/javaCases/variableCalculationTest.java @@ -0,0 +1,34 @@ +class TestClass{ + + int aPlusB(int a, int b){ + return a + b; + } + + int aMinusB(int a, int b){ + return a - b; + } + + int aTimeB(int a, int b){ + return a * b; + } + + int aDivB(int a, int b){ + return a / b; + } + + int colmplexCalc (int a, int b){ + return a * (b / 1); + } + + boolean aSmallerB (int a, int b){ + return a < b; + } + + boolean aGreaterB (int a, int b){ + return a > b; + } + + boolean aEqualsB (int a, int b){ + return a == b; + } +} \ No newline at end of file diff --git a/src/test/resources/input/javaCases/variableCompareTest.java b/src/test/resources/input/javaCases/variableCompareTest.java new file mode 100644 index 0000000..dc01954 --- /dev/null +++ b/src/test/resources/input/javaCases/variableCompareTest.java @@ -0,0 +1,30 @@ +class TestClass{ + + boolean true(){ + return true; + } + + boolean false(){ + return false(); + } + + boolean trueAndTrue(){ + return true && true; + } + + boolean trueAndFalse(){ + return true && true; + } + + boolean falseAndFalse(){ + return false && false; + } + + boolean trueOrFalse(){ + return true || false; + } + + boolean falseOrFalse(){ + return false || false; + } +} \ No newline at end of file