From 0ba054ddb8fc5eadd8c98d9fa0583552888e4574 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Fri, 6 Feb 2026 16:17:16 +0100 Subject: [PATCH 1/9] fix CDGen-CoCo: CDAssociationUnique --- .../cdgen/cocos/CDAssociationUnique.java | 71 ++++++++++++------- .../cocos/CDAssociationUniqueInHierarchy.java | 17 ++--- .../cdgen/cocos/CDAssociationUniqueTest.java | 35 +++++++++ 3 files changed, 88 insertions(+), 35 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..2f5a16ac5 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -17,9 +17,7 @@ */ public class CDAssociationUnique implements CDBasisASTCDDefinitionCoCo { - /** - * @param node class to check. - */ + /** @param node class to check. */ @Override public void check(ASTCDDefinition node) { @@ -38,39 +36,60 @@ public void check(ASTCDDefinition node) { // 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); + AssocSide.LEFT)) && sharedNavigability(assoc1,assoc2,false)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName())); } // 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); + AssocSide.RIGHT)) && sharedNavigability(assoc1,assoc2,false)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // 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); + AssocSide.RIGHT)) && sharedNavigability(assoc1,assoc2,true)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // ... 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); + AssocSide.LEFT)) && sharedNavigability(assoc1,assoc2,true)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), + findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName())); } } } } } - - /** - * helper-method to find types by full-name - */ + + private boolean sharedNavigability(ASTCDAssociation assoc1, ASTCDAssociation assoc2, + boolean reverse) { + if (reverse) { + return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() + && assoc2.getCDAssocDir().isDefinitiveNavigableLeft()) + || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && assoc2.getCDAssocDir().isDefinitiveNavigableRight()) + || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()) + || (!assoc2.getCDAssocDir().isDefinitiveNavigableLeft() + && !assoc2.getCDAssocDir().isDefinitiveNavigableRight()); + } else { + return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() + && assoc2.getCDAssocDir().isDefinitiveNavigableRight()) + || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && assoc2.getCDAssocDir().isDefinitiveNavigableLeft()) + || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()) + || (!assoc2.getCDAssocDir().isDefinitiveNavigableLeft() + && !assoc2.getCDAssocDir().isDefinitiveNavigableRight()); + } + } + + /** helper-method to find types by full-name */ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { Optional optSymbol = node.getEnclosingScope().resolveCDType(fullName); @@ -78,18 +97,16 @@ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { return optSymbol.get().getAstNode(); } - Log.error("0xCDCE2: Could not find: " + fullName + "."); + Log.error("0xCDCE2: Could not find: " + fullName + ".", node.get_SourcePositionStart()); return null; } /** Check if type2 is the same as type1. */ - protected void checkRef(ASTCDDefinition node, ASTCDType type1, ASTCDType type2, - ASTCDAssociation assoc1) { + protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, ASTCDType type2) { if (type1.equals(type2)) { - Log.error(String.format("0xCDCE1: %s has a duplicate association to %s", type1.getName(), - type2.getName()), assoc1.isPresent_SourcePositionStart() ? assoc1 - .get_SourcePositionStart() : null, assoc1.isPresent_SourcePositionEnd() ? assoc1 - .get_SourcePositionEnd() : null); + Log.error(String.format("0xCDCE1: %s has duplicate associations at %s and %s.", + type1.getName(), assoc1.get_SourcePositionStart(), assoc2.get_SourcePositionStart()), + assoc2.get_SourcePositionStart()); } } @@ -114,7 +131,7 @@ else if (assoc.isPresentName()) { } } - private enum AssocSide { + protected enum AssocSide { LEFT, RIGHT; } diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java index 60921f77b..8b91070de 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java @@ -16,16 +16,15 @@ public class CDAssociationUniqueInHierarchy extends CDAssociationUnique { @Override - protected void checkRef(ASTCDDefinition node, ASTCDType type1, ASTCDType type2, - ASTCDAssociation assoc1) { - super.checkRef(node, type1, type2, assoc1); + protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, ASTCDType type2) { + super.checkRef(assoc1, assoc2, type1, type2); // We now also check if the types are in a sub/super-type relation - checkSuper(type1, type2); - checkSuper(type2, type1); + checkSuper(assoc1, assoc2, type1, type2); + checkSuper(assoc2, assoc1, type2, type1); } /** Check if type2 is a super-type of type1. */ - protected void checkSuper(ASTCDType type1, ASTCDType type2) { + protected void checkSuper(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, ASTCDType type2) { Stack typesToVisit = new Stack<>(); @@ -38,8 +37,10 @@ protected void checkSuper(ASTCDType type1, ASTCDType type2) { while (!typesToVisit.isEmpty()) { final TypeSymbol nextType = typesToVisit.pop(); if (nextType.getFullName().equals(type2.getSymbol().getFullName())) { - Log.error(String.format("0xCDCE6: %s redefines an association of %s.", type1.getName(), - type2.getName())); + Log.error(String.format("0xCDCE6: %s redefines an association of %s from %s at %s", + type1.getName(), type2.getName(), assoc2.get_SourcePositionStart(), + assoc1.get_SourcePositionStart()), + assoc1.get_SourcePositionStart()); return; } 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..b5803a2e7 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -55,5 +55,40 @@ public void testUniqueAssocName() throws IOException { + " association assoc1 A -> B;" + " association assoc2 A -> B;" + "}"; runTest(model, false); } + + @Test + public void testOpposedAssocs() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association A <- B;" + "}"; + runTest(model, false); + } + + @Test + public void testOpposedAssocs2() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association B -> A;" + "}"; + runTest(model, false); + } + + @Test + public void testNonOpposedAssocs() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association A <-> B;" + "}"; + runTestForErrorCode(model, ERROR_CODE); + } + + @Test + public void testNonOpposedAssocs2() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association A -- B;" + "}"; + runTestForErrorCode(model, ERROR_CODE); + } + + @Test + public void testNonOpposedAssocs3() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association B <- A;" + "}"; + runTestForErrorCode(model, ERROR_CODE); + } } From f3a9bbdb4615908f0c01b83643ceb9972246ac47 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Fri, 6 Feb 2026 16:18:23 +0100 Subject: [PATCH 2/9] use CD2JavaGenCoCos in CDGenTool --- cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java index 0d137d979..1b017b6e7 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java +++ b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java @@ -13,12 +13,15 @@ import de.monticore.cd4analysis.trafo.CDAssociationCreateFieldsFromAllRoles; import de.monticore.cd4analysis.trafo.CDAssociationCreateFieldsFromNavigableRoles; import de.monticore.cd4code.CD4CodeMill; +import de.monticore.cd4code._cocos.CD4CodeCoCoChecker; import de.monticore.cd4code._symboltable.ICD4CodeArtifactScope; import de.monticore.cd4code._visitor.CD4CodeTraverser; +import de.monticore.cd4code.cocos.CD4CodeCoCosDelegator; import de.monticore.cdbasis.CDBasisMill; import de.monticore.cdbasis._ast.ASTCDClass; import de.monticore.cdbasis._ast.ASTCDCompilationUnit; import de.monticore.cdbasis.trafo.CDBasisDefaultPackageTrafo; +import de.monticore.cdgen.cocos.CD2JavaGenCoCos; import de.monticore.cdinterfaceandenum._ast.ASTCDEnum; import de.monticore.cdinterfaceandenum._ast.ASTCDInterface; import de.monticore.generating.GeneratorSetup; @@ -388,7 +391,8 @@ public void runBeforeSTCoCos(ASTCDCompilationUnit ast) { * @param ast the original ast */ public void runCoCos(ASTCDCompilationUnit ast) { - super.runCoCos(ast); + CD4CodeCoCoChecker checker = new CD2JavaGenCoCos().getCheckerForAllCoCos(); + checker.checkAll(ast); } @Override From a49e9d7b341840ae20be97bc65ac72d64c3177b5 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Fri, 6 Feb 2026 16:24:03 +0100 Subject: [PATCH 3/9] reformat code with spotless --- .../java/de/monticore/cdgen/CDGenTool.java | 1 - .../cdgen/cocos/CDAssociationUnique.java | 78 ++++++++++--------- .../cocos/CDAssociationUniqueInHierarchy.java | 14 ++-- .../cdgen/cocos/CDAssociationUniqueTest.java | 10 +-- 4 files changed, 52 insertions(+), 51 deletions(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java index 1b017b6e7..ebd1f4276 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java +++ b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java @@ -16,7 +16,6 @@ import de.monticore.cd4code._cocos.CD4CodeCoCoChecker; import de.monticore.cd4code._symboltable.ICD4CodeArtifactScope; import de.monticore.cd4code._visitor.CD4CodeTraverser; -import de.monticore.cd4code.cocos.CD4CodeCoCosDelegator; import de.monticore.cdbasis.CDBasisMill; import de.monticore.cdbasis._ast.ASTCDClass; import de.monticore.cdbasis._ast.ASTCDCompilationUnit; 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 2f5a16ac5..917b32f46 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -35,60 +35,61 @@ public void check(ASTCDDefinition node) { // 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)) && sharedNavigability(assoc1,assoc2,false)) { - checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName())); + if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, AssocSide.LEFT)) + && sharedNavigability(assoc1, assoc2, false)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName() + .getQName()), findTypeByFullName(assoc2, assoc2.getRightQualifiedName() + .getQName())); } // 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)) && sharedNavigability(assoc1,assoc2,false)) { - checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); + AssocSide.RIGHT)) && sharedNavigability(assoc1, assoc2, false)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName() + .getQName()), findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // We also consider a left-to-right role name match ... - if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, - AssocSide.RIGHT)) && sharedNavigability(assoc1,assoc2,true)) { - checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); + if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, AssocSide.RIGHT)) + && sharedNavigability(assoc1, assoc2, true)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName() + .getQName()), findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // ... as well as a right-to-left match - if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, - AssocSide.LEFT)) && sharedNavigability(assoc1,assoc2,true)) { - checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName().getQName()), - findTypeByFullName(assoc2, assoc2.getRightQualifiedName().getQName())); + if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, AssocSide.LEFT)) + && sharedNavigability(assoc1, assoc2, true)) { + checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName() + .getQName()), findTypeByFullName(assoc2, assoc2.getRightQualifiedName() + .getQName())); } } } } } - + private boolean sharedNavigability(ASTCDAssociation assoc1, ASTCDAssociation assoc2, boolean reverse) { if (reverse) { - return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() - && assoc2.getCDAssocDir().isDefinitiveNavigableLeft()) - || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && assoc2.getCDAssocDir().isDefinitiveNavigableRight()) - || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()) - || (!assoc2.getCDAssocDir().isDefinitiveNavigableLeft() - && !assoc2.getCDAssocDir().isDefinitiveNavigableRight()); - } else { - return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() - && assoc2.getCDAssocDir().isDefinitiveNavigableRight()) - || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && assoc2.getCDAssocDir().isDefinitiveNavigableLeft()) - || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()) - || (!assoc2.getCDAssocDir().isDefinitiveNavigableLeft() - && !assoc2.getCDAssocDir().isDefinitiveNavigableRight()); + return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() && assoc2.getCDAssocDir() + .isDefinitiveNavigableLeft()) || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && assoc2.getCDAssocDir().isDefinitiveNavigableRight()) || (!assoc1.getCDAssocDir() + .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir() + .isDefinitiveNavigableRight()) || (!assoc2.getCDAssocDir() + .isDefinitiveNavigableLeft() && !assoc2.getCDAssocDir() + .isDefinitiveNavigableRight()); + } + else { + return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() && assoc2.getCDAssocDir() + .isDefinitiveNavigableRight()) || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && assoc2.getCDAssocDir().isDefinitiveNavigableLeft()) || (!assoc1.getCDAssocDir() + .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir() + .isDefinitiveNavigableRight()) || (!assoc2.getCDAssocDir() + .isDefinitiveNavigableLeft() && !assoc2.getCDAssocDir() + .isDefinitiveNavigableRight()); } } - + /** helper-method to find types by full-name */ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { @@ -102,11 +103,12 @@ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { } /** Check if type2 is the same as type1. */ - protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, ASTCDType type2) { + protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, + ASTCDType type2) { if (type1.equals(type2)) { - Log.error(String.format("0xCDCE1: %s has duplicate associations at %s and %s.", - type1.getName(), assoc1.get_SourcePositionStart(), assoc2.get_SourcePositionStart()), - assoc2.get_SourcePositionStart()); + Log.error(String.format("0xCDCE1: %s has duplicate associations at %s and %s.", type1 + .getName(), assoc1.get_SourcePositionStart(), assoc2.get_SourcePositionStart()), assoc2 + .get_SourcePositionStart()); } } diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java index 8b91070de..ad7507bbe 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java @@ -2,7 +2,6 @@ package de.monticore.cdgen.cocos; import de.monticore.cdassociation._ast.ASTCDAssociation; -import de.monticore.cdbasis._ast.ASTCDDefinition; import de.monticore.cdbasis._ast.ASTCDType; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.se_rwth.commons.logging.Log; @@ -16,7 +15,8 @@ public class CDAssociationUniqueInHierarchy extends CDAssociationUnique { @Override - protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, ASTCDType type2) { + protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, + ASTCDType type2) { super.checkRef(assoc1, assoc2, type1, type2); // We now also check if the types are in a sub/super-type relation checkSuper(assoc1, assoc2, type1, type2); @@ -24,7 +24,8 @@ protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDT } /** Check if type2 is a super-type of type1. */ - protected void checkSuper(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, ASTCDType type2) { + protected void checkSuper(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, + ASTCDType type2) { Stack typesToVisit = new Stack<>(); @@ -37,10 +38,9 @@ protected void checkSuper(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTC while (!typesToVisit.isEmpty()) { final TypeSymbol nextType = typesToVisit.pop(); if (nextType.getFullName().equals(type2.getSymbol().getFullName())) { - Log.error(String.format("0xCDCE6: %s redefines an association of %s from %s at %s", - type1.getName(), type2.getName(), assoc2.get_SourcePositionStart(), - assoc1.get_SourcePositionStart()), - assoc1.get_SourcePositionStart()); + Log.error(String.format("0xCDCE6: %s redefines an association of %s from %s at %s", type1 + .getName(), type2.getName(), assoc2.get_SourcePositionStart(), assoc1 + .get_SourcePositionStart()), assoc1.get_SourcePositionStart()); return; } 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 b5803a2e7..d7860cd29 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -55,35 +55,35 @@ public void testUniqueAssocName() throws IOException { + " association assoc1 A -> B;" + " association assoc2 A -> B;" + "}"; runTest(model, false); } - + @Test public void testOpposedAssocs() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + " association A -> B;" + " association A <- B;" + "}"; runTest(model, false); } - + @Test public void testOpposedAssocs2() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + " association A -> B;" + " association B -> A;" + "}"; runTest(model, false); } - + @Test public void testNonOpposedAssocs() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + " association A -> B;" + " association A <-> B;" + "}"; runTestForErrorCode(model, ERROR_CODE); } - + @Test public void testNonOpposedAssocs2() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + " association A -> B;" + " association A -- B;" + "}"; runTestForErrorCode(model, ERROR_CODE); } - + @Test public void testNonOpposedAssocs3() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" From f666b968cfa3535229ead2b8d08bc7a097a2bdf2 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Fri, 6 Feb 2026 17:32:26 +0100 Subject: [PATCH 4/9] only consider navigable roles in CDAssociationUnique and CDAssociationUniqueInHierarchy --- .../cdgen/cocos/CDAssociationUnique.java | 41 ++++++++----------- .../cdgen/cocos/CDAssociationUniqueTest.java | 14 +++++++ 2 files changed, 30 insertions(+), 25 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 917b32f46..9bcccf098 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -36,7 +36,7 @@ public void check(ASTCDDefinition node) { // 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)) - && sharedNavigability(assoc1, assoc2, false)) { + && isNavigable(assoc1, AssocSide.LEFT) && isNavigable(assoc2, AssocSide.LEFT)) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getRightQualifiedName() .getQName())); @@ -45,20 +45,21 @@ && sharedNavigability(assoc1, assoc2, false)) { // 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)) && sharedNavigability(assoc1, assoc2, false)) { + AssocSide.RIGHT)) && isNavigable(assoc1, AssocSide.RIGHT) && isNavigable(assoc2, + AssocSide.RIGHT)) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // We also consider a left-to-right role name match ... if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, AssocSide.RIGHT)) - && sharedNavigability(assoc1, assoc2, true)) { + && isNavigable(assoc1, AssocSide.LEFT) && isNavigable(assoc2, AssocSide.RIGHT)) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // ... as well as a right-to-left match if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, AssocSide.LEFT)) - && sharedNavigability(assoc1, assoc2, true)) { + && isNavigable(assoc1, AssocSide.RIGHT) && isNavigable(assoc2, AssocSide.LEFT)) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getRightQualifiedName() .getQName())); @@ -67,29 +68,19 @@ && sharedNavigability(assoc1, assoc2, true)) { } } } - - private boolean sharedNavigability(ASTCDAssociation assoc1, ASTCDAssociation assoc2, - boolean reverse) { - if (reverse) { - return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() && assoc2.getCDAssocDir() - .isDefinitiveNavigableLeft()) || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && assoc2.getCDAssocDir().isDefinitiveNavigableRight()) || (!assoc1.getCDAssocDir() - .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir() - .isDefinitiveNavigableRight()) || (!assoc2.getCDAssocDir() - .isDefinitiveNavigableLeft() && !assoc2.getCDAssocDir() - .isDefinitiveNavigableRight()); - } - else { - return (assoc1.getCDAssocDir().isDefinitiveNavigableRight() && assoc2.getCDAssocDir() - .isDefinitiveNavigableRight()) || (assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && assoc2.getCDAssocDir().isDefinitiveNavigableLeft()) || (!assoc1.getCDAssocDir() - .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir() - .isDefinitiveNavigableRight()) || (!assoc2.getCDAssocDir() - .isDefinitiveNavigableLeft() && !assoc2.getCDAssocDir() - .isDefinitiveNavigableRight()); + + private static boolean isNavigable(ASTCDAssociation assoc1, AssocSide side1) { + if (side1.equals(AssocSide.LEFT) ) { + return assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); + } else { + return assoc1.getCDAssocDir().isDefinitiveNavigableRight() + || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() + && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); } } - + /** helper-method to find types by full-name */ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { 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 d7860cd29..af2bffe1f 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -55,6 +55,20 @@ public void testUniqueAssocName() throws IOException { + " association assoc1 A -> B;" + " association assoc2 A -> B;" + "}"; runTest(model, false); } + + @Test + public void testOnlyNavigable() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association A -> (r) B;" + "}"; + runTest(model, false); + } + + @Test + public void testOnlyNavigableReverse() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association B (r) <- A;" + "}"; + runTest(model, false); + } @Test public void testOpposedAssocs() throws IOException { From 2311491851107e8163222e65a1269afc30d98fd2 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Fri, 6 Feb 2026 17:33:25 +0100 Subject: [PATCH 5/9] remove Interface-CoCos from CD2JavaGenCoCos --- .../src/main/java/de/monticore/cdgen/cocos/CD2JavaGenCoCos.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CD2JavaGenCoCos.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CD2JavaGenCoCos.java index 587fe0559..de1da55b1 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CD2JavaGenCoCos.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CD2JavaGenCoCos.java @@ -10,8 +10,6 @@ public class CD2JavaGenCoCos extends CD4CodeCoCosDelegator { protected void addCheckerForAllCoCos(CD4CodeCoCoChecker checker) { super.addCheckerForAllCoCos(checker); checker.addCoCo(new CDAssociationUniqueInHierarchy()); - checker.addCoCo(new CDNoAttributesInInterfaces()); - checker.addCoCo(new CDNoOutgoingAssocs4Interfaces()); checker.addCoCo(new CDSingleClassInheritance()); } From 839dc841295682a8145ecbdc2c72d109f812be15 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Fri, 6 Feb 2026 17:44:26 +0100 Subject: [PATCH 6/9] spottles --- .../cdgen/cocos/CDAssociationUnique.java | 21 +++++++++---------- .../cdgen/cocos/CDAssociationUniqueTest.java | 4 ++-- 2 files changed, 12 insertions(+), 13 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 9bcccf098..bad4a2bc2 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -46,7 +46,7 @@ && isNavigable(assoc1, AssocSide.LEFT) && isNavigable(assoc2, AssocSide.LEFT)) { // same if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, AssocSide.RIGHT)) && isNavigable(assoc1, AssocSide.RIGHT) && isNavigable(assoc2, - AssocSide.RIGHT)) { + AssocSide.RIGHT)) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } @@ -68,19 +68,18 @@ && isNavigable(assoc1, AssocSide.RIGHT) && isNavigable(assoc2, AssocSide.LEFT)) } } } - + private static boolean isNavigable(ASTCDAssociation assoc1, AssocSide side1) { - if (side1.equals(AssocSide.LEFT) ) { - return assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); - } else { - return assoc1.getCDAssocDir().isDefinitiveNavigableRight() - || (!assoc1.getCDAssocDir().isDefinitiveNavigableLeft() - && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); + if (side1.equals(AssocSide.LEFT)) { + return assoc1.getCDAssocDir().isDefinitiveNavigableLeft() || (!assoc1.getCDAssocDir() + .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); + } + else { + return assoc1.getCDAssocDir().isDefinitiveNavigableRight() || (!assoc1.getCDAssocDir() + .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); } } - + /** helper-method to find types by full-name */ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { 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 af2bffe1f..0423983b5 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -55,14 +55,14 @@ public void testUniqueAssocName() throws IOException { + " association assoc1 A -> B;" + " association assoc2 A -> B;" + "}"; runTest(model, false); } - + @Test public void testOnlyNavigable() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + " association A -> B;" + " association A -> (r) B;" + "}"; runTest(model, false); } - + @Test public void testOnlyNavigableReverse() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" From 40754026ed75b3a2f4015bee14c356690de03a52 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Fri, 6 Feb 2026 21:08:36 +0100 Subject: [PATCH 7/9] ignore associations with an unspecified direction in CDAssociationUnique --- .../monticore/cdgen/cocos/CDAssociationUnique.java | 13 ++++++++----- .../cdgen/cocos/CDAssociationUniqueTest.java | 9 ++++++++- 2 files changed, 16 insertions(+), 6 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 bad4a2bc2..77424df14 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -36,7 +36,8 @@ public void check(ASTCDDefinition node) { // 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)) - && isNavigable(assoc1, AssocSide.LEFT) && isNavigable(assoc2, AssocSide.LEFT)) { + && assoc1.getCDAssocDir().isDefinitiveNavigableLeft() && assoc2.getCDAssocDir() + .isDefinitiveNavigableLeft()) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getRightQualifiedName() .getQName())); @@ -45,21 +46,23 @@ && isNavigable(assoc1, AssocSide.LEFT) && isNavigable(assoc2, AssocSide.LEFT)) { // 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)) && isNavigable(assoc1, AssocSide.RIGHT) && isNavigable(assoc2, - AssocSide.RIGHT)) { + AssocSide.RIGHT)) && assoc1.getCDAssocDir().isDefinitiveNavigableRight() && assoc2 + .getCDAssocDir().isDefinitiveNavigableRight()) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // We also consider a left-to-right role name match ... if (deriveRoleName(assoc1, AssocSide.LEFT).equals(deriveRoleName(assoc2, AssocSide.RIGHT)) - && isNavigable(assoc1, AssocSide.LEFT) && isNavigable(assoc2, AssocSide.RIGHT)) { + && assoc1.getCDAssocDir().isDefinitiveNavigableLeft() && assoc2.getCDAssocDir() + .isDefinitiveNavigableRight()) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getRightQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getLeftQualifiedName().getQName())); } // ... as well as a right-to-left match if (deriveRoleName(assoc1, AssocSide.RIGHT).equals(deriveRoleName(assoc2, AssocSide.LEFT)) - && isNavigable(assoc1, AssocSide.RIGHT) && isNavigable(assoc2, AssocSide.LEFT)) { + && assoc1.getCDAssocDir().isDefinitiveNavigableRight() && assoc2.getCDAssocDir() + .isDefinitiveNavigableLeft()) { checkRef(assoc1, assoc2, findTypeByFullName(assoc1, assoc1.getLeftQualifiedName() .getQName()), findTypeByFullName(assoc2, assoc2.getRightQualifiedName() .getQName())); 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 0423983b5..cb144640f 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/cocos/CDAssociationUniqueTest.java @@ -94,7 +94,7 @@ public void testNonOpposedAssocs() throws IOException { @Test public void testNonOpposedAssocs2() throws IOException { String model = "classdiagram DuplicateAssocs {" + " class A; class B;" - + " association A -> B;" + " association A -- B;" + "}"; + + " association A -> B;" + " association A <-> B;" + "}"; runTestForErrorCode(model, ERROR_CODE); } @@ -105,4 +105,11 @@ public void testNonOpposedAssocs3() throws IOException { runTestForErrorCode(model, ERROR_CODE); } + @Test + public void testNonOpposedAssocsUnspecified() throws IOException { + String model = "classdiagram DuplicateAssocs {" + " class A; class B;" + + " association A -> B;" + " association A -- B;" + "}"; + runTest(model, false); + } + } From 14d6202f8a7a82f41b8bfe0371883a4d45161526 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Wed, 4 Mar 2026 13:37:58 +0100 Subject: [PATCH 8/9] resolve comments --- .../cdgen/cocos/CDAssociationUnique.java | 26 +++++++------------ .../cocos/CDAssociationUniqueInHierarchy.java | 3 ++- 2 files changed, 12 insertions(+), 17 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 77424df14..c6afc4a49 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -16,8 +16,7 @@ * Checks that there are not multiple occurrences of the same association between types */ public class CDAssociationUnique implements CDBasisASTCDDefinitionCoCo { - - /** @param node class to check. */ + @Override public void check(ASTCDDefinition node) { @@ -71,18 +70,7 @@ public void check(ASTCDDefinition node) { } } } - - private static boolean isNavigable(ASTCDAssociation assoc1, AssocSide side1) { - if (side1.equals(AssocSide.LEFT)) { - return assoc1.getCDAssocDir().isDefinitiveNavigableLeft() || (!assoc1.getCDAssocDir() - .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); - } - else { - return assoc1.getCDAssocDir().isDefinitiveNavigableRight() || (!assoc1.getCDAssocDir() - .isDefinitiveNavigableLeft() && !assoc1.getCDAssocDir().isDefinitiveNavigableRight()); - } - } - + /** helper-method to find types by full-name */ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { @@ -99,8 +87,14 @@ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDType type1, ASTCDType type2) { if (type1.equals(type2)) { - Log.error(String.format("0xCDCE1: %s has duplicate associations at %s and %s.", type1 - .getName(), assoc1.get_SourcePositionStart(), assoc2.get_SourcePositionStart()), assoc2 + Log.error(String.format("0xCDCE1: %s has duplicate associations %s at %s and %s, " + + "i.e. 2 different associations with the same target role-name for a given source-type." + + "This may lead to conflicts in the generated code and is therefore not permitted " + + "for code generation purposes.", + type1 + .getName(), assoc1.getPrintableName(), assoc1.get_SourcePositionStart(), + assoc2.get_SourcePositionStart()), + assoc2 .get_SourcePositionStart()); } } diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java index ad7507bbe..d23675e93 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java @@ -38,7 +38,8 @@ protected void checkSuper(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTC while (!typesToVisit.isEmpty()) { final TypeSymbol nextType = typesToVisit.pop(); if (nextType.getFullName().equals(type2.getSymbol().getFullName())) { - Log.error(String.format("0xCDCE6: %s redefines an association of %s from %s at %s", type1 + Log.error(String.format("0xCDCE6: %s redefines an association of %s from %s at %s." + + "Redefining associations are not supported by code generators.", type1 .getName(), type2.getName(), assoc2.get_SourcePositionStart(), assoc1 .get_SourcePositionStart()), assoc1.get_SourcePositionStart()); return; From 791d7efe0c9f1cb0395991e2b1bd0a7acd55b463 Mon Sep 17 00:00:00 2001 From: Max Philip Stachon Date: Wed, 4 Mar 2026 13:48:03 +0100 Subject: [PATCH 9/9] spotless --- .../cdgen/cocos/CDAssociationUnique.java | 15 ++++++--------- .../cocos/CDAssociationUniqueInHierarchy.java | 6 +++--- 2 files changed, 9 insertions(+), 12 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 c6afc4a49..2c302aba6 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUnique.java @@ -16,7 +16,7 @@ * Checks that there are not multiple occurrences of the same association between types */ public class CDAssociationUnique implements CDBasisASTCDDefinitionCoCo { - + @Override public void check(ASTCDDefinition node) { @@ -70,7 +70,7 @@ public void check(ASTCDDefinition node) { } } } - + /** helper-method to find types by full-name */ protected ASTCDType findTypeByFullName(ASTCDAssociation node, String fullName) { @@ -89,13 +89,10 @@ protected void checkRef(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTCDT if (type1.equals(type2)) { Log.error(String.format("0xCDCE1: %s has duplicate associations %s at %s and %s, " + "i.e. 2 different associations with the same target role-name for a given source-type." - + "This may lead to conflicts in the generated code and is therefore not permitted " - + "for code generation purposes.", - type1 - .getName(), assoc1.getPrintableName(), assoc1.get_SourcePositionStart(), - assoc2.get_SourcePositionStart()), - assoc2 - .get_SourcePositionStart()); + + "This may lead to conflicts in the generated code and is therefore not permitted " + + "for code generation purposes.", type1.getName(), assoc1.getPrintableName(), assoc1 + .get_SourcePositionStart(), assoc2.get_SourcePositionStart()), assoc2 + .get_SourcePositionStart()); } } diff --git a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java index d23675e93..66d0d8fc2 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java +++ b/cdlang/src/main/java/de/monticore/cdgen/cocos/CDAssociationUniqueInHierarchy.java @@ -39,9 +39,9 @@ protected void checkSuper(ASTCDAssociation assoc1, ASTCDAssociation assoc2, ASTC final TypeSymbol nextType = typesToVisit.pop(); if (nextType.getFullName().equals(type2.getSymbol().getFullName())) { Log.error(String.format("0xCDCE6: %s redefines an association of %s from %s at %s." - + "Redefining associations are not supported by code generators.", type1 - .getName(), type2.getName(), assoc2.get_SourcePositionStart(), assoc1 - .get_SourcePositionStart()), assoc1.get_SourcePositionStart()); + + "Redefining associations are not supported by code generators.", type1.getName(), + type2.getName(), assoc2.get_SourcePositionStart(), assoc1.get_SourcePositionStart()), + assoc1.get_SourcePositionStart()); return; }