diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index 49deeb3..c4d3da4 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -799,6 +799,16 @@ public class ContextAnalysis extends KlangBaseVisitor { throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } + if (structDefs.containsKey(structFieldName)) { + var error = "Struct field name " + structFieldName + " shadows a struct of the same name."; + throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + } + + if (enumDefs.containsKey(structFieldName)) { + var error = "Struct field name " + structFieldName + " shadows an enum of the same name."; + throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + } + var structField = new StructField(structFieldName); structField.type = structFieldType; structField.line = line; diff --git a/src/test/java/StructDefinitionTest.java b/src/test/java/StructDefinitionTest.java index b3150f3..11dce9c 100644 --- a/src/test/java/StructDefinitionTest.java +++ b/src/test/java/StructDefinitionTest.java @@ -27,6 +27,38 @@ public class StructDefinitionTest { assertDoesNotThrow(() -> ctxAnal.visit(tree)); } + @Test + void shouldNotThrowIfStructFieldTypeIsReferringToStruct() { + // given + var tree = Helper.prepareParser("struct a { hello: int; } struct b { world: a; } function foo(): int { return 1; } foo();"); + var ctxAnal = new ContextAnalysis(Helper.getFuncs(tree), Helper.getStructs(tree), Helper.getEnums(tree)); + + // when / then + assertDoesNotThrow(() -> ctxAnal.visit(tree)); + } + + @Test + void shouldThrowExceptionIfStructFieldNameShadowsAStruct() { + // given + var tree = Helper.prepareParser("struct bar { a: int; } struct baz { bar: int; } function foo(): 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:36 Struct field name bar shadows a struct of the same name.", e.getMessage()); + } + + @Test + void shouldThrowExceptionIfStructFieldNameShadowsAnEnum() { + // given + var tree = Helper.prepareParser("enum bar { A, B } struct baz { bar: int; } function foo(): 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:31 Struct field name bar shadows an enum of the same name.", e.getMessage()); + } + @Test void shouldThrowExceptionIfStructFieldTypeIsNotDefined() { // given