Refactor FunctionDefinition and Parameter context analysis and extend the type check to include enums.

This commit is contained in:
2023-03-15 17:47:58 +01:00
parent 9a58afb550
commit 3b928d621b
2 changed files with 106 additions and 55 deletions

View File

@@ -1,34 +1,82 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
import static org.junit.jupiter.api.Assertions.*;
public class FunctionDefinitionTest {
@Test
void typeNotDefined() {
ParseTree tree = Helper.prepareParser("function foo(): schwurbel { return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
var enums = Helper.getEnums(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs, enums);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:0 Type schwurbel not defined.", e.getMessage());
void shouldNotThrowIfReturnTypeIsReferringToAnEnum() {
// given
var tree = Helper.prepareParser(" enum bar {A,B,C} function foo(a: int): bar { return bar.A; } foo();");
var ctxAnal = new ContextAnalysis(
Helper.getFuncs(tree),
Helper.getStructs(tree),
Helper.getEnums(tree)
);
// when / then
assertDoesNotThrow(() -> ctxAnal.visit(tree));
}
@Test
void noReturnExpression() {
ParseTree tree = Helper.prepareParser("function foo(): int { let x: int; x = 0; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
var enums = Helper.getEnums(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs, enums);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:0 Function foo has to return something of type int.", e.getMessage());
void shouldNotThrowIfParameterTypeIsReferringToAnEnum() {
// given
var tree = Helper.prepareParser(" enum bar {A,B,C} function foo(a: bar): int { return 1; } foo(bar.A);");
var ctxAnal = new ContextAnalysis(
Helper.getFuncs(tree),
Helper.getStructs(tree),
Helper.getEnums(tree)
);
// when / then
assertDoesNotThrow(() -> ctxAnal.visit(tree));
}
@Test
void shouldThrowExceptionIfParameterTypeIsNotDefined() {
// given
var tree = Helper.prepareParser("function foo(a: schwurbel): int { return 1; } foo();");
var ctxAnal = new ContextAnalysis(
Helper.getFuncs(tree),
Helper.getStructs(tree),
Helper.getEnums(tree)
);
// when / then
var e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:14 Type schwurbel not defined.", e.getMessage());
}
@Test
void shouldThrowExceptionIfReturnTypeIsNotDefined() {
// given
var tree = Helper.prepareParser("function foo(): schwurbel { return 1; } foo();");
var ctxAnal = new ContextAnalysis(
Helper.getFuncs(tree),
Helper.getStructs(tree),
Helper.getEnums(tree)
);
// when / then
var e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:14 Type schwurbel not defined.", e.getMessage());
}
@Test
void shouldThrowExceptionIfReturnStatementIsMissing() {
// given
var tree = Helper.prepareParser("function foo(): int { let x: int; x = 0; } foo();");
var ctxAnal = new ContextAnalysis(
Helper.getFuncs(tree),
Helper.getStructs(tree),
Helper.getEnums(tree)
);
// when / then
var e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:20 Function foo has to return something of type int.", e.getMessage());
}
}