Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import de.monticore.cd.cocos.CoCoParent;
import de.monticore.cd4analysis._cocos.CD4AnalysisCoCoChecker;
import de.monticore.cd4analysis.cocos.ebnf.CDAssociationValidRoleSymbolsInScope;

public class CD4AnalysisCoCos extends CoCoParent<CD4AnalysisCoCoChecker> {
@Override
Expand All @@ -16,4 +17,9 @@ protected void addCheckerForAllCoCos(CD4AnalysisCoCoChecker checker) {
addCheckerForMcgCoCos(checker);
addCheckerForMcg2EbnfCoCos(checker);
}

@Override
protected void addEbnfCoCos(CD4AnalysisCoCoChecker checker) {
checker.addCoCo(new CDAssociationValidRoleSymbolsInScope());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.cd4analysis.cocos.ebnf;

import de.monticore.cdassociation._ast.ASTCDAssociation;
import de.monticore.cdassociation._symboltable.CDRoleSymbol;
import de.monticore.cdbasis._ast.ASTCDDefinition;
import de.monticore.cdbasis._cocos.CDBasisASTCDDefinitionCoCo;
import de.se_rwth.commons.logging.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* This CoCo checks for the usage of identical role names across multiple
* associations for a given reference type. The presence of duplicate role
* names can lead to ambiguity when accessing the referenced elements,
* and results in incomplete storage of CDRoleSymbols within the
* scope and symbol table.
* <p>
* This CoCo only considers the roles of an isolated reference type, as this
* serves as the fundamental basis. More in-depth CoCos use the symbol table
* and are faulty if it is faulty.
* <p>
* Example:
* <pre>
* class Person {
* }
* association knows [1] Person -> Person [*];
* </pre>
* Since no explicit role names were provided, the name of the reference type (in lowercase)
* is used as the role name. Since this is identical in both cases, only one of the two
* CDRoleSymbols is stored in the scope of the Person type.
*/
public class CDAssociationValidRoleSymbolsInScope implements CDBasisASTCDDefinitionCoCo {

@Override
public void check(ASTCDDefinition definition) {
// maps class to all contained role names
Map<String, List<String>> knownRoleNames = new HashMap<>();
for (ASTCDAssociation assoc : definition.getCDAssociationsList()) {
// left side
CDRoleSymbol rightRoleSymbol = assoc.getRight().getSymbol();
String leftTypeFQN = assoc.getLeftQualifiedName().getQName();
knownRoleNames.putIfAbsent(leftTypeFQN, new ArrayList<>());

if (knownRoleNames.get(leftTypeFQN).contains(rightRoleSymbol.getName())) {
Log.error("0xCDCE4: Duplicate role (" + rightRoleSymbol.getName() + ") in reference Type "
+ assoc.getLeft().getMCQualifiedType().printType(),
rightRoleSymbol.getSourcePosition());
}
else {
knownRoleNames.get(leftTypeFQN).add(rightRoleSymbol.getName());
}

// right side
CDRoleSymbol leftRoleSymbol = assoc.getLeft().getSymbol();
String rightTypeFQN = assoc.getRightQualifiedName().getQName();
knownRoleNames.putIfAbsent(rightTypeFQN, new ArrayList<>());

if (knownRoleNames.get(rightTypeFQN).contains(leftRoleSymbol.getName())) {
Log.error("0xCDCE4: Duplicate role (" + leftRoleSymbol.getName() + ") in reference Type "
+ assoc.getRight().getMCQualifiedType().printType(),
leftRoleSymbol.getSourcePosition());
}
else {
knownRoleNames.get(rightTypeFQN).add(leftRoleSymbol.getName());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ public static void addRoleToTheirType(CDRoleSymbol symbol, TypeSymbol otherType)
if (!spannedScope.getCDRoleSymbols().containsKey(symbol.getName())) {
// add the symbol to the type; add to all relevant lists
spannedScope.add(symbol);
} else {
Log.warn("0xCDCE5: Ignored duplicate role symbol (" + symbol.getName()+") for reference Type "+otherType.getFullName(), symbol.getSourcePosition());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package de.monticore.cd4analysis.cocos.ebnf;

import de.monticore.cd4analysis.CD4AnalysisTestBasis;
import de.monticore.cdbasis._ast.ASTCDCompilationUnit;
import de.se_rwth.commons.logging.Log;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class CDAssociationValidRoleSymbolInScopeTest extends CD4AnalysisTestBasis {

@Test
public void testValid() throws IOException {
String modelPath = "cd4analysis/cocos/CDAssociationValidRoleSymbolInScope.cd";

coCoChecker.addCoCo(new CDAssociationValidRoleSymbolsInScope());
ASTCDCompilationUnit ast = parse(modelPath);
prepareST(ast);

coCoChecker.checkAll(ast);
assertEquals(0, Log.getFindings().size());
}

@Test
public void testInvalid() throws IOException {
String modelPath = "cd4analysis/cocos/CDAssociationValidRoleSymbolInScopeInvalid.cd";

coCoChecker.addCoCo(new CDAssociationValidRoleSymbolsInScope());
ASTCDCompilationUnit ast = parse(modelPath);
prepareST(ast);

coCoChecker.checkAll(ast);
assertEquals(2, Log.getFindings().size());
assertTrue(Log.getFindings().get(0).getMsg().startsWith("0xCDCE5"));
assertTrue(Log.getFindings().get(1).getMsg().startsWith("0xCDCE4"));
Log.clearFindings();
}

@Test
public void testInvalid2() throws IOException {
String modelPath = "cd4analysis/cocos/CDAssociationValidRoleSymbolInScopeInvalid2.cd";

coCoChecker.addCoCo(new CDAssociationValidRoleSymbolsInScope());
ASTCDCompilationUnit ast = parse(modelPath);
prepareST(ast);

coCoChecker.checkAll(ast);
assertEquals(4, Log.getFindings().size());
assertTrue(Log.getFindings().get(0).getMsg().startsWith("0xCDCE5"));
assertTrue(Log.getFindings().get(1).getMsg().startsWith("0xCDCE5"));
assertTrue(Log.getFindings().get(2).getMsg().startsWith("0xCDCE4"));
assertTrue(Log.getFindings().get(3).getMsg().startsWith("0xCDCE4"));
Log.clearFindings();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* (c) https://github.com/MontiCore/monticore */

classdiagram CDAssociationValidRoleSymbolInScope {

class Person {
public String fullName;
int age;
}

association marriage [1] Person (partnerOpposite) <-> (partner) Person [1];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* (c) https://github.com/MontiCore/monticore */

classdiagram CDAssociationValidRoleSymbolInScopeInvalid {

class Person {
public String fullName;
int age;
}

association marriage [1] Person <-> Person [1];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* (c) https://github.com/MontiCore/monticore */

classdiagram CDAssociationValidRoleSymbolInScopeInvalid2 {

class Person {
public String fullName;
int age;
}

association mother [1] Person <-> (child) Person [1];
association father [1] Person <-> (child) Person [1];
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ classdiagram InviDas {
String name;
}

association DataEntry -> DataEntry [*];
association DataEntry -> (linked) DataEntry [*];
association DataEntry -> DataCategory [*];

/*************************************************************************************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ classdiagram MaCoCo {
}

association [1] Konto (konto) <-> (gesamtBudget) Budget [0..1];
association [1] Konto -> (kommentare) Freitext [*];
association [1] Konto -> (notiz) Freitext [0..1];
association [1] Konto (kommentiert) -> (kommentare) Freitext [*];
association [1] Konto (annotiert) -> (notiz) Freitext [0..1];
association [1] Konto <-> MailAlert [*];
association [1] Konto -> (abgleichsKonto) ExternKonto [0..1];

Expand Down
6 changes: 3 additions & 3 deletions cdtool/src/test/java/de/monticore/CDDiffCLIToolTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ public void init() {

@Test
public void testChain() {
final String cd1 = TOOL_PATH + "cddiff/Employees/Employees2.cd";
final String cd2 = TOOL_PATH + "cddiff/Employees/Employees1.cd";
final String cd1 = TOOL_PATH + "cddiff/Employees/Employees10.cd";
final String cd2 = TOOL_PATH + "cddiff/Employees/Employees9.cd";
final String output = "./target/generated/chain";
String[] args = {
"-i", cd1, "--merge", cd2, "--semdiff", cd2, "-o", output, "-pp", "Employees12.cd"
"-i", cd1, "--merge", cd2, "--semdiff", cd2, "-o", output, "-pp", "Employees910.cd"
};
CD4CodeTool.main(args);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* (c) https://github.com/MontiCore/monticore */

import java.util.Date;
import java.lang.String;

classdiagram Employees10 {
enum PositionKind{fullTime, partTime, external;}

class Employee {
PositionKind kind;
}

class Task {
Date startDate;
}

class Manager extends Employee;

association [*] Employee (manages) -> (managedBy) Manager [0..1];
association [1] Employee (priorityTask) -- (createdBy) Task [0..1];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* (c) https://github.com/MontiCore/monticore */

import java.util.Date;

classdiagram Employees9 {
enum PositionKind{fullTime, partTime;}

class Employee {
PositionKind kind;
}

class Task {
Date startDate;
}

class Manager;

association [*] Employee (manages) -> (managedBy) Manager [0..1];
association [1] Employee (tasks) -- (assignedTo) Task [*];
}
Loading