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 @@ -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) {
Expand Down Expand Up @@ -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.",
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
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.SubPartNamesInConnectionExistCoCo;
import de.se_rwth.commons.logging.Finding;
import de.se_rwth.commons.logging.Log;
import org.junit.jupiter.api.AfterEach;
Expand All @@ -22,7 +22,7 @@

import static org.assertj.core.api.Assertions.assertThat;

public class UniqueSubPartNamesInConnectionCoCoTest {
public class SubPartNamesInConnectionExistCoCoTest {

private static final String MODEL_PATH = "src/test/resources/parser";

Expand Down Expand Up @@ -78,24 +78,6 @@ public void testInvalidUndefined() throws IOException {
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 =
Expand All @@ -113,24 +95,6 @@ public void testInvalidBothUndefined() throws IOException {
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");
}

private ASTSysMLModel parse(String model) throws IOException {
var optAst = SysMLv2Mill.parser().parse_String(model);
assertThat(optAst).isPresent();
Expand All @@ -146,7 +110,7 @@ private ISysMLv2ArtifactScope createSt(ASTSysMLModel ast) {

private List<Finding> check(ASTSysMLModel ast) {
var checker = new SysMLv2CoCoChecker();
checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo());
checker.addCoCo(new SubPartNamesInConnectionExistCoCo());
Log.enableFailQuick(false);
checker.checkAll(ast);
return Log.getFindings().stream().filter(Finding::isError).collect(
Expand Down
104 changes: 104 additions & 0 deletions language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* (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.UniqueSubPartNamesInParentCoCo;
import de.se_rwth.commons.logging.Finding;
import de.se_rwth.commons.logging.Log;
import org.junit.jupiter.api.*;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;

public class UniqueSubPartNamesInParentCoCoTest {

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;"
+ "}";

var ast = parse(validModel);
createSt(ast);
var errors = check(ast);
assertThat(errors).hasSize(0);
}

@Test
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;"
+ "part a: B;"
+ "}";

var ast = parse(invalidModel);
createSt(ast);
var errors = check(ast);
assertThat(errors).hasSize(2);
assertThat(errors.get(0).getMsg()).contains("0x10AA7");
}

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<Finding> check(ASTSysMLModel ast) {
var checker = new SysMLv2CoCoChecker();
checker.addCoCo(new UniqueSubPartNamesInParentCoCo());
Log.enableFailQuick(false);
checker.checkAll(ast);
return Log.getFindings().stream().filter(Finding::isError).collect(
Collectors.toList());
}

@AfterEach
void clearLog() {
Log.clearFindings();
Log.enableFailQuick(true);
}
}
}
Loading