diff --git a/gradle.properties b/gradle.properties index 7886dac0..c5eb4f77 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.23 +version = 7.8.24 diff --git a/language/src/main/grammars/de/monticore/lang/SysMLImportsAndPackages.mc4 b/language/src/main/grammars/de/monticore/lang/SysMLImportsAndPackages.mc4 index 69b2e9fb..2e426e08 100644 --- a/language/src/main/grammars/de/monticore/lang/SysMLImportsAndPackages.mc4 +++ b/language/src/main/grammars/de/monticore/lang/SysMLImportsAndPackages.mc4 @@ -43,7 +43,7 @@ component grammar SysMLImportsAndPackages extends SysMLBasis { * Metadata is additional data that can be used to annotate * the elements of a model. */ - SysMLMetaDataDefinition implements SysMLElement = + symbol scope SysMLMetaDataDefinition implements SysMLType, SysMLElement = Modifier UserDefinedKeyword* "metadata" "def" SysMLIdentifier? Name SysMLCardinality? Specialization* ("{" diff --git a/language/src/main/grammars/de/monticore/lang/SysMLParts.mc4 b/language/src/main/grammars/de/monticore/lang/SysMLParts.mc4 index 19bf0cf9..48f02081 100644 --- a/language/src/main/grammars/de/monticore/lang/SysMLParts.mc4 +++ b/language/src/main/grammars/de/monticore/lang/SysMLParts.mc4 @@ -8,7 +8,7 @@ component grammar SysMLParts extends SysMLBasis { * Defaults to "delayed". */ SysMLCausality implements SysMLElement = - "timing" (["instant"] | ["delayed"]) ";" ; + "timing" timing:Name ";" ; /* * ################################################################## 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 1096b91e..9b9ace6f 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -41,6 +41,7 @@ import de.monticore.lang.sysmlv2.cocos.SubcomponentOutputConnectionDirectionCoCo; import de.monticore.lang.sysmlv2.cocos.TypeCheck3TransitionGuards; import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInParentCoCo; +import de.monticore.lang.sysmlv2.cocos.ValidCausalityTimingCoCo; import de.monticore.lang.sysmlv2.cocos.WarnNonExhibited; import de.monticore.lang.sysmlv2.symboltable.completers.CausalityCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectRefinementCompleter; @@ -123,6 +124,7 @@ public void runDefaultCoCos(ASTSysMLModel ast) { checker.addCoCo(new QualifiedPortNameExistsCoCo()); // Check ambiguous names checker.addCoCo(new UniqueSubPartNamesInParentCoCo()); + checker.addCoCo(new ValidCausalityTimingCoCo()); checker.checkAll(ast); } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/_symboltable/ISysMLv2Scope.java b/language/src/main/java/de/monticore/lang/sysmlv2/_symboltable/ISysMLv2Scope.java index 3711631a..d4a3ac4d 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/_symboltable/ISysMLv2Scope.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/_symboltable/ISysMLv2Scope.java @@ -11,6 +11,7 @@ import de.monticore.lang.sysmlconstraints._ast.ASTRequirementUsage; import de.monticore.lang.sysmlconstraints._symboltable.RequirementSubjectSymbol; import de.monticore.lang.sysmlconstraints.symboltable.adapters.RequirementSubject2VariableSymbolAdapter; +import de.monticore.lang.sysmlimportsandpackages._symboltable.SysMLMetaDataDefinitionSymbol; import de.monticore.lang.sysmloccurrences.symboltable.adapters.ItemDef2TypeSymbolAdapter; import de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol; import de.monticore.lang.sysmlparts._symboltable.PartUsageSymbol; @@ -28,6 +29,7 @@ import de.monticore.lang.sysmlstates.symboltable.adapters.StateDef2TypeSymbolAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.AttributeUsage2PortSymbolAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.Constraint2SpecificationAdapter; +import de.monticore.lang.sysmlv2.symboltable.adapters.MetadataDef2TypeSymbolAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.PartDef2ComponentAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.Requirement2RequirementCCAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.Requirement2SpecificationAdapter; @@ -251,6 +253,12 @@ default List resolveAdaptedTypeLocallyMany( adapted.add(new ItemDef2TypeSymbolAdapter(itemDef.get())); } + // MetadataDef zu Types + var metadataDef = resolveSysMLMetaDataDefinitionLocally(name); + if (metadataDef.isPresent()) { + adapted.add(new MetadataDef2TypeSymbolAdapter(metadataDef.get())); + } + return adapted; } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ValidCausalityTimingCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ValidCausalityTimingCoCo.java new file mode 100644 index 00000000..18f43fe9 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ValidCausalityTimingCoCo.java @@ -0,0 +1,24 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlparts._ast.ASTSysMLCausality; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTSysMLCausalityCoCo; +import de.se_rwth.commons.logging.Log; + +import java.util.Set; + +public class ValidCausalityTimingCoCo implements SysMLPartsASTSysMLCausalityCoCo { + protected static final Set VALID_TIMINGS = Set.of("instant", "delayed"); + + @Override + public void check(ASTSysMLCausality node) { + if (!VALID_TIMINGS.contains(node.getTiming())) { + Log.error( + "0x10AA8 Illegal timing value '" + node.getTiming() + + "'. Only 'instant' and 'delayed' are allowed.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd() + ); + } + } +} \ No newline at end of file diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/MetadataDef2TypeSymbolAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/MetadataDef2TypeSymbolAdapter.java new file mode 100644 index 00000000..2442fe41 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/MetadataDef2TypeSymbolAdapter.java @@ -0,0 +1,53 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.symboltable.adapters; + +import com.google.common.base.Preconditions; +import de.monticore.lang.sysmlimportsandpackages._symboltable.SysMLMetaDataDefinitionSymbol; +import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.se_rwth.commons.SourcePosition; + +public class MetadataDef2TypeSymbolAdapter extends TypeSymbol { + protected SysMLMetaDataDefinitionSymbol adaptee; + + public MetadataDef2TypeSymbolAdapter(SysMLMetaDataDefinitionSymbol adaptee) { + super(Preconditions.checkNotNull(adaptee.getName())); + this.adaptee = adaptee; + } + + protected SysMLMetaDataDefinitionSymbol getAdaptee() { + return adaptee; + } + + @Override + public void setName(String name) { + Preconditions.checkNotNull(name); + Preconditions.checkArgument(!name.isBlank()); + getAdaptee().setName(name); + } + + @Override + public String getName() { + return getAdaptee().getName(); + } + + @Override + public String getFullName() { + return getAdaptee().getFullName(); + } + + @Override + public IBasicSymbolsScope getSpannedScope() { + return getAdaptee().getSpannedScope(); + } + + @Override + public IBasicSymbolsScope getEnclosingScope() { + return getAdaptee().getEnclosingScope(); + } + + @Override + public SourcePosition getSourcePosition() { + return getAdaptee().getSourcePosition(); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/CausalityCompleter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/CausalityCompleter.java index e32b0043..229e4c36 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/CausalityCompleter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/CausalityCompleter.java @@ -11,6 +11,8 @@ * anhand der besitzenden (umliegenden) PartDefinition. */ public class CausalityCompleter implements SysMLPartsVisitor2 { + protected static final String INSTANT = "instant"; + @Override public void visit(ASTPortUsage node) { if (node.getEnclosingScope().isPresentSpanningSymbol()) { @@ -18,7 +20,9 @@ public void visit(ASTPortUsage node) { if(enclosingSymbol instanceof PartDefSymbol && enclosingSymbol.isPresentAstNode()) { var ast = (ASTPartDef) enclosingSymbol.getAstNode(); node.getSymbol().setStrong( - ast.getSysMLElements(ASTSysMLCausality.class).stream().noneMatch(ASTSysMLCausality::isInstant) + ast.getSysMLElements(ASTSysMLCausality.class).stream() + .map(ASTSysMLCausality::getTiming) + .noneMatch(INSTANT::equals) ); } } diff --git a/language/src/test/java/cocos/ValidCausalityTimingCoCoTest.java b/language/src/test/java/cocos/ValidCausalityTimingCoCoTest.java new file mode 100644 index 00000000..7b049007 --- /dev/null +++ b/language/src/test/java/cocos/ValidCausalityTimingCoCoTest.java @@ -0,0 +1,60 @@ +/* (c) https://github.com/MontiCore/monticore */ +package cocos; + +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2._cocos.SysMLv2CoCoChecker; +import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; +import de.monticore.lang.sysmlv2.cocos.ValidCausalityTimingCoCo; +import de.se_rwth.commons.logging.Log; +import de.se_rwth.commons.logging.LogStub; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ValidCausalityTimingCoCoTest { + private final SysMLv2Parser parser = new SysMLv2Parser(); + + @BeforeAll + public static void init() { + LogStub.init(); + SysMLv2Mill.init(); + } + + @BeforeEach + public void reset() { + Log.getFindings().clear(); + } + + @Test + void testDelayedTimingAndMetadataNameCanCoexist() throws IOException { + var ast = parser.parse_String("package Demo { metadata def delayed; part def P { timing delayed; } }"); + + assertThat(ast).isPresent(); + assertThat(parser.hasErrors()).isFalse(); + + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new ValidCausalityTimingCoCo()); + checker.checkAll(ast.get()); + + assertThat(Log.getFindings()).isEmpty(); + } + + @Test + void testInvalidTimingValueProducesFinding() throws IOException { + var ast = parser.parse_String("part def P { timing asap; }"); + + assertThat(ast).isPresent(); + assertThat(parser.hasErrors()).isFalse(); + + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new ValidCausalityTimingCoCo()); + checker.checkAll(ast.get()); + + assertThat(Log.getFindings()).isNotEmpty(); + assertThat(Log.getFindings().get(0).getMsg()).contains("0x10AA8"); + } +} \ No newline at end of file diff --git a/language/src/test/java/symboltable/MetadataDefinitionSymbolTest.java b/language/src/test/java/symboltable/MetadataDefinitionSymbolTest.java new file mode 100644 index 00000000..55731040 --- /dev/null +++ b/language/src/test/java/symboltable/MetadataDefinitionSymbolTest.java @@ -0,0 +1,47 @@ +/* (c) https://github.com/MontiCore/monticore */ +package symboltable; + +import de.monticore.lang.sysmlimportsandpackages._ast.ASTSysMLMetaDataDefinition; +import de.monticore.lang.sysmlimportsandpackages._ast.ASTSysMLPackage; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.se_rwth.commons.logging.Log; +import de.se_rwth.commons.logging.LogStub; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MetadataDefinitionSymbolTest { + + private static final String LOG_NAME = MetadataDefinitionSymbolTest.class.getName(); + + @Test + public void testMetadataDefinitionCreatesTypeSymbol() throws Exception { + LogStub.init(); + Log.getFindings().clear(); + + var tool = new SysMLv2Tool(); + tool.init(); + + String model = "package Demo {\n" + + " metadata def delayed;\n" + + " part def P {\n" + + " timing delayed;\n" + + " }\n" + + "}\n"; + + var ast = SysMLv2Mill.parser().parse_String(model); + assertThat(ast).isPresent(); + + var artifactScope = tool.createSymbolTable(ast.get()); + + var pkg = (ASTSysMLPackage) ast.get().getSysMLElement(0); + + var metadataDef = (ASTSysMLMetaDataDefinition) pkg.getSysMLElement(0); + assertThat(metadataDef.getName()).isEqualTo("delayed"); + + assertThat(artifactScope.getSubScopes()).hasSize(1); + assertThat(artifactScope.getSubScopes().get(0).resolveSysMLMetaDataDefinition("delayed")).isPresent(); + assertThat(artifactScope.getSubScopes().get(0).resolveType("delayed")).isPresent(); + } +}