From 2bdd9c54dd4fb4a1cf7ef6d48ae5590551d6ed2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Gr=C3=BCn?= Date: Mon, 20 Apr 2026 17:58:31 +0200 Subject: [PATCH 1/4] #251 Test zum resolven von Variablen erstellt. --- .../astrules/ASTResolveVariablesTest.java | 114 ++++++++++++++++++ .../src/test/resources/symSymbolTables/A.sym | 1 + .../src/test/resources/symSymbolTables/A2.sym | 1 + 3 files changed, 116 insertions(+) create mode 100644 language/src/test/java/astrules/ASTResolveVariablesTest.java create mode 100644 language/src/test/resources/symSymbolTables/A.sym create mode 100644 language/src/test/resources/symSymbolTables/A2.sym diff --git a/language/src/test/java/astrules/ASTResolveVariablesTest.java b/language/src/test/java/astrules/ASTResolveVariablesTest.java new file mode 100644 index 00000000..0b0d2d17 --- /dev/null +++ b/language/src/test/java/astrules/ASTResolveVariablesTest.java @@ -0,0 +1,114 @@ +package astrules; + +import de.monticore.io.paths.MCPath; +import de.monticore.lang.sysmlbasis._symboltable.ISysMLBasisScope; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; + +import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; +import de.se_rwth.commons.logging.Log; +import de.se_rwth.commons.logging.LogStub; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Diese Testklasse validiert die Resolve-Funktion für Variablenreferenzen in SysMLv2-Code. + * + * testCreateSymFiles erstellt symboltable-Dateien, um damit die Resolve-Funktion + * zu testen ohne dass sie Zugriff auf den AST benötigt. + * + * testResolveOfVariables testet die Auflösung von Variablen wie 'a' und 'a.b' in einem Beispielmodell. + * + */ +public class ASTResolveVariablesTest { + + private static final String JSON_OUTPUT_DIR = "src/test/resources/symSymbolTables"; + private static final SysMLv2Tool tool = new SysMLv2Tool(); + + @BeforeAll + public static void init() { + LogStub.init(); + SysMLv2Mill.init(); + } + + @BeforeEach + public void reset() { + SysMLv2Mill.globalScope().clear(); + SysMLv2Mill.initializePrimitives(); + SysMLv2Mill.addCollectionTypes(); + Log.clearFindings(); + } + + //@Test + public void testCreateSymFiles() throws IOException { + List models = List.of( + "attribute def A { attribute b: boolean; }", + "attribute def A2 { attribute a:A; attribute b2: boolean; }" + ); + + // Model verarbeiten + for (var model : models) { + var ast = SysMLv2Mill.parser().parse_String(model).get(); + var artifactScope = tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + tool.storeSymbols(artifactScope, + JSON_OUTPUT_DIR + "/" + artifactScope.getName() + ".sym"); + } + } + + // Der test soll fehlschlagen, da die resolve Funktion a.b aktuell + // noch nicht finden kann + //@Test + public void testResolveOfVariable() throws IOException { + String model = "attribute a:A; constraint { a.b }"; + var ast = SysMLv2Mill.parser().parse_String(model).get(); + + SysMLv2Mill.globalScope().setSymbolPath(new MCPath(Paths.get(JSON_OUTPUT_DIR))); + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + ISysMLBasisScope scope = ast.getSysMLElement(1).getEnclosingScope(); + Optional a = scope.resolveVariable("a"); + assertThat(a).isPresent(); + Optional ab = scope.resolveVariable("a.b"); + assertThat(ab).isPresent(); + } + + // Der test soll fehlschlagen, da die resolve Funktion a2.b2 und a2.a.b + // aktuell noch nicht finden kann + //@Test + public void testResolveOfVariable2() throws IOException { + String model = "attribute a2:A2; constraint { a2.a.b }"; + var ast = SysMLv2Mill.parser().parse_String(model).get(); + + SysMLv2Mill.globalScope().setSymbolPath(new MCPath(Paths.get(JSON_OUTPUT_DIR))); + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + ISysMLBasisScope scope = ast.getSysMLElement(1).getEnclosingScope(); + Optional a2 = scope.resolveVariable("a2"); + assertThat(a2).isPresent(); + Optional a2b2 = scope.resolveVariable("a2.b2"); + assertThat(a2b2).isPresent(); + Optional a2ab = scope.resolveVariable("a2.a.b"); + assertThat(a2ab).isPresent(); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } +} diff --git a/language/src/test/resources/symSymbolTables/A.sym b/language/src/test/resources/symSymbolTables/A.sym new file mode 100644 index 00000000..7382ad19 --- /dev/null +++ b/language/src/test/resources/symSymbolTables/A.sym @@ -0,0 +1 @@ +{"generated-using":"www.MontiCore.de technology","name":"A","symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeDefSymbol","name":"A","fullName":"A","spannedScope":{"symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol","name":"b","fullName":"A.b","types":[{"kind":"de.monticore.types.check.SymTypePrimitive","primitiveName":"boolean"}],"in":true}]}}]} \ No newline at end of file diff --git a/language/src/test/resources/symSymbolTables/A2.sym b/language/src/test/resources/symSymbolTables/A2.sym new file mode 100644 index 00000000..a14fd788 --- /dev/null +++ b/language/src/test/resources/symSymbolTables/A2.sym @@ -0,0 +1 @@ +{"generated-using":"www.MontiCore.de technology","name":"A2","symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeDefSymbol","name":"A2","fullName":"A2","spannedScope":{"symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol","name":"a","fullName":"A2.a","types":[{"kind":"de.monticore.types.check.SymTypeOfObject","objName":"A"}],"in":true},{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol","name":"b2","fullName":"A2.b2","types":[{"kind":"de.monticore.types.check.SymTypePrimitive","primitiveName":"boolean"}],"in":true}]}}]} \ No newline at end of file From 6ee880fb6bef0c07270222ca59310fbbabe8e944 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Tue, 21 Apr 2026 14:17:03 +0200 Subject: [PATCH 2/4] Einfacher --- .../astrules/ASTResolveVariablesTest.java | 97 ++++--------------- .../src/test/resources/symSymbolTables/A.sym | 1 - .../src/test/resources/symSymbolTables/A2.sym | 1 - 3 files changed, 21 insertions(+), 78 deletions(-) delete mode 100644 language/src/test/resources/symSymbolTables/A.sym delete mode 100644 language/src/test/resources/symSymbolTables/A2.sym diff --git a/language/src/test/java/astrules/ASTResolveVariablesTest.java b/language/src/test/java/astrules/ASTResolveVariablesTest.java index 0b0d2d17..be87ab25 100644 --- a/language/src/test/java/astrules/ASTResolveVariablesTest.java +++ b/language/src/test/java/astrules/ASTResolveVariablesTest.java @@ -2,16 +2,16 @@ import de.monticore.io.paths.MCPath; import de.monticore.lang.sysmlbasis._symboltable.ISysMLBasisScope; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlimportsandpackages._ast.ASTSysMLPackage; import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.LogStub; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import java.io.IOException; import java.nio.file.Paths; @@ -31,84 +31,29 @@ */ public class ASTResolveVariablesTest { - private static final String JSON_OUTPUT_DIR = "src/test/resources/symSymbolTables"; - private static final SysMLv2Tool tool = new SysMLv2Tool(); - - @BeforeAll - public static void init() { - LogStub.init(); - SysMLv2Mill.init(); - } - - @BeforeEach - public void reset() { - SysMLv2Mill.globalScope().clear(); - SysMLv2Mill.initializePrimitives(); - SysMLv2Mill.addCollectionTypes(); - Log.clearFindings(); - } - - //@Test - public void testCreateSymFiles() throws IOException { - List models = List.of( - "attribute def A { attribute b: boolean; }", - "attribute def A2 { attribute a:A; attribute b2: boolean; }" - ); - - // Model verarbeiten - for (var model : models) { - var ast = SysMLv2Mill.parser().parse_String(model).get(); - var artifactScope = tool.createSymbolTable(ast); - tool.completeSymbolTable(ast); - tool.finalizeSymbolTable(ast); - tool.storeSymbols(artifactScope, - JSON_OUTPUT_DIR + "/" + artifactScope.getName() + ".sym"); - } - } - - // Der test soll fehlschlagen, da die resolve Funktion a.b aktuell - // noch nicht finden kann - //@Test + //@Disabled("Resolve von a.b schlägt noch fehl") + @Test public void testResolveOfVariable() throws IOException { - String model = "attribute a:A; constraint { a.b }"; - var ast = SysMLv2Mill.parser().parse_String(model).get(); - - SysMLv2Mill.globalScope().setSymbolPath(new MCPath(Paths.get(JSON_OUTPUT_DIR))); - tool.createSymbolTable(ast); - tool.completeSymbolTable(ast); - tool.finalizeSymbolTable(ast); - - ISysMLBasisScope scope = ast.getSysMLElement(1).getEnclosingScope(); - Optional a = scope.resolveVariable("a"); - assertThat(a).isPresent(); - Optional ab = scope.resolveVariable("a.b"); - assertThat(ab).isPresent(); - } - - // Der test soll fehlschlagen, da die resolve Funktion a2.b2 und a2.a.b - // aktuell noch nicht finden kann - //@Test - public void testResolveOfVariable2() throws IOException { - String model = "attribute a2:A2; constraint { a2.a.b }"; + LogStub.init(); + var tool = new SysMLv2Tool(); + tool.init(); + + var model = "" + + "package Test {\n" + + " attribute def A { attribute b: boolean; }\n" + + " attribute a: A;\n" + + " constraint { a.b }\n" + + "}"; var ast = SysMLv2Mill.parser().parse_String(model).get(); - - SysMLv2Mill.globalScope().setSymbolPath(new MCPath(Paths.get(JSON_OUTPUT_DIR))); tool.createSymbolTable(ast); tool.completeSymbolTable(ast); tool.finalizeSymbolTable(ast); - ISysMLBasisScope scope = ast.getSysMLElement(1).getEnclosingScope(); - Optional a2 = scope.resolveVariable("a2"); - assertThat(a2).isPresent(); - Optional a2b2 = scope.resolveVariable("a2.b2"); - assertThat(a2b2).isPresent(); - Optional a2ab = scope.resolveVariable("a2.a.b"); - assertThat(a2ab).isPresent(); - } + var testPackage = (ASTSysMLPackage) ast.getSysMLElement(0); + var constr = (ASTConstraintUsage) testPackage.getSysMLElement(2); + var expr = constr.getExpression(); - @AfterEach - void clearLog() { - Log.clearFindings(); - Log.enableFailQuick(true); + var variable = ((ISysMLv2Scope)expr.getEnclosingScope()).resolveVariable("a.b"); + assertThat(variable).isPresent(); } } diff --git a/language/src/test/resources/symSymbolTables/A.sym b/language/src/test/resources/symSymbolTables/A.sym deleted file mode 100644 index 7382ad19..00000000 --- a/language/src/test/resources/symSymbolTables/A.sym +++ /dev/null @@ -1 +0,0 @@ -{"generated-using":"www.MontiCore.de technology","name":"A","symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeDefSymbol","name":"A","fullName":"A","spannedScope":{"symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol","name":"b","fullName":"A.b","types":[{"kind":"de.monticore.types.check.SymTypePrimitive","primitiveName":"boolean"}],"in":true}]}}]} \ No newline at end of file diff --git a/language/src/test/resources/symSymbolTables/A2.sym b/language/src/test/resources/symSymbolTables/A2.sym deleted file mode 100644 index a14fd788..00000000 --- a/language/src/test/resources/symSymbolTables/A2.sym +++ /dev/null @@ -1 +0,0 @@ -{"generated-using":"www.MontiCore.de technology","name":"A2","symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeDefSymbol","name":"A2","fullName":"A2","spannedScope":{"symbols":[{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol","name":"a","fullName":"A2.a","types":[{"kind":"de.monticore.types.check.SymTypeOfObject","objName":"A"}],"in":true},{"kind":"de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol","name":"b2","fullName":"A2.b2","types":[{"kind":"de.monticore.types.check.SymTypePrimitive","primitiveName":"boolean"}],"in":true}]}}]} \ No newline at end of file From 2a7b9c82b34f8db53c36424415c2f254f6510313 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Tue, 21 Apr 2026 15:47:50 +0200 Subject: [PATCH 3/4] resolveField --- language/src/test/java/astrules/ASTResolveVariablesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language/src/test/java/astrules/ASTResolveVariablesTest.java b/language/src/test/java/astrules/ASTResolveVariablesTest.java index be87ab25..f4101fa8 100644 --- a/language/src/test/java/astrules/ASTResolveVariablesTest.java +++ b/language/src/test/java/astrules/ASTResolveVariablesTest.java @@ -53,7 +53,7 @@ public void testResolveOfVariable() throws IOException { var constr = (ASTConstraintUsage) testPackage.getSysMLElement(2); var expr = constr.getExpression(); - var variable = ((ISysMLv2Scope)expr.getEnclosingScope()).resolveVariable("a.b"); + var variable = ((ISysMLv2Scope)expr.getEnclosingScope()).resolveField("a.b"); assertThat(variable).isPresent(); } } From 3429d042851afaf9397f41ddac3ee2520d7978cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Gr=C3=BCn?= Date: Tue, 28 Apr 2026 03:57:29 +0200 Subject: [PATCH 4/4] #251 Test zum resolven von Fields ohne Adapter erstellt --- .../astrules/ASTResolveVariablesTest.java | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/language/src/test/java/astrules/ASTResolveVariablesTest.java b/language/src/test/java/astrules/ASTResolveVariablesTest.java index f4101fa8..cb63b272 100644 --- a/language/src/test/java/astrules/ASTResolveVariablesTest.java +++ b/language/src/test/java/astrules/ASTResolveVariablesTest.java @@ -1,37 +1,35 @@ package astrules; -import de.monticore.io.paths.MCPath; -import de.monticore.lang.sysmlbasis._symboltable.ISysMLBasisScope; import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; import de.monticore.lang.sysmlimportsandpackages._ast.ASTSysMLPackage; import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2ArtifactScope; import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; -import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; -import de.se_rwth.commons.logging.Log; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolBuilder; +import de.monticore.symbols.basicsymbols._symboltable.VariableSymbolBuilder; +import de.monticore.symbols.oosymbols._symboltable.FieldSymbolBuilder; +import de.monticore.types.check.SymTypeExpressionFactory; import de.se_rwth.commons.logging.LogStub; import org.junit.jupiter.api.*; import java.io.IOException; -import java.nio.file.Paths; -import java.util.List; -import java.util.Optional; + import static org.assertj.core.api.Assertions.assertThat; /** - * Diese Testklasse validiert die Resolve-Funktion für Variablenreferenzen in SysMLv2-Code. - * - * testCreateSymFiles erstellt symboltable-Dateien, um damit die Resolve-Funktion - * zu testen ohne dass sie Zugriff auf den AST benötigt. - * - * testResolveOfVariables testet die Auflösung von Variablen wie 'a' und 'a.b' in einem Beispielmodell. + * Diese Testklasse validiert die Resolve-Funktion für Feldausdrücke (wie 'a.b') in SysMLv2-Code. * + * testResolveOfVariable testet die direkte Auflösung von Feldausdrücken wie 'a.b' durch Parsing eines + * kompletten SysMLv2-Modells. Das Ziel ist, einen Feldausdruck zu resolven, ohne vorher manuell die Variable + * zu resolven und dann in deren Typ nach dem Feld zu suchen. Weitere Tests mit komplexeren Verschachtelungen + * werden später hinzugefügt. */ public class ASTResolveVariablesTest { - //@Disabled("Resolve von a.b schlägt noch fehl") + @Disabled("Resolve von a.b schlägt noch fehl") @Test public void testResolveOfVariable() throws IOException { LogStub.init(); @@ -56,4 +54,32 @@ public void testResolveOfVariable() throws IOException { var variable = ((ISysMLv2Scope)expr.getEnclosingScope()).resolveField("a.b"); assertThat(variable).isPresent(); } + + @Disabled("Resolve von a.b schlägt noch fehl") + @Test + public void testResolveFieldWithoutAdapters() { + LogStub.init(); + SysMLv2Mill.init(); + ISysMLv2ArtifactScope artifactScope = SysMLv2Mill.artifactScope(); + SysMLv2Mill.prepareGlobalScope(); + + var booleanSymbol = SysMLv2Mill.globalScope().resolveType("boolean").get(); + artifactScope.add(booleanSymbol); + + var boolType = SymTypeExpressionFactory.createPrimitive(booleanSymbol); + var fieldSymbol = new FieldSymbolBuilder().setName("b").setType(boolType).build(); + artifactScope.add(fieldSymbol); + var typeAScope = SysMLv2Mill.scope(); + typeAScope.add(fieldSymbol); + var typeSymbolA = new TypeSymbolBuilder().setName("A").setSpannedScope(typeAScope).build(); + artifactScope.add(typeSymbolA); + + var typeA = SymTypeExpressionFactory.createTypeObject(typeSymbolA); + var variableSymbol = new VariableSymbolBuilder().setName("a").setType(typeA).build(); + artifactScope.add(variableSymbol); + + var field = artifactScope.resolveField("a.b"); + assertThat(field).isPresent(); + + } }