From 62e974dbdc5ee4f14f3ad5ec3ee898b048988206 Mon Sep 17 00:00:00 2001 From: MKZaito <127297267+MKZaito@users.noreply.github.com> Date: Fri, 30 Jan 2026 18:03:22 +0100 Subject: [PATCH 1/4] clean up SubPartNamesInConnectionExistCoCo remove ambiguous name check from SubPartNamesInConnectionExistCoCo --- ...=> SubPartNamesInConnectionExistCoCo.java} | 15 +-- ...SubPartNamesInConnectionExistCoCoTest.java | 126 ++++++++++++++++++ 2 files changed, 132 insertions(+), 9 deletions(-) rename language/src/main/java/de/monticore/lang/sysmlv2/cocos/{UniqueSubPartNamesInConnectionCoCo.java => SubPartNamesInConnectionExistCoCo.java} (82%) create mode 100644 language/src/test/java/cocos/SubPartNamesInConnectionExistCoCoTest.java diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubPartNamesInConnectionExistCoCo.java similarity index 82% rename from language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java rename to language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubPartNamesInConnectionExistCoCo.java index 70161fe8..683f207c 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubPartNamesInConnectionExistCoCo.java @@ -10,9 +10,9 @@ /** * CoCo3: Jeder in "connect a.b to c.d" verwendete Name von Subkomponenten (a und c) - * muss eindeutig im Modell vorhanden sein. + * muss im Modell vorhanden sein. */ -public class UniqueSubPartNamesInConnectionCoCo implements SysMLPartsASTConnectionUsageCoCo { +public class SubPartNamesInConnectionExistCoCo implements SysMLPartsASTConnectionUsageCoCo { @Override public void check(ASTConnectionUsage node) { @@ -42,13 +42,10 @@ protected void checkSubcomponentQualifier(ISysMLPartsScope scope, .size(); if (matches > 1) { - Log.error( - "0x10AA3 The subcomponent name used in 'connect' \"" + subName - + "\" is not unique in the model.", - node.get_SourcePositionStart(), - node.get_SourcePositionEnd() - ); - } else if (matches != 1) { /** matches = 0 */ + /* + * ambiguous names in PartDefinition are caught by UniqueSubPartNamesInParentCoCo + */ + } else if (matches == 0) { Log.error( "0x10AA3 The subcomponent name used in 'connect' \"" + subName + "\" does not exist in the model.", diff --git a/language/src/test/java/cocos/SubPartNamesInConnectionExistCoCoTest.java b/language/src/test/java/cocos/SubPartNamesInConnectionExistCoCoTest.java new file mode 100644 index 00000000..a662826d --- /dev/null +++ b/language/src/test/java/cocos/SubPartNamesInConnectionExistCoCoTest.java @@ -0,0 +1,126 @@ +/* (c) https://github.com/MontiCore/monticore */ +package cocos; + +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._ast.ASTSysMLModel; +import de.monticore.lang.sysmlv2._cocos.SysMLv2CoCoChecker; +import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2ArtifactScope; +import de.monticore.lang.sysmlv2.cocos.SubPartNamesInConnectionExistCoCo; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SubPartNamesInConnectionExistCoCoTest { + + private static final String MODEL_PATH = "src/test/resources/parser"; + + private SysMLv2Parser parser = SysMLv2Mill.parser(); + + @BeforeAll + public static void init() { + Log.init(); + SysMLv2Mill.init(); + } + + @BeforeEach + public void reset() { + SysMLv2Mill.globalScope().clear(); + SysMLv2Mill.initializePrimitives(); + SysMLv2Mill.addCollectionTypes(); + Log.clearFindings(); + } + + @Nested + public class UniqueSubPartNamesInConnectionCoCoTests { + @Test + public void testValid() throws IOException { + String validModel = + "part def A { port p: int; }" + + "part def B { port q: ~int; }" + + "part def System {" + + "part a: A;" + + "part b: B;" + + "connect a.p to b.q;" + + "}"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testInvalidUndefined() throws IOException { + String invalidModel = + "part def A { port p: int; }" + + "part def B { port q: ~int; }" + + "part def System {" + + "part a: A;" + + "connect a.p to c.q;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA3"); + } + + @Test + public void testInvalidBothUndefined() throws IOException { + String invalidModel = + "part def A { port p; }" + + "part def System {" + + "part a: A;" + + "connect undefined1.p to undefined2.p;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(2); + assertThat(errors.get(0).getMsg()).contains("0x10AA3"); + assertThat(errors.get(1).getMsg()).contains("0x10AA3"); + } + + private ASTSysMLModel parse(String model) throws IOException { + var optAst = SysMLv2Mill.parser().parse_String(model); + assertThat(optAst).isPresent(); + return optAst.get(); + } + + private ISysMLv2ArtifactScope createSt(ASTSysMLModel ast) { + var tool = new SysMLv2Tool(); + var scope = tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + return scope; + } + + private List check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new SubPartNamesInConnectionExistCoCo()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(Finding::isError).collect( + Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + } +} From 6dc4de21f6ea1d3c48712e0a8eeb652163aba84a Mon Sep 17 00:00:00 2001 From: MKZaito <127297267+MKZaito@users.noreply.github.com> Date: Fri, 30 Jan 2026 13:03:11 +0100 Subject: [PATCH 2/4] add UniqueSubPartNamesInParentCoCo --- .../cocos/UniqueSubPartNamesInParentCoCo.java | 35 +++++++++ ...> UniqueSubPartNamesInParentCoCoTest.java} | 72 ++----------------- 2 files changed, 42 insertions(+), 65 deletions(-) create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java rename language/src/test/java/cocos/{UniqueSubPartNamesInConnectionCoCoTest.java => UniqueSubPartNamesInParentCoCoTest.java} (53%) diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java new file mode 100644 index 00000000..9bd3f697 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java @@ -0,0 +1,35 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTPartUsageCoCo; +import de.monticore.symboltable.modifiers.AccessModifier; +import de.se_rwth.commons.logging.Log; + +/** + * CoCo: Jede Subkomponente muss einen eindeutigen Namen haben + */ +public class UniqueSubPartNamesInParentCoCo implements SysMLPartsASTPartUsageCoCo { + + @Override + public void check(ASTPartUsage node) { + + var scope = node.getEnclosingScope(); + + String partName = node.getName(); + + int matches = scope + .resolvePartUsageLocallyMany(false, partName, + AccessModifier.ALL_INCLUSION, p -> true) + .size(); + + if (matches > 1) { + Log.error( + "0x10AA7 The subcomponent name used in 'def' \"" + partName + + "\" is not unique in the model.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd() + ); + } + } +} diff --git a/language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java b/language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java similarity index 53% rename from language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java rename to language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java index 38913d6b..3eeaba20 100644 --- a/language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java +++ b/language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java @@ -7,14 +7,10 @@ import de.monticore.lang.sysmlv2._cocos.SysMLv2CoCoChecker; import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; import de.monticore.lang.sysmlv2._symboltable.ISysMLv2ArtifactScope; -import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInConnectionCoCo; +import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInParentCoCo; import de.se_rwth.commons.logging.Finding; import de.se_rwth.commons.logging.Log; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import java.io.IOException; import java.util.List; @@ -22,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; -public class UniqueSubPartNamesInConnectionCoCoTest { +public class UniqueSubPartNamesInParentCoCoTest { private static final String MODEL_PATH = "src/test/resources/parser"; @@ -52,7 +48,6 @@ public void testValid() throws IOException { + "part def System {" + "part a: A;" + "part b: B;" - + "connect a.p to b.q;" + "}"; var ast = parse(validModel); @@ -62,73 +57,20 @@ public void testValid() throws IOException { } @Test - public void testInvalidUndefined() throws IOException { + public void testInvalidDoubleDefined() throws IOException { String invalidModel = "part def A { port p: int; }" + "part def B { port q: ~int; }" + "part def System {" + "part a: A;" - + "connect a.p to c.q;" + + "part a: B;" + "}"; - var ast = parse(invalidModel); - createSt(ast); - var errors = check(ast); - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getMsg()).contains("0x10AA3"); - } - - @Test - public void testInvalidDuplicateName() throws IOException { - String invalidModel = - "part def A { port p; }" - + "part def System {" - + "part a: A;" - + "part a: A;" - + "connect a.p to a.p;" - + "}"; - - var ast = parse(invalidModel); - createSt(ast); - var errors = check(ast); - assertThat(errors).hasSize(2); - assertThat(errors.get(0).getMsg()).contains("0x10AA3"); - assertThat(errors.get(1).getMsg()).contains("0x10AA3"); - } - - @Test - public void testInvalidBothUndefined() throws IOException { - String invalidModel = - "part def A { port p; }" - + "part def System {" - + "part a: A;" - + "connect undefined1.p to undefined2.p;" - + "}"; - - var ast = parse(invalidModel); - createSt(ast); - var errors = check(ast); - assertThat(errors).hasSize(2); - assertThat(errors.get(0).getMsg()).contains("0x10AA3"); - assertThat(errors.get(1).getMsg()).contains("0x10AA3"); - } - - @Test - public void testInvalidUndefinedAndDuplicateName() throws IOException { - String invalidModel = - "part def A { port p; }" - + "part def System {" - + "part duplicate1: A;" - + "part duplicate1: ~A;" - + "connect duplicate1.p to undefined3.p;" - + "}"; - var ast = parse(invalidModel); createSt(ast); var errors = check(ast); assertThat(errors).hasSize(2); - assertThat(errors.get(0).getMsg()).contains("0x10AA3"); - assertThat(errors.get(1).getMsg()).contains("0x10AA3"); + assertThat(errors.get(0).getMsg()).contains("0x10AA7"); } private ASTSysMLModel parse(String model) throws IOException { @@ -146,7 +88,7 @@ private ISysMLv2ArtifactScope createSt(ASTSysMLModel ast) { private List check(ASTSysMLModel ast) { var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo()); + checker.addCoCo(new UniqueSubPartNamesInParentCoCo()); Log.enableFailQuick(false); checker.checkAll(ast); return Log.getFindings().stream().filter(Finding::isError).collect( From 79c57059d6973086a36d29b73f28cfa845b3180e Mon Sep 17 00:00:00 2001 From: MKZaito <127297267+MKZaito@users.noreply.github.com> Date: Fri, 30 Jan 2026 18:13:49 +0100 Subject: [PATCH 3/4] update SysMLv2Tool Checker --- .../main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java index 98922538..4bd3bc19 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -46,7 +46,8 @@ import de.monticore.lang.sysmlv2.cocos.QualifiedPortNameExistsCoCo; import de.monticore.lang.sysmlv2.cocos.RefinementTargetDefinitionExistsCoCo; import de.monticore.lang.sysmlv2.cocos.SubcomponentOutputConnectionDirectionCoCo; -import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInConnectionCoCo; +import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInParentCoCo; +import de.monticore.lang.sysmlv2.cocos.SubPartNamesInConnectionExistCoCo; import de.monticore.lang.sysmlv2.symboltable.completers.CausalityCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectRefinementCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectionCompleter; @@ -126,11 +127,13 @@ public void runDefaultCoCos(ASTSysMLModel ast) { checker.addCoCo(new PartTypeDefinitionExistsCoCo()); checker.addCoCo(new RefinementTargetDefinitionExistsCoCo()); // Connection CoCos - checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo()); + checker.addCoCo(new SubPartNamesInConnectionExistCoCo()); checker.addCoCo(new QualifiedPortNameExistsCoCo()); checker.addCoCo(new SubcomponentOutputConnectionDirectionCoCo()); checker.addCoCo(new ParentComponentInputConnectionDirectionCoCo()); - + // Check ambiguous names + checker.addCoCo(new UniqueSubPartNamesInParentCoCo()); + checker.checkAll(ast); } From 72c7e13f8d4f1d1ebc5dc9431c042ff5661d1afb Mon Sep 17 00:00:00 2001 From: MKZaito <127297267+MKZaito@users.noreply.github.com> Date: Fri, 30 Jan 2026 18:14:06 +0100 Subject: [PATCH 4/4] version bump to 7.8.7 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index ff425dfa..1966761e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,4 +25,4 @@ assertj_version = 3.21.0 junit_version = 5.8.2 # Version of published artifacts -version = 7.8.6 +version = 7.8.7