From 273231e29fc9be942bf448b740958483016978e4 Mon Sep 17 00:00:00 2001 From: Vanol Nguemo Tadoum Date: Mon, 6 Jul 2026 20:32:37 +0200 Subject: [PATCH 1/7] Fix redundant CD2Pojo association check --- .../cdgen/cocos/CDAssociationUnique.java | 87 ++++++++++--------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java index f4144774b..9d218dd86 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -26,45 +26,19 @@ public void check(ASTCDDefinition node) { List alreadyChecked = new ArrayList<>(); // we check for each pair of associations - for (ASTCDAssociation assoc1 : node.getCDAssociationsList()) { + for (ASTCDAssociation assoc2 : node.getCDAssociationsList()) { - alreadyChecked.add(assoc1); - - for (ASTCDAssociation assoc2 : node.getCDAssociationsList()) { - - // only check each pair once - if (assoc2 != assoc1 && !alreadyChecked.contains(assoc2)) { - - // if they share a left role-name, the referenced types on the right should not be the - // same - if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, - AssocSide.LEFT))) { - checkRef(node, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName()), assoc1); - } - - // if they share a right role-name, the referenced types on the left should not be the - // same - if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, - AssocSide.RIGHT))) { - checkRef(node, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName()), assoc1); - } - - // We also consider a left-to-right role name match ... - if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, - AssocSide.RIGHT))) { - checkRef(node, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName()), assoc1); - } - // ... as well as a right-to-left match - if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, - AssocSide.LEFT))) { - checkRef(node, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName()), assoc1); + for (ASTCDAssociation assoc1 : alreadyChecked) { + for (AssociationReference ref1 : getAssociationReferences(assoc1)) { + for (AssociationReference ref2 : getAssociationReferences(assoc2)) { + if (ref1.name.equals(ref2.name)) { + checkRef(node, ref1.sourceType, ref2.sourceType, assoc2); + } } } } + + alreadyChecked.add(assoc2); } } @@ -85,6 +59,9 @@ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { /** Check if type2 is the same as type1. */ protected void checkRef(ASTCDDefinition node, ASTCDType type1, ASTCDType type2, ASTCDAssociation assoc1) { + if (type1 == null || type2 == null) { + return; + } if (type1.equals(type2)) { Log.error(String.format("0xCDCE1: %s has a duplicate association to %s", type1.getName(), type2.getName()), assoc1.isPresent_SourcePositionStart() ? assoc1 @@ -102,20 +79,52 @@ protected String deriveRoleName(ASTCDAssociation assoc, AssocSide side) { else { assocSide = assoc.getRight(); } - if (assocSide.isPresentCDRole()) { - return assocSide.getCDRole().getName(); - } - else if (assoc.isPresentName()) { + if (assoc.isPresentName()) { return StringUtils.uncapitalize(assoc.getName()); } + else if (assocSide.isPresentCDRole()) { + return assocSide.getCDRole().getName(); + } else { return StringUtils.uncapitalize(assocSide.getMCQualifiedType().getMCQualifiedName() .getBaseName()); } } + protected List getAssociationReferences(ASTCDAssociation assoc) { + List references = new ArrayList<>(); + + boolean navigableLeft = assoc.getCDAssocDir().isDefinitiveNavigableLeft(); + boolean navigableRight = assoc.getCDAssocDir().isDefinitiveNavigableRight(); + boolean undirected = !navigableLeft && !navigableRight; + + if (navigableRight || undirected) { + references.add(new AssociationReference(findTypeByFullName(assoc, assoc + .getLeftQualifiedName().getQName()), deriveRoleName(assoc, AssocSide.RIGHT))); + } + if (navigableLeft || undirected) { + references.add(new AssociationReference(findTypeByFullName(assoc, assoc + .getRightQualifiedName().getQName()), deriveRoleName(assoc, AssocSide.LEFT))); + } + + return references; + } + private enum AssocSide { LEFT, RIGHT; } + protected static class AssociationReference { + + protected final ASTCDType sourceType; + + protected final String name; + + protected AssociationReference(ASTCDType sourceType, String name) { + this.sourceType = sourceType; + this.name = name; + } + + } + } From 9241ed6ed490b1e66d539e73bbbb6d74bb048e4c Mon Sep 17 00:00:00 2001 From: Vanol Nguemo Tadoum Date: Mon, 6 Jul 2026 20:33:25 +0200 Subject: [PATCH 2/7] add tests --- .../cd/cdgen/BuilderDecoratorTest.java | 26 +++++++++++-------- .../cdgen/cocos/CDAssociationUniqueTest.java | 14 ++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java index 719647678..e3c31193d 100644 --- a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java +++ b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java @@ -9,6 +9,7 @@ import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.io.paths.MCPath; import de.monticore.runtime.junit.MCAssertions; +add import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Assertions; import java.nio.file.Paths; @@ -19,7 +20,7 @@ import java.util.Optional; class BuilderDecoratorTest extends AbstractDecoratorTest { - + @Test public void testBuilder() throws Exception { var opt = CD4CodeMill.parser() @@ -61,17 +62,20 @@ public void testBuilder() throws Exception { + " }\n" + "}"); // @formatter:on - + Assertions.assertTrue(opt.isPresent()); - + super.doTest(opt.get()); - - for (int i = 0; i < 7; i++) // Test, that the warning about missing setters is present - MCAssertions.assertHasFinding(f -> f.getMsg().startsWith("Requested setter of TestBuilder") - && f.isWarning()); + + // Test that the warnings about missing setters are present. + Assertions.assertEquals(7, Log.getFindings().stream().filter(f -> f.getMsg().startsWith( + "Requested setter of TestBuilder") && f.isWarning()).count()); + Assertions.assertTrue(Log.getFindings().stream().allMatch(f -> f.getMsg().startsWith( + "Requested setter of TestBuilder") && f.isWarning())); + Log.clearFindings(); MCAssertions.assertNoFindings(); } - + @Test public void testTemplateExistence() { //test existence of the templates @@ -85,12 +89,12 @@ public void testTemplateExistence() { Assertions.assertTrue(Files.exists(temPath)); } } - + @Override protected Optional getHandWrittenPath() { return Optional.of(new MCPath("src/cdGenIntTestHwc/java")); } - + @Override public void initializeDecConf(GlobalExtensionManagement glex, DecoratorConfig config, GeneratorSetup setup) { @@ -107,5 +111,5 @@ public void initializeDecConf(GlobalExtensionManagement glex, DecoratorConfig co config.withDecorator(new CardinalityDefaultDecorator()); config.configDefault(CardinalityDefaultDecorator.class, MatchResult.APPLY); } - + } diff --git a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java index bf2ce95dd..521ddcc60 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -42,6 +42,13 @@ public void testDuplicatesWithImplicitRoles() throws IOException { runTestForErrorCode(model, ERROR_CODE); } + @Test + public void testUniqueExplicitRole() throws IOException { + String model = "classdiagram UniqueAssocs {" + " class A; class B;" + + " association A -> B;" + " association A -> (other) B;" + "}"; + runTest(model, false); + } + @Test public void testDuplicatesInReverse() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" @@ -56,4 +63,11 @@ public void testUniqueAssocName() throws IOException { runTest(model, false); } + @Test + public void testUniqueAssocNameWithSameRole() throws IOException { + String model = "classdiagram UniqueAssocs {" + " class A; class B;" + + " association assoc1 A -> (b) B;" + " association assoc2 A -> (b) B;" + "}"; + runTest(model, false); + } + } From 22aec90c8c540da2a47fd40e73dda5d9b9671cd4 Mon Sep 17 00:00:00 2001 From: Vanol Nguemo Tadoum Date: Tue, 7 Jul 2026 00:51:49 +0200 Subject: [PATCH 3/7] resolve conflicts --- .../de/monticore/cd/cdgen/BuilderDecoratorTest.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java index 9691a9c54..25cf24bf2 100644 --- a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java +++ b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java @@ -9,6 +9,7 @@ import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.io.paths.MCPath; import de.monticore.runtime.junit.MCAssertions; +import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Assertions; import java.nio.file.Paths; @@ -71,9 +72,12 @@ class Level2class implements Level1Interface{ super.doTest(opt.get()); - for (int i = 0; i < 7; i++) // Test, that the warning about missing setters is present - MCAssertions.assertHasFinding(f -> f.getMsg().startsWith("Requested setter of TestBuilder") - && f.isWarning()); + // Test that the warnings about missing setters are present. + Assertions.assertEquals(7, Log.getFindings().stream().filter(f -> f.getMsg().startsWith( + "Requested setter of TestBuilder") && f.isWarning()).count()); + Assertions.assertTrue(Log.getFindings().stream().allMatch(f -> f.getMsg().startsWith( + "Requested setter of TestBuilder") && f.isWarning())); + Log.clearFindings(); } @Test From 2d447825db1dfd22bb5b89ba7fb3cc3f18841946 Mon Sep 17 00:00:00 2001 From: Vanol Nguemo Tadoum Date: Tue, 7 Jul 2026 01:31:06 +0200 Subject: [PATCH 4/7] fix formating --- .../java/de/monticore/cdgen/cocos/CDAssociationUnique.java | 4 ++-- .../test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java | 1 - .../de/monticore/cdgen/cocos/CDAssociationUniqueTest.java | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java index 9d218dd86..bc753c968 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -99,8 +99,8 @@ protected List getAssociationReferences(ASTCDAssociation a boolean undirected = !navigableLeft && !navigableRight; if (navigableRight || undirected) { - references.add(new AssociationReference(findTypeByFullName(assoc, assoc - .getLeftQualifiedName().getQName()), deriveRoleName(assoc, AssocSide.RIGHT))); + references.add(new AssociationReference(findTypeByFullName(assoc, assoc.getLeftQualifiedName() + .getQName()), deriveRoleName(assoc, AssocSide.RIGHT))); } if (navigableLeft || undirected) { references.add(new AssociationReference(findTypeByFullName(assoc, assoc diff --git a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java index 25cf24bf2..a110db7ba 100644 --- a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java +++ b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java @@ -8,7 +8,6 @@ import de.monticore.generating.GeneratorSetup; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.io.paths.MCPath; -import de.monticore.runtime.junit.MCAssertions; import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Assertions; diff --git a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java index 521ddcc60..e868dd47d 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -44,8 +44,8 @@ public void testDuplicatesWithImplicitRoles() throws IOException { @Test public void testUniqueExplicitRole() throws IOException { - String model = "classdiagram UniqueAssocs {" + " class A; class B;" - + " association A -> B;" + " association A -> (other) B;" + "}"; + String model = "classdiagram UniqueAssocs {" + " class A; class B;" + " association A -> B;" + + " association A -> (other) B;" + "}"; runTest(model, false); } From 6e1e608726caab83a4c0b6eca0d0caf50a930ace Mon Sep 17 00:00:00 2001 From: Vanol Nguemo Tadoum Date: Tue, 7 Jul 2026 13:38:49 +0200 Subject: [PATCH 5/7] move changes to a new coco --- .../cocos/CDAssociationReferenceUnique.java | 102 ++++++++++++++++++ .../cdgen/cocos/CDAssociationUnique.java | 87 +++++++-------- .../CDAssociationReferenceUniqueTest.java | 69 ++++++++++++ .../cdgen/cocos/CDAssociationUniqueTest.java | 14 --- 4 files changed, 210 insertions(+), 62 deletions(-) create mode 100644 cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java create mode 100644 cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationReferenceUniqueTest.java diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java new file mode 100644 index 000000000..05efbc3df --- /dev/null +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java @@ -0,0 +1,102 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.cdgen.cocos; + +import de.monticore.cdassociation._ast.ASTCDAssocSide; +import de.monticore.cdassociation._ast.ASTCDAssociation; +import de.monticore.cdbasis._ast.ASTCDDefinition; +import de.monticore.cdbasis._ast.ASTCDType; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; + +/** + * Checks that generated association references are unique for CD2Java/CD2Pojo. + */ +public class CDAssociationReferenceUnique extends CDAssociationUniqueInHierarchy { + + @Override + public void check(ASTCDDefinition node) { + List alreadyChecked = new ArrayList<>(); + + // we check for each pair of associations + for (ASTCDAssociation assoc2 : node.getCDAssociationsList()) { + for (ASTCDAssociation assoc1 : alreadyChecked) { + for (AssociationReference ref1 : getAssociationReferences(assoc1)) { + for (AssociationReference ref2 : getAssociationReferences(assoc2)) { + if (ref1.name.equals(ref2.name)) { + checkRef(node, ref1.sourceType, ref2.sourceType, assoc2); + } + } + } + } + + alreadyChecked.add(assoc2); + } + } + + @Override + protected void checkRef(ASTCDDefinition node, ASTCDType type1, ASTCDType type2, + ASTCDAssociation assoc1) { + if (type1 == null || type2 == null) { + return; + } + super.checkRef(node, type1, type2, assoc1); + } + + protected List getAssociationReferences(ASTCDAssociation assoc) { + List references = new ArrayList<>(); + + boolean navigableLeft = assoc.getCDAssocDir().isDefinitiveNavigableLeft(); + boolean navigableRight = assoc.getCDAssocDir().isDefinitiveNavigableRight(); + boolean undirected = !navigableLeft && !navigableRight; + + if (navigableRight || undirected) { + references.add(new AssociationReference(findTypeByFullName(assoc, assoc.getLeftQualifiedName() + .getQName()), deriveReferenceName(assoc, AssocSide.RIGHT))); + } + if (navigableLeft || undirected) { + references.add(new AssociationReference(findTypeByFullName(assoc, assoc + .getRightQualifiedName().getQName()), deriveReferenceName(assoc, AssocSide.LEFT))); + } + + return references; + } + + protected String deriveReferenceName(ASTCDAssociation assoc, AssocSide side) { + ASTCDAssocSide assocSide; + if (side.equals(AssocSide.LEFT)) { + assocSide = assoc.getLeft(); + } + else { + assocSide = assoc.getRight(); + } + if (assoc.isPresentName()) { + return StringUtils.uncapitalize(assoc.getName()); + } + else if (assocSide.isPresentCDRole()) { + return assocSide.getCDRole().getName(); + } + else { + return StringUtils.uncapitalize(assocSide.getMCQualifiedType().getMCQualifiedName() + .getBaseName()); + } + } + + protected enum AssocSide { + LEFT, RIGHT; + } + + protected static class AssociationReference { + + protected final ASTCDType sourceType; + + protected final String name; + + protected AssociationReference(ASTCDType sourceType, String name) { + this.sourceType = sourceType; + this.name = name; + } + + } + +} diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java index bc753c968..f4144774b 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -26,19 +26,45 @@ public void check(ASTCDDefinition node) { List alreadyChecked = new ArrayList<>(); // we check for each pair of associations - for (ASTCDAssociation assoc2 : node.getCDAssociationsList()) { + for (ASTCDAssociation assoc1 : node.getCDAssociationsList()) { - for (ASTCDAssociation assoc1 : alreadyChecked) { - for (AssociationReference ref1 : getAssociationReferences(assoc1)) { - for (AssociationReference ref2 : getAssociationReferences(assoc2)) { - if (ref1.name.equals(ref2.name)) { - checkRef(node, ref1.sourceType, ref2.sourceType, assoc2); - } + alreadyChecked.add(assoc1); + + for (ASTCDAssociation assoc2 : node.getCDAssociationsList()) { + + // only check each pair once + if (assoc2 != assoc1 && !alreadyChecked.contains(assoc2)) { + + // if they share a left role-name, the referenced types on the right should not be the + // same + if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, + AssocSide.LEFT))) { + checkRef(node, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName()), assoc1); + } + + // if they share a right role-name, the referenced types on the left should not be the + // same + if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, + AssocSide.RIGHT))) { + checkRef(node, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName()), assoc1); + } + + // We also consider a left-to-right role name match ... + if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, + AssocSide.RIGHT))) { + checkRef(node, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName()), assoc1); + } + // ... as well as a right-to-left match + if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, + AssocSide.LEFT))) { + checkRef(node, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName()), assoc1); } } } - - alreadyChecked.add(assoc2); } } @@ -59,9 +85,6 @@ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { /** Check if type2 is the same as type1. */ protected void checkRef(ASTCDDefinition node, ASTCDType type1, ASTCDType type2, ASTCDAssociation assoc1) { - if (type1 == null || type2 == null) { - return; - } if (type1.equals(type2)) { Log.error(String.format("0xCDCE1: %s has a duplicate association to %s", type1.getName(), type2.getName()), assoc1.isPresent_SourcePositionStart() ? assoc1 @@ -79,52 +102,20 @@ protected String deriveRoleName(ASTCDAssociation assoc, AssocSide side) { else { assocSide = assoc.getRight(); } - if (assoc.isPresentName()) { - return StringUtils.uncapitalize(assoc.getName()); - } - else if (assocSide.isPresentCDRole()) { + if (assocSide.isPresentCDRole()) { return assocSide.getCDRole().getName(); } + else if (assoc.isPresentName()) { + return StringUtils.uncapitalize(assoc.getName()); + } else { return StringUtils.uncapitalize(assocSide.getMCQualifiedType().getMCQualifiedName() .getBaseName()); } } - protected List getAssociationReferences(ASTCDAssociation assoc) { - List references = new ArrayList<>(); - - boolean navigableLeft = assoc.getCDAssocDir().isDefinitiveNavigableLeft(); - boolean navigableRight = assoc.getCDAssocDir().isDefinitiveNavigableRight(); - boolean undirected = !navigableLeft && !navigableRight; - - if (navigableRight || undirected) { - references.add(new AssociationReference(findTypeByFullName(assoc, assoc.getLeftQualifiedName() - .getQName()), deriveRoleName(assoc, AssocSide.RIGHT))); - } - if (navigableLeft || undirected) { - references.add(new AssociationReference(findTypeByFullName(assoc, assoc - .getRightQualifiedName().getQName()), deriveRoleName(assoc, AssocSide.LEFT))); - } - - return references; - } - private enum AssocSide { LEFT, RIGHT; } - protected static class AssociationReference { - - protected final ASTCDType sourceType; - - protected final String name; - - protected AssociationReference(ASTCDType sourceType, String name) { - this.sourceType = sourceType; - this.name = name; - } - - } - } diff --git a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationReferenceUniqueTest.java b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationReferenceUniqueTest.java new file mode 100644 index 000000000..06ee230d0 --- /dev/null +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationReferenceUniqueTest.java @@ -0,0 +1,69 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.cdgen.cocos; + +import de.monticore.cd4code._cocos.CD4CodeCoCoChecker; +import de.monticore.cd4code.cocos.AbstractJavaGenCoCoTest; +import java.io.IOException; +import org.junit.jupiter.api.Test; + +public class CDAssociationReferenceUniqueTest extends AbstractJavaGenCoCoTest { + + @Override + protected CD4CodeCoCoChecker createChecker() { + CD4CodeCoCoChecker checker = new CD4CodeCoCoChecker(); + checker.addCoCo(new CDAssociationReferenceUnique()); + return checker; + } + + private static final String ERROR_CODE = "0xCDCE1"; + + @Test + public void testUniqueNames() throws IOException { + String model = "classdiagram UniqueAssocs {" + " class A; class B;" + " association A -> B;" + + " association A (l) -> (r) B;" + "}"; + runTest(model, false); + } + + @Test + public void testDuplicatesWithExplicitRoles() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association A -> (b) B;" + "}"; + runTestForErrorCode(model, ERROR_CODE); + } + + @Test + public void testDuplicatesWithImplicitRoles() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association A -> B;" + "}"; + runTestForErrorCode(model, ERROR_CODE); + } + + @Test + public void testUniqueExplicitRole() throws IOException { + String model = "classdiagram UniqueAssocs {" + " class A; class B;" + " association A -> B;" + + " association A -> (other) B;" + "}"; + runTest(model, false); + } + + @Test + public void testDuplicatesInReverse() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association B <- A;" + "}"; + runTestForErrorCode(model, ERROR_CODE); + } + + @Test + public void testUniqueAssocName() throws IOException { + String model = "classdiagram UniqueAssocs {" + " class A; class B;" + + " association assoc1 A -> B;" + " association assoc2 A -> B;" + "}"; + runTest(model, false); + } + + @Test + public void testUniqueAssocNameWithSameRole() throws IOException { + String model = "classdiagram UniqueAssocs {" + " class A; class B;" + + " association assoc1 A -> (b) B;" + " association assoc2 A -> (b) B;" + "}"; + runTest(model, false); + } + +} diff --git a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java index e868dd47d..bf2ce95dd 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -42,13 +42,6 @@ public void testDuplicatesWithImplicitRoles() throws IOException { runTestForErrorCode(model, ERROR_CODE); } - @Test - public void testUniqueExplicitRole() throws IOException { - String model = "classdiagram UniqueAssocs {" + " class A; class B;" + " association A -> B;" - + " association A -> (other) B;" + "}"; - runTest(model, false); - } - @Test public void testDuplicatesInReverse() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" @@ -63,11 +56,4 @@ public void testUniqueAssocName() throws IOException { runTest(model, false); } - @Test - public void testUniqueAssocNameWithSameRole() throws IOException { - String model = "classdiagram UniqueAssocs {" + " class A; class B;" - + " association assoc1 A -> (b) B;" + " association assoc2 A -> (b) B;" + "}"; - runTest(model, false); - } - } From c1013fb764a3bcd6050c5a7b2619e193085265b2 Mon Sep 17 00:00:00 2001 From: Vanol Nguemo Tadoum Date: Tue, 7 Jul 2026 13:43:32 +0200 Subject: [PATCH 6/7] remove some changes --- .../de/monticore/cd/cdgen/BuilderDecoratorTest.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java index a110db7ba..9691a9c54 100644 --- a/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java +++ b/cdlang/src/test/java/de/monticore/cd/cdgen/BuilderDecoratorTest.java @@ -8,7 +8,7 @@ import de.monticore.generating.GeneratorSetup; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.io.paths.MCPath; -import de.se_rwth.commons.logging.Log; +import de.monticore.runtime.junit.MCAssertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Assertions; import java.nio.file.Paths; @@ -71,12 +71,9 @@ class Level2class implements Level1Interface{ super.doTest(opt.get()); - // Test that the warnings about missing setters are present. - Assertions.assertEquals(7, Log.getFindings().stream().filter(f -> f.getMsg().startsWith( - "Requested setter of TestBuilder") && f.isWarning()).count()); - Assertions.assertTrue(Log.getFindings().stream().allMatch(f -> f.getMsg().startsWith( - "Requested setter of TestBuilder") && f.isWarning())); - Log.clearFindings(); + for (int i = 0; i < 7; i++) // Test, that the warning about missing setters is present + MCAssertions.assertHasFinding(f -> f.getMsg().startsWith("Requested setter of TestBuilder") + && f.isWarning()); } @Test From 00eac32a5caf7fa03c91e0097a2ac9be1c7b2dd2 Mon Sep 17 00:00:00 2001 From: Vanol Nguemo Tadoum Date: Thu, 9 Jul 2026 09:50:21 +0200 Subject: [PATCH 7/7] minor --- .../cocos/CDAssociationReferenceUnique.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java index 05efbc3df..c1d4af6ec 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationReferenceUnique.java @@ -10,14 +10,14 @@ import java.util.*; /** - * Checks that generated association references are unique for CD2Java/CD2Pojo. + * Checks that generated association references are unique. */ public class CDAssociationReferenceUnique extends CDAssociationUniqueInHierarchy { - + @Override public void check(ASTCDDefinition node) { List alreadyChecked = new ArrayList<>(); - + // we check for each pair of associations for (ASTCDAssociation assoc2 : node.getCDAssociationsList()) { for (ASTCDAssociation assoc1 : alreadyChecked) { @@ -29,11 +29,11 @@ public void check(ASTCDDefinition node) { } } } - + alreadyChecked.add(assoc2); } } - + @Override protected void checkRef(ASTCDDefinition node, ASTCDType type1, ASTCDType type2, ASTCDAssociation assoc1) { @@ -42,14 +42,14 @@ protected void checkRef(ASTCDDefinition node, ASTCDType type1, ASTCDType type2, } super.checkRef(node, type1, type2, assoc1); } - + protected List getAssociationReferences(ASTCDAssociation assoc) { List references = new ArrayList<>(); - + boolean navigableLeft = assoc.getCDAssocDir().isDefinitiveNavigableLeft(); boolean navigableRight = assoc.getCDAssocDir().isDefinitiveNavigableRight(); boolean undirected = !navigableLeft && !navigableRight; - + if (navigableRight || undirected) { references.add(new AssociationReference(findTypeByFullName(assoc, assoc.getLeftQualifiedName() .getQName()), deriveReferenceName(assoc, AssocSide.RIGHT))); @@ -58,10 +58,10 @@ protected List getAssociationReferences(ASTCDAssociation a references.add(new AssociationReference(findTypeByFullName(assoc, assoc .getRightQualifiedName().getQName()), deriveReferenceName(assoc, AssocSide.LEFT))); } - + return references; } - + protected String deriveReferenceName(ASTCDAssociation assoc, AssocSide side) { ASTCDAssocSide assocSide; if (side.equals(AssocSide.LEFT)) { @@ -81,22 +81,22 @@ else if (assocSide.isPresentCDRole()) { .getBaseName()); } } - + protected enum AssocSide { LEFT, RIGHT; } - + protected static class AssociationReference { - + protected final ASTCDType sourceType; - + protected final String name; - + protected AssociationReference(ASTCDType sourceType, String name) { this.sourceType = sourceType; this.name = name; } - + } - + }