From c1c9bad8b98571d1f1291369cd39855867d7efaf Mon Sep 17 00:00:00 2001 From: adriancostin-sd Date: Tue, 4 Nov 2025 09:16:55 +0200 Subject: [PATCH 01/29] Release 7.8.1 - Timing wird dynamisch bestimmt (#27), update nth stream lib test definition --- gradle.properties | 2 +- .../AttributeUsage2PortSymbolAdapter.java | 15 ++++++++++++--- .../resources/cocos/constraints/4_valid.sysml | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index 72d223ad..7f67428c 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.0 +version = 7.8.1 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java index d6844f99..4350c499 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java @@ -2,7 +2,9 @@ import de.monticore.lang.componentconnector._symboltable.MildPortSymbol; import de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol; +import de.monticore.lang.sysmlparts._symboltable.PartDefSymbol; import de.monticore.lang.sysmlparts._symboltable.PortUsageSymbol; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; import de.monticore.symbols.compsymbols._symboltable.ICompSymbolsScope; import de.monticore.symbols.compsymbols._symboltable.Timing; import de.monticore.types.check.SymTypeExpressionFactory; @@ -26,9 +28,7 @@ public AttributeUsage2PortSymbolAdapter( this.adaptee = adaptee; this.incoming = incoming; this.outgoing = !this.incoming; - // TODO Timing aus Komponente frickeln, in der die PortUsage liegt in deren Definition das Attribut liegt - this.timing = Timing.TIMED; - // TODO s.o. + this.timing = determineTiming(container); this.stronglyCausal = container.isStrong(); // Das muss anscheinend gesetzt sein, weil die MC-Interna immer über das Feld herausfinden, ob sie getEnclosingScope @@ -71,6 +71,15 @@ public Timing getTiming() { return timing; } + private Timing determineTiming(PortUsageSymbol container) { + var scope = (ISysMLv2Scope) container.getEnclosingScope(); + + boolean hasTsyn = scope.getLocalStateUsageSymbols().stream() + .anyMatch(sym -> sym.getUserDefinedKeywordsList().contains("tsyn")); + + return hasTsyn ? Timing.TIMED_SYNC : Timing.TIMED; + } + @Override public boolean equals(Object other) { if(other instanceof AttributeUsage2PortSymbolAdapter) { diff --git a/language/src/test/resources/cocos/constraints/4_valid.sysml b/language/src/test/resources/cocos/constraints/4_valid.sysml index ac0d6851..31becb82 100644 --- a/language/src/test/resources/cocos/constraints/4_valid.sysml +++ b/language/src/test/resources/cocos/constraints/4_valid.sysml @@ -7,6 +7,6 @@ part def LogicBasedConstraints { port myPortDef: Integers; constraint constraintName { - myPortDef.natAttr.nth(3).nth(3).get() > 1 + myPortDef.natAttr.nth(3).nth(3) > 1 } } From 228573790b764906016bbc0fa03de0fbbe036919 Mon Sep 17 00:00:00 2001 From: Justus R <103401898+justusrm@users.noreply.github.com> Date: Fri, 9 Jan 2026 10:38:56 +0100 Subject: [PATCH 02/29] Backporting typecheck3 to 7.8.x (#40) * TypeCheck3 with Streams (#30) ## Changelog ### Added * TypeCheck3 implementation (Closes #29) * Extended streams compatibility to additionally interpret port usages with one attribute as a C&C ports ### Changed * nat is now a primitive instead of a SymTypeOfObject (for typecheck3 compatibility) * deprecated TypeCheck1, TypeCheck1 CoCos, added TypeCheck3 CoCos ### Fixed * CC Port resolution for FQNs that contain that contain more than two parts * added "::" as potential delimiter for resolution (cherry picked from commit ef2cc5ede0ac1164dde3ecef7e9f8f1c32176968) * #115 version bump to 7.8.2 --------- Co-authored-by: adriancostin-sd --- gradle.properties | 2 +- .../componentconnector/StreamTimingUtil.java | 19 + .../AnonymousUsage2VariableSymbolAdapter.java | 1 - .../AttributeUsage2VariableSymbolAdapter.java | 4 +- .../PortUsage2VariableSymbolAdapter.java | 1 - .../completers/ConvertEnumUsagesToFields.java | 37 +- .../monticore/lang/sysmlv2/SysMLv2Mill.java | 37 +- .../monticore/lang/sysmlv2/SysMLv2Tool.java | 13 + .../sysmlv2/_symboltable/ISysMLv2Scope.java | 27 +- .../sysmlv2/cocos/AssignActionTypeCheck.java | 1 + .../sysmlv2/cocos/AssignActionTypeCheck3.java | 22 ++ .../sysmlv2/cocos/ConstraintIsBoolean.java | 1 + .../sysmlv2/cocos/ConstraintIsBooleanTC3.java | 41 +++ .../sysmlv2/cocos/SendActionTypeCheck.java | 1 + .../sysmlv2/cocos/SendActionTypeCheck3.java | 21 ++ .../sysmlv2/cocos/SpecializationExists.java | 1 + .../cocos/SpecializationExistsTC3.java | 22 ++ .../cocos/TypeCheck3TransitionGuards.java | 39 +++ .../cocos/TypeCheckTransitionGuards.java | 1 + .../adapters/ConfigurationWrapper.java | 5 +- .../symboltable/adapters/OutputWrapper.java | 1 - .../completers/TypesCompleter.java | 21 +- ...SysMLDeriveSymTypeOfStreamExpressions.java | 1 + .../lang/sysmlv2/types/SysMLDeriver.java | 1 + .../sysmlv2/types/SysMLExressionsDeriver.java | 1 + .../lang/sysmlv2/types/SysMLSynthesizer.java | 1 + ...sMLv2DeriveSymTypeOfCommonExpressions.java | 1 + .../SysMLCommonExpressionsTypeVisitor.java | 326 ++++++++++++++++++ .../types3/SysMLMCBasicTypesTypeVisitor.java | 15 + .../SysMLOCLExpressionsTypeVisitor.java | 13 + .../SysMLSetExpressionsTypeVisitor.java | 23 ++ .../sysmlv2/types3/SysMLSymTypeRelations.java | 28 ++ .../lang/sysmlv2/types3/SysMLTypeCheck3.java | 101 ++++++ .../SysMLTypeVisitorOperatorCalculator.java | 51 +++ .../SysMLWithinScopeBasicSymbolResolver.java | 213 ++++++++++++ .../test/java/cocos/ConstraintCoCoTest.java | 7 +- .../test/java/types3/ConstraintCoCoTest.java | 202 +++++++++++ ...AccessExpressionInConstraintUsageTest.java | 157 +++++++++ ...FieldAccessExpressionInStateUsageTest.java | 251 ++++++++++++++ .../src/test/java/types3/NegationTest.java | 156 +++++++++ .../java/types3/SpecializationExistsTest.java | 111 ++++++ .../StreamConstructorExpressionsTest.java | 186 ++++++++++ .../TC3FieldAccessInteroperabilityTest.java | 200 +++++++++++ .../cocos/constraints/17_invalid.sysml | 15 + .../cocos/constraints/17_valid.sysml | 15 + .../cocos/constraints/18_invalid.sysml | 14 + .../cocos/constraints/18_valid.sysml | 14 + .../implicitFieldAccess/11_invalid.sysml | 12 + .../implicitFieldAccess/11_valid.sysml | 12 + .../implicitFieldAccess/14_invalid.sysml | 14 + .../implicitFieldAccess/14_valid.sysml | 14 + .../implicitFieldAccess/15_invalid.sysml | 12 + .../implicitFieldAccess/15_valid.sysml | 12 + .../implicitFieldAccess/17_invalid.sysml | 14 + .../implicitFieldAccess/17_valid.sysml | 14 + .../implicitFieldAccess/18_invalid.sysml | 14 + .../implicitFieldAccess/18_valid.sysml | 14 + .../implicitFieldAccess/19_invalid.sysml | 12 + .../implicitFieldAccess/19_valid.sysml | 12 + .../implicitFieldAccess/2_invalid.sysml | 17 + .../implicitFieldAccess/2_valid.sysml | 13 + .../implicitFieldAccess/4_invalid.sysml | 12 + .../implicitFieldAccess/4_valid.sysml | 12 + 63 files changed, 2582 insertions(+), 49 deletions(-) create mode 100644 language/src/main/java/de/monticore/lang/componentconnector/StreamTimingUtil.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck3.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBooleanTC3.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck3.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExistsTC3.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheck3TransitionGuards.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLCommonExpressionsTypeVisitor.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLMCBasicTypesTypeVisitor.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSetExpressionsTypeVisitor.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSymTypeRelations.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeVisitorOperatorCalculator.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLWithinScopeBasicSymbolResolver.java create mode 100644 language/src/test/java/types3/ConstraintCoCoTest.java create mode 100644 language/src/test/java/types3/FieldAccessExpressionInConstraintUsageTest.java create mode 100644 language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java create mode 100644 language/src/test/java/types3/NegationTest.java create mode 100644 language/src/test/java/types3/SpecializationExistsTest.java create mode 100644 language/src/test/java/types3/StreamConstructorExpressionsTest.java create mode 100644 language/src/test/java/types3/TC3FieldAccessInteroperabilityTest.java create mode 100644 language/src/test/resources/cocos/constraints/17_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/17_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/18_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/18_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/11_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/11_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/14_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/14_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/15_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/15_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/17_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/17_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/18_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/18_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/19_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/19_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/2_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/2_valid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/4_invalid.sysml create mode 100644 language/src/test/resources/cocos/constraints/implicitFieldAccess/4_valid.sysml diff --git a/gradle.properties b/gradle.properties index 7f67428c..cda01f97 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.1 +version = 7.8.2 diff --git a/language/src/main/java/de/monticore/lang/componentconnector/StreamTimingUtil.java b/language/src/main/java/de/monticore/lang/componentconnector/StreamTimingUtil.java new file mode 100644 index 00000000..0482bfd3 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/componentconnector/StreamTimingUtil.java @@ -0,0 +1,19 @@ +package de.monticore.lang.componentconnector; + +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symbols.compsymbols._symboltable.Timing; + +public class StreamTimingUtil { + public static String mapTimingToStreamType(Timing timing) { + switch (timing) { + case TIMED: + return "EventStream"; + case TIMED_SYNC: + return "SyncStream"; + case UNTIMED: + return "UntimedStream"; + default: + throw new IllegalArgumentException("Unexpected value: " + timing); + } + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AnonymousUsage2VariableSymbolAdapter.java b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AnonymousUsage2VariableSymbolAdapter.java index 8ec62bfd..9c7ec4d0 100644 --- a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AnonymousUsage2VariableSymbolAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AnonymousUsage2VariableSymbolAdapter.java @@ -14,7 +14,6 @@ public class AnonymousUsage2VariableSymbolAdapter extends FieldSymbol { public AnonymousUsage2VariableSymbolAdapter(AnonymousUsageSymbol adaptee) { super(adaptee.getName()); this.adaptee = adaptee; - this.accessModifier = adaptee.getAccessModifier(); } protected AnonymousUsageSymbol getAdaptee() { diff --git a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AttributeUsage2VariableSymbolAdapter.java b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AttributeUsage2VariableSymbolAdapter.java index ce15c4ff..fc553293 100644 --- a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AttributeUsage2VariableSymbolAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/AttributeUsage2VariableSymbolAdapter.java @@ -5,6 +5,7 @@ import de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol; import de.monticore.symbols.oosymbols._symboltable.FieldSymbol; import de.monticore.symbols.oosymbols._symboltable.IOOSymbolsScope; +import de.monticore.symboltable.modifiers.AccessModifier; import de.monticore.types.check.SymTypeExpression; import de.se_rwth.commons.SourcePosition; @@ -14,7 +15,8 @@ public class AttributeUsage2VariableSymbolAdapter extends FieldSymbol { public AttributeUsage2VariableSymbolAdapter(AttributeUsageSymbol adaptee) { super(adaptee.getName()); this.adaptee = adaptee; - this.accessModifier = adaptee.getAccessModifier(); + // For the time being field is public for TypeCheck compatibility + this.setIsPublic(true); } protected AttributeUsageSymbol getAdaptee() { diff --git a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/PortUsage2VariableSymbolAdapter.java b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/PortUsage2VariableSymbolAdapter.java index eaa8bbc0..7bdd4891 100644 --- a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/PortUsage2VariableSymbolAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/adapters/PortUsage2VariableSymbolAdapter.java @@ -13,7 +13,6 @@ public class PortUsage2VariableSymbolAdapter extends VariableSymbol { public PortUsage2VariableSymbolAdapter(PortUsageSymbol adaptee) { super(adaptee.getName()); this.adaptee = adaptee; - this.accessModifier = adaptee.getAccessModifier(); } protected PortUsageSymbol getAdaptee() { diff --git a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/completers/ConvertEnumUsagesToFields.java b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/completers/ConvertEnumUsagesToFields.java index 05161f14..477a61aa 100644 --- a/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/completers/ConvertEnumUsagesToFields.java +++ b/language/src/main/java/de/monticore/lang/sysmlparts/symboltable/completers/ConvertEnumUsagesToFields.java @@ -1,5 +1,7 @@ package de.monticore.lang.sysmlparts.symboltable.completers; +import de.monticore.lang.sysmlbasis._ast.ASTAnonymousReference; +import de.monticore.lang.sysmlbasis._ast.ASTSysMLTyping; import de.monticore.lang.sysmlparts.SysMLPartsMill; import de.monticore.lang.sysmlparts._ast.ASTEnumDef; import de.monticore.lang.sysmlparts._ast.ASTEnumUsage; @@ -10,7 +12,7 @@ * Enum-Literale sollen sich wie Fields verhalten. Allerdings haben die Dinger nicht immer einen Namen (auf * Lexer/Parser-Ebene). Deswegen kann man nicht einfach "EnumUsage extends Field = ..." in die Grammatik schreiben. Die * empfohlene Lösung des MC-Teams ist es die EnumUsageSymbols einfach duch FieldSymbols auszutauschen bzw. diese - * hinzuzufügen. + * hinzuzufügen. Das gleiche für AnonymousReference. */ public class ConvertEnumUsagesToFields implements SysMLPartsVisitor2 { @@ -20,21 +22,28 @@ public void visit(ASTEnumDef node) { var type = SymTypeExpressionFactory.createTypeObject(node.getName(), node.getEnclosingScope()); for(var elem: node.getSysMLElementList()) { - if(elem instanceof ASTEnumUsage) { - var usage = (ASTEnumUsage) elem; + var baseBuilder = SysMLPartsMill.fieldSymbolBuilder() + .setAstNodeAbsent() + .setIsStatic(true) + .setIsPublic(true) + .setType(type); + + if(elem instanceof ASTEnumUsage && ((ASTEnumUsage)elem).isPresentName()) { // each named enum usage behaves like a static field whose type is the enclosing def - if(usage.isPresentName()) { - var field = SysMLPartsMill.fieldSymbolBuilder() - .setAstNodeAbsent() - .setName(usage.getName()) - .setIsStatic(true) - .setType(type) - .build(); - node.getSpannedScope().add(field); - } + baseBuilder.setName(((ASTEnumUsage)elem).getName()); + node.getSpannedScope().add(baseBuilder.build()); + } + else if (elem instanceof ASTAnonymousReference && + ((ASTAnonymousReference)elem).getSpecializationList() + .stream() + .filter(spec -> spec instanceof ASTSysMLTyping) + .findAny() + .isEmpty()) { + // same for anonymous references in this context that do not have a type + // cannot use completed type because we are in the ordered ST completion phase + baseBuilder.setName(((ASTAnonymousReference) elem).getName()); + node.getSpannedScope().add(baseBuilder.build()); } } - } - } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java index 890c5be2..04fd57b2 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java @@ -31,10 +31,7 @@ public class SysMLv2Mill extends SysMLv2MillTOP { public static void prepareGlobalScope() { SysMLv2Mill.initializePrimitives(); SysMLv2Mill.addStringType(); - // Doppelt gemoppelt? - MCCollectionSymTypeRelations.init(); SysMLv2Mill.addCollectionTypes(); - OCLSymTypeRelations.init(); } /** @@ -71,7 +68,7 @@ protected void _addStringType() { var type = OOSymbolsMill.oOTypeSymbolBuilder() .setName("String") - .setSpannedScope(new OOSymbolsScope()) + .setSpannedScope(scope()) .build(); SysMLv2Mill.globalScope().add(type); @@ -80,14 +77,14 @@ protected void _addStringType() { protected OOTypeSymbol buildOptionalType() { var typeVar = BasicSymbolsMill.typeVarSymbolBuilder().setName("T").build(); - var spannedScope = new OOSymbolsScope(); + var spannedScope = scope(); spannedScope.add(typeVar); spannedScope.add( SysMLv2Mill.functionSymbolBuilder() .setName("get") .setType(SymTypeExpressionFactory.createTypeVariable(typeVar)) - .setSpannedScope(new BasicSymbolsScope()) + .setSpannedScope(scope()) .build() ); @@ -123,7 +120,7 @@ protected void _addStreamType() { protected OOTypeSymbol buildStreamType() { var typeVar = BasicSymbolsMill.typeVarSymbolBuilder().setName("E").build(); - var spannedScope = new OOSymbolsScope(); + var spannedScope = scope(); spannedScope.add(typeVar); spannedScope.add(buildSnthFunction(typeVar)); spannedScope.add(buildLengthFunction()); @@ -175,7 +172,7 @@ protected void _addCollectionTypes() { } protected OOTypeSymbol buildCollectionType(String name, String... typeVars) { - var spannedScope = new OOSymbolsScope(); + var spannedScope = scope(); Arrays .stream(typeVars) @@ -200,7 +197,7 @@ protected SymTypePrimitive buildNatType() { } protected FunctionSymbol buildSnthFunction(TypeVarSymbol typeVar) { - var parameterList = new BasicSymbolsScope(); + var parameterList = scope(); VariableSymbol parameter = SysMLv2Mill.variableSymbolBuilder().setName( "n").setType(buildIntType()).build(); @@ -221,7 +218,7 @@ protected FunctionSymbol buildLengthFunction() { return SysMLv2Mill.functionSymbolBuilder() .setName("length") .setType(buildIntType()) - .setSpannedScope(new BasicSymbolsScope()) + .setSpannedScope(scope()) .build(); } @@ -229,7 +226,7 @@ protected FunctionSymbol buildCountFunction() { return SysMLv2Mill.functionSymbolBuilder() .setName("count") .setType(buildIntType()) - .setSpannedScope(new BasicSymbolsScope()) + .setSpannedScope(scope()) .build(); } @@ -237,7 +234,7 @@ protected FunctionSymbol buildHeadFunction(TypeVarSymbol typeVar) { return SysMLv2Mill.functionSymbolBuilder() .setName("head") .setType(SymTypeExpressionFactory.createTypeVariable(typeVar)) - .setSpannedScope(new BasicSymbolsScope()) + .setSpannedScope(scope()) .build(); } @@ -249,13 +246,13 @@ protected FunctionSymbol buildTailFunction(TypeSymbol listSymbol, listSymbol, SymTypeExpressionFactory.createTypeVariable(typeVar)) ) - .setSpannedScope(new BasicSymbolsScope()) + .setSpannedScope(scope()) .build(); } protected FunctionSymbol buildAppendFunction(TypeSymbol listSymbol, TypeVarSymbol typeVar) { - var scope = new BasicSymbolsScope(); + var scope = scope(); scope.add(SysMLv2Mill.variableSymbolBuilder() .setName("xs") .setType(SymTypeExpressionFactory.createGenerics( @@ -281,12 +278,12 @@ protected FunctionSymbol buildValuesFunction(TypeVarSymbol typeVar) { listSymbol, SymTypeExpressionFactory.createTypeVariable(typeVar)) ) - .setSpannedScope(new BasicSymbolsScope()) + .setSpannedScope(scope()) .build(); } protected FunctionSymbol buildTimesFunction(TypeSymbol streamSymbol, TypeVarSymbol typeVar) { - var parameterList = new BasicSymbolsScope(); + var parameterList = scope(); VariableSymbol parameter = SysMLv2Mill.variableSymbolBuilder().setName( "k").setType(buildNatType()).build(); @@ -304,7 +301,7 @@ protected FunctionSymbol buildTimesFunction(TypeSymbol streamSymbol, TypeVarSymb protected FunctionSymbol buildAtTimeFunction(TypeSymbol streamSymbol, TypeVarSymbol typeVar) { - var scope = new BasicSymbolsScope(); + var scope = scope(); scope.add(SysMLv2Mill.variableSymbolBuilder() .setName("t") .setType(buildNatType()) @@ -328,12 +325,12 @@ protected FunctionSymbol buildMessagesFunction(TypeSymbol streamSymbol, streamSymbol, SymTypeExpressionFactory.createTypeVariable(typeVar)) ) - .setSpannedScope(new BasicSymbolsScope()) + .setSpannedScope(scope()) .build(); } protected FunctionSymbol buildTakesFunction(TypeSymbol streamSymbol, TypeVarSymbol typeVar) { - var parameterList = new BasicSymbolsScope(); + var parameterList = scope(); VariableSymbol parameter = SysMLv2Mill.variableSymbolBuilder() .setName("k") @@ -356,7 +353,7 @@ protected FunctionSymbol buildTakesFunction(TypeSymbol streamSymbol, TypeVarSymb } protected FunctionSymbol buildInfTimesFunction(TypeSymbol streamSymbol, TypeVarSymbol typeVar) { - var parameterList = new BasicSymbolsScope(); + var parameterList = scope(); parameterList.add(typeVar); var returnType = SymTypeExpressionFactory.createGenerics( 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 df9e98ae..bb49c544 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -24,7 +24,9 @@ import de.monticore.lang.sysmlv2._symboltable.SysMLv2Symbols2Json; import de.monticore.lang.sysmlv2._visitor.SysMLv2Traverser; import de.monticore.lang.sysmlv2.cocos.AssignActionTypeCheck; +import de.monticore.lang.sysmlv2.cocos.AssignActionTypeCheck3; import de.monticore.lang.sysmlv2.cocos.ConstraintIsBoolean; +import de.monticore.lang.sysmlv2.cocos.ConstraintIsBooleanTC3; import de.monticore.lang.sysmlv2.cocos.FlowCheckCoCo; import de.monticore.lang.sysmlv2.cocos.NameCompatible4Isabelle; import de.monticore.lang.sysmlv2.cocos.OneCardinality; @@ -32,9 +34,12 @@ import de.monticore.lang.sysmlv2.cocos.PortDefinitionExistsCoCo; import de.monticore.lang.sysmlv2.cocos.RefinementCyclic; import de.monticore.lang.sysmlv2.cocos.SendActionTypeCheck; +import de.monticore.lang.sysmlv2.cocos.SendActionTypeCheck3; import de.monticore.lang.sysmlv2.cocos.SpecializationExists; +import de.monticore.lang.sysmlv2.cocos.SpecializationExistsTC3; import de.monticore.lang.sysmlv2.cocos.StateSupertypes; import de.monticore.lang.sysmlv2.cocos.TypeCheckTransitionGuards; +import de.monticore.lang.sysmlv2.cocos.TypeCheck3TransitionGuards; import de.monticore.lang.sysmlv2.cocos.WarnNonExhibited; import de.monticore.lang.sysmlv2.symboltable.completers.CausalityCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectRefinementCompleter; @@ -46,6 +51,7 @@ import de.monticore.lang.sysmlv2.symboltable.completers.TypesCompleter; import de.monticore.lang.sysmlv2.types.SysMLDeriver; import de.monticore.lang.sysmlv2.types.SysMLSynthesizer; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; import de.monticore.ocl.oclexpressions.symboltable.OCLExpressionsSymbolTableCompleter; import de.monticore.prettyprint.IndentPrinter; import de.monticore.symbols.oosymbols._symboltable.MethodSymbolDeSer; @@ -79,6 +85,7 @@ public void init() { SysMLv2Mill.globalScope().clear(); SysMLv2Mill.prepareGlobalScope(); loadStreamSymbolsFromJar(); + SysMLTypeCheck3.init(); } @Override @@ -105,6 +112,10 @@ public void runDefaultCoCos(ASTSysMLModel ast) { checker.addCoCo(new TypeCheckTransitionGuards()); checker.addCoCo(new SendActionTypeCheck()); checker.addCoCo(new AssignActionTypeCheck()); + // TC3 + checker.addCoCo(new SendActionTypeCheck3()); + checker.addCoCo(new AssignActionTypeCheck3()); + checker.addCoCo(new TypeCheck3TransitionGuards()); checker.checkAll(ast); } @@ -118,7 +129,9 @@ public void runAdditionalCoCos( // general checker.addCoCo(new ConstraintIsBoolean()); + checker.addCoCo(new ConstraintIsBooleanTC3()); checker.addCoCo(new SpecializationExists()); + checker.addCoCo(new SpecializationExistsTC3()); // Not-supported language elements checker.addCoCo(new NoExitActions()); 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 f69d3650..e688cbc9 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 @@ -40,6 +40,7 @@ import de.se_rwth.commons.Names; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; @@ -280,11 +281,33 @@ default List resolveAdaptedMildPortLocallyMany( // Splitten von Namen - oder ob man irgendwie // nach vollqualifizierten Sachen suchen kann (und vielleicht auch erst // danach schaut, was es war)? + String delimiter; if (name.contains(".")) { - var port = name.split("\\.")[0]; + delimiter = "."; + } + else if (name.contains("::")) { + delimiter = "::"; + } + else { + delimiter = null; + } + + if (delimiter != null) { + List parts = new ArrayList<>(); + int pos = 0; + int idx; + while ((idx = name.indexOf(delimiter, pos)) != -1) { + parts.add(name.substring(pos, idx)); + pos = idx + delimiter.length(); + } + parts.add(name.substring(pos)); + String[] nameParts = parts.toArray(new String[0]); + + // usage could be fully qualified + var port = String.join(delimiter, Arrays.copyOfRange(nameParts, 0, nameParts.length - 1)); var portUsage = resolvePortUsageLocally(port); if (portUsage.isPresent()) { - var attr = name.split("\\.")[1]; + var attr = nameParts[nameParts.length -1]; var input = portUsage.get().getInputAttributes().stream().filter( a -> a.getName().equals(attr)).findFirst(); var output = portUsage.get().getOutputAttributes().stream().filter( diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java index 97ac6265..470c7e66 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java @@ -7,6 +7,7 @@ import de.monticore.lang.sysmlv2.types.SysMLDeriver; import de.monticore.types.check.TypeCheck; +@Deprecated public class AssignActionTypeCheck implements SysMLActionsASTAssignmentActionUsageCoCo { @Override diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck3.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck3.java new file mode 100644 index 00000000..0e4184ca --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck3.java @@ -0,0 +1,22 @@ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlactions._ast.ASTAssignmentActionUsage; +import de.monticore.lang.sysmlactions._cocos.SysMLActionsASTAssignmentActionUsageCoCo; +import de.monticore.types.check.TypeCheck; +import de.monticore.types3.TypeCheck3; + +public class AssignActionTypeCheck3 implements SysMLActionsASTAssignmentActionUsageCoCo { + + @Override + public void check(ASTAssignmentActionUsage node) { + // Wir gehen davon aus, dass Send-Actions die Kanäle auf Ports nicht als Strom, + // sondern Element-Weise (i.e. Event-basiert) verarbeiten + + var type = TypeCheck3.typeOf(node.getValueExpression()); + if(type.isObscureType()) { + // Error should already be logged? + } + // Vergleich zum Target steht noch aus. + // TODO Target zur Expression erheben (Grammatik ändenr), Checken, dann vergleichen + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java index 1d996e27..da64dfc0 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java @@ -10,6 +10,7 @@ import de.se_rwth.commons.SourcePositionBuilder; import de.se_rwth.commons.logging.Log; +@Deprecated public class ConstraintIsBoolean implements SysMLConstraintsASTConstraintUsageCoCo { @Override public void check(ASTConstraintUsage node) { diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBooleanTC3.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBooleanTC3.java new file mode 100644 index 00000000..1528b02a --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBooleanTC3.java @@ -0,0 +1,41 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.expressions.expressionsbasis._ast.ASTExpression; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlconstraints._cocos.SysMLConstraintsASTConstraintUsageCoCo; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types3.TypeCheck3; +import de.se_rwth.commons.SourcePosition; +import de.se_rwth.commons.SourcePositionBuilder; +import de.se_rwth.commons.logging.Log; + +public class ConstraintIsBooleanTC3 implements SysMLConstraintsASTConstraintUsageCoCo { + + @Override public void check(ASTConstraintUsage node) { + // Expression ausgraben + ASTExpression expr = node.getExpression(); + + try { + SymTypeExpression type = TypeCheck3.typeOf(expr); + if(type.isObscureType()) { + var start = node.get_SourcePositionStart(); + var end = constraintEnd(start); + Log.error("0x80001 Failed to derive a type!", start, end); + } + else if(!type.printFullName().equals("boolean")) { + Log.error("0x80002 The expression type is '" + type.printFullName() + "' but should be boolean!", expr.get_SourcePositionStart(), expr.get_SourcePositionEnd()); + } + } + catch (Exception e) { + var start = node.get_SourcePositionStart(); + var end = constraintEnd(start); + Log.error("0x80003 " + e.getClass().getSimpleName() + " while type checking!", start, end); + } + } + + private SourcePosition constraintEnd(SourcePosition start) { + return new SourcePositionBuilder().setFileName(start.getFileName().get()).setLine(start.getLine()).setColumn( + start.getColumn() + 11).build(); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java index bbf0d636..25803f74 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java @@ -4,6 +4,7 @@ import de.monticore.lang.sysmlactions._cocos.SysMLActionsASTSendActionUsageCoCo; import de.monticore.lang.sysmlv2.types.SysMLDeriver; +@Deprecated public class SendActionTypeCheck implements SysMLActionsASTSendActionUsageCoCo { @Override diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck3.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck3.java new file mode 100644 index 00000000..03562cb2 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck3.java @@ -0,0 +1,21 @@ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlactions._ast.ASTSendActionUsage; +import de.monticore.lang.sysmlactions._cocos.SysMLActionsASTSendActionUsageCoCo; +import de.monticore.types3.TypeCheck3; + +public class SendActionTypeCheck3 implements SysMLActionsASTSendActionUsageCoCo { + + @Override + public void check(ASTSendActionUsage node) { + // Wir gehen davon aus, dass Send-Actions die Kanäle auf Ports nicht als Strom, + // sondern Element-Weise (i.e. Event-basiert) verarbeiten + + var payloadType = TypeCheck3.typeOf(node.getPayload()); + if(payloadType.isObscureType()) { + // Error should already be logged? + } + // Vergleich zum Target steht noch aus. + // TODO Target zur Expression erheben (Grammatik ändenr), Checken, dann vergleichen + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java index 1876f560..eabc1000 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java @@ -7,6 +7,7 @@ import de.monticore.lang.sysmlv2.types.SysMLSynthesizer; import de.se_rwth.commons.logging.Log; +@Deprecated public class SpecializationExists implements SysMLBasisASTSpecializationCoCo { @Override diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExistsTC3.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExistsTC3.java new file mode 100644 index 00000000..4a48a70b --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExistsTC3.java @@ -0,0 +1,22 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlbasis._ast.ASTSpecialization; +import de.monticore.lang.sysmlbasis._cocos.SysMLBasisASTSpecializationCoCo; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; +import de.monticore.types3.TypeCheck3; + +public class SpecializationExistsTC3 implements SysMLBasisASTSpecializationCoCo { + + @Override + public void check(ASTSpecialization node) { + if (node.getEnclosingScope() instanceof ISysMLv2Scope) { + // We synthesize the SymType from ASTs + for(var typeAst : node.getSuperTypesList()) { + // This will throw an 0xA0324 if the type does not exist. + TypeCheck3.symTypeFromAST(typeAst); + } + } + } + +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheck3TransitionGuards.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheck3TransitionGuards.java new file mode 100644 index 00000000..17a2e5f6 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheck3TransitionGuards.java @@ -0,0 +1,39 @@ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.expressions.expressionsbasis._ast.ASTExpression; +import de.monticore.lang.sysmlstates._ast.ASTSysMLTransition; +import de.monticore.lang.sysmlstates._cocos.SysMLStatesASTSysMLTransitionCoCo; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types3.TypeCheck3; +import de.se_rwth.commons.logging.Log; + +public class TypeCheck3TransitionGuards implements SysMLStatesASTSysMLTransitionCoCo { + + @Override + public void check(ASTSysMLTransition node) { + if(node.isPresentGuard()) { + // Expression ausgraben + ASTExpression expr = node.getGuard(); + + try { + SymTypeExpression type = TypeCheck3.typeOf(expr); + if(type.isObscureType()) { + Log.error("0x80004 Failed to derive a type!", + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd()); + } + else if(!type.isPrimitive() || !type.asPrimitive().getPrimitiveName().equals("boolean")) { + Log.error("0x80005 The expression type is '" + type.printFullName() + "' but should be boolean!", + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd()); + } + } + catch (Exception e) { + Log.error("0x80006 " + e.getClass().getSimpleName() + " while type checking!", + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd()); + } + } + } + +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java index 94780546..15a4f6e5 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java @@ -7,6 +7,7 @@ import de.monticore.types.check.TypeCheckResult; import de.se_rwth.commons.logging.Log; +@Deprecated public class TypeCheckTransitionGuards implements SysMLStatesASTSysMLTransitionCoCo { @Override diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/ConfigurationWrapper.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/ConfigurationWrapper.java index c35ce86b..e6a0bcda 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/ConfigurationWrapper.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/ConfigurationWrapper.java @@ -16,7 +16,6 @@ import de.monticore.lang.sysmlv2._prettyprint.SysMLv2FullPrettyPrinter; import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; import de.monticore.lang.sysmlactions.visitors.SendActionAssignmentsVisitor; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; import de.monticore.literals.mccommonliterals._symboltable.IMCCommonLiteralsScope; import de.monticore.literals.mcliteralsbasis._symboltable.IMCLiteralsBasisScope; import de.monticore.mcbasics._symboltable.IMCBasicsScope; @@ -24,6 +23,7 @@ import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; import de.monticore.symbols.compsymbols._symboltable.ICompSymbolsScope; import de.monticore.types.mcbasictypes._symboltable.IMCBasicTypesScope; +import de.monticore.types3.TypeCheck3; import de.se_rwth.commons.SourcePosition; import java.util.Collection; @@ -82,8 +82,7 @@ public ConfigurationWrapper( // Wenn der Automat generell Listen senden kann, zB. eine Event- // Automat, dann wird der Typ des Values angeschaut und // entschieden, ob der Output "isListValue" gesetzt bekommt - var typeOfValue = new SysMLDeriver(false) - .deriveType(value).getResult(); + var typeOfValue = TypeCheck3.typeOf(value); if(typeOfValue.printFullName().contains("List")) { isListValue = true; } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/OutputWrapper.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/OutputWrapper.java index 1762ebca..d8fc1083 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/OutputWrapper.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/OutputWrapper.java @@ -11,7 +11,6 @@ import de.monticore.lang.componentconnector._visitor.ComponentConnectorTraverser; import de.monticore.lang.sysmlv2._symboltable.ISysMLv2GlobalScope; import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; import de.monticore.literals.mccommonliterals._symboltable.IMCCommonLiteralsScope; import de.monticore.literals.mcliteralsbasis._symboltable.IMCLiteralsBasisScope; import de.monticore.mcbasics._symboltable.IMCBasicsScope; diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java index 3c3f588c..0c1f1baa 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java @@ -1,16 +1,19 @@ /* (c) https://github.com/MontiCore/monticore */ package de.monticore.lang.sysmlv2.symboltable.completers; +import de.monticore.lang.sysmlbasis._ast.ASTAnonymousReference; import de.monticore.lang.sysmlbasis._ast.ASTAnonymousUsage; import de.monticore.lang.sysmlbasis._ast.ASTSpecialization; import de.monticore.lang.sysmlbasis._ast.ASTSysMLParameter; import de.monticore.lang.sysmlbasis._ast.ASTSysMLTyping; +import de.monticore.lang.sysmlbasis._symboltable.AnonymousReferenceSymbol; import de.monticore.lang.sysmlbasis._symboltable.AnonymousUsageSymbol; import de.monticore.lang.sysmlbasis._visitor.SysMLBasisVisitor2; import de.monticore.lang.sysmlconstraints._ast.ASTRequirementSubject; import de.monticore.lang.sysmlconstraints._symboltable.RequirementSubjectSymbol; import de.monticore.lang.sysmlconstraints._visitor.SysMLConstraintsVisitor2; import de.monticore.lang.sysmlparts._ast.ASTAttributeUsage; +import de.monticore.lang.sysmlparts._ast.ASTEnumDef; import de.monticore.lang.sysmlparts._ast.ASTPartUsage; import de.monticore.lang.sysmlparts._ast.ASTPortUsage; import de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol; @@ -18,6 +21,7 @@ import de.monticore.lang.sysmlparts._visitor.SysMLPartsVisitor2; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symboltable.modifiers.BasicAccessModifier; import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionFactory; import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType; @@ -51,7 +55,12 @@ private List getTypeCompletion(List specia (IBasicSymbolsScope) mcType.getEnclosingScope()); } else if(mcType.getDefiningSymbol().isPresent() && mcType.getDefiningSymbol().get() instanceof TypeSymbol) { - res = SymTypeExpressionFactory.createTypeExpression((TypeSymbol) mcType.getDefiningSymbol().get()); + // hacky setup such that nat remains a primitive + if (mcType.getDefiningSymbol().get().getName().equals("nat")) { + res = SymTypeExpressionFactory.createPrimitive((TypeSymbol) mcType.getDefiningSymbol().get()); + } else { + res = SymTypeExpressionFactory.createTypeExpression((TypeSymbol) mcType.getDefiningSymbol().get()); + } } else if(mcType.getDefiningSymbol().isEmpty()) { Log.warn("Defining symbol for " + mcType.printType() + " was not set."); @@ -120,6 +129,8 @@ public void visit(ASTAttributeUsage node) { // type List types = getTypeCompletion(node.getSpecializationList(), false); + symbol.setAccessModifier(BasicAccessModifier.ALL_INCLUSION); + symbol.setTypesList(types); } } @@ -144,4 +155,12 @@ public void visit(ASTRequirementSubject node) { } } + @Override + public void visit(ASTAnonymousReference node) { + if(node.isPresentSymbol()) { + AnonymousReferenceSymbol symbol = node.getSymbol(); + List types = getTypeCompletion(node.getSpecializationList(), false); + symbol.setTypesList(types); + } + } } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriveSymTypeOfStreamExpressions.java b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriveSymTypeOfStreamExpressions.java index f2ba75b4..bc7ccb9c 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriveSymTypeOfStreamExpressions.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriveSymTypeOfStreamExpressions.java @@ -13,6 +13,7 @@ import java.util.List; +@Deprecated public class SysMLDeriveSymTypeOfStreamExpressions extends AbstractDeriveFromExpression implements StreamExpressionsVisitor2, StreamExpressionsHandler { diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriver.java b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriver.java index 1f90e20c..e59805cf 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriver.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLDeriver.java @@ -13,6 +13,7 @@ import de.monticore.types.check.DeriveSymTypeOfMCCommonLiterals; import de.monticore.types.check.SynthesizeSymTypeFromMCBasicTypes; +@Deprecated public class SysMLDeriver extends AbstractDerive { /** *

{@code isStream} is used to determine whether the type of the expression is calculated as a Stream, diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLExressionsDeriver.java b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLExressionsDeriver.java index b4aaaca1..db209532 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLExressionsDeriver.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLExressionsDeriver.java @@ -13,6 +13,7 @@ import de.monticore.types.check.TypeCheckResult; import de.se_rwth.commons.logging.Log; +@Deprecated public class SysMLExressionsDeriver extends AbstractDeriveFromExpression implements SysMLExpressionsVisitor2, SysMLExpressionsHandler { diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLSynthesizer.java b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLSynthesizer.java index 67b34988..c49bc594 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLSynthesizer.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLSynthesizer.java @@ -8,6 +8,7 @@ import de.monticore.types.check.SynthesizeSymTypeFromMCCollectionTypes; import de.monticore.types.check.SynthesizeSymTypeFromMCSimpleGenericTypes; +@Deprecated public class SysMLSynthesizer extends AbstractSynthesize { public SysMLSynthesizer() { diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java index 3fb2d1a3..2cbd75bb 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java @@ -32,6 +32,7 @@ *

In SysMLv2, the expression in StateUsage is not type of Stream. * Rewrite method {@link #calculateFieldAccess(ASTFieldAccessExpression, boolean)} for this purpose.

*/ +@Deprecated public class SysMLv2DeriveSymTypeOfCommonExpressions extends DeriveSymTypeOfCommonExpressions { /** * @see SysMLDeriver#isStream diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLCommonExpressionsTypeVisitor.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLCommonExpressionsTypeVisitor.java new file mode 100644 index 00000000..f7071ddf --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLCommonExpressionsTypeVisitor.java @@ -0,0 +1,326 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.expressions.commonexpressions._ast.ASTArrayAccessExpression; +import de.monticore.expressions.commonexpressions._ast.ASTFieldAccessExpression; +import de.monticore.expressions.commonexpressions._ast.ASTFieldAccessExpressionBuilder; +import de.monticore.expressions.commonexpressions._ast.ASTLogicalNotExpression; +import de.monticore.expressions.commonexpressions._symboltable.ICommonExpressionsScope; +import de.monticore.expressions.commonexpressions._visitor.CommonExpressionsTraverser; +import de.monticore.expressions.commonexpressions.types3.CommonExpressionsTypeVisitor; +import de.monticore.expressions.expressionsbasis._ast.ASTExpression; +import de.monticore.expressions.expressionsbasis._ast.ASTNameExpression; +import de.monticore.lang.componentconnector.StreamTimingUtil; +import de.monticore.lang.componentconnector._symboltable.IComponentConnectorScope; +import de.monticore.lang.sysmlactions._ast.ASTAssignmentActionUsage; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlexpressions._ast.ASTConditionalNotExpression; +import de.monticore.lang.sysmlexpressions._ast.ASTInfinity; +import de.monticore.lang.sysmlexpressions._ast.ASTSubsetEquationExpression; +import de.monticore.lang.sysmlexpressions._ast.ASTSubsetExpression; +import de.monticore.lang.sysmlexpressions._ast.ASTSupersetEquationExpression; +import de.monticore.lang.sysmlexpressions._ast.ASTSupersetExpression; +import de.monticore.lang.sysmlexpressions._ast.ASTSysMLFieldAccessExpression; +import de.monticore.lang.sysmlexpressions._ast.ASTSysMLInstantiation; +import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsHandler; +import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsTraverser; +import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsVisitor2; +import de.monticore.lang.sysmlparts._ast.ASTPartDef; +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlparts._symboltable.ISysMLPartsScope; +import de.monticore.lang.sysmlparts._symboltable.PartDefSymbol; +import de.monticore.lang.sysmlparts._symboltable.PartUsageSymbol; +import de.monticore.lang.sysmlparts._symboltable.PortDefSymbol; +import de.monticore.lang.sysmlstates._ast.ASTStateDef; +import de.monticore.lang.sysmlstates._ast.ASTStateUsage; +import de.monticore.lang.sysmlstates._symboltable.StateDefSymbol; +import de.monticore.lang.sysmlstates._symboltable.StateUsageSymbol; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2ArtifactScope; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2GlobalScope; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; +import de.monticore.ocl.setexpressions._ast.ASTSetNotInExpression; +import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.symbols.basicsymbols._symboltable.FunctionSymbol; +import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; +import de.monticore.symbols.compsymbols._symboltable.PortSymbol; +import de.monticore.symboltable.modifiers.AccessModifier; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import de.monticore.types.check.SymTypeOfFunction; +import de.monticore.types.mcbasictypes._ast.ASTMCType; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types3.SymTypeRelations; +import de.monticore.types3.util.TypeContextCalculator; +import de.monticore.types3.util.TypeVisitorLifting; +import de.monticore.types3.util.TypeVisitorOperatorCalculator; +import de.monticore.types3.util.WithinScopeBasicSymbolsResolver; +import de.monticore.types3.util.WithinTypeBasicSymbolsResolver; +import de.se_rwth.commons.logging.Log; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; + +import static de.monticore.types.check.SymTypeExpressionFactory.createObscureType; + +/** + * Handles type checking the sysmlv2 standard and the particularities of the spes + * language profile regarding streams in expressions. + * 1. Ports in specifications have implicit stream types and are injected in the + * type check at field access derivation and at name expression derivation. + * Also implements the following design decisions using two modes: + * Mode 1: TypeCheck interprets an Expression for a port usage as an implicit + * field access if there is only one attribute inside. Explicit field accesses + * are still supported by ignoring the field access if its type correct. + * Mode 2: TypeCheck finds multiple attributes, and thus multiple channels and + * reverts to the standard (with streams) TypeCheck without implicit field accesses. + */ +public class SysMLCommonExpressionsTypeVisitor extends CommonExpressionsTypeVisitor implements + SysMLExpressionsVisitor2, SysMLExpressionsHandler { + + protected SysMLExpressionsTraverser traverser; + + @Override + public SysMLExpressionsTraverser getTraverser() { + return traverser; + } + + @Override + public void setTraverser(SysMLExpressionsTraverser traverser) { + this.traverser = traverser; + } + + @Override + public void endVisit(ASTConditionalNotExpression expr) { + SymTypeExpression inner = + getType4Ast().getPartialTypeOfExpr(expr.getExpression()); + SymTypeExpression result = getTypeForPrefixOrLogError( + "0xB0165", expr, "not", + SysMLTypeVisitorOperatorCalculator.conditionalNot(inner), inner + ); + getType4Ast().setTypeOfExpression(expr, result); + } + + @Override + public void endVisit(ASTInfinity node) { + // backwards compatibility + getType4Ast().setTypeOfExpression(node, SymTypeExpressionFactory.createPrimitive("int")); + } + + @Override + public void endVisit(ASTSysMLFieldAccessExpression node) { + // does not work with inheritance traverser because this is the handler and + endVisit((ASTFieldAccessExpression) node); + } + + @Override + public void traverse(ASTSysMLFieldAccessExpression node) { + traverse((ASTFieldAccessExpression) node); + } + + @Override + protected Optional calculateExprFieldAccess( + ASTFieldAccessExpression expr, + boolean resultsAreOptional) { + Optional type; + final String name = expr.getName(); + if (!getType4Ast().hasTypeOfExpression(expr.getExpression())) { + Log.error("0xFD231 internal error:" + + "unable to find type identifier for field access", + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd() + ); + type = Optional.empty(); + } + else { + SymTypeExpression innerAsExprType = + getType4Ast().getPartialTypeOfExpr(expr.getExpression()); + + //++++++++++ modify start here ++++++++++ + + Optional optPort = Optional.empty(); + if (expr.getExpression() instanceof ASTArrayAccessExpression) { + optPort = ((IComponentConnectorScope) expr.getEnclosingScope()).resolvePort(SysMLv2Mill.prettyPrint( + new ASTFieldAccessExpressionBuilder() + .setExpression(((ASTArrayAccessExpression)expr.getExpression()).getExpression()) + .setName(name) + .build(), + false)); + } else if (expr.getExpression() instanceof ASTNameExpression) { + optPort = ((IComponentConnectorScope) expr.getEnclosingScope()).resolvePort(SysMLv2Mill.prettyPrint(expr, false)); + } + + var innerTypeIsPortDef = innerAsExprType.hasTypeInfo() && + innerAsExprType + .getTypeInfo() + .getSpannedScope() + .getSpanningSymbol() instanceof PortDefSymbol + || innerAsExprType.isArrayType() && + innerAsExprType + .asArrayType() + .getArgument() + .getTypeInfo() + .getSpannedScope() + .getSpanningSymbol() instanceof PortDefSymbol; + + // If no C&C port was found OR the inner expression refers to a port definition + if (optPort.isEmpty() || innerTypeIsPortDef) { + + // Case 1: This is not an implicit field access, we still have to compute it. + // Fall back to the default field access computation + if (WithinTypeBasicSymbolsResolver.canResolveIn(innerAsExprType)) { + AccessModifier modifier = innerAsExprType.hasTypeInfo() ? + TypeContextCalculator.getAccessModifier( + innerAsExprType.getTypeInfo(), expr.getEnclosingScope() + ) : + AccessModifier.ALL_INCLUSION; + + type = resolveVariablesAndFunctionsWithinType( + innerAsExprType, + name, + modifier, + v -> true, + f -> true + ); + + // We can only check if we are not in an automata as state machines always define a scope + if (type.isPresent() && + !type.get().isFunctionType() && + !SysMLWithinScopeBasicSymbolResolver.isDefinedInStateMachine( + getAsBasicSymbolsScope(expr.getEnclosingScope())) && + optPort.isPresent()) { + // found a C&C port -> Adjust type to Stream + var streamType = WithinScopeBasicSymbolsResolver.resolveType( + getAsBasicSymbolsScope(expr.getEnclosingScope()), + StreamTimingUtil.mapTimingToStreamType( + optPort.get().getTiming())); + + if (streamType.isEmpty()) { + Log.error("tried to resolve \"" + name + "\"" + + " given expression of type " + + innerAsExprType.printFullName() + + " but no stream symbol could be resolved.", + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd() + ); + } + else { + streamType.get().asGenericType().setArgument(0, type.get()); + } + + type = streamType; + } + + //++++++++++ modify end here ++++++++++ + + // Log remark about access modifier, + // if access modifier is the reason it has not been resolved + if (type.isEmpty() && !resultsAreOptional) { + Optional potentialResult = + resolveVariablesAndFunctionsWithinType( + innerAsExprType, + name, + AccessModifier.ALL_INCLUSION, + v -> true, + f -> true + ); + if (potentialResult.isPresent()) { + Log.warn("tried to resolve \"" + name + "\"" + + " given expression of type " + + innerAsExprType.printFullName() + + " and symbols have been found" + + ", but due to the access modifiers (e.g., public)" + + ", nothing could be resolved", + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd() + ); + } + } + } + // extension point + else { + Log.error("0xFDB3A unexpected field access \"" + + expr.getName() + + "\" for type " + + innerAsExprType.printFullName(), + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd() + ); + type = Optional.empty(); + } + } + else { + // Case 2: this is an explicit FA and the type of the inner expression is forwarded + // to the outer expression as it was already computed in a previous step + type = Optional.of(innerAsExprType); + } + } + return type; + } + + @Override + public void endVisit(ASTSubsetExpression expr) { + SymTypeExpression left = getType4Ast().getPartialTypeOfExpr(expr.getLeft()); + SymTypeExpression right = getType4Ast().getPartialTypeOfExpr(expr.getRight()); + + SymTypeExpression result = + TypeVisitorLifting.liftDefault( + this::calculateSubsetExpression) + .apply(left, right); + getType4Ast().setTypeOfExpression(expr, result); + } + + @Override + public void endVisit(ASTSubsetEquationExpression expr) { + SymTypeExpression left = getType4Ast().getPartialTypeOfExpr(expr.getLeft()); + SymTypeExpression right = getType4Ast().getPartialTypeOfExpr(expr.getRight()); + + SymTypeExpression result = + TypeVisitorLifting.liftDefault( + this::calculateSubsetExpression) + .apply(left, right); + getType4Ast().setTypeOfExpression(expr, result); + } + + @Override + public void endVisit(ASTSupersetExpression expr) { + SymTypeExpression left = getType4Ast().getPartialTypeOfExpr(expr.getLeft()); + SymTypeExpression right = getType4Ast().getPartialTypeOfExpr(expr.getRight()); + + SymTypeExpression result = + TypeVisitorLifting.liftDefault( + this::calculateSubsetExpression) + .apply(left, right); + getType4Ast().setTypeOfExpression(expr, result); + } + + @Override + public void endVisit(ASTSupersetEquationExpression expr) { + SymTypeExpression left = getType4Ast().getPartialTypeOfExpr(expr.getLeft()); + SymTypeExpression right = getType4Ast().getPartialTypeOfExpr(expr.getRight()); + + SymTypeExpression result = + TypeVisitorLifting.liftDefault( + this::calculateSubsetExpression) + .apply(left, right); + getType4Ast().setTypeOfExpression(expr, result); + } + + protected SymTypeExpression calculateSubsetExpression( + SymTypeExpression left, SymTypeExpression right) { + + if (SymTypeRelations.isCompatible(left, right) && MCCollectionSymTypeRelations.isSet(left)) { + return SymTypeExpressionFactory.createPrimitive(BasicSymbolsMill.BOOLEAN); + } + return SymTypeExpressionFactory.createObscureType(); + } + + @Override + public void endVisit(ASTSysMLInstantiation expr) { + getType4Ast().setTypeOfExpression(expr, getType4Ast().getPartialTypeOfTypeId( + expr.getMCType())); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLMCBasicTypesTypeVisitor.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLMCBasicTypesTypeVisitor.java new file mode 100644 index 00000000..c46ce9e8 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLMCBasicTypesTypeVisitor.java @@ -0,0 +1,15 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.lang.sysmlexpressions._ast.ASTMCPrimitiveTypeWithNat; +import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsVisitor2; +import de.monticore.types.mcbasictypes._ast.ASTMCPrimitiveType; +import de.monticore.types.mcbasictypes.types3.MCBasicTypesTypeVisitor; + +public class SysMLMCBasicTypesTypeVisitor extends MCBasicTypesTypeVisitor implements + SysMLExpressionsVisitor2 { + + @Override + public void endVisit(ASTMCPrimitiveTypeWithNat node) { + endVisit((ASTMCPrimitiveType) node); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java new file mode 100644 index 00000000..00571202 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java @@ -0,0 +1,13 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.lang.sysmlexpressions._ast.ASTExistsExpression; +import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsVisitor2; +import de.monticore.ocl.oclexpressions.types3.OCLExpressionsTypeVisitor; + +public class SysMLOCLExpressionsTypeVisitor extends OCLExpressionsTypeVisitor implements + SysMLExpressionsVisitor2 { + @Override + public void endVisit(ASTExistsExpression node) { + endVisit((de.monticore.ocl.oclexpressions._ast.ASTExistsExpression) node); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSetExpressionsTypeVisitor.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSetExpressionsTypeVisitor.java new file mode 100644 index 00000000..cc366e3c --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSetExpressionsTypeVisitor.java @@ -0,0 +1,23 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.lang.sysmlexpressions._ast.ASTElementOfExpression; +import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsVisitor2; +import de.monticore.ocl.setexpressions._ast.ASTSetInExpressionBuilder; +import de.monticore.ocl.setexpressions.types3.SetExpressionsTypeVisitor; + +public class SysMLSetExpressionsTypeVisitor extends SetExpressionsTypeVisitor implements + SysMLExpressionsVisitor2 { + @Override + public void endVisit(ASTElementOfExpression node) { + var setInExpr = new ASTSetInExpressionBuilder() + .setElem(node.getLeft()) + .setSet(node.getRight()) + .set_SourcePositionStart(node.get_SourcePositionStart()) + .set_SourcePositionEnd(node.get_SourcePositionEnd()) + .build(); + + endVisit(setInExpr); + + getType4Ast().setTypeOfExpression(node, getType4Ast().getTypeOfExpression(setInExpr)); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSymTypeRelations.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSymTypeRelations.java new file mode 100644 index 00000000..97c88757 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLSymTypeRelations.java @@ -0,0 +1,28 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.ocl.types3.OCLSymTypeRelations; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types3.util.BuiltInTypeRelations; +import de.monticore.types3.util.SymTypeRelationsDefaultDelegatee; + +public abstract class SysMLSymTypeRelations extends OCLSymTypeRelations { + + public static void init() { + setDelegate(new SysMLSymTypeRelationsDelegatee()); + } + + // selecting the concrete implementations + protected static class SysMLSymTypeRelationsDelegatee extends + SymTypeRelationsDefaultDelegatee { + public SysMLSymTypeRelationsDelegatee() { + builtInRelationsDelegate = new BuiltInTypeRelations() { + @Override + public boolean isIntegralType(SymTypeExpression type) { + return super.isIntegralType(type) || + type.isPrimitive() && + type.asPrimitive().getPrimitiveName().equals("nat"); + } + }; + } + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java new file mode 100644 index 00000000..06827a24 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java @@ -0,0 +1,101 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2._visitor.SysMLv2Traverser; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.ocl.types3.OCLSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; +import de.monticore.types3.util.MapBasedTypeCheck3; +import de.monticore.visitor.ITraverser; +import de.se_rwth.commons.logging.Log; + +/** + * TypeCheck3 implementation for the SysMLv2 language. After calling {@link #init()}, this + * implementation will be available through the TypeCheck3 interface. + */ +public class SysMLTypeCheck3 extends MapBasedTypeCheck3 { + + public static void init() { + initTC3Delegate(); + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + } + + public static void reset() { + TypeCheck3.resetDelegate(); + StreamSymTypeRelations.reset(); + SysMLWithinScopeBasicSymbolResolver.reset(); + SysMLTypeVisitorOperatorCalculator.reset(); + CommonExpressionsLValueRelations.reset(); + MCCollectionSymTypeRelations.reset(); + OCLSymTypeRelations.reset(); + } + + protected static void initTC3Delegate() { + Log.trace("init SysMLTypeCheck3", "TypeCheck setup"); + + SysMLv2Traverser typeTraverser = SysMLv2Mill.inheritanceTraverser(); + Type4Ast type4Ast = new Type4Ast(); + + // Expressions + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + typeTraverser.add4SysMLExpressions(forSets); + + // MCTypes + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + // TODO are MCSimpleGenerics required? + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + // create delegate + SysMLTypeCheck3 sysmlTC3 = new SysMLTypeCheck3(typeTraverser, type4Ast); + sysmlTC3.setThisAsDelegate(); + } + + public SysMLTypeCheck3( + ITraverser typeTraverser, Type4Ast type4Ast) { + super(typeTraverser, type4Ast); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeVisitorOperatorCalculator.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeVisitorOperatorCalculator.java new file mode 100644 index 00000000..654c98d6 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeVisitorOperatorCalculator.java @@ -0,0 +1,51 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import de.monticore.types3.SymTypeRelations; +import de.monticore.types3.util.TypeVisitorLifting; +import de.monticore.types3.util.TypeVisitorOperatorCalculator; +import de.monticore.types3.util.WithinScopeBasicSymbolsResolver; +import de.se_rwth.commons.logging.Log; + +import java.util.Optional; + +public class SysMLTypeVisitorOperatorCalculator extends + TypeVisitorOperatorCalculator { + + public static void init() { + Log.trace("init SysMLTypeVisitorOperatorCalculator", "TypeCheck setup"); + setDelegate(new SysMLTypeVisitorOperatorCalculator()); + } + + @Override + protected SymTypeExpression calculateLogicalNot(SymTypeExpression inner) { + var result = super.calculateLogicalNot(inner); + if (SymTypeRelations.isBoolean(result)) { + return result; + } + // TODO resolve for Stream and deepEquals + else if (inner.hasTypeInfo() && inner.getTypeInfo().isPresentSuperClass() && + inner.getTypeInfo().getSuperClass().print().equals("Stream")) { + return inner; + } + + return SymTypeExpressionFactory.createObscureType(); + } + + public static Optional conditionalNot(SymTypeExpression inner) { + return ((SysMLTypeVisitorOperatorCalculator)getDelegate())._conditionalNot(inner); + } + + protected Optional _conditionalNot(SymTypeExpression inner) { + SymTypeExpression result = + TypeVisitorLifting.liftDefault(this::calculateConditionalNot) + .apply(inner); + return obscure2Empty(result); + } + + protected SymTypeExpression calculateConditionalNot(SymTypeExpression inner) { + return super.calculateLogicalNot(inner); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLWithinScopeBasicSymbolResolver.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLWithinScopeBasicSymbolResolver.java new file mode 100644 index 00000000..d072808b --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLWithinScopeBasicSymbolResolver.java @@ -0,0 +1,213 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.expressions.commonexpressions._symboltable.ICommonExpressionsScope; +import de.monticore.lang.componentconnector.StreamTimingUtil; +import de.monticore.lang.sysmlparts._ast.ASTPartDef; +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlparts._symboltable.PortDefSymbol; +import de.monticore.lang.sysmlstates._ast.ASTStateDef; +import de.monticore.lang.sysmlstates._ast.ASTStateUsage; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2ArtifactScope; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2GlobalScope; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; +import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symboltable.ISymbol; +import de.monticore.symboltable.modifiers.AccessModifier; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import de.monticore.types.check.SymTypeOfFunction; +import de.monticore.types.check.SymTypeSourceInfo; +import de.monticore.types3.util.TypeContextCalculator; +import de.monticore.types3.util.WithinScopeBasicSymbolsResolver; +import de.monticore.types3.util.WithinTypeBasicSymbolsResolver; +import de.se_rwth.commons.logging.Log; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + * Implements the normal and implicit field access modes for the TypeCheck. + * We determine the type of the NameExpression according to if it is a port usage, + * how many attributes it has and if it is a stream type or not. + */ +public class SysMLWithinScopeBasicSymbolResolver extends + WithinScopeBasicSymbolsResolver { + + public static void init() { + WithinScopeBasicSymbolsResolver.setDelegate(new SysMLWithinScopeBasicSymbolResolver()); + } + + @Override + protected Optional _resolveNameAsExpr( + IBasicSymbolsScope enclosingScope, String name) { + Log.errorIfNull(enclosingScope); + Log.errorIfNull(name); + // collect all (potential) types + Set types = new HashSet<>(); + + // to circumvent current shortcomings in our resolver, + // we resolve with the resolver AND resolve with the within type resolver + // afterwards we evaluate which result to use + + // not necessarily in an enclosing type + Optional optVar = + resolveVariableWithoutSuperTypes(enclosingScope, name); + + //++++++++++ modify start here ++++++++++ + + if (optVar.isPresent() && enclosingScope instanceof ISysMLv2Scope && + (optVar.get().hasTypeInfo() || + optVar.get().isArrayType() && optVar.get().asArrayType().getArgument().hasTypeInfo()) + ) { + // found var. + IBasicSymbolsScope scope; + var typeToLookIn = optVar.get(); + if (optVar.get().isArrayType()) { + scope = typeToLookIn.asArrayType().getArgument().getTypeInfo().getSpannedScope(); + typeToLookIn = typeToLookIn.asArrayType().getArgument(); + } + else { + scope = optVar.get().getTypeInfo().getSpannedScope(); + } + + var attr = ((ISysMLv2Scope) scope).getLocalAttributeUsageSymbols(); + if (attr.size() == 1 && scope.getSpanningSymbol() instanceof PortDefSymbol) { + // its an implicit field access representing a port + var actualType = WithinTypeBasicSymbolsResolver.resolveVariable( + typeToLookIn, attr.get(0).getName(), AccessModifier.ALL_INCLUSION, + v -> true); + + if (!isDefinedInStateMachine(enclosingScope)) { + // We are in stream mode + + // We have to resolve for port to determine its timing + var optPort = ((ISysMLv2Scope) enclosingScope).resolvePort(name + "." + attr.get(0).getName()); + + var streamType = WithinScopeBasicSymbolsResolver.resolveType( + enclosingScope, + StreamTimingUtil.mapTimingToStreamType( + optPort.get().getTiming())); + + if (streamType.isEmpty()) { + Log.error("0xFDA26 internal error: " + + "cannot resolve stream symbol for " + name + ". Were stream symbols loaded? " + ); + } else { + if (actualType.get().isArrayType()) { + streamType.get().asGenericType().setArgument(0, + actualType.get().asArrayType().getArgument()); + actualType.get().asArrayType().setArgument(streamType.get()); + } else { + streamType.get().asGenericType().setArgument(0, + actualType.get()); + + actualType = streamType; + } + } + } + // if present + if (optVar.get().isArrayType()) { + optVar.get().asArrayType().setArgument(actualType.get()); + } + else { + optVar = actualType; + } + } + } + + //++++++++++ modify end here ++++++++++ + + List funcs = + resolveFunctionsWithoutSuperTypes(enclosingScope, name); + // within type + Optional enclosingType = + TypeContextCalculator.getEnclosingType(enclosingScope); + Optional varInType = Optional.empty(); + List funcsInType = Collections.emptyList(); + if (enclosingType.isPresent()) { + SymTypeExpression enclosingTypeExpr = + SymTypeExpressionFactory.createFromSymbol(enclosingType.get()); + AccessModifier modifier = TypeContextCalculator + .getAccessModifier(enclosingType.get(), enclosingScope); + varInType = WithinTypeBasicSymbolsResolver.resolveVariable( + enclosingTypeExpr, name, modifier, getVariablePredicate()); + funcsInType = WithinTypeBasicSymbolsResolver.resolveFunctions( + enclosingTypeExpr, name, modifier, getFunctionPredicate()); + } + // get the correct variable + if (varInType.isPresent() && optVar.isPresent()) { + SymTypeSourceInfo varInTypeInfo = varInType.get().getSourceInfo(); + SymTypeSourceInfo optVarInfo = optVar.get().getSourceInfo(); + if (varInTypeInfo.getSourceSymbol().isPresent() && + optVarInfo.getSourceSymbol().isPresent() + ) { + ISymbol varInTypeVarSymbol = varInTypeInfo.getSourceSymbol().get(); + ISymbol optVarVarSymbol = optVarInfo.getSourceSymbol().get(); + if (optVarVarSymbol.getEnclosingScope() + .isProperSubScopeOf(varInTypeVarSymbol.getEnclosingScope()) + ) { + types.add(optVar.get()); + } + else { + types.add(varInType.get()); + } + } + else { + Log.error("0xFDA25 internal error: " + + "expected variable symbol for resolved variable " + name + ); + } + } + else if (varInType.isPresent()) { + types.add(varInType.get()); + } + else if (optVar.isPresent()) { + types.add(optVar.get()); + } + // get the correct functions + // heuristic, as we assume the resolver to be extended in the near future, + // and the correct solution would take longer to implement, + // in Javalight, these cases may never happen anyways + types.addAll(funcsInType); + for (SymTypeOfFunction func : funcs) { + if (funcsInType.stream().noneMatch(f -> f.getSymbol() == func.getSymbol())) { + types.add(func); + } + } + + if (types.size() <= 1) { + return types.stream().findAny(); + } + else { + // this can be extended to mark the intersection as + // an intersection that one has to select a type of. + // The current interpretation is, that the result is all the possible types, + // e.g. "a.b" could have the types of (int, int->int, boolean->int). + // in Java, this would be filtered out earlier, + // however, we support more (e.g. SymTypeOfFunction). + return Optional.of(SymTypeExpressionFactory.createIntersection(types)); + } + } + + protected static boolean isDefinedInStateMachine(IBasicSymbolsScope scope) { + var enclosingScope = (ISysMLv2Scope) scope; + if (enclosingScope.getAstNode() instanceof ASTStateDef || + enclosingScope.getAstNode() instanceof ASTStateUsage + ) { + return true; + } + else if (enclosingScope.getAstNode() instanceof ASTPartDef || + enclosingScope.getAstNode() instanceof ASTPartUsage || + enclosingScope instanceof ISysMLv2ArtifactScope || + enclosingScope instanceof ISysMLv2GlobalScope + ) { + return false; + } + else + return isDefinedInStateMachine(scope.getEnclosingScope()); + } +} diff --git a/language/src/test/java/cocos/ConstraintCoCoTest.java b/language/src/test/java/cocos/ConstraintCoCoTest.java index 6cd634b2..09ed9b5a 100644 --- a/language/src/test/java/cocos/ConstraintCoCoTest.java +++ b/language/src/test/java/cocos/ConstraintCoCoTest.java @@ -31,7 +31,6 @@ public class ConstraintCoCoTest { @BeforeAll public static void init() { LogStub.init(); - OCLSymTypeRelations.init(); SysMLv2Mill.init(); } @@ -49,7 +48,7 @@ public class ConstraintCoCoTest { "4_valid.sysml", // stream snth "5_valid.sysml", // port::channel-syntax with comparison //"6_valid.sysml", // port::channel-syntax with literal - //"7_valid.sysml", // INF literal + "7_valid.sysml", // INF literal "8_valid.sysml", // forall construct "9_valid.sysml", // constraint with literal //"10_valid.sysml", // attribute definition without port @@ -58,7 +57,7 @@ public class ConstraintCoCoTest { "13_valid.sysml", // OCL exists expression "14_valid.sysml", // StreamConstructor Expression "15_valid.sysml", //Times function for StreamConstructor Expression - "16_valid.sysml", //Inftimes and takes function + "16_valid.sysml", //Inftimes and takes function }) public void testValid(String modelName) throws IOException { var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); @@ -94,7 +93,7 @@ public void testValid(String modelName) throws IOException { "13_invalid.sysml", // OCL exists expression "14_invalid.sysml", // StreamConstructor Expression "15_invalid.sysml", //Times function for StreamConstructor Expression - "16_invalid.sysml", //Inftimes and takes function + "16_invalid.sysml", //Inftimes and takes function }) public void testInvalid(String modelName) throws IOException { var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); diff --git a/language/src/test/java/types3/ConstraintCoCoTest.java b/language/src/test/java/types3/ConstraintCoCoTest.java new file mode 100644 index 00000000..b033bf3e --- /dev/null +++ b/language/src/test/java/types3/ConstraintCoCoTest.java @@ -0,0 +1,202 @@ +/* (c) https://github.com/MontiCore/monticore */ +package types3; + +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +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.cocos.ConstraintIsBooleanTC3; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.ocl.types3.OCLSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.streams.StreamSymTypeRelations; +import de.monticore.types3.util.MapBasedTypeCheck3; +import de.monticore.types3.util.WithinScopeBasicSymbolsResolver; +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.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ConstraintCoCoTest { + + private static final String MODEL_PATH = "src/test/resources/cocos/constraints"; + + private SysMLv2Tool tool; + + @BeforeAll public static void init() { + LogStub.init(); + } + + @BeforeEach public void reset() { + Log.getFindings().clear(); + tool = new SysMLv2Tool(); + tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); + } + + @ParameterizedTest(name = "{index} - {0} does pass all checks w/o errors") + @ValueSource(strings = { "1_valid.sysml", + // boolean operator with literals + "2_valid.sysml", // resolve & compare ports + "3_valid.sysml", // resolve & compare channels + "4_valid.sysml", // stream snth + "5_valid.sysml", // port::channel-syntax with comparison + //"6_valid.sysml", // port::channel-syntax with literal + "7_valid.sysml", // INF literal + "8_valid.sysml", // forall construct + "9_valid.sysml", // constraint with literal + //"10_valid.sysml", // attribute definition without port + "11_valid.sysml", // stream length + "12_valid.sysml", // constraint with parameter + "13_valid.sysml", // OCL exists expression + "14_valid.sysml", // StreamConstructor Expression + "15_valid.sysml", //Times function for StreamConstructor Expression + "16_valid.sysml", //Inftimes and takes function + "17_valid.sysml", // user defined type + "18_valid.sysml", // user defined type channels + + "implicitFieldAccess/2_valid.sysml", // resolve & compare ports + "implicitFieldAccess/4_valid.sysml", // stream snth + "implicitFieldAccess/11_valid.sysml", // stream length + "implicitFieldAccess/14_valid.sysml", // StreamConstructor Expression + "implicitFieldAccess/15_valid.sysml", //Times function for StreamConstructor Expression + "implicitFieldAccess/17_valid.sysml", // user defined type + "implicitFieldAccess/18_valid.sysml", // user defined type channels + "implicitFieldAccess/19_valid.sysml", // interoperability between implicit and explicit + + }) + public void testValid(String modelName) throws IOException { + var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); + assertThat(optAst).isPresent(); + + ASTSysMLModel ast = optAst.get(); + + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new ConstraintIsBooleanTC3()); + checker.checkAll(ast); + + assertTrue(Log.getFindings().isEmpty(), () -> Log.getFindings().toString()); + } + + @ParameterizedTest(name = "{index} - {0} does pass all checks w/o errors") + @ValueSource(strings = { "1_invalid.sysml", + // boolean operator with literals + "2_invalid.sysml", // resolve & compare ports + "3_invalid.sysml", // resolve & compare channels + "4_invalid.sysml", // stream snth + "5_invalid.sysml", // port::channel-syntax with comparison + "6_invalid.sysml", // port::channel-syntax with literal + "7_invalid.sysml", // INF literal + "8_invalid.sysml", // forall construct + "9_invalid.sysml", // constraint with literal + //"10_invalid.sysml", // attribute definition without port + "11_invalid.sysml", // stream length + //"12_invalid.sysml", // constraint with parameter + "13_invalid.sysml", // OCL exists expression + "14_invalid.sysml", // StreamConstructor Expression + "15_invalid.sysml", //Times function for StreamConstructor Expression + "16_invalid.sysml", //Inftimes and takes function + "17_invalid.sysml", // user defined type + "18_invalid.sysml", // user defined type channels + + "implicitFieldAccess/2_invalid.sysml", // resolve & compare ports + "implicitFieldAccess/4_invalid.sysml", // stream snth + "implicitFieldAccess/11_invalid.sysml", // stream length + "implicitFieldAccess/14_invalid.sysml", // StreamConstructor Expression + "implicitFieldAccess/15_invalid.sysml", //Times function for StreamConstructor Expression + "implicitFieldAccess/17_invalid.sysml", // user defined type + "implicitFieldAccess/18_invalid.sysml", // user defined type channels + "implicitFieldAccess/19_invalid.sysml", // interoperability between implicit and explicit + }) + public void testInvalid(String modelName) throws IOException { + var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); + assertThat(optAst).isPresent(); + + ASTSysMLModel ast = optAst.get(); + + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new ConstraintIsBooleanTC3()); + Log.enableFailQuick(false); + checker.checkAll(ast); + assertFalse(Log.getFindings().isEmpty()); + Log.clearFindings(); + Log.enableFailQuick(true); + } +} diff --git a/language/src/test/java/types3/FieldAccessExpressionInConstraintUsageTest.java b/language/src/test/java/types3/FieldAccessExpressionInConstraintUsageTest.java new file mode 100644 index 00000000..fa96a73b --- /dev/null +++ b/language/src/test/java/types3/FieldAccessExpressionInConstraintUsageTest.java @@ -0,0 +1,157 @@ +package types3; + +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; +import de.monticore.lang.sysmlv2.types.SysMLDeriver; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; +import de.monticore.types3.util.MapBasedTypeCheck3; +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.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.IOException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FieldAccessExpressionInConstraintUsageTest { + + private final SysMLv2Parser parser = new SysMLv2Parser(); + private final SysMLv2Tool tool = new SysMLv2Tool(); + + @BeforeAll + public static void init() { + LogStub.init(); + } + + @BeforeEach + public void reset() { + Log.getFindings().clear(); + tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); + } + + @ParameterizedTest + @ValueSource(strings = { + "port def F { attribute a: boolean[2]; } part s { port f: F; constraint e { f.a[1] } }", + "port def F { attribute a: boolean; } part s { port f: F[1]; constraint e { f[1].a } }", + + "port def F { attribute a: boolean[2]; } part s { port f: F; constraint e { f[1] } }", + "port def F { attribute a: boolean; } part s { port f: F[1]; constraint e { f[1] } }" + }) public void test4ValidExpr1(String model) throws IOException { + var ast = parser.parse_String(model); + assertThat(ast).isPresent(); + var astSysMLModel = ast.get(); + + tool.createSymbolTable(astSysMLModel); + tool.completeSymbolTable(astSysMLModel); + tool.finalizeSymbolTable(astSysMLModel); + + var sysmlelements = astSysMLModel.getSysMLElementList(); + var astPartUsage = sysmlelements.get(1); + var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); + var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); + var type = TypeCheck3.typeOf(expr); + assertFalse(type.isObscureType()); + assertThat(type.printFullName()).isEqualTo("EventStream.EventStream"); + } + + @ParameterizedTest + @ValueSource(strings = { + "port def F { attribute a: boolean; } part s { port f: F[2]; constraint e { f.a } }", + "port def F { attribute a: boolean; } part s { port f: F[2]; constraint e { f } }" + }) + public void test4InvalidExpr(String model) throws IOException { + var ast = parser.parse_String(model);; + assertThat(ast).isPresent(); + var astSysMLModel = ast.get(); + + tool.createSymbolTable(astSysMLModel); + tool.completeSymbolTable(astSysMLModel); + tool.finalizeSymbolTable(astSysMLModel); + + var sysmlelements = astSysMLModel.getSysMLElementList(); + var astPartUsage = sysmlelements.get(1); + var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); + var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); + var type = TypeCheck3.typeOf(expr); + assertTrue(type.isObscureType() || + !Log.getFindings().isEmpty() || + !type.printFullName().equals("EventStream.EventStream")); + } +} + + diff --git a/language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java b/language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java new file mode 100644 index 00000000..28f5b240 --- /dev/null +++ b/language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java @@ -0,0 +1,251 @@ +package types3; + +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlparts._ast.ASTAttributeUsage; +import de.monticore.lang.sysmlparts._ast.ASTPartDef; +import de.monticore.lang.sysmlparts._ast.ASTPortDef; +import de.monticore.lang.sysmlstates._ast.ASTStateUsage; +import de.monticore.lang.sysmlstates._ast.ASTSysMLTransition; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; +import de.monticore.lang.sysmlv2.types.SysMLDeriver; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; +import de.monticore.types3.util.MapBasedTypeCheck3; +import de.se_rwth.commons.logging.Log; +import de.se_rwth.commons.logging.LogStub; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.util.stream.Stream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + *

This test is about TypeCheck3 deriving the types of FieldAccessExpressions in StateUsages.

+ * + *

When ASTFieldAccessExpression and ASTOCLArrayQualification are in StateUsage + * we test whether they are not calculated as Stream such as in constraints.

+ */ +public class FieldAccessExpressionInStateUsageTest { + + private final SysMLv2Parser parser = new SysMLv2Parser(); + private final SysMLv2Tool tool = new SysMLv2Tool(); + + @BeforeAll + public static void init() { + LogStub.init(); + } + + @BeforeEach + public void reset() { + Log.getFindings().clear(); + tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); + } + + static Stream createInputs() { + return Stream.of( + Arguments.of( + "port def F { attribute a: boolean; }" + + "part def X { port f: F; state s { transition first S if f then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; }" + + "part def X { port f: F; state s { transition first S if f[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1][1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; } part def X { port f: F; constraint e { f } }") + + + ,Arguments.of( + "port def F { attribute a: boolean; }" + + "part def X { port f: F; state s { transition first S if f.a then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; }" + + "part def X { port f: F; state s { transition first S if f.a[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; } part def X { port f: F; constraint e { f.a } }") + ,Arguments.of( + "port def F { attribute a: boolean; } part def X { port f: F[3]; constraint e { f[1].a } }") + + + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; }" + + "part def X { port f: F; state s { transition first S if f.a then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; }" + + "part def X { port f: F; state s { transition first S if f.a[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F; constraint e { f.a } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F[3]; constraint e { f[1].a } }") + ); + } + + static Stream createInvalidInputs() { + return Stream.of( + Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; }" + + "part def X { port f: F; state s { transition first S if f then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; }" + + "part def X { port f: F; state s { transition first S if f[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1][1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F; constraint e { f } }") + // TODO one field access with a stream method + ); + } + + @ParameterizedTest + @MethodSource({ "createInputs" }) + public void test(String model) throws IOException { + var ast = parser.parse_String(model); + assertThat(ast).isPresent(); + var astSysmlmodel = ast.get(); + SysMLv2Mill.scopesGenitorDelegator().createFromAST(astSysmlmodel); + tool.completeSymbolTable(astSysmlmodel); + var astPartdef = astSysmlmodel.getSysMLElementList().get(1); + var astSysmlelement = ((ASTPartDef) astPartdef).getSysMLElement(1); + if (astSysmlelement instanceof ASTStateUsage) { + var astTransition = ((ASTStateUsage) astSysmlelement).getSysMLElement(0); + var expr = ((ASTSysMLTransition) astTransition).getGuard(); + var type = TypeCheck3.typeOf(expr); + assertThat(type.printFullName()).isEqualTo("boolean"); + } else if (astSysmlelement instanceof ASTConstraintUsage) { + var expr = ((ASTConstraintUsage) astSysmlelement).getExpression(); + var type = TypeCheck3.typeOf(expr); + assertThat(type.printFullName()).isEqualTo( + "EventStream.EventStream"); + } + else { + Assertions.fail("ASTSysMLElement should here be ASTStateUsage"); + } + } + + @ParameterizedTest + @MethodSource({ "createInvalidInputs" }) + public void testInvalid(String model) throws IOException { + var ast = parser.parse_String(model); + assertThat(ast).isPresent(); + var astSysmlmodel = ast.get(); + SysMLv2Mill.scopesGenitorDelegator().createFromAST(astSysmlmodel); + tool.completeSymbolTable(astSysmlmodel); + var astPartdef = astSysmlmodel.getSysMLElementList().get(1); + var astSysmlelement = ((ASTPartDef) astPartdef).getSysMLElement(1); + SymTypeExpression type = SymTypeExpressionFactory.createObscureType(); + + Log.enableFailQuick(false); + + if (astSysmlelement instanceof ASTStateUsage) { + var astTransition = ((ASTStateUsage) astSysmlelement).getSysMLElement(0); + var expr = ((ASTSysMLTransition) astTransition).getGuard(); + type = TypeCheck3.typeOf(expr); + } else if (astSysmlelement instanceof ASTConstraintUsage) { + var expr = ((ASTConstraintUsage) astSysmlelement).getExpression(); + type = TypeCheck3.typeOf(expr); + } + else { + Assertions.fail("ASTSysMLElement should here be ASTStateUsage"); + } + + assertTrue(!type.isPrimitive() || !type.asPrimitive().getPrimitiveName().equals("boolean")); + Log.enableFailQuick(true); + } +} diff --git a/language/src/test/java/types3/NegationTest.java b/language/src/test/java/types3/NegationTest.java new file mode 100644 index 00000000..0e90be87 --- /dev/null +++ b/language/src/test/java/types3/NegationTest.java @@ -0,0 +1,156 @@ +package types3; + +import de.monticore.expressions.commonexpressions._ast.ASTEqualsExpression; +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.ocl.oclexpressions._ast.ASTForallExpression; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; +import de.monticore.types3.util.MapBasedTypeCheck3; +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.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.IOException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class NegationTest { + + private final SysMLv2Parser parser = new SysMLv2Parser(); + private final SysMLv2Tool tool = new SysMLv2Tool(); + + @BeforeAll + public static void init() { + LogStub.init(); + } + + @BeforeEach + public void reset() { + Log.getFindings().clear(); + tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); + } + + @ParameterizedTest + @ValueSource(strings = { + "port def F { in attribute val: boolean; } part s { port f: F; constraint e { forall long t: f.val.nth(t) == !f.val.nth(t) } }" + }) + public void testNotBooleanStream(String model) throws IOException { + var ast = parser.parse_String(model); + assertThat(ast).isPresent(); + var astSysMLModel = ast.get(); + + tool.createSymbolTable(astSysMLModel); + tool.completeSymbolTable(astSysMLModel); + tool.finalizeSymbolTable(astSysMLModel); + + var sysmlelements = astSysMLModel.getSysMLElementList(); + var astPartUsage = sysmlelements.get(1); + var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); + var forAllExpr = (ASTForallExpression)(((ASTConstraintUsage) constraintUsage).getExpression()); + var equalsExpr = (ASTEqualsExpression) forAllExpr.getExpression(); + var rightType = TypeCheck3.typeOf(equalsExpr.getRight()); + var leftType = TypeCheck3.typeOf(equalsExpr.getLeft()); + assertFalse(rightType.isObscureType()); + assertThat(rightType.printFullName()).isEqualTo("UntimedStream.UntimedStream"); + assertTrue(rightType.deepEquals(leftType)); + } + + @ParameterizedTest + @ValueSource(strings = { + "part s { constraint e { forall nat t: true == !false } }" + }) + public void testNotBoolean(String model) throws IOException { + var ast = parser.parse_String(model); + assertThat(ast).isPresent(); + var astSysMLModel = ast.get(); + + tool.createSymbolTable(astSysMLModel); + tool.completeSymbolTable(astSysMLModel); + tool.finalizeSymbolTable(astSysMLModel); + + var sysmlelements = astSysMLModel.getSysMLElementList(); + var astPartUsage = sysmlelements.get(0); + var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(0); + var forAllExpr = (ASTForallExpression)(((ASTConstraintUsage) constraintUsage).getExpression()); + var equalsExpr = (ASTEqualsExpression) forAllExpr.getExpression(); + var rightType = TypeCheck3.typeOf(equalsExpr.getRight()); + var leftType = TypeCheck3.typeOf(equalsExpr.getLeft()); + assertFalse(rightType.isObscureType()); + assertThat(rightType.printFullName()).isEqualTo("boolean"); + assertTrue(rightType.deepEquals(leftType)); + } +} diff --git a/language/src/test/java/types3/SpecializationExistsTest.java b/language/src/test/java/types3/SpecializationExistsTest.java new file mode 100644 index 00000000..ed1ee86f --- /dev/null +++ b/language/src/test/java/types3/SpecializationExistsTest.java @@ -0,0 +1,111 @@ +/* (c) https://github.com/MontiCore/monticore */ +package types3; + +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._symboltable.ISysMLv2ArtifactScope; +import de.monticore.lang.sysmlv2.cocos.SpecializationExists; +import de.monticore.lang.sysmlv2.cocos.SpecializationExistsTC3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.types3.TypeCheck3; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Prüft das Finden von Types der Specializations + */ +public class SpecializationExistsTest { + + @BeforeAll + static void setup() { + SysMLv2Mill.init(); + } + + @BeforeEach + void clear() { + SysMLv2Mill.globalScope().clear(); + SysMLv2Mill.initializePrimitives(); + SysMLv2Mill.addCollectionTypes(); + SysMLTypeCheck3.reset(); + SysMLTypeCheck3.init(); + Log.clearFindings(); + } + + @Test + public void testMissingDefinition() throws IOException { + var model = "requirement Invalid { subject s: NonExistent; }"; + var ast = parse(model); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0xA0324 Cannot find symbol NonExistent"); + } + + @Test + public void testExistingDefinition() throws IOException { + var model = "part def Existent; requirement Valid { subject s: Existent; }"; + var ast = parse(model); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + // Should also work with state defs + @Test + public void testExistingStateDefinition() throws IOException { + var model = "state def Existent; requirement Valid { subject s: Existent; }"; + var ast = parse(model); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testExistingCollectionType() throws IOException { + var model = "attribute def Existent; part def Valid { attribute e: List; }"; + var ast = parse(model); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + 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 check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new SpecializationExistsTC3()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(f -> f.isError()).collect(Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + +} diff --git a/language/src/test/java/types3/StreamConstructorExpressionsTest.java b/language/src/test/java/types3/StreamConstructorExpressionsTest.java new file mode 100644 index 00000000..276c7697 --- /dev/null +++ b/language/src/test/java/types3/StreamConstructorExpressionsTest.java @@ -0,0 +1,186 @@ +package types3; + +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; +import de.monticore.lang.sysmlv2.types.SysMLDeriver; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.SymTypeRelations; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; +import de.monticore.types3.util.MapBasedTypeCheck3; +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.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class StreamConstructorExpressionsTest { + + private final SysMLv2Parser parser = new SysMLv2Parser(); + private final SysMLv2Tool tool = new SysMLv2Tool(); + + @BeforeAll + public static void setup() { + LogStub.init(); + SysMLv2Mill.init(); + } + + @BeforeEach + public void clear() { + Log.clearFindings(); + tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); + } + + @ParameterizedTest + @ValueSource(strings = { + "port def F { attribute a: boolean; } part s { port f: F; constraint e {} }", + "port def F { attribute a: boolean; } part s { port f: F; constraint e {} }" + }) + public void test4validStream(String model) throws IOException { + var ast = parser.parse_String(model); + + assertThat(ast).isPresent(); + assertThat(Log.getFindings()).isEmpty(); + var astSysMLModel = ast.get(); + + tool.createSymbolTable(astSysMLModel); + tool.completeSymbolTable(astSysMLModel); + tool.finalizeSymbolTable(astSysMLModel); + + var sysmlelements = astSysMLModel.getSysMLElementList(); + var astPartUsage = sysmlelements.get(1); + var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); + var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); + var type = SymTypeRelations.normalize(TypeCheck3.typeOf(expr)); + assertThat(type.printFullName()).isEqualTo("EventStream.EventStream"); + } + + @ParameterizedTest + @ValueSource(strings = { + "port def F { attribute a: boolean; } part s { port f: F; constraint e {} }", + "port def F { attribute a: boolean; } part s { port f: F; constraint e { >} }" + }) + public void test4ValidMixedStream(String model) throws IOException { + var ast = parser.parse_String(model); + + assertThat(ast).isPresent(); + assertThat(Log.getFindings()).isEmpty(); + var astSysMLModel = ast.get(); + + tool.createSymbolTable(astSysMLModel); + tool.completeSymbolTable(astSysMLModel); + tool.finalizeSymbolTable(astSysMLModel); + + var sysmlelements = astSysMLModel.getSysMLElementList(); + var astPartUsage = sysmlelements.get(1); + var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); + var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); + var type = TypeCheck3.typeOf(expr); + + // Streams are based on union types. So the following expressions are correct, albeit innerly incompatible + assertTrue(type.isGenericType() && type.asGenericType().getArgument(0).isUnionType()); + var args = type.asGenericType().getArgument(0).asUnionType().getUnionizedTypeSet().toArray(); + assertFalse(SymTypeRelations.isCompatible((SymTypeExpression) args[0], (SymTypeExpression) args[1])); + assertTrue(Log.getFindings().isEmpty()); + } + + @ParameterizedTest + @ValueSource(strings = { + "port def F { attribute a: boolean; } part s { port f: F; constraint e { == } }", + "port def F { attribute a: boolean; } part s { port f: F; constraint e { > == < >} }" + }) + public void test4InvalidStream(String model) throws IOException { + var ast = parser.parse_String(model); + + assertThat(ast).isPresent(); + assertThat(Log.getFindings()).isEmpty(); + var astSysMLModel = ast.get(); + + tool.createSymbolTable(astSysMLModel); + tool.completeSymbolTable(astSysMLModel); + tool.finalizeSymbolTable(astSysMLModel); + + var sysmlelements = astSysMLModel.getSysMLElementList(); + var astPartUsage = sysmlelements.get(1); + var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); + var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); + var type = TypeCheck3.typeOf(expr); + + assertTrue(type.isObscureType()); + assertFalse(Log.getFindings().isEmpty()); + } +} diff --git a/language/src/test/java/types3/TC3FieldAccessInteroperabilityTest.java b/language/src/test/java/types3/TC3FieldAccessInteroperabilityTest.java new file mode 100644 index 00000000..bf4b6185 --- /dev/null +++ b/language/src/test/java/types3/TC3FieldAccessInteroperabilityTest.java @@ -0,0 +1,200 @@ +package types3; + +import de.monticore.expressions.commonexpressions._ast.ASTEqualsExpression; +import de.monticore.expressions.commonexpressions._ast.ASTFieldAccessExpression; +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis._ast.ASTNameExpression; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlparts._ast.ASTPartDef; +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.cocos.ConstraintIsBooleanTC3; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; +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; +import static org.junit.jupiter.api.Assertions.*; + +public class TC3FieldAccessInteroperabilityTest { + private SysMLv2Tool tool; + @BeforeAll + public static void init() { + LogStub.init(); + } + + @BeforeEach + public void reset() { + Log.getFindings().clear(); + tool = new SysMLv2Tool(); + tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); + } + @Test + public void testInteroperabilityWithoutTCReset() throws IOException { + var optAst = SysMLv2Mill.parser().parse_String( "" + + "port def Naturals {\n" + + " out attribute channel: nat;\n" + + "}\n" + + "\n" + + "part def LogicBasedConstraints {\n" + + " port input: ~Naturals;\n" + + " port output: Naturals;\n" + + "\n" + + " constraint streams {\n" + + " input == input.channel\n" + + " }\n" + + "}\n"); + assertThat(optAst).isPresent(); + + ASTSysMLModel ast = optAst.get(); + + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + var expression = (ASTEqualsExpression)((ASTPartDef)ast.getSysMLElement(1)) + .getSysMLElements(ASTConstraintUsage.class) + .get(0) + .getExpression(); + + var typeEq = TypeCheck3.typeOf(expression); + assertTrue(typeEq.isPrimitive() && typeEq.asPrimitive().getPrimitiveName().equals("boolean")); + + var leftNameExpr = (ASTNameExpression)expression.getLeft(); + var typeLeftNameExpr = TypeCheck3.typeOf(leftNameExpr); + assertEquals("EventStream", typeLeftNameExpr.print()); + + var rightFieldAccess = (ASTFieldAccessExpression)expression.getRight(); + var typeRightFieldAccess = TypeCheck3.typeOf(rightFieldAccess); + assertEquals("EventStream", typeRightFieldAccess.print()); + + var rightNameExpr = (ASTNameExpression)((ASTFieldAccessExpression)expression.getRight()).getExpression(); + var typeRightNameExpr = TypeCheck3.typeOf(rightNameExpr); + // this is the side effect of the 2-modes typecheck implementation. + // Deriving the type of a port usage cannot not reliably be done. + // Only port usages are affected. + assertNotEquals("Naturals", typeRightNameExpr.print()); + assertEquals("EventStream", typeRightNameExpr.print()); + + assertTrue(Log.getFindings().isEmpty(), () -> Log.getFindings().toString()); + } + + @Test + public void testInvalidWithoutTCReset() throws IOException { + var optAst = SysMLv2Mill.parser().parse_String( "" + + "port def Naturals {\n" + + " out attribute channel: nat;\n" + + " out attribute channel1: nat;\n" + + "}\n" + + "\n" + + "part def LogicBasedConstraints {\n" + + " port input: ~Naturals;\n" + + " port output: Naturals;\n" + + "\n" + + " constraint streams {\n" + + " input == input.channel\n" + + " }\n" + + "}\n"); + assertThat(optAst).isPresent(); + + ASTSysMLModel ast = optAst.get(); + + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + var expression = (ASTEqualsExpression)((ASTPartDef)ast.getSysMLElement(1)) + .getSysMLElements(ASTConstraintUsage.class) + .get(0) + .getExpression(); + + var typeEq = TypeCheck3.typeOf(expression); + // in the case there are multiple C&C ports, only field accesses are streams + assertTrue(typeEq.isObscureType()); + + var leftNameExpr = (ASTNameExpression)expression.getLeft(); + var typeLeftNameExpr = TypeCheck3.typeOf(leftNameExpr); + assertEquals("Naturals", typeLeftNameExpr.print()); + + var rightFieldAccess = (ASTFieldAccessExpression)expression.getRight(); + var typeRightFieldAccess = TypeCheck3.typeOf(rightFieldAccess); + assertEquals("EventStream", typeRightFieldAccess.print()); + + var rightNameExpr = (ASTNameExpression)((ASTFieldAccessExpression)expression.getRight()).getExpression(); + var typeRightNameExpr = TypeCheck3.typeOf(rightNameExpr); + assertEquals("Naturals", typeRightNameExpr.print()); + + assertFalse(Log.getFindings().isEmpty(), () -> Log.getFindings().toString()); + } +} diff --git a/language/src/test/resources/cocos/constraints/17_invalid.sysml b/language/src/test/resources/cocos/constraints/17_invalid.sysml new file mode 100644 index 00000000..2fada1ee --- /dev/null +++ b/language/src/test/resources/cocos/constraints/17_invalid.sysml @@ -0,0 +1,15 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: int; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + + constraint constraintName { + myPortDef.natAttr.nth(3).nth(2) < myPortDef.natAttr.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/17_valid.sysml b/language/src/test/resources/cocos/constraints/17_valid.sysml new file mode 100644 index 00000000..25bd1798 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/17_valid.sysml @@ -0,0 +1,15 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: int; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + + constraint constraintName { + myPortDef.natAttr.nth(3).nth(2) == myPortDef.natAttr.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/18_invalid.sysml b/language/src/test/resources/cocos/constraints/18_invalid.sysml new file mode 100644 index 00000000..f3333e3a --- /dev/null +++ b/language/src/test/resources/cocos/constraints/18_invalid.sysml @@ -0,0 +1,14 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: int; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + constraint constraintName { + myPortDef.natAttr.nth(3).nth(2).a < myPortDef.a.natAttr.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/18_valid.sysml b/language/src/test/resources/cocos/constraints/18_valid.sysml new file mode 100644 index 00000000..423cab73 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/18_valid.sysml @@ -0,0 +1,14 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: int; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + constraint constraintName { + myPortDef.natAttr.nth(3).nth(2).a < myPortDef.natAttr.nth(3).nth(3).a + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/11_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/11_invalid.sysml new file mode 100644 index 00000000..6e423d52 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/11_invalid.sysml @@ -0,0 +1,12 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Integers { + out attribute channel: int; +} + +part def LogicBasedConstraints { + port input: ~Integers; + + constraint streams { + input.length() > true + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/11_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/11_valid.sysml new file mode 100644 index 00000000..aad2617d --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/11_valid.sysml @@ -0,0 +1,12 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Booleans { + out attribute boolAttr: boolean; +} + +part def LogicBasedConstraints { + port myPortDef: Booleans; + + constraint constraintName { + myPortDef.len() > 1 + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/14_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/14_invalid.sysml new file mode 100644 index 00000000..84763491 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/14_invalid.sysml @@ -0,0 +1,14 @@ +package 'Inverter' { + port def Booleans { + in attribute val: boolean; + } + + part def Inverter { + port input: Booleans; + port output: ~Booleans; + + assert constraint { + input == implies output == + } + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/14_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/14_valid.sysml new file mode 100644 index 00000000..d186b4ed --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/14_valid.sysml @@ -0,0 +1,14 @@ +package 'Inverter' { + port def Booleans { + in attribute val: boolean; + } + + part def Inverter { + port input: Booleans; + port output: ~Booleans; + + assert constraint { + input == implies output == + } + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/15_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/15_invalid.sysml new file mode 100644 index 00000000..19b54a46 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/15_invalid.sysml @@ -0,0 +1,12 @@ +port def Booleans { + in attribute val: boolean; +} + +part def Inverter { + port i: Booleans; + port o: ~Booleans; + + assert constraint { + forall nat k: i== .times(k, 5) implies o == .times(k) + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/15_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/15_valid.sysml new file mode 100644 index 00000000..31ae1b18 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/15_valid.sysml @@ -0,0 +1,12 @@ +port def Booleans { + in attribute val: boolean; +} + +part def Inverter { + port i: Booleans; + port o: ~Booleans; + + assert constraint { + forall long k: i == .times(k) implies o == .times(k) + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/17_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/17_invalid.sysml new file mode 100644 index 00000000..a56dcf2a --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/17_invalid.sysml @@ -0,0 +1,14 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: int; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + constraint constraintName { + myPortDef.nth(3).nth(2) < myPortDef.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/17_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/17_valid.sysml new file mode 100644 index 00000000..c596e24f --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/17_valid.sysml @@ -0,0 +1,14 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: int; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + constraint constraintName { + myPortDef.nth(3).nth(2) == myPortDef.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/18_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/18_invalid.sysml new file mode 100644 index 00000000..904d4028 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/18_invalid.sysml @@ -0,0 +1,14 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: boolean; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + constraint constraintName { + myPortDef.nth(3).nth(2).a < myPortDef.a.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/18_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/18_valid.sysml new file mode 100644 index 00000000..5c637644 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/18_valid.sysml @@ -0,0 +1,14 @@ +/* (c) https://github.com/MontiCore/monticore */ +attribute def A { + attribute a: int; +} +port def Integers { + out attribute natAttr: A; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + constraint constraintName { + myPortDef.nth(3).nth(2).a < myPortDef.nth(3).nth(3).a + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/19_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/19_invalid.sysml new file mode 100644 index 00000000..74470f73 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/19_invalid.sysml @@ -0,0 +1,12 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Integers { + out attribute natAttr: int; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + + constraint constraintName { + myPortDef.nth(3).nth(3).natAttr > myPortDef.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/19_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/19_valid.sysml new file mode 100644 index 00000000..b29efbdf --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/19_valid.sysml @@ -0,0 +1,12 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Integers { + out attribute natAttr: int; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + + constraint constraintName { + myPortDef.natAttr.nth(3).nth(3) > myPortDef.nth(3).nth(3) + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/2_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/2_invalid.sysml new file mode 100644 index 00000000..0605c1c6 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/2_invalid.sysml @@ -0,0 +1,17 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Integers { + out attribute channel: int; +} + +port def Booleans { + out attribute channel: boolean; +} + +part def LogicBasedConstraints { + port input: ~Integers; + port output: Booleans; + + constraint streams { + input == output + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/2_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/2_valid.sysml new file mode 100644 index 00000000..40f652d6 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/2_valid.sysml @@ -0,0 +1,13 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Integers { + out attribute channel: int; +} + +part def LogicBasedConstraints { + port input: ~Integers; + port output: Integers; + + constraint streams { + input == output + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/4_invalid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/4_invalid.sysml new file mode 100644 index 00000000..4e9a0c85 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/4_invalid.sysml @@ -0,0 +1,12 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Integers { + out attribute channel: int; +} + +part def LogicBasedConstraints { + port input: ~Integers; + + constraint streams { + input.snth(5) > true + } +} diff --git a/language/src/test/resources/cocos/constraints/implicitFieldAccess/4_valid.sysml b/language/src/test/resources/cocos/constraints/implicitFieldAccess/4_valid.sysml new file mode 100644 index 00000000..98343fa5 --- /dev/null +++ b/language/src/test/resources/cocos/constraints/implicitFieldAccess/4_valid.sysml @@ -0,0 +1,12 @@ +/* (c) https://github.com/MontiCore/monticore */ +port def Integers { + out attribute natAttr: int; +} + +part def LogicBasedConstraints { + port myPortDef: Integers; + + constraint constraintName { + myPortDef.nth(3).nth(3) > 1 + } +} From 6fb10d09eb5296e363d3676d91990674af105a1d Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Mon, 12 Jan 2026 11:55:46 +0100 Subject: [PATCH 03/29] Backporting 6 CoCos (#43) * PartTypeDefinitionExistsCoCo (#32) * CoCo1 Every type used in "part name:type" has to be an existing Part-Definition * Test for MKPXCoCo1 * rename and changed error code * RefinementTargetDefinitionExistsCoCo (#33) * CoCo2 Every name used in "part def X refines Name" has to be an existing Part-Definition. * add Test for MKPX_CoCo2 * renamed and changed error codes * UniqueSubPartNamesInConnectionCoCo (#34) * CoCo3 * Test for MKPX_CoCo3 * wrong import * rennamed and changed error codes * QualifiedPortNameExistsCoCo (#35) * CoCo4 * not responsible for undefined parts covered in MKPX_CoCo3 * Test for MKPX_CoCo4 * add parser and Model Path * Missing Import SysMLv2Parser * Missing import assertFalse * Update MKPXCoCo4Test.java * Update MKPXCoCo4Test.java * Update MKPXCoCo4Test.java * Update MKPXCoCo4Test.java * syntax error fixed * renamed and changed error code * ParentComponentInputConnectionDirectionCoCo (#37) * CoCo6 * clean up * Update MKPX_CoCo6.java * Test for MKPX_CoCo6 * add parser and model path * Missing Import SysMLv2Parser * Missing import assertFalse * Update MKPXCoCo6Test.java * Update MKPXCoCo6Test.java * Update MKPXCoCo6Test.java * explicit port direction * fixed resolving issue * added warnings for inout ports * rename and new error codes * conjugated Ports allowed and Tests added * SubcomponentOutputConnectionDirectionCoCo (#36) * CoCo5 * wrong dir and clean up * add Test for MKPX_CoCo5 * add parser and model path * Missing Import SysMLv2Parser * Missing import assertFalse * Update MKPXCoCo5Test.java * Update MKPXCoCo5Test.java * Update MKPX_CoCo5.java * Revert "Update MKPX_CoCo5.java" This reverts commit ae76ff63630a7c01eb9602fc1d2fd0e3103888b2. * Update MKPX_CoCo5.java * Revert "Update MKPX_CoCo5.java" This reverts commit 710e2b812b7d20161129b66eafb7a84dfaeb30ae. * Update MKPXCoCo5Test.java * Update MKPXCoCo5Test.java * Update MKPXCoCo5Test.java * Update MKPXCoCo5Test.java * Update MKPXCoCo5Test.java * Update MKPXCoCo5Test.java * Update MKPX_CoCo5.java * Update MKPX_CoCo5.java * Update MKPXCoCo5Test.java * Update MKPX_CoCo5.java * explicit port def from (0_valid.sysml) * syntax error * Update MKPXCoCo5Test.java * Update MKPXCoCo5Test.java * fixed resolving method * added warning for inout ports * extended warning for target port * renamed and new error codes * allow conjugated ports * added Tests for conjuagted Ports * clean up * Update SubcomponentOutputConnectionDirectionCoCo.java * Clean Up Tests (#42) use SysMLv2Tool for scope genration and symboltable creation * version bump to 7.8.3 --- gradle.properties | 2 +- ...ComponentInputConnectionDirectionCoCo.java | 197 ++++++++++++++++++ .../cocos/PartTypeDefinitionExistsCoCo.java | 39 ++++ .../cocos/QualifiedPortNameExistsCoCo.java | 96 +++++++++ .../RefinementTargetDefinitionExistsCoCo.java | 41 ++++ ...omponentOutputConnectionDirectionCoCo.java | 194 +++++++++++++++++ .../UniqueSubPartNamesInConnectionCoCo.java | 72 +++++++ ...onentInputConnectionDirectionCoCoTest.java | 157 ++++++++++++++ .../PartTypeDefinitionExistsCoCoTest.java | 107 ++++++++++ .../QualifiedPortNameExistsCoCoTest.java | 110 ++++++++++ ...inementTargetDefinitionExistsCoCoTest.java | 98 +++++++++ ...nentOutputConnectionDirectionCoCoTest.java | 175 ++++++++++++++++ ...niqueSubPartNamesInConnectionCoCoTest.java | 162 ++++++++++++++ 13 files changed, 1449 insertions(+), 1 deletion(-) create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/PartTypeDefinitionExistsCoCo.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/QualifiedPortNameExistsCoCo.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/RefinementTargetDefinitionExistsCoCo.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java create mode 100644 language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java create mode 100644 language/src/test/java/cocos/PartTypeDefinitionExistsCoCoTest.java create mode 100644 language/src/test/java/cocos/QualifiedPortNameExistsCoCoTest.java create mode 100644 language/src/test/java/cocos/RefinementTargetDefinitionExistsCoCoTest.java create mode 100644 language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java create mode 100644 language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java diff --git a/gradle.properties b/gradle.properties index cda01f97..4cf7d37a 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.2 +version = 7.8.3 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java new file mode 100644 index 00000000..49e05c85 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java @@ -0,0 +1,197 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlbasis._ast.ASTModifier; +import de.monticore.lang.sysmlbasis._ast.ASTSysMLTyping; +import de.monticore.lang.sysmlparts._ast.ASTAttributeUsage; +import de.monticore.lang.sysmlparts._ast.ASTConnectionUsage; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTConnectionUsageCoCo; +import de.monticore.lang.sysmlparts._symboltable.ISysMLPartsScope; +import de.monticore.lang.sysmlparts._symboltable.PartDefSymbol; +import de.monticore.lang.sysmlparts._symboltable.PartUsageSymbol; +import de.monticore.lang.sysmlparts._symboltable.PortUsageSymbol; +import de.monticore.lang.sysmlbasis._ast.ASTEndpoint; +import de.monticore.symboltable.modifiers.AccessModifier; +import de.se_rwth.commons.logging.Log; + +import java.util.List; +import java.util.Optional; + +/** + * ParentComponentInputConnectionDirectionCoCo + * Inputs von Oberkomponenten können nur zu Inputs von Subkomponenten oder Outputs der Oberkomponenten verbunden werden + * (alternative Formulierung): + * Inputs von Oberkomponenten können nicht zu Outputs von Subkomponenten verbunden werden. + */ +public class ParentComponentInputConnectionDirectionCoCo implements SysMLPartsASTConnectionUsageCoCo { + + @Override + public void check(ASTConnectionUsage node) { + // Skip validation if endpoints are missing + if (!node.isPresentSrc() || !node.isPresentTgt()) { + return; + } + + ASTEndpoint src = node.getSrc(); + ASTEndpoint tgt = node.getTgt(); + + String srcQName = endpointQName(src); + String tgtQName = endpointQName(tgt); + + ISysMLPartsScope scope = node.getEnclosingScope(); + + // Determine if endpoints reference subcomponents + boolean tgtIsSub = isSubcomponentEndpoint(tgtQName); + boolean srcIsSub = isSubcomponentEndpoint(srcQName); + + // Resolve port symbols + PortUsageSymbol tgtPort = resolvePortSymbol(scope, tgtQName, tgtIsSub); + PortUsageSymbol srcPort = resolvePortSymbol(scope, srcQName, srcIsSub); + + // If any port is unresolvable, let other CoCos handle it + if (srcPort == null || tgtPort == null) { + return; + } + + // Classify ports + boolean tgtIsInput = portIsInput(tgtPort); + boolean tgtIsOutput = portIsOutput(tgtPort); + + // Allowed connections: + // 1. Subcomponent with Input ports + // 2. Parent component with Output ports + boolean allowed = (tgtIsSub && tgtIsInput) || (!tgtIsSub && tgtIsOutput); + + if(srcIsSub || !portIsInput(srcPort)){ + // Source is neither input nor ParentComponent + // CoCo does not apply + return; + } + if( + (portIsInOutput(srcPort)) || + (portIsInOutput(tgtPort)) + ) { + Log.warn("0x10AA6 Warning: Connection involves an 'inout' port which may have ambiguous directionality.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd()); + } + + if (!allowed) { + Log.error( + "0x10AA6 Illegal connection: inputs of parent components can only be " + + "connected to inputs of subcomponents or outputs of the parent component.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd() + ); + } + } + + // -------- Hilfsmethoden -------- + + /** Qualified Name des Endpunkts als String. */ + protected String endpointQName(ASTEndpoint ep) { + if (ep.getMCQualifiedName() != null) { + return ep.getMCQualifiedName().toString(); + } + return ""; + } + + /** + * Heuristik: ein Name mit '.' steht für einen Port einer Subkomponente, + * z.B. "a.out". Ohne Punkt = Port der Oberkomponente. + */ + protected boolean isSubcomponentEndpoint(String qname) { + return qname.contains("."); + } + + /** Resolve port symbol based on whether it's in a subcomponent */ + protected PortUsageSymbol resolvePortSymbol(ISysMLPartsScope scope, + String qname, boolean isSub) { + if (isSub) { + return resolvePortOfSubPart(scope, qname); + } else { + return resolvePort(scope, qname); + } + } + + /** Resolve PortUsageSymbol by qualified name */ + protected PortUsageSymbol resolvePort(ISysMLPartsScope scope, String qname) { + List result = scope.resolvePortUsageSubKinds( + true, // search in enclosing scopes + qname, // qualified name, e.g., "a.out" + AccessModifier.ALL_INCLUSION, // ignore visibility + p -> true // no additional filtering + ); + + if (result.isEmpty()) { + return scope.resolvePortUsage(qname).orElse(null); + } + // If multiple candidates, take the first (should be unique in your models) + return result.get(0); + } + + /** Resolve port within a subcomponent */ + protected PortUsageSymbol resolvePortOfSubPart(ISysMLPartsScope scope, + String qname) { + // Split "a.out" into part "a" and port "out" + int lastDot = qname.lastIndexOf('.'); + if (lastDot == -1) { + return null; + } + + String partName = qname.substring(0, lastDot); + String portName = qname.substring(lastDot + 1); + + // Resolve the subcomponent + Optional partSymbol = scope.resolvePartUsage(partName); + if (partSymbol.isEmpty()) { + return null; + } + + Optional partDef = partSymbol.get().getPartDef(); + if (partDef.isPresent()) { + ISysMLPartsScope partScope = partDef.get().getSpannedScope(); + return resolvePort(partScope, portName); + } + + return null; + } + + /** Extract modifiers from PortUsageSymbol */ + protected ASTModifier getModifiersFromPortUsageSymbol(PortUsageSymbol symbol) { + ASTAttributeUsage portAttributeUsageAST = (ASTAttributeUsage) + symbol.getAstNode() + .getPortDefs() + .get(0) + .getSysMLElementList() + .get(0); + return portAttributeUsageAST.getModifier(); + } + + protected boolean portIsInput(PortUsageSymbol symbol) { + ASTModifier mods = getModifiersFromPortUsageSymbol(symbol); + boolean portIsInAndNotConjugated = mods.isIn() && !portIsConjugated(symbol); + boolean portIsOutAndConjugated = mods.isOut() && portIsConjugated(symbol); + return (portIsInAndNotConjugated || portIsOutAndConjugated); + } + + protected boolean portIsOutput(PortUsageSymbol symbol) { + ASTModifier mods = getModifiersFromPortUsageSymbol(symbol); + boolean portIsOutAndNotConjugated = mods.isOut() && !portIsConjugated(symbol); + boolean portIsInAndConjugated = mods.isIn() && portIsConjugated(symbol); + return (portIsOutAndNotConjugated || portIsInAndConjugated); + } + + protected boolean portIsInOutput(PortUsageSymbol symbol) { + ASTModifier mods = getModifiersFromPortUsageSymbol(symbol); + return mods.isInout(); + } + + protected boolean portIsConjugated(PortUsageSymbol symbol) { + return + ((ASTSysMLTyping) symbol + .getAstNode() + .getSpecialization(0)) + .isConjugated(); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/PartTypeDefinitionExistsCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/PartTypeDefinitionExistsCoCo.java new file mode 100644 index 00000000..faced490 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/PartTypeDefinitionExistsCoCo.java @@ -0,0 +1,39 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlbasis._ast.ASTSpecialization; +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTPartUsageCoCo; +import de.monticore.types.mcbasictypes._ast.ASTMCType; +import de.se_rwth.commons.logging.Log; + +import java.util.stream.Collectors; + +/** + * CoCo1: Jeder in "part name:Typ" verwendete Typ muss eine existierende Part-Definition sein. + */ +public class PartTypeDefinitionExistsCoCo implements SysMLPartsASTPartUsageCoCo { + + protected String printPartType(ASTMCType type) { + return type.printType(); + } + + @Override + public void check(ASTPartUsage node) { + var nonExistent = node.streamSpecializations() + .flatMap(ASTSpecialization::streamSuperTypes) + .filter(t -> + node.getEnclosingScope().resolvePartDef(printPartType(t)).isEmpty() + ) + .collect(Collectors.toList()); + + for (var problem : nonExistent) { + Log.error( + "0x10AA1 The type referenced in a PartUsage \"" + printPartType(problem) + + "\" does not exist as a part definition.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd() + ); + } + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/QualifiedPortNameExistsCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/QualifiedPortNameExistsCoCo.java new file mode 100644 index 00000000..f63d428e --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/QualifiedPortNameExistsCoCo.java @@ -0,0 +1,96 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlbasis._ast.ASTEndpoint; +import de.monticore.lang.sysmlparts._ast.ASTConnectionUsage; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTConnectionUsageCoCo; +import de.monticore.lang.sysmlparts._symboltable.ISysMLPartsScope; +import de.monticore.lang.sysmlparts._symboltable.PartDefSymbol; +import de.monticore.lang.sysmlparts._symboltable.PartUsageSymbol; +import de.monticore.symboltable.modifiers.AccessModifier; +import de.se_rwth.commons.logging.Log; + +import java.util.List; +import java.util.Optional; + +/** + * QualifiedPortNameExistsCoCo: + * In einer Verbindung "connect a.b to c.d" muss jeder verwendete (qualifizierte) Portname existieren. + */ +public class QualifiedPortNameExistsCoCo implements SysMLPartsASTConnectionUsageCoCo { + + @Override + public void check(ASTConnectionUsage node) { + if (!node.isPresentSrc() || !node.isPresentTgt()) { + return; // keine Verbindung + } + + ISysMLPartsScope scope = node.getEnclosingScope(); + + checkEndpoint(scope, node.getSrc(), node); + checkEndpoint(scope, node.getTgt(), node); + } + + protected void checkEndpoint(ISysMLPartsScope scope, + ASTEndpoint endpoint, + ASTConnectionUsage conn) { + String qname = endpointQName(endpoint); + if (qname.isEmpty()) { + return; + } + + String[] parts = qname.split("\\."); + + // Qualifizierter Name: a.b -> resolve a (PartUsage), dann b in PartDef + if (parts.length >= 2) { + String partName = parts[0]; + String portName = parts[parts.length - 1]; + + Optional partOpt = scope.resolvePartUsageLocally(partName); + + if (partOpt.isEmpty()) { + // Existenz der Subkomponente wird bereits in MKPX_CoCo3 geprüft. + return; + } + + var partDefOpt = partOpt.get().getPartDef(); + if (partDefOpt.isEmpty()) { + // CoCo3 + return; + } + + PartDefSymbol partDef = partDefOpt.get(); + boolean portExistsInDef = partDef.getSpannedScope() + .resolvePortUsageLocallyMany(false, portName, AccessModifier.ALL_INCLUSION, p -> true) + .size() == 1; + + if (!portExistsInDef) { + Log.error( + "0x10AA4 The port '" + portName + "' does not exist in the definition of subcomponent '" + + partName + "'.", + conn.get_SourcePositionStart(), + conn.get_SourcePositionEnd() + ); + } + } + else { + // Unqualifiziert: Port der Oberkomponente muss lokal existieren + String portName = parts[0]; + List localPorts = scope.resolvePortUsageLocallyMany( + false, portName, AccessModifier.ALL_INCLUSION, p -> true); + if (localPorts.isEmpty()) { + Log.error( + "0x10AA4 The port used in 'connect' '" + portName + + "' does not exist in the parent component.", + conn.get_SourcePositionStart(), + conn.get_SourcePositionEnd() + ); + } + } + } + + /** Liefert den qualifizierten Namen des Endpunkts als String. */ + protected String endpointQName(ASTEndpoint ep) { + return ep.getMCQualifiedName() != null ? ep.getMCQualifiedName().toString() : ""; + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/RefinementTargetDefinitionExistsCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/RefinementTargetDefinitionExistsCoCo.java new file mode 100644 index 00000000..3b7338d3 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/RefinementTargetDefinitionExistsCoCo.java @@ -0,0 +1,41 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlbasis._ast.ASTSpecialization; +import de.monticore.lang.sysmlbasis._ast.ASTSysMLRefinement; +import de.monticore.lang.sysmlparts._ast.ASTPartDef; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTPartDefCoCo; +import de.monticore.types.mcbasictypes._ast.ASTMCType; +import de.se_rwth.commons.logging.Log; + +import java.util.stream.Collectors; + +/** + * CoCo2: Jeder im "part def X refines Name" verwendete Name muss eine existierende Part-Definition sein. + */ +public class RefinementTargetDefinitionExistsCoCo implements SysMLPartsASTPartDefCoCo { + + protected String printPartType(ASTMCType type) { + return type.printType(); + } + + @Override + public void check(ASTPartDef node) { + var nonExistent = node.streamSpecializations() + .filter(s -> s instanceof ASTSysMLRefinement) + .flatMap(ASTSpecialization::streamSuperTypes) + .filter(t -> + node.getEnclosingScope().resolvePartDef(printPartType(t)).isEmpty() + ) + .collect(Collectors.toList()); + + for (var problem : nonExistent) { + Log.error( + "0x10AA2 The name used in 'refines' \"" + printPartType(problem) + + "\" does not exist as a part definition.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd() + ); + } + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java new file mode 100644 index 00000000..8a3389c3 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java @@ -0,0 +1,194 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlbasis._ast.ASTModifier; +import de.monticore.lang.sysmlbasis._ast.ASTEndpoint; +import de.monticore.lang.sysmlbasis._ast.ASTSysMLTyping; +import de.monticore.lang.sysmlparts._ast.ASTAttributeUsage; +import de.monticore.lang.sysmlparts._ast.ASTConnectionUsage; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTConnectionUsageCoCo; +import de.monticore.lang.sysmlparts._symboltable.*; +import de.monticore.symboltable.modifiers.AccessModifier; +import de.se_rwth.commons.logging.Log; + +import java.util.List; +import java.util.Optional; + +/** + * SubcomponentOutputConnectionDirectionCoCo + * Checks that outputs of subcomponents can only be connected to: + * 1. Inputs of subcomponents, or + * 2. Outputs of the parent component. + */ +public class SubcomponentOutputConnectionDirectionCoCo implements SysMLPartsASTConnectionUsageCoCo { + + @Override + public void check(ASTConnectionUsage node) { + // Skip validation if endpoints are missing + if (!node.isPresentSrc() || !node.isPresentTgt()) { + return; + } + + ASTEndpoint src = node.getSrc(); + ASTEndpoint tgt = node.getTgt(); + + String srcQName = endpointQName(src); + String tgtQName = endpointQName(tgt); + + ISysMLPartsScope scope = node.getEnclosingScope(); + + // Determine if endpoints reference subcomponents + boolean tgtIsSub = isSubcomponentEndpoint(tgtQName); + boolean srcIsSub = isSubcomponentEndpoint(srcQName); + + // Resolve port symbols + PortUsageSymbol tgtPort = resolvePortSymbol(scope, tgtQName, tgtIsSub); + PortUsageSymbol srcPort = resolvePortSymbol(scope, srcQName, srcIsSub); + + // If any port is unresolvable, let other CoCos handle it + if (srcPort == null || tgtPort == null) { + return; + } + + // Classify ports + boolean tgtIsInput = portIsInput(tgtPort); + boolean tgtIsOutput = portIsOutput(tgtPort); + + // Allowed connections: + // 1. Subcomponent with Input ports + // 2. Parent component with Output ports + boolean allowed = (tgtIsSub && tgtIsInput) || (!tgtIsSub && tgtIsOutput); + + if(!srcIsSub || !portIsOutput(srcPort)){ + // Source is neither output nor Subcomponent + // CoCo does not apply + return; + } + if( + (portIsInOutput(srcPort)) || + (portIsInOutput(tgtPort)) + ) { + Log.warn("0x10AA5 Warning: Connection involves an 'inout' port which may have ambiguous directionality.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd()); + } + + if (!allowed) { + Log.error( + "0x10AA5 Illegal connection: outputs of subcomponents can only be " + + "connected to inputs of subcomponents or outputs of the parent component.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd() + ); + } + } + + // -------- Hilfsmethoden -------- + + /** Qualified Name des Endpunkts als String. */ + protected String endpointQName(ASTEndpoint ep) { + if (ep.getMCQualifiedName() != null) { + return ep.getMCQualifiedName().toString(); + } + return ""; + } + + /** + * Heuristik: ein Name mit '.' steht für einen Port einer Subkomponente, + * z.B. "a.out". Ohne Punkt = Port der Oberkomponente. + */ + protected boolean isSubcomponentEndpoint(String qname) { + return qname.contains("."); + } + + /** Resolve port symbol based on whether it's in a subcomponent */ + protected PortUsageSymbol resolvePortSymbol(ISysMLPartsScope scope, + String qname, boolean isSub) { + if (isSub) { + return resolvePortOfSubPart(scope, qname); + } else { + return resolvePort(scope, qname); + } + } + + /** Resolve PortUsageSymbol by qualified name */ + protected PortUsageSymbol resolvePort(ISysMLPartsScope scope, String qname) { + List result = scope.resolvePortUsageSubKinds( + true, // search in enclosing scopes + qname, // qualified name, e.g., "a.out" + AccessModifier.ALL_INCLUSION, // ignore visibility + p -> true // no additional filtering + ); + + if (result.isEmpty()) { + return scope.resolvePortUsage(qname).orElse(null); + } + // If multiple candidates, take the first (should be unique in your models) + return result.get(0); + } + + /** Resolve port within a subcomponent */ + protected PortUsageSymbol resolvePortOfSubPart(ISysMLPartsScope scope, + String qname) { + // Split "a.out" into part "a" and port "out" + int lastDot = qname.lastIndexOf('.'); + if (lastDot == -1) { + return null; + } + + String partName = qname.substring(0, lastDot); + String portName = qname.substring(lastDot + 1); + + // Resolve the subcomponent + Optional partSymbol = scope.resolvePartUsage(partName); + if (partSymbol.isEmpty()) { + return null; + } + + Optional partDef = partSymbol.get().getPartDef(); + if (partDef.isPresent()) { + ISysMLPartsScope partScope = partDef.get().getSpannedScope(); + return resolvePort(partScope, portName); + } + + return null; + } + + /** Extract modifiers from PortUsageSymbol */ + protected ASTModifier getModifiersFromPortUsageSymbol(PortUsageSymbol symbol) { + ASTAttributeUsage portAttributeUsageAST = (ASTAttributeUsage) + symbol.getAstNode() + .getPortDefs() + .get(0) + .getSysMLElementList() + .get(0); + return portAttributeUsageAST.getModifier(); + } + + protected boolean portIsInput(PortUsageSymbol symbol) { + ASTModifier mods = getModifiersFromPortUsageSymbol(symbol); + boolean portIsInAndNotConjugated = mods.isIn() && !portIsConjugated(symbol); + boolean portIsOutAndConjugated = mods.isOut() && portIsConjugated(symbol); + return (portIsInAndNotConjugated || portIsOutAndConjugated); + } + + protected boolean portIsOutput(PortUsageSymbol symbol) { + ASTModifier mods = getModifiersFromPortUsageSymbol(symbol); + boolean portIsOutAndNotConjugated = mods.isOut() && !portIsConjugated(symbol); + boolean portIsInAndConjugated = mods.isIn() && portIsConjugated(symbol); + return (portIsOutAndNotConjugated || portIsInAndConjugated); + } + + protected boolean portIsInOutput(PortUsageSymbol symbol) { + ASTModifier mods = getModifiersFromPortUsageSymbol(symbol); + return mods.isInout(); + } + + protected boolean portIsConjugated(PortUsageSymbol symbol) { + return + ((ASTSysMLTyping) symbol + .getAstNode() + .getSpecialization(0)) + .isConjugated(); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java new file mode 100644 index 00000000..70161fe8 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java @@ -0,0 +1,72 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.sysmlbasis._ast.ASTEndpoint; +import de.monticore.lang.sysmlparts._ast.ASTConnectionUsage; +import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTConnectionUsageCoCo; +import de.monticore.lang.sysmlparts._symboltable.ISysMLPartsScope; +import de.monticore.symboltable.modifiers.AccessModifier; +import de.se_rwth.commons.logging.Log; + +/** + * CoCo3: Jeder in "connect a.b to c.d" verwendete Name von Subkomponenten (a und c) + * muss eindeutig im Modell vorhanden sein. + */ +public class UniqueSubPartNamesInConnectionCoCo implements SysMLPartsASTConnectionUsageCoCo { + + @Override + public void check(ASTConnectionUsage node) { + if (!node.isPresentSrc() || !node.isPresentTgt()) { + return; // keine Verbindung + } + + var scope = node.getEnclosingScope(); + + checkSubcomponentQualifier(scope, node.getSrc(), node); + checkSubcomponentQualifier(scope, node.getTgt(), node); + } + + protected void checkSubcomponentQualifier(ISysMLPartsScope scope, + ASTEndpoint endpoint, + ASTConnectionUsage node) { + String qname = endpointQName(endpoint); + String subName = extractFirstSegment(qname); + + if (subName == null) { + return; + } + + int matches = scope + .resolvePartUsageLocallyMany(false, subName, + AccessModifier.ALL_INCLUSION, p -> true) + .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 */ + Log.error( + "0x10AA3 The subcomponent name used in 'connect' \"" + subName + + "\" does not exist in the model.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd() + ); + } + } + + protected String endpointQName(ASTEndpoint ep) { + return ep.getMCQualifiedName() != null ? ep.getMCQualifiedName().toString() : ""; + } + + protected String extractFirstSegment(String qname) { + int dot = qname.indexOf('.'); + if (dot > 0) { + return qname.substring(0, dot); + } + return null; + } +} diff --git a/language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java b/language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java new file mode 100644 index 00000000..4374e2b7 --- /dev/null +++ b/language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java @@ -0,0 +1,157 @@ +/* (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.ParentComponentInputConnectionDirectionCoCo; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ParentComponentInputConnectionDirectionCoCoTest { + + 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 InputConnectionTests { + @Test + public void testValid() throws IOException { + String validModel = + "port def InPort { in attribute data: int; }" + + "port def OutPort { out attribute data: int; }" + + "part def A { port input: InPort; }" + + "part def B { port output: OutPort; }" + + "part def System {" + + "port sysIn: InPort;" + + "port sysInAnother: InPort;" + + "port sysOut: OutPort;" + + "part a: A;" + + "part b: B;" + + "connect sysIn to a.input;" + + "connect sysInAnother to sysOut;" + + "}"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testValidConjugatedModel() throws IOException { + String validModel = + "port def InPort { in attribute data: int; }" + + "part def A { port input: InPort; }" + + "part def B { port output: ~InPort; }" + + "part def System {" + + "port sysIn: InPort;" + + "port sysInAnother: InPort;" + + "port sysOut: ~InPort;" + + "part a: A;" + + "part b: B;" + + "connect sysIn to a.input;" + + "connect sysInAnother to sysOut;" + + "}"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testInvalid() throws IOException { + String invalidModel = + "port def InPort { in attribute data: int; }" + + "port def OutPort { out attribute data: int; }" + + "part def A { port output: OutPort; }" + + "part def System {" + + "port sysIn: InPort;" + + "part a: A;" + + "connect sysIn to a.output;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA6"); + } + + @Test + public void testInvalidConjugatedModel() throws IOException { + String invalidModel = + "port def InPort { in attribute data: int; }" + + "part def A { port output: ~InPort; }" + + "part def System {" + + "port sysIn: InPort;" + + "part a: A;" + + "connect sysIn to a.output;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA6"); + } + + 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 check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new ParentComponentInputConnectionDirectionCoCo()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(Finding::isError).collect( + Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + } +} diff --git a/language/src/test/java/cocos/PartTypeDefinitionExistsCoCoTest.java b/language/src/test/java/cocos/PartTypeDefinitionExistsCoCoTest.java new file mode 100644 index 00000000..a5a0f380 --- /dev/null +++ b/language/src/test/java/cocos/PartTypeDefinitionExistsCoCoTest.java @@ -0,0 +1,107 @@ +/* (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.PartTypeDefinitionExistsCoCo; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PartTypeDefinitionExistsCoCoTest { + + 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 PartTypeDefinitionExistsCoCoTests { + @Test + public void testValid() throws IOException { + String validModel = + "part def SubComponent1;" + + "part def SubComponent2;" + + "part def MainComponent{" + + "part subcomp1: SubComponent1;" + + "part subcomp2: SubComponent2;" + + "}"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testInvalid() throws IOException { + String invalidModel = + "part def SubComponent1;" + + "part def MainComponent{" + + "part subcomp1: SubComponent1;" + + "part subcomp2: UndefinedComponent;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA1"); + } + + 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 check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new PartTypeDefinitionExistsCoCo()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(Finding::isError).collect( + Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + } +} diff --git a/language/src/test/java/cocos/QualifiedPortNameExistsCoCoTest.java b/language/src/test/java/cocos/QualifiedPortNameExistsCoCoTest.java new file mode 100644 index 00000000..b55a6e8e --- /dev/null +++ b/language/src/test/java/cocos/QualifiedPortNameExistsCoCoTest.java @@ -0,0 +1,110 @@ +/* (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.QualifiedPortNameExistsCoCo; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QualifiedPortNameExistsCoCoTest { + + 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 QualifiedPortNameExistsCoCoTests { + @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;" + + "connect a.p to b.q;" + + "}"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testInvalid() throws IOException { + String invalidModel = + "part def A { port p: int; }" + + "part def B { port q: ~int; }" + + "part def System {" + + "part a: A;" + + "part b: B;" + + "connect a.wrongName to b.q;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA4"); + } + + 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 check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new QualifiedPortNameExistsCoCo()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(Finding::isError).collect( + Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + } +} diff --git a/language/src/test/java/cocos/RefinementTargetDefinitionExistsCoCoTest.java b/language/src/test/java/cocos/RefinementTargetDefinitionExistsCoCoTest.java new file mode 100644 index 00000000..a9e924de --- /dev/null +++ b/language/src/test/java/cocos/RefinementTargetDefinitionExistsCoCoTest.java @@ -0,0 +1,98 @@ +/* (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.RefinementTargetDefinitionExistsCoCo; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RefinementTargetDefinitionExistsCoCoTest { + + 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 RefinementTargetDefinitionExistsCoCoTests { + @Test + public void testValid() throws IOException { + String validModel = + "part def BasePart;" + + "part def Refining refines BasePart;"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testInvalid() throws IOException { + String invalidModel = "part def Refining refines UndefinedBasePart;"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA2"); + } + + 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 check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new RefinementTargetDefinitionExistsCoCo()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(Finding::isError).collect( + Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + } +} diff --git a/language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java b/language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java new file mode 100644 index 00000000..18c74360 --- /dev/null +++ b/language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java @@ -0,0 +1,175 @@ +/* (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.SubcomponentOutputConnectionDirectionCoCo; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SubcomponentOutputConnectionDirectionCoCoTest { + + 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 OutputConnectionTests { + + @Test + public void testValid() throws IOException { + String validModel = + "port def OutPort { out attribute data: int; }" + + "port def InPort { in attribute data: int; }" + + "part def A { port output: OutPort; }" + + "part def B { port input: InPort; }" + + "part def C { port output: OutPort; }" + + "part def System {" + + "port sysOutput: OutPort;" + + "part a: A;" + + "part b: B;" + + "part c: C;" + + "connect a.output to b.input;" // (Sub) Output -> (Sub) Input + + "connect c.output to sysOutput;" // (Sub) Output -> (main) Output + + "}"; + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testValidConjugatedModel() throws IOException { + String validModel = + "port def OutPort { out attribute data: int; }" + + "part def A { port output: OutPort; }" + + "part def B { port input: ~OutPort; }" + + "part def C { port output: OutPort; }" + + "part def System {" + + "port sysOutput: OutPort;" + + "part a: A;" + + "part b: B;" + + "part c: C;" + + "connect a.output to b.input;" // (Sub) Output -> (Sub) Input + + "connect c.output to sysOutput;" // (Sub) Output -> (main) Output + + "}"; + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testInvalidSubOutToSubOut() throws IOException { + String invalidModel = + "port def OutPort { out attribute data: int; }" + + "part def A { port output: OutPort; }" + + "part def B { port output: OutPort; }" + + "part def System {" + + "part a: A;" + + "part b: B;" + + "connect a.output to b.output;" // (Sub) Output -> (Sub) Output + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA5"); + } + + @Test + public void testInvalidSubOutToMainInConjugatedModel() throws IOException { + String invalidModel = + "port def OutPort { out attribute data: int; }" + + "part def A { port output: OutPort; }" + + "part def System {" + + "port sysInput: ~OutPort;" + + "part a: A;" + + "connect a.output to sysInput;" // (Sub) Output -> (main) Input + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA5"); + } + + @Test + public void testInvalidSubOutToMainIn() throws IOException { + String invalidModel = + "port def OutPort { out attribute data: int; }" + + "port def InPort { in attribute data: int; }" + + "part def A { port output: OutPort; }" + + "part def System {" + + "port sysInput: InPort;" + + "part a: A;" + + "connect a.output to sysInput;" // (Sub) Output -> (main) Input + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA5"); + } + + 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 check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new SubcomponentOutputConnectionDirectionCoCo()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(Finding::isError).collect( + Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + } +} diff --git a/language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java b/language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java new file mode 100644 index 00000000..38913d6b --- /dev/null +++ b/language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java @@ -0,0 +1,162 @@ +/* (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.UniqueSubPartNamesInConnectionCoCo; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UniqueSubPartNamesInConnectionCoCoTest { + + 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;" + + "connect a.p to b.q;" + + "}"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + + @Test + public void testInvalidUndefined() throws IOException { + String invalidModel = + "part def A { port p: int; }" + + "part def B { port q: ~int; }" + + "part def System {" + + "part a: A;" + + "connect a.p to c.q;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + 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 = + "part def A { port p; }" + + "part def System {" + + "part a: A;" + + "connect undefined1.p to undefined2.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 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(); + return optAst.get(); + } + + private ISysMLv2ArtifactScope createSt(ASTSysMLModel ast) { + var tool = new SysMLv2Tool(); + var scope = tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + return scope; + } + + private List check(ASTSysMLModel ast) { + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo()); + Log.enableFailQuick(false); + checker.checkAll(ast); + return Log.getFindings().stream().filter(Finding::isError).collect( + Collectors.toList()); + } + + @AfterEach + void clearLog() { + Log.clearFindings(); + Log.enableFailQuick(true); + } + } +} From b470d3148ecfac64ce31d135a58ea59fa57ef679 Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:28:02 +0100 Subject: [PATCH 04/29] add CoCos to Checker (#44) * add CoCos to Checker * version bump to 7.8.4 --- gradle.properties | 2 +- .../de/monticore/lang/sysmlv2/SysMLv2Tool.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4cf7d37a..5af85ba3 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.3 +version = 7.8.4 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 bb49c544..c8960180 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,12 @@ import de.monticore.lang.sysmlv2.cocos.TypeCheckTransitionGuards; import de.monticore.lang.sysmlv2.cocos.TypeCheck3TransitionGuards; import de.monticore.lang.sysmlv2.cocos.WarnNonExhibited; +import de.monticore.lang.sysmlv2.cocos.PartTypeDefinitionExistsCoCo; +import de.monticore.lang.sysmlv2.cocos.ParentComponentInputConnectionDirectionCoCo; +import de.monticore.lang.sysmlv2.cocos.QualifiedPortNameExistsCoCo; +import de.monticore.lang.sysmlv2.cocos.RefinementTargetDefinitionExistsCoCo; +import de.monticore.lang.sysmlv2.cocos.SubcomponentOutputConnectionDirectionCoCo; +import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInConnectionCoCo; import de.monticore.lang.sysmlv2.symboltable.completers.CausalityCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectRefinementCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectionCompleter; @@ -167,6 +173,16 @@ public void runAdditionalCoCos( checker.addCoCo(new PortDefinitionExistsCoCo()); checker.addCoCo(new PartBehaviorCoCo()); + // Check Definitions exist + checker.addCoCo(new PartTypeDefinitionExistsCoCo()); + checker.addCoCo(new RefinementTargetDefinitionExistsCoCo()); + + // Connection CoCos + checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo()); + checker.addCoCo(new QualifiedPortNameExistsCoCo()); + checker.addCoCo(new SubcomponentOutputConnectionDirectionCoCo()); + checker.addCoCo(new ParentComponentInputConnectionDirectionCoCo()); + checker.checkAll(ast); } From e84c971614f74b5910b480c31862ca020ce8fb13 Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Sun, 18 Jan 2026 09:07:04 +0100 Subject: [PATCH 05/29] CoCos to default and version bump (#46) * switched some CoCos from extended Checker to default Checker * version bump to 7.8.5 --- gradle.properties | 2 +- .../monticore/lang/sysmlv2/SysMLv2Tool.java | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5af85ba3..5fd9e5fe 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.4 +version = 7.8.5 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 c8960180..98922538 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -122,6 +122,15 @@ public void runDefaultCoCos(ASTSysMLModel ast) { checker.addCoCo(new SendActionTypeCheck3()); checker.addCoCo(new AssignActionTypeCheck3()); checker.addCoCo(new TypeCheck3TransitionGuards()); + // Check Definitions exist + checker.addCoCo(new PartTypeDefinitionExistsCoCo()); + checker.addCoCo(new RefinementTargetDefinitionExistsCoCo()); + // Connection CoCos + checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo()); + checker.addCoCo(new QualifiedPortNameExistsCoCo()); + checker.addCoCo(new SubcomponentOutputConnectionDirectionCoCo()); + checker.addCoCo(new ParentComponentInputConnectionDirectionCoCo()); + checker.checkAll(ast); } @@ -173,16 +182,6 @@ public void runAdditionalCoCos( checker.addCoCo(new PortDefinitionExistsCoCo()); checker.addCoCo(new PartBehaviorCoCo()); - // Check Definitions exist - checker.addCoCo(new PartTypeDefinitionExistsCoCo()); - checker.addCoCo(new RefinementTargetDefinitionExistsCoCo()); - - // Connection CoCos - checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo()); - checker.addCoCo(new QualifiedPortNameExistsCoCo()); - checker.addCoCo(new SubcomponentOutputConnectionDirectionCoCo()); - checker.addCoCo(new ParentComponentInputConnectionDirectionCoCo()); - checker.checkAll(ast); } From 255df7bd60e9c8e0c406ac162ca45add22a891aa Mon Sep 17 00:00:00 2001 From: Dovydas Skauranskas <109866625+DovydasSkauranskas@users.noreply.github.com> Date: Thu, 22 Jan 2026 12:42:17 +0200 Subject: [PATCH 06/29] Eps added to global scope (#47) * Eps added to global scope * Version erhoeht --- gradle.properties | 2 +- .../monticore/lang/sysmlv2/SysMLv2Mill.java | 18 +++++++ .../test/java/symboltable/TsynTypeTest.java | 50 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 language/src/test/java/symboltable/TsynTypeTest.java diff --git a/gradle.properties b/gradle.properties index 5fd9e5fe..ff425dfa 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.5 +version = 7.8.6 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java index 04fd57b2..d9dc1f6b 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Mill.java @@ -32,6 +32,7 @@ public static void prepareGlobalScope() { SysMLv2Mill.initializePrimitives(); SysMLv2Mill.addStringType(); SysMLv2Mill.addCollectionTypes(); + SysMLv2Mill.addTsynTypes(); } /** @@ -171,6 +172,23 @@ protected void _addCollectionTypes() { } } + public static void addTsynTypes() { + getMill()._addTsynTypes(); + } + + protected void _addTsynTypes() { + if (SysMLv2Mill.globalScope().resolveType("Eps").isEmpty()) { + var eps = typeSymbolBuilder() + .setName("Eps") + .setEnclosingScope(globalScope()) + .setFullName("Eps") + .setSpannedScope(scope()) + .setAccessModifier(AccessModifier.ALL_INCLUSION) + .build(); + SysMLv2Mill.globalScope().add(eps); + } + } + protected OOTypeSymbol buildCollectionType(String name, String... typeVars) { var spannedScope = scope(); diff --git a/language/src/test/java/symboltable/TsynTypeTest.java b/language/src/test/java/symboltable/TsynTypeTest.java new file mode 100644 index 00000000..6b7eed4e --- /dev/null +++ b/language/src/test/java/symboltable/TsynTypeTest.java @@ -0,0 +1,50 @@ +package symboltable; + +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._ast.ASTSysMLModel; +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; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TsynTypeTest { + + @BeforeAll + static void setup() { + SysMLv2Mill.init(); + } + + @BeforeEach + public void init() { + LogStub.init(); + SysMLv2Mill.globalScope().clear(); + SysMLv2Mill.initializePrimitives(); + SysMLv2Mill.addCollectionTypes(); + SysMLv2Mill.addTsynTypes(); + Log.clearFindings(); + } + + @Test + public void testEpsInModel() throws IOException { + var tool = new SysMLv2Tool(); + + var model = "part def Valid { attribute e: Eps; }"; + var optAst = SysMLv2Mill.parser().parse_String(model); + + assertThat(optAst).isPresent(); + ASTSysMLModel ast = optAst.get(); + + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + + assertTrue(Log.getFindings().isEmpty(), () -> Log.getFindings().toString()); + } + +} From 12e3e3736044211bd6284db0cbe7f50512773b1e Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Thu, 5 Feb 2026 15:15:57 +0100 Subject: [PATCH 07/29] CoCo: Erkennung doppelt verwendeter Part-Namen (Backport) (#49) * clean up SubPartNamesInConnectionExistCoCo remove ambiguous name check from SubPartNamesInConnectionExistCoCo * add UniqueSubPartNamesInParentCoCo * update SysMLv2Tool Checker * version bump to 7.8.7 --- gradle.properties | 2 +- .../monticore/lang/sysmlv2/SysMLv2Tool.java | 9 +- ...=> SubPartNamesInConnectionExistCoCo.java} | 15 +-- .../cocos/UniqueSubPartNamesInParentCoCo.java | 35 ++++++ ...ubPartNamesInConnectionExistCoCoTest.java} | 42 +------ .../UniqueSubPartNamesInParentCoCoTest.java | 104 ++++++++++++++++++ 6 files changed, 155 insertions(+), 52 deletions(-) rename language/src/main/java/de/monticore/lang/sysmlv2/cocos/{UniqueSubPartNamesInConnectionCoCo.java => SubPartNamesInConnectionExistCoCo.java} (82%) create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java rename language/src/test/java/cocos/{UniqueSubPartNamesInConnectionCoCoTest.java => SubPartNamesInConnectionExistCoCoTest.java} (72%) create mode 100644 language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java diff --git a/gradle.properties b/gradle.properties index ff425dfa..1966761e 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.6 +version = 7.8.7 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 98922538..4bd3bc19 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -46,7 +46,8 @@ import de.monticore.lang.sysmlv2.cocos.QualifiedPortNameExistsCoCo; import de.monticore.lang.sysmlv2.cocos.RefinementTargetDefinitionExistsCoCo; import de.monticore.lang.sysmlv2.cocos.SubcomponentOutputConnectionDirectionCoCo; -import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInConnectionCoCo; +import de.monticore.lang.sysmlv2.cocos.UniqueSubPartNamesInParentCoCo; +import de.monticore.lang.sysmlv2.cocos.SubPartNamesInConnectionExistCoCo; import de.monticore.lang.sysmlv2.symboltable.completers.CausalityCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectRefinementCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectionCompleter; @@ -126,11 +127,13 @@ public void runDefaultCoCos(ASTSysMLModel ast) { checker.addCoCo(new PartTypeDefinitionExistsCoCo()); checker.addCoCo(new RefinementTargetDefinitionExistsCoCo()); // Connection CoCos - checker.addCoCo(new UniqueSubPartNamesInConnectionCoCo()); + checker.addCoCo(new SubPartNamesInConnectionExistCoCo()); checker.addCoCo(new QualifiedPortNameExistsCoCo()); checker.addCoCo(new SubcomponentOutputConnectionDirectionCoCo()); checker.addCoCo(new ParentComponentInputConnectionDirectionCoCo()); - + // Check ambiguous names + checker.addCoCo(new UniqueSubPartNamesInParentCoCo()); + checker.checkAll(ast); } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubPartNamesInConnectionExistCoCo.java similarity index 82% rename from language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java rename to language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubPartNamesInConnectionExistCoCo.java index 70161fe8..683f207c 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInConnectionCoCo.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubPartNamesInConnectionExistCoCo.java @@ -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) { @@ -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.", diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java new file mode 100644 index 00000000..9bd3f697 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/UniqueSubPartNamesInParentCoCo.java @@ -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() + ); + } + } +} diff --git a/language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java b/language/src/test/java/cocos/SubPartNamesInConnectionExistCoCoTest.java similarity index 72% rename from language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java rename to language/src/test/java/cocos/SubPartNamesInConnectionExistCoCoTest.java index 38913d6b..a662826d 100644 --- a/language/src/test/java/cocos/UniqueSubPartNamesInConnectionCoCoTest.java +++ b/language/src/test/java/cocos/SubPartNamesInConnectionExistCoCoTest.java @@ -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; @@ -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"; @@ -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 = @@ -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(); @@ -146,7 +110,7 @@ private ISysMLv2ArtifactScope createSt(ASTSysMLModel ast) { private List 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( diff --git a/language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java b/language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java new file mode 100644 index 00000000..3eeaba20 --- /dev/null +++ b/language/src/test/java/cocos/UniqueSubPartNamesInParentCoCoTest.java @@ -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 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); + } + } +} From c590793f061a42e4d945af970eb7702fe3e894b0 Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:55:34 +0100 Subject: [PATCH 08/29] 7.8.8: Fix for LanguageServer Listing Errors Multiple Times (Backport) (#53) * Override runCoCosForAllDocuments Generated class "SysMLv2LspCoCoRunnerTOP" was missing the line 38: "di.findings.clear()" which lead to multiple Error listing * version bump to 7.8.8 --- gradle.properties | 2 +- .../language_access/SysMLv2LspCoCoRunner.java | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 1966761e..2298e42d 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.7 +version = 7.8.8 diff --git a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java index 16948795..426438ca 100644 --- a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java +++ b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java @@ -2,6 +2,8 @@ import de.mclsg.lsp.document_management.DocumentManager; import de.monticore.lang.sysmlv2._ast.ASTSysMLModel; +import de.monticore.lang.sysmlv2._lsp.SysMLv2DocumentInformationFilter; +import de.se_rwth.commons.logging.Log; public class SysMLv2LspCoCoRunner extends SysMLv2LspCoCoRunnerTOP { public SysMLv2LspCoCoRunner(DocumentManager documentManager) { @@ -23,5 +25,27 @@ public void runAllCoCos(ASTSysMLModel ast){ } } + @Override + public void runCoCosForAllDocuments(){ + documentManager.getAllDocumentInformation(new SysMLv2DocumentInformationFilter()).forEach(di -> { + Log.enableFailQuick(false); + + if(di.ast != null){ + Log.getFindings().clear(); + try { + runAllCoCos((ASTSysMLModel) di.ast); + } finally { + di.findings.clear(); + di.findings.addAll(Log.getFindings()); + /* + * did-change message from Client triggers runAllCoCos. Each Error + * from those CoCos is logged in Findings and then added to + * DocumentInformation. These are then displayed to the User. + */ + } + } + }); + } + } From d6ccd2c39e5214dbeef4f13e23fda838b3cf1774 Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:15:42 +0100 Subject: [PATCH 09/29] 7.8.9: Fix for CoCos Assuming Direction In Connection (Backport) (#54) * check both possible directions SysML v2 'Connection' elements do not inherently specify flow direction * version bump to 7.8.9 * edit ParentComponentInputConnectionDirectionCoCo description * remove unnecessary comments --- gradle.properties | 2 +- ...ComponentInputConnectionDirectionCoCo.java | 37 ++++++++++++--- ...omponentOutputConnectionDirectionCoCo.java | 21 +++++++-- ...onentInputConnectionDirectionCoCoTest.java | 45 +++++++++++++++++++ ...nentOutputConnectionDirectionCoCoTest.java | 30 ++++++++++++- 5 files changed, 121 insertions(+), 14 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2298e42d..272a1e37 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.8 +version = 7.8.9 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java index 49e05c85..a05e694c 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ParentComponentInputConnectionDirectionCoCo.java @@ -18,10 +18,9 @@ import java.util.Optional; /** - * ParentComponentInputConnectionDirectionCoCo - * Inputs von Oberkomponenten können nur zu Inputs von Subkomponenten oder Outputs der Oberkomponenten verbunden werden - * (alternative Formulierung): - * Inputs von Oberkomponenten können nicht zu Outputs von Subkomponenten verbunden werden. + * Checks that Inputs of the parent component can only be connected to: + * 1. Inputs of subcomponents, or + * 2. Outputs of the parent component. */ public class ParentComponentInputConnectionDirectionCoCo implements SysMLPartsASTConnectionUsageCoCo { @@ -56,17 +55,41 @@ public void check(ASTConnectionUsage node) { // Classify ports boolean tgtIsInput = portIsInput(tgtPort); boolean tgtIsOutput = portIsOutput(tgtPort); + boolean srcIsInput = portIsInput(srcPort); + boolean srcIsOutput = portIsOutput(srcPort); // Allowed connections: // 1. Subcomponent with Input ports // 2. Parent component with Output ports - boolean allowed = (tgtIsSub && tgtIsInput) || (!tgtIsSub && tgtIsOutput); + // 3. Connection does not imply flow directions. + // This information must be inferred by port attributes + boolean allowed = true; - if(srcIsSub || !portIsInput(srcPort)){ - // Source is neither input nor ParentComponent + if (!((srcIsInput && !srcIsSub) || (tgtIsInput && !tgtIsSub))) { + // Both Endpoints are not a Parent input // CoCo does not apply return; + } else { + // At least one endpoint is of the Parent component + // Check if the OTHER endpoint satisfies the rule + + // If src is parent input + if (srcIsInput && !srcIsSub) { + allowed = allowed && ( + (tgtIsInput && tgtIsSub) || // tgt is sub input + (tgtIsOutput && !tgtIsSub) // tgt is parent output + ); + } + + // If tgt is parent input + if (tgtIsInput && !tgtIsSub) { + allowed = allowed && ( + (srcIsInput && srcIsSub) || // src is sub input + (srcIsOutput && !srcIsSub) // src is parent output + ); + } } + if( (portIsInOutput(srcPort)) || (portIsInOutput(tgtPort)) diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java index 8a3389c3..9832bbaf 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SubcomponentOutputConnectionDirectionCoCo.java @@ -15,7 +15,6 @@ import java.util.Optional; /** - * SubcomponentOutputConnectionDirectionCoCo * Checks that outputs of subcomponents can only be connected to: * 1. Inputs of subcomponents, or * 2. Outputs of the parent component. @@ -53,14 +52,28 @@ public void check(ASTConnectionUsage node) { // Classify ports boolean tgtIsInput = portIsInput(tgtPort); boolean tgtIsOutput = portIsOutput(tgtPort); + boolean srcIsInput = portIsInput(srcPort); + boolean srcIsOutput = portIsOutput(srcPort); // Allowed connections: // 1. Subcomponent with Input ports // 2. Parent component with Output ports - boolean allowed = (tgtIsSub && tgtIsInput) || (!tgtIsSub && tgtIsOutput); + // 3. Connection does not imply flow directions. + // This information must be inferred by port attributes + boolean allowed = true; - if(!srcIsSub || !portIsOutput(srcPort)){ - // Source is neither output nor Subcomponent + // Handle src as sub output + if (srcIsOutput && srcIsSub) { + allowed = (tgtIsInput && tgtIsSub) || (tgtIsOutput && !tgtIsSub); + } + + // Handle tgt as sub output (if not already failed) + if (allowed && tgtIsOutput && tgtIsSub) { + allowed = (srcIsInput && srcIsSub) || (srcIsOutput && !srcIsSub); + } + + if(!((srcIsOutput && srcIsSub) || (tgtIsOutput && tgtIsSub))){ + // Both Endpoints are not a Subcomponent output // CoCo does not apply return; } diff --git a/language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java b/language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java index 4374e2b7..11aedaa9 100644 --- a/language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java +++ b/language/src/test/java/cocos/ParentComponentInputConnectionDirectionCoCoTest.java @@ -67,6 +67,29 @@ public void testValid() throws IOException { assertThat(errors).hasSize(0); } + @Test + public void testValidSwitchTgtAndSrc() throws IOException { + String validModel = + "port def InPort { in attribute data: int; }" + + "port def OutPort { out attribute data: int; }" + + "part def A { port input: InPort; }" + + "part def B { port output: OutPort; }" + + "part def System {" + + "port sysIn: InPort;" + + "port sysInAnother: InPort;" + + "port sysOut: OutPort;" + + "part a: A;" + + "part b: B;" + + "connect a.input to sysIn;" + + "connect sysOut to sysInAnother;" + + "}"; + + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + @Test public void testValidConjugatedModel() throws IOException { String validModel = @@ -126,6 +149,28 @@ public void testInvalidConjugatedModel() throws IOException { assertThat(errors.get(0).getMsg()).contains("0x10AA6"); } + @Test + public void testInvalidConjugatedModelSwitchTgtAndSrc() throws IOException { + /* (Sub) Output -> (main) Input + * (also caught by SubcomponentOutputConnectionDirectionCoCo, so the + * connection would throw 0x10AA5 and 0x10AA6 in the actual Server) + */ + String invalidModel = + "port def InPort { in attribute data: int; }" + + "part def A { port output: ~InPort; }" + + "part def System {" + + "port sysIn: InPort;" + + "part a: A;" + + "connect a.output to sysIn;" + + "}"; + + var ast = parse(invalidModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(1); + assertThat(errors.get(0).getMsg()).contains("0x10AA6"); + } + private ASTSysMLModel parse(String model) throws IOException { var optAst = SysMLv2Mill.parser().parse_String(model); assertThat(optAst).isPresent(); diff --git a/language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java b/language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java index 18c74360..21d7d903 100644 --- a/language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java +++ b/language/src/test/java/cocos/SubcomponentOutputConnectionDirectionCoCoTest.java @@ -67,6 +67,28 @@ public void testValid() throws IOException { assertThat(errors).hasSize(0); } + @Test + public void testValidSwitchSrcAndTgt() throws IOException { + String validModel = + "port def OutPort { out attribute data: int; }" + + "port def InPort { in attribute data: int; }" + + "part def A { port output: OutPort; }" + + "part def B { port input: InPort; }" + + "part def C { port output: OutPort; }" + + "part def System {" + + "port sysOutput: OutPort;" + + "part a: A;" + + "part b: B;" + + "part c: C;" + + "connect b.input to a.output;" // (Sub) Output -> (Sub) Input + + "connect sysOutput to c.output;" // (Sub) Output -> (main) Output + + "}"; + var ast = parse(validModel); + createSt(ast); + var errors = check(ast); + assertThat(errors).hasSize(0); + } + @Test public void testValidConjugatedModel() throws IOException { String validModel = @@ -126,7 +148,11 @@ public void testInvalidSubOutToMainInConjugatedModel() throws IOException { } @Test - public void testInvalidSubOutToMainIn() throws IOException { + public void testInvalidSubOutToMainInSwitchSrcAndTgt() throws IOException { + /* (Sub) Output -> (main) Input + * (also caught by ParentComponentInputConnectionDirectionCoCo, so the + * connection would throw 0x10AA5 and 0x10AA6 in the actual Server) + */ String invalidModel = "port def OutPort { out attribute data: int; }" + "port def InPort { in attribute data: int; }" @@ -134,7 +160,7 @@ public void testInvalidSubOutToMainIn() throws IOException { + "part def System {" + "port sysInput: InPort;" + "part a: A;" - + "connect a.output to sysInput;" // (Sub) Output -> (main) Input + + "connect sysInput to a.output;" + "}"; var ast = parse(invalidModel); From 23e9b264617aa7df7f567481f62e1949d4462215 Mon Sep 17 00:00:00 2001 From: Justus R <103401898+justusrm@users.noreply.github.com> Date: Wed, 11 Feb 2026 14:40:11 +0100 Subject: [PATCH 10/29] #119 Added RequirementSubject2Variable symbol adapter (#56) * #119 Added RequirementSubject2Variable symbol adapter * #131 smaller refactor, removing duplicate type setter * #131 refactor var names * #115 version bump to 7.8.5 * #131 version bump to 7.8.10 --- gradle.properties | 2 +- ...uirementSubject2VariableSymbolAdapter.java | 76 +++++++++++++++++++ .../sysmlv2/_symboltable/ISysMLv2Scope.java | 9 +++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 language/src/main/java/de/monticore/lang/sysmlconstraints/symboltable/adapters/RequirementSubject2VariableSymbolAdapter.java diff --git a/gradle.properties b/gradle.properties index 272a1e37..3802c6c2 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.9 +version = 7.8.10 diff --git a/language/src/main/java/de/monticore/lang/sysmlconstraints/symboltable/adapters/RequirementSubject2VariableSymbolAdapter.java b/language/src/main/java/de/monticore/lang/sysmlconstraints/symboltable/adapters/RequirementSubject2VariableSymbolAdapter.java new file mode 100644 index 00000000..201aa6b0 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlconstraints/symboltable/adapters/RequirementSubject2VariableSymbolAdapter.java @@ -0,0 +1,76 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlconstraints.symboltable.adapters; + +import com.google.common.base.Preconditions; +import de.monticore.lang.sysmlconstraints._symboltable.RequirementSubjectSymbol; +import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; +import de.monticore.types.check.SymTypeExpression; +import de.se_rwth.commons.SourcePosition; +import de.se_rwth.commons.logging.Log; + +public class RequirementSubject2VariableSymbolAdapter extends VariableSymbol { + protected RequirementSubjectSymbol adaptee; + + public RequirementSubject2VariableSymbolAdapter(RequirementSubjectSymbol adaptee) { + super(adaptee.getName()); + this.adaptee = adaptee; + } + + protected RequirementSubjectSymbol getAdaptee() { + return adaptee; + } + + @Override + public SymTypeExpression getType() { + var types = this.adaptee.getTypesList(); + if(types.size() != 1) { + Log.trace("Experiencing Subj. with > 1 types", getClass().getName()); + return null; + } + return types.get(0); + } + + @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 getEnclosingScope() { + return getAdaptee().getEnclosingScope(); + } + + @Override + public SourcePosition getSourcePosition() { + return getAdaptee().getSourcePosition(); + } + + @Override + public RequirementSubject2VariableSymbolAdapter deepClone() { + RequirementSubject2VariableSymbolAdapter clone = new RequirementSubject2VariableSymbolAdapter(this.getAdaptee()); + clone.setAccessModifier(this.getAccessModifier()); + clone.setEnclosingScope(this.getEnclosingScope()); + clone.setFullName(this.getFullName()); + clone.setIsReadOnly(this.isIsReadOnly()); + if (this.isPresentAstNode()) { + clone.setAstNode(this.getAstNode()); + } + if (this.getType() != null) { + clone.setType(this.getType().deepClone()); + } + return clone; + } +} 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 e688cbc9..5e841780 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 @@ -9,6 +9,8 @@ import de.monticore.lang.sysmlbasis._ast.ASTSpecialization; import de.monticore.lang.sysmlbasis._symboltable.AnonymousUsageSymbol; 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.sysmloccurrences.symboltable.adapters.ItemDef2TypeSymbolAdapter; import de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol; import de.monticore.lang.sysmlparts._symboltable.PartUsageSymbol; @@ -68,6 +70,8 @@ default List resolveAdaptedVariableLocallyMany( AccessModifier.ALL_INCLUSION, x -> true); var attributes = resolveAttributeUsageLocallyMany(false, name, AccessModifier.ALL_INCLUSION, x -> true); + var requirementSubjects = resolveRequirementSubjectLocallyMany(false, name, + AccessModifier.ALL_INCLUSION, x -> true); var anonymous = resolveAnonymousUsageLocallyMany(false, name, AccessModifier.ALL_INCLUSION, x -> true); @@ -117,6 +121,11 @@ default List resolveAdaptedVariableLocallyMany( } } + for (RequirementSubjectSymbol reqSub : requirementSubjects) { + var variable = new RequirementSubject2VariableSymbolAdapter(reqSub); + adapted.add(variable); + } + for (AnonymousUsageSymbol anonymousUsage : anonymous) { var types = new ArrayList(); types.addAll(anonymousUsage.getTypesList()); From c7767a1854864d82bc8a0387cd953e915b9066c7 Mon Sep 17 00:00:00 2001 From: Justus R <103401898+justusrm@users.noreply.github.com> Date: Wed, 11 Feb 2026 14:49:02 +0100 Subject: [PATCH 11/29] 7.8.11: Added Requirements to CC-Language (#57) * #119 Added RequirementSubject2Variable symbol adapter * #131 Added RequirmentUsage (id per name) to CC, Implemented sysmlv2 to CC Adapter * #131 smaller refactoring for var names * #131 smaller refactor, removing duplicate type setter * #131 refactor var names * #131 removed testcode comments * #115 version bump to 7.8.5 * #131 version bump to 7.8.5 * #131 version bump to 7.8.10 * #131 version bump to 7.8.11 --- .../de/monticore/lang/ComponentConnector.mc4 | 5 +++++ gradle.properties | 2 +- .../sysmlv2/_symboltable/ISysMLv2Scope.java | 18 ++++++++++++++++++ .../Requirement2RequirementCCAdapter.java | 19 +++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java diff --git a/cc/src/main/grammars/de/monticore/lang/ComponentConnector.mc4 b/cc/src/main/grammars/de/monticore/lang/ComponentConnector.mc4 index 4b7251a3..e0ccf2a1 100644 --- a/cc/src/main/grammars/de/monticore/lang/ComponentConnector.mc4 +++ b/cc/src/main/grammars/de/monticore/lang/ComponentConnector.mc4 @@ -156,4 +156,9 @@ component grammar ComponentConnector transitions: Transition* ; + /** + * Requirements: Wir berücksichtigen primär die Namen der Requirements + */ + interface symbol Requirement = Name; + } diff --git a/gradle.properties b/gradle.properties index 3802c6c2..41a9b47a 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.10 +version = 7.8.11 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 5e841780..3711631a 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 @@ -29,9 +29,11 @@ import de.monticore.lang.sysmlv2.symboltable.adapters.AttributeUsage2PortSymbolAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.Constraint2SpecificationAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.PartDef2ComponentAdapter; +import de.monticore.lang.sysmlv2.symboltable.adapters.Requirement2RequirementCCAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.Requirement2SpecificationAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.StateUsage2AutomatonAdapter; import de.monticore.lang.sysmlv2.symboltable.adapters.StateUsage2EventAutomatonAdapter; +import de.monticore.lang.componentconnector._symboltable.RequirementSymbol; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; @@ -51,6 +53,22 @@ public interface ISysMLv2Scope extends ISysMLv2ScopeTOP { + @Override + default List resolveRequirementLocallyMany( + boolean foundSymbols, + String name, AccessModifier modifier, + Predicate predicate) { + var adapted = new ArrayList(); + var req = resolveRequirementUsageLocally(name); + + if(req.isPresent()) { + var ccReq = new Requirement2RequirementCCAdapter(req.get()); + adapted.add(ccReq); + } + + return adapted; + } + /** * Adaptiert AttributeUsages oder PortUsages zu Variablen. *
diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java new file mode 100644 index 00000000..df2f3a43 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java @@ -0,0 +1,19 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2.symboltable.adapters; + +import de.monticore.lang.componentconnector._symboltable.RequirementSymbol; +import de.monticore.lang.sysmlconstraints._ast.ASTRequirementUsage; +import de.monticore.lang.sysmlconstraints._symboltable.RequirementUsageSymbol; + +public class Requirement2RequirementCCAdapter extends RequirementSymbol { + private ASTRequirementUsage ccAST; + + public Requirement2RequirementCCAdapter(RequirementUsageSymbol requirementUsageSymbol) { + super(requirementUsageSymbol.getFullName()); + this.ccAST = requirementUsageSymbol.getAstNode(); + } + + public ASTRequirementUsage getCcAST() { + return ccAST; + } +} From 60e528e4cce9831fd0a73337a6bee468de01c37b Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Wed, 11 Feb 2026 16:27:57 +0100 Subject: [PATCH 12/29] 7.8.12: Possibility to configure which CoCos are run --- gradle.properties | 2 +- .../sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 41a9b47a..d82b48cd 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.11 +version = 7.8.12 diff --git a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java index 426438ca..329ad223 100644 --- a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java +++ b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/language_access/SysMLv2LspCoCoRunner.java @@ -17,7 +17,9 @@ public boolean needsSymbols() { @Override public void runAllCoCos(ASTSysMLModel ast){ - tool.runDefaultCoCos(ast); + if(System.getenv("SYSML_DEFAULT_COCOS") == null) { + tool.runDefaultCoCos(ast); + } // Runs additional (verification-specific) CoCos when variable is set. // Defaults to not running them. if(System.getenv("SYSML_ADDITIONAL_COCOS") != null) { From f78d92258b8ba2cd7fa8e0ace6265e8a11fd2e84 Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:05:28 +0100 Subject: [PATCH 13/29] 7.8.13: Added Quickfix for Duplicate Names in Subparts (#59) * implement QuickFix for UniqueSubPartNameCoCo * version bumb to 7.8.13 --- gradle.properties | 2 +- .../SysMLv2CodeActionProvider.java | 1 + .../code_action/UniqueSubPartName.java | 170 ++++++++++++++++++ 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/UniqueSubPartName.java diff --git a/gradle.properties b/gradle.properties index d82b48cd..9c6432fc 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.12 +version = 7.8.13 diff --git a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/SysMLv2CodeActionProvider.java b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/SysMLv2CodeActionProvider.java index 1c33c6e0..ae9be4e8 100644 --- a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/SysMLv2CodeActionProvider.java +++ b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/SysMLv2CodeActionProvider.java @@ -18,6 +18,7 @@ public SysMLv2CodeActionProvider(DocumentManager documentManager, AstPrettyPrinter astSysMLModelAstPrettyPrinter) { super(documentManager, astSysMLModelAstPrettyPrinter); coCoCodeActionProviders.add(new UpperCaseBlockName(documentManager)); + coCoCodeActionProviders.add(new UniqueSubPartName(documentManager)); coCoCodeActionProviders.add(new MissingRefinement(documentManager)); coCoCodeActionProviders.add(new MissingRefiner(documentManager)); } diff --git a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/UniqueSubPartName.java b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/UniqueSubPartName.java new file mode 100644 index 00000000..7a58a183 --- /dev/null +++ b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/features/code_action/UniqueSubPartName.java @@ -0,0 +1,170 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.lang.sysmlv2._lsp.features.code_action; + +import de.mclsg.lsp.document_management.DocumentInformation; +import de.mclsg.lsp.document_management.DocumentManager; +import de.monticore.ast.ASTNode; +import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlparts._symboltable.PartUsageSymbol; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; +import de.monticore.symboltable.modifiers.AccessModifier; +import org.eclipse.lsp4j.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +/** + * CodeAction for UniqueSubPartNamesInParentCoCo with ErrorCode 0x10AA7. Suggest + * a new name by appending "A". + */ +public class UniqueSubPartName extends CoCoCodeActionProvider { + + public UniqueSubPartName(DocumentManager documentManager) { + super(documentManager, "0x10AA7"); + } + + @Override + public List createFixesFor(TextDocumentItem document, + Diagnostic diagnostic) { + List res = new ArrayList<>(); + Optional di = documentManager.getDocumentInformation( + document); + + if (di.isEmpty()) { + return res; + } + + ASTNode ast = di.get().ast; + + Range diagnosticRange = diagnostic.getRange(); + int diagnosticLine = diagnosticRange.getStart().getLine(); + int diagnosticColumn = diagnosticRange.getStart().getCharacter(); + + traverse((ISysMLv2Scope) ast.getEnclosingScope(), symbol -> { + if (symbol == null || symbol.getAstNode() == null) { + return; + } + + ASTPartUsage node = symbol.getAstNode(); + + if (!isContainedInPosition(node, diagnosticLine, diagnosticColumn)) { + return; // Skip if this node doesn't contain the diagnostic position + } + + if (triggeredCoCo(node) && node.isPresentName()) { + String currentName = node.getName(); + String newName = suggestedName(currentName); + + CodeAction ca = new CodeAction( + String.format("Change name to '%s'", newName)); + ca.setKind(CodeActionKind.QuickFix); + + TextEdit textEdit = new TextEdit(); + Position pStart = calculateStartPosition(document, node, currentName); + Position pEnd = new Position(pStart.getLine(), + pStart.getCharacter() + currentName.length()); + + textEdit.setRange(new Range(pStart, pEnd)); + textEdit.setNewText(newName); + + ca.setEdit(new WorkspaceEdit(Collections.singletonMap(document.getUri(), + Collections.singletonList(textEdit)))); + res.add(ca); + } + }); + + return res; + } + + // Simply appends "A", can be changed in the future + private String suggestedName(String oldName){ + return oldName + "A"; + } + + private static void traverse(ISysMLv2Scope scope, + Consumer f) { + if (scope != null) { + scope.getPartUsageSymbols().entries().forEach( + entry -> f.accept(entry.getValue())); + scope.getSubScopes().forEach(s -> traverse(s, f)); + } + } + + // Returns true if this node has triggered 0x10AA7 + private boolean triggeredCoCo(ASTPartUsage node) { + var scope = node.getEnclosingScope(); + String partName = node.getName(); + + var allMatches = scope.resolvePartUsageLocallyMany(false, partName, + AccessModifier.ALL_INCLUSION, p -> true); + + return allMatches.size() > 1; + } + + /** + * Finds the exact start position of the part name. + * + * Skips the 'part' keyword and any following whitespaces + * to avoid editing keywords and other syntax elements. + */ + protected Position calculateStartPosition(TextDocumentItem document, + ASTPartUsage partUsage, + String currentName) { + int lineIdx = partUsage.get_SourcePositionStart().getLine() - 1; + int nameIdx = partUsage.get_SourcePositionStart().getColumn() - 1; + + String[] lines = document.getText().split("\\r?\\n"); + if (lineIdx < lines.length) { + String line = lines[lineIdx]; + + int startIdx = Math.max(0, nameIdx); + + int partIdx = line.indexOf("part", startIdx); + if (partIdx != -1) { + startIdx = partIdx + 4; // Skip "part" + + // Skip any whitespace after "part" + while (startIdx < line.length() && Character.isWhitespace(line.charAt(startIdx))) { + startIdx++; + } + } + + nameIdx = line.indexOf(currentName, startIdx); + + } + return new Position(lineIdx, nameIdx); + } + + /** + * Verifies that the diagnostic is pointing at the exact node as the same line + * is not enough. + * Example: "part a : type; part b : type;" + */ + private static boolean isContainedInPosition(ASTPartUsage node, + int diagnosticLine, + int diagnosticColumn) { + + int startLine = node.get_SourcePositionStart().getLine() - 1; + int endLine = node.get_SourcePositionEnd().getLine() - 1; + + boolean containsPosition = false; + if (diagnosticLine >= startLine && diagnosticLine <= endLine) { + if (diagnosticLine == startLine) { + containsPosition = diagnosticColumn >= + node.get_SourcePositionStart().getColumn() - 1; + } + else if (diagnosticLine == endLine) { + containsPosition = diagnosticColumn <= + node.get_SourcePositionEnd().getColumn() - 1; + } + else { + containsPosition = true; + } + } + return containsPosition; + } + +} From dfe9665b96b58401a57dc1e5d66af694d78252d9 Mon Sep 17 00:00:00 2001 From: Dovydas Skauranskas <109866625+DovydasSkauranskas@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:35:38 +0200 Subject: [PATCH 14/29] MCStructuralTypes wird im Grammar importiert (#62) --- .../src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 | 1 + .../de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 b/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 index 0968db61..91cedf60 100644 --- a/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 +++ b/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 @@ -4,6 +4,7 @@ package de.monticore.lang; component grammar SysMLExpressions extends de.monticore.literals.MCCommonLiterals, // SignedLiteral de.monticore.types.MCBasicTypes, // MCType + de.monticore.types.MCStructuralTypes, de.monticore.expressions.CommonExpressions, // FieldAccessExpression de.monticore.ocl.OCLExpressions, // ExistsExpression de.monticore.ocl.SetExpressions, // UnionExpression diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java index 06827a24..642921ac 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java @@ -9,6 +9,7 @@ import de.monticore.ocl.types3.OCLSymTypeRelations; import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types.mcstructuraltypes.types3.MCStructuralTypesTypeVisitor; import de.monticore.types3.Type4Ast; import de.monticore.types3.TypeCheck3; import de.monticore.types3.streams.StreamSymTypeRelations; @@ -84,6 +85,10 @@ protected static void initTC3Delegate() { typeTraverser.add4MCBasicTypes(forBasicTypes); typeTraverser.add4SysMLExpressions(forBasicTypes); + var forStructuralTypes = new MCStructuralTypesTypeVisitor(); + forStructuralTypes.setType4Ast(type4Ast); + typeTraverser.add4MCStructuralTypes(forStructuralTypes); + // TODO are MCSimpleGenerics required? var forCollectionTypes = new MCCollectionTypesTypeVisitor(); forCollectionTypes.setType4Ast(type4Ast); From eb6e6e0853cdb5e13b7a15e56a6f117189ecb46b Mon Sep 17 00:00:00 2001 From: Mike <127297267+MKZaito@users.noreply.github.com> Date: Tue, 17 Feb 2026 19:03:37 +0100 Subject: [PATCH 15/29] 7.8.14: Allow Relativ ModelPaths and take current Workspace as Default (#63) * Update MCLSG Version to 7.8.1 * version bumb to 7.8.14 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 9c6432fc..c3e21634 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,10 +19,10 @@ sysmlGitlab = https://git.rwth-aachen.de/api/v4/projects/37093/packages/m # Dependencies mc_version = 7.8.0 -mclsg_version = 7.8.0 +mclsg_version = 7.8.1 se_commons_version = 7.8.0 assertj_version = 3.21.0 junit_version = 5.8.2 # Version of published artifacts -version = 7.8.13 +version = 7.8.14 From a993b4920c7763b4095d944ccf4ca557ad9350c9 Mon Sep 17 00:00:00 2001 From: Justus R <103401898+justusrm@users.noreply.github.com> Date: Tue, 24 Feb 2026 10:10:36 +0100 Subject: [PATCH 16/29] 7.8.15 Adapting CC-Requirement Adapter to work without sysml-ast reference (#65) * Removed intermediate constraints-ast from cc-ast representations * Version bump to 7.8.15 --- gradle.properties | 2 +- .../adapters/Requirement2RequirementCCAdapter.java | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index c3e21634..183af661 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.14 +version = 7.8.15 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java index df2f3a43..a54e28e5 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/Requirement2RequirementCCAdapter.java @@ -2,18 +2,12 @@ package de.monticore.lang.sysmlv2.symboltable.adapters; import de.monticore.lang.componentconnector._symboltable.RequirementSymbol; -import de.monticore.lang.sysmlconstraints._ast.ASTRequirementUsage; import de.monticore.lang.sysmlconstraints._symboltable.RequirementUsageSymbol; public class Requirement2RequirementCCAdapter extends RequirementSymbol { - private ASTRequirementUsage ccAST; public Requirement2RequirementCCAdapter(RequirementUsageSymbol requirementUsageSymbol) { super(requirementUsageSymbol.getFullName()); - this.ccAST = requirementUsageSymbol.getAstNode(); } - public ASTRequirementUsage getCcAST() { - return ccAST; - } } From 1c3f2fcbd624e27f6841a2c4c9044384d22c8fd4 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Tue, 24 Feb 2026 12:15:49 +0100 Subject: [PATCH 17/29] 7.8.16: old type check removed, new type check disabled --- build.gradle | 10 +- gradle.properties | 2 +- .../monticore/lang/sysmlv2/SysMLv2Tool.java | 41 +-- .../sysmlv2/cocos/AssignActionTypeCheck.java | 29 -- .../sysmlv2/cocos/ConstraintIsBoolean.java | 45 ---- .../sysmlv2/cocos/SendActionTypeCheck.java | 25 -- .../sysmlv2/cocos/SpecializationExists.java | 26 -- .../cocos/TypeCheckTransitionGuards.java | 43 --- .../test/java/cocos/ConstraintCoCoTest.java | 97 ++++++- .../java/cocos/RequirementSubjectTest.java | 4 +- .../SpecializationExistsCoCoTest.java} | 6 +- .../java/cocos/SpecializationExistsTest.java | 107 -------- .../java/cocos/{spesml => }/SpesMLTest.java | 2 +- .../src/test/java/symboltable/SymTabTest.java | 4 +- ...AccessExpressionInConstraintUsageTest.java | 15 +- ...FieldAccessExpressionInStateUsageTest.java | 203 ++++++++++---- .../src/test/java/typecheck/NegationTest.java | 92 ++++++- .../StreamConstructorExpressionsTest.java | 4 +- .../TC3FieldAccessInteroperabilityTest.java | 4 +- .../TypeCheck4CardinalExpressionsTest.java | 86 ------ ...heck4StreamConstructorExpressionsTest.java | 91 ------- .../test/java/types3/ConstraintCoCoTest.java | 202 -------------- ...FieldAccessExpressionInStateUsageTest.java | 251 ------------------ .../src/test/java/types3/NegationTest.java | 156 ----------- 24 files changed, 354 insertions(+), 1191 deletions(-) delete mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java delete mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java delete mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java delete mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java delete mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java rename language/src/test/java/{types3/SpecializationExistsTest.java => cocos/SpecializationExistsCoCoTest.java} (95%) delete mode 100644 language/src/test/java/cocos/SpecializationExistsTest.java rename language/src/test/java/cocos/{spesml => }/SpesMLTest.java (99%) rename language/src/test/java/{types3 => typecheck}/FieldAccessExpressionInConstraintUsageTest.java (91%) rename language/src/test/java/{types3 => typecheck}/StreamConstructorExpressionsTest.java (98%) rename language/src/test/java/{types3 => typecheck}/TC3FieldAccessInteroperabilityTest.java (98%) delete mode 100644 language/src/test/java/typecheck/TypeCheck4CardinalExpressionsTest.java delete mode 100644 language/src/test/java/typecheck/TypeCheck4StreamConstructorExpressionsTest.java delete mode 100644 language/src/test/java/types3/ConstraintCoCoTest.java delete mode 100644 language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java delete mode 100644 language/src/test/java/types3/NegationTest.java diff --git a/build.gradle b/build.gradle index deae1268..cfee3749 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ subprojects { group = 'de.monticore.lang.sysml_v2' // Needs to be after java plugin - sourceCompatibility = "11" + sourceCompatibility = JavaVersion.VERSION_11 project.buildDir = "target" @@ -19,8 +19,12 @@ subprojects { } // Java JDK Warning - if (JavaVersion.current() > sourceCompatibility) { - logger.warn("\u001B[33m Warning: You are currently using JDK Version " + JavaVersion.current() + ". " + "Higher JDK versions may cause compatibility problems. JDK 11 is recommended. \u001B[0m") + if (JavaVersion.current() > sourceCompatibility + && JavaVersion.current() != JavaVersion.VERSION_17) + { + logger.warn("\u001B[33m Warning: You are currently using JDK Version " + + JavaVersion.current() + ". " + "Higher JDK versions may cause " + + "compatibility problems. JDK 11 or 17 is recommended. \u001B[0m") } // Use the same testing framework for all modules diff --git a/gradle.properties b/gradle.properties index 183af661..03e261a4 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.15 +version = 7.8.16 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 4bd3bc19..2f3bded0 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -4,6 +4,7 @@ import de.monticore.lang.componentconnector.SerializationUtil; import de.monticore.lang.sysmlactions._cocos.SysMLActionsASTActionDefCoCo; import de.monticore.lang.sysmlconstraints._cocos.SysMLConstraintsASTConstraintDefCoCo; +import de.monticore.lang.sysmlconstraints._cocos.SysMLConstraintsASTRequirementDefCoCo; import de.monticore.lang.sysmlimportsandpackages._cocos.SysMLImportsAndPackagesASTSysMLPackageCoCo; import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTAttributeDefCoCo; import de.monticore.lang.sysmlparts._cocos.SysMLPartsASTPartDefCoCo; @@ -11,7 +12,6 @@ import de.monticore.lang.sysmlparts.coco.PortDefHasOneType; import de.monticore.lang.sysmlparts.coco.PortDefNeedsDirection; import de.monticore.lang.sysmlparts.symboltable.completers.ConvertEnumUsagesToFields; -import de.monticore.lang.sysmlconstraints._cocos.SysMLConstraintsASTRequirementDefCoCo; import de.monticore.lang.sysmlstates._cocos.SysMLStatesASTStateDefCoCo; import de.monticore.lang.sysmlstates._cocos.SysMLStatesASTStateUsageCoCo; import de.monticore.lang.sysmlstates.cocos.NoDoActions; @@ -23,31 +23,24 @@ import de.monticore.lang.sysmlv2._symboltable.ISysMLv2GlobalScope; import de.monticore.lang.sysmlv2._symboltable.SysMLv2Symbols2Json; import de.monticore.lang.sysmlv2._visitor.SysMLv2Traverser; -import de.monticore.lang.sysmlv2.cocos.AssignActionTypeCheck; import de.monticore.lang.sysmlv2.cocos.AssignActionTypeCheck3; -import de.monticore.lang.sysmlv2.cocos.ConstraintIsBoolean; -import de.monticore.lang.sysmlv2.cocos.ConstraintIsBooleanTC3; import de.monticore.lang.sysmlv2.cocos.FlowCheckCoCo; import de.monticore.lang.sysmlv2.cocos.NameCompatible4Isabelle; import de.monticore.lang.sysmlv2.cocos.OneCardinality; +import de.monticore.lang.sysmlv2.cocos.ParentComponentInputConnectionDirectionCoCo; import de.monticore.lang.sysmlv2.cocos.PartBehaviorCoCo; +import de.monticore.lang.sysmlv2.cocos.PartTypeDefinitionExistsCoCo; import de.monticore.lang.sysmlv2.cocos.PortDefinitionExistsCoCo; +import de.monticore.lang.sysmlv2.cocos.QualifiedPortNameExistsCoCo; import de.monticore.lang.sysmlv2.cocos.RefinementCyclic; -import de.monticore.lang.sysmlv2.cocos.SendActionTypeCheck; +import de.monticore.lang.sysmlv2.cocos.RefinementTargetDefinitionExistsCoCo; import de.monticore.lang.sysmlv2.cocos.SendActionTypeCheck3; -import de.monticore.lang.sysmlv2.cocos.SpecializationExists; -import de.monticore.lang.sysmlv2.cocos.SpecializationExistsTC3; import de.monticore.lang.sysmlv2.cocos.StateSupertypes; -import de.monticore.lang.sysmlv2.cocos.TypeCheckTransitionGuards; -import de.monticore.lang.sysmlv2.cocos.TypeCheck3TransitionGuards; -import de.monticore.lang.sysmlv2.cocos.WarnNonExhibited; -import de.monticore.lang.sysmlv2.cocos.PartTypeDefinitionExistsCoCo; -import de.monticore.lang.sysmlv2.cocos.ParentComponentInputConnectionDirectionCoCo; -import de.monticore.lang.sysmlv2.cocos.QualifiedPortNameExistsCoCo; -import de.monticore.lang.sysmlv2.cocos.RefinementTargetDefinitionExistsCoCo; +import de.monticore.lang.sysmlv2.cocos.SubPartNamesInConnectionExistCoCo; 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.SubPartNamesInConnectionExistCoCo; +import de.monticore.lang.sysmlv2.cocos.WarnNonExhibited; import de.monticore.lang.sysmlv2.symboltable.completers.CausalityCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectRefinementCompleter; import de.monticore.lang.sysmlv2.symboltable.completers.DirectionCompleter; @@ -114,18 +107,16 @@ public void prettyPrint(ASTSysMLModel ast, String file) { @Override public void runDefaultCoCos(ASTSysMLModel ast) { var checker = new SysMLv2CoCoChecker(); - checker.addCoCo((SysMLStatesASTStateDefCoCo) new StateSupertypes()); - checker.addCoCo((SysMLStatesASTStateUsageCoCo) new StateSupertypes()); - checker.addCoCo(new TypeCheckTransitionGuards()); - checker.addCoCo(new SendActionTypeCheck()); - checker.addCoCo(new AssignActionTypeCheck()); - // TC3 + // Type Check checker.addCoCo(new SendActionTypeCheck3()); checker.addCoCo(new AssignActionTypeCheck3()); checker.addCoCo(new TypeCheck3TransitionGuards()); - // Check Definitions exist + // Check that Defs exist checker.addCoCo(new PartTypeDefinitionExistsCoCo()); checker.addCoCo(new RefinementTargetDefinitionExistsCoCo()); + // Check that Defs are of correct type + checker.addCoCo((SysMLStatesASTStateDefCoCo) new StateSupertypes()); + checker.addCoCo((SysMLStatesASTStateUsageCoCo) new StateSupertypes()); // Connection CoCos checker.addCoCo(new SubPartNamesInConnectionExistCoCo()); checker.addCoCo(new QualifiedPortNameExistsCoCo()); @@ -145,12 +136,6 @@ public void runAdditionalCoCos( de.monticore.lang.sysmlv2._ast.ASTSysMLModel ast) { var checker = new SysMLv2CoCoChecker(); - // general - checker.addCoCo(new ConstraintIsBoolean()); - checker.addCoCo(new ConstraintIsBooleanTC3()); - checker.addCoCo(new SpecializationExists()); - checker.addCoCo(new SpecializationExistsTC3()); - // Not-supported language elements checker.addCoCo(new NoExitActions()); checker.addCoCo((SysMLStatesASTStateDefCoCo) new NoDoActions()); diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java deleted file mode 100644 index 470c7e66..00000000 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/AssignActionTypeCheck.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.monticore.lang.sysmlv2.cocos; - -import de.monticore.lang.sysmlactions._ast.ASTAssignmentActionUsage; -import de.monticore.lang.sysmlactions._ast.ASTSendActionUsage; -import de.monticore.lang.sysmlactions._cocos.SysMLActionsASTAssignmentActionUsageCoCo; -import de.monticore.lang.sysmlactions._cocos.SysMLActionsASTSendActionUsageCoCo; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; -import de.monticore.types.check.TypeCheck; - -@Deprecated -public class AssignActionTypeCheck implements SysMLActionsASTAssignmentActionUsageCoCo { - - @Override - public void check(ASTAssignmentActionUsage node) { - // Wir gehen davon aus, dass Send-Actions die Kanäle auf Ports nicht als Strom, - // sondern Element-Weise (i.e. Event-basiert) verarbeiten - var deriver = new SysMLDeriver(false); - deriver.init(); - var tc = new TypeCheck(); - - var type = deriver.deriveType(node.getValueExpression()); - if(!type.isPresentResult() || type.getResult().isObscureType()) { - // Error should already be logged? - } - // Vergleich zum Target steht noch aus. - // TODO Target zur Expression erheben (Grammatik ändenr), Checken, dann vergleichen - } - -} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java deleted file mode 100644 index da64dfc0..00000000 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/ConstraintIsBoolean.java +++ /dev/null @@ -1,45 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.lang.sysmlv2.cocos; - -import de.monticore.expressions.expressionsbasis._ast.ASTExpression; -import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; -import de.monticore.lang.sysmlconstraints._cocos.SysMLConstraintsASTConstraintUsageCoCo; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; -import de.monticore.types.check.TypeCheckResult; -import de.se_rwth.commons.SourcePosition; -import de.se_rwth.commons.SourcePositionBuilder; -import de.se_rwth.commons.logging.Log; - -@Deprecated -public class ConstraintIsBoolean implements SysMLConstraintsASTConstraintUsageCoCo { - - @Override public void check(ASTConstraintUsage node) { - // Expression ausgraben - ASTExpression expr = node.getExpression(); - - // TypeCheck (Deriver) initialisieren - var deriver = new SysMLDeriver(true); - - try { - TypeCheckResult type = deriver.deriveType(expr); - if(!type.isPresentResult() || type.getResult().getTypeInfo() == null) { - var start = node.get_SourcePositionStart(); - var end = constraintEnd(start); - Log.error("0x80001 Failed to derive a type!", start, end); - } - else if(!type.getResult().printFullName().equals("boolean")) { - Log.error("0x80002 The expression type is '" + type.getResult().printFullName() + "' but should be boolean!", expr.get_SourcePositionStart(), expr.get_SourcePositionEnd()); - } - } - catch (Exception e) { - var start = node.get_SourcePositionStart(); - var end = constraintEnd(start); - Log.error("0x80003 " + e.getClass().getSimpleName() + " while type checking!", start, end); - } - } - - private SourcePosition constraintEnd(SourcePosition start) { - return new SourcePositionBuilder().setFileName(start.getFileName().get()).setLine(start.getLine()).setColumn( - start.getColumn() + 11).build(); - } -} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java deleted file mode 100644 index 25803f74..00000000 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SendActionTypeCheck.java +++ /dev/null @@ -1,25 +0,0 @@ -package de.monticore.lang.sysmlv2.cocos; - -import de.monticore.lang.sysmlactions._ast.ASTSendActionUsage; -import de.monticore.lang.sysmlactions._cocos.SysMLActionsASTSendActionUsageCoCo; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; - -@Deprecated -public class SendActionTypeCheck implements SysMLActionsASTSendActionUsageCoCo { - - @Override - public void check(ASTSendActionUsage node) { - // Wir gehen davon aus, dass Send-Actions die Kanäle auf Ports nicht als Strom, - // sondern Element-Weise (i.e. Event-basiert) verarbeiten - var deriver = new SysMLDeriver(false); - deriver.init(); - - var payloadType = deriver.deriveType(node.getPayload()); - if(!payloadType.isPresentResult() || payloadType.getResult().isObscureType()) { - // Error should already be logged? - } - // Vergleich zum Target steht noch aus. - // TODO Target zur Expression erheben (Grammatik ändenr), Checken, dann vergleichen - } - -} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java deleted file mode 100644 index eabc1000..00000000 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/SpecializationExists.java +++ /dev/null @@ -1,26 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.lang.sysmlv2.cocos; - -import de.monticore.lang.sysmlbasis._ast.ASTSpecialization; -import de.monticore.lang.sysmlbasis._cocos.SysMLBasisASTSpecializationCoCo; -import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; -import de.monticore.lang.sysmlv2.types.SysMLSynthesizer; -import de.se_rwth.commons.logging.Log; - -@Deprecated -public class SpecializationExists implements SysMLBasisASTSpecializationCoCo { - - @Override - public void check(ASTSpecialization node) { - if (node.getEnclosingScope() instanceof ISysMLv2Scope) { - var scope = (ISysMLv2Scope)node.getEnclosingScope(); - // Synthesizers are used to "build" the SymType from ASTs - var synthesizer = new SysMLSynthesizer(); - for(var typeAst : node.getSuperTypesList()) { - // This will throw an 0xA0324 if the type does not exist. - synthesizer.synthesizeType(typeAst); - } - } - } - -} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java deleted file mode 100644 index 15a4f6e5..00000000 --- a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/TypeCheckTransitionGuards.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.monticore.lang.sysmlv2.cocos; - -import de.monticore.expressions.expressionsbasis._ast.ASTExpression; -import de.monticore.lang.sysmlstates._ast.ASTSysMLTransition; -import de.monticore.lang.sysmlstates._cocos.SysMLStatesASTSysMLTransitionCoCo; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; -import de.monticore.types.check.TypeCheckResult; -import de.se_rwth.commons.logging.Log; - -@Deprecated -public class TypeCheckTransitionGuards implements SysMLStatesASTSysMLTransitionCoCo { - - @Override - public void check(ASTSysMLTransition node) { - if(node.isPresentGuard()) { - // Expression ausgraben - ASTExpression expr = node.getGuard(); - - // TypeCheck (Deriver) initialisieren - var deriver = new SysMLDeriver(false); - - try { - TypeCheckResult type = deriver.deriveType(expr); - if(!type.isPresentResult() || type.getResult().getTypeInfo() == null) { - Log.error("0x80004 Failed to derive a type!", - expr.get_SourcePositionStart(), - expr.get_SourcePositionEnd()); - } - else if(!type.getResult().printFullName().equals("boolean")) { - Log.error("0x80005 The expression type is '" + type.getResult().printFullName() + "' but should be boolean!", - expr.get_SourcePositionStart(), - expr.get_SourcePositionEnd()); - } - } - catch (Exception e) { - Log.error("0x80006 " + e.getClass().getSimpleName() + " while type checking!", - expr.get_SourcePositionStart(), - expr.get_SourcePositionEnd()); - } - } - } - -} diff --git a/language/src/test/java/cocos/ConstraintCoCoTest.java b/language/src/test/java/cocos/ConstraintCoCoTest.java index 09ed9b5a..10873836 100644 --- a/language/src/test/java/cocos/ConstraintCoCoTest.java +++ b/language/src/test/java/cocos/ConstraintCoCoTest.java @@ -1,17 +1,29 @@ /* (c) https://github.com/MontiCore/monticore */ package cocos; +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; 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.cocos.ConstraintIsBoolean; -import de.monticore.ocl.types3.OCLSymTypeRelations; -import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.lang.sysmlv2.cocos.ConstraintIsBooleanTC3; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.streams.StreamSymTypeRelations; import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.LogStub; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; @@ -31,13 +43,61 @@ public class ConstraintCoCoTest { @BeforeAll public static void init() { LogStub.init(); - SysMLv2Mill.init(); } @BeforeEach public void reset() { Log.getFindings().clear(); tool = new SysMLv2Tool(); tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); } @ParameterizedTest(name = "{index} - {0} does pass all checks w/o errors") @@ -58,6 +118,18 @@ public class ConstraintCoCoTest { "14_valid.sysml", // StreamConstructor Expression "15_valid.sysml", //Times function for StreamConstructor Expression "16_valid.sysml", //Inftimes and takes function + "17_valid.sysml", // user defined type + "18_valid.sysml", // user defined type channels + + "implicitFieldAccess/2_valid.sysml", // resolve & compare ports + "implicitFieldAccess/4_valid.sysml", // stream snth + "implicitFieldAccess/11_valid.sysml", // stream length + "implicitFieldAccess/14_valid.sysml", // StreamConstructor Expression + "implicitFieldAccess/15_valid.sysml", //Times function for StreamConstructor Expression + "implicitFieldAccess/17_valid.sysml", // user defined type + "implicitFieldAccess/18_valid.sysml", // user defined type channels + "implicitFieldAccess/19_valid.sysml", // interoperability between implicit and explicit + }) public void testValid(String modelName) throws IOException { var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); @@ -70,7 +142,7 @@ public void testValid(String modelName) throws IOException { tool.finalizeSymbolTable(ast); var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new ConstraintIsBoolean()); + checker.addCoCo(new ConstraintIsBooleanTC3()); checker.checkAll(ast); assertTrue(Log.getFindings().isEmpty(), () -> Log.getFindings().toString()); @@ -94,6 +166,17 @@ public void testValid(String modelName) throws IOException { "14_invalid.sysml", // StreamConstructor Expression "15_invalid.sysml", //Times function for StreamConstructor Expression "16_invalid.sysml", //Inftimes and takes function + "17_invalid.sysml", // user defined type + "18_invalid.sysml", // user defined type channels + + "implicitFieldAccess/2_invalid.sysml", // resolve & compare ports + "implicitFieldAccess/4_invalid.sysml", // stream snth + "implicitFieldAccess/11_invalid.sysml", // stream length + "implicitFieldAccess/14_invalid.sysml", // StreamConstructor Expression + "implicitFieldAccess/15_invalid.sysml", //Times function for StreamConstructor Expression + "implicitFieldAccess/17_invalid.sysml", // user defined type + "implicitFieldAccess/18_invalid.sysml", // user defined type channels + "implicitFieldAccess/19_invalid.sysml", // interoperability between implicit and explicit }) public void testInvalid(String modelName) throws IOException { var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); @@ -106,7 +189,7 @@ public void testInvalid(String modelName) throws IOException { tool.finalizeSymbolTable(ast); var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new ConstraintIsBoolean()); + checker.addCoCo(new ConstraintIsBooleanTC3()); Log.enableFailQuick(false); checker.checkAll(ast); assertFalse(Log.getFindings().isEmpty()); diff --git a/language/src/test/java/cocos/RequirementSubjectTest.java b/language/src/test/java/cocos/RequirementSubjectTest.java index 1d2b75da..f1c1ca9e 100644 --- a/language/src/test/java/cocos/RequirementSubjectTest.java +++ b/language/src/test/java/cocos/RequirementSubjectTest.java @@ -3,7 +3,7 @@ import de.monticore.lang.sysmlv2._ast.ASTSysMLModel; import de.monticore.lang.sysmlv2._cocos.SysMLv2CoCoChecker; -import de.monticore.lang.sysmlv2.cocos.ConstraintIsBoolean; +import de.monticore.lang.sysmlv2.cocos.ConstraintIsBooleanTC3; import de.se_rwth.commons.logging.Finding; import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.Test; @@ -37,7 +37,7 @@ public void testInvalid() throws IOException { private List check(ASTSysMLModel ast) { var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new ConstraintIsBoolean()); + checker.addCoCo(new ConstraintIsBooleanTC3()); Log.enableFailQuick(false); checker.checkAll(ast); return Log.getFindings().stream().filter(f -> f.isError()).collect(Collectors.toList()); diff --git a/language/src/test/java/types3/SpecializationExistsTest.java b/language/src/test/java/cocos/SpecializationExistsCoCoTest.java similarity index 95% rename from language/src/test/java/types3/SpecializationExistsTest.java rename to language/src/test/java/cocos/SpecializationExistsCoCoTest.java index ed1ee86f..60fd5a15 100644 --- a/language/src/test/java/types3/SpecializationExistsTest.java +++ b/language/src/test/java/cocos/SpecializationExistsCoCoTest.java @@ -1,15 +1,13 @@ /* (c) https://github.com/MontiCore/monticore */ -package types3; +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._symboltable.ISysMLv2ArtifactScope; -import de.monticore.lang.sysmlv2.cocos.SpecializationExists; import de.monticore.lang.sysmlv2.cocos.SpecializationExistsTC3; import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; -import de.monticore.types3.TypeCheck3; import de.se_rwth.commons.logging.Finding; import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.AfterEach; @@ -26,7 +24,7 @@ /** * Prüft das Finden von Types der Specializations */ -public class SpecializationExistsTest { +public class SpecializationExistsCoCoTest { @BeforeAll static void setup() { diff --git a/language/src/test/java/cocos/SpecializationExistsTest.java b/language/src/test/java/cocos/SpecializationExistsTest.java deleted file mode 100644 index 097f0b7b..00000000 --- a/language/src/test/java/cocos/SpecializationExistsTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* (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._symboltable.ISysMLv2ArtifactScope; -import de.monticore.lang.sysmlv2.cocos.SpecializationExists; -import de.se_rwth.commons.logging.Finding; -import de.se_rwth.commons.logging.Log; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Prüft das Finden von Types der Specializations - */ -public class SpecializationExistsTest { - - @BeforeAll - static void setup() { - SysMLv2Mill.init(); - } - - @BeforeEach - void clear() { - SysMLv2Mill.globalScope().clear(); - SysMLv2Mill.initializePrimitives(); - SysMLv2Mill.addCollectionTypes(); - Log.clearFindings(); - } - - @Test - public void testMissingDefinition() throws IOException { - var model = "requirement Invalid { subject s: NonExistent; }"; - var ast = parse(model); - createSt(ast); - var errors = check(ast); - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getMsg()).contains("0xA0324 Cannot find symbol NonExistent"); - } - - @Test - public void testExistingDefinition() throws IOException { - var model = "part def Existent; requirement Valid { subject s: Existent; }"; - var ast = parse(model); - createSt(ast); - var errors = check(ast); - assertThat(errors).hasSize(0); - } - - // Should also work with state defs - @Test - public void testExistingStateDefinition() throws IOException { - var model = "state def Existent; requirement Valid { subject s: Existent; }"; - var ast = parse(model); - createSt(ast); - var errors = check(ast); - assertThat(errors).hasSize(0); - } - - @Test - public void testExistingCollectionType() throws IOException { - var model = "attribute def Existent; part def Valid { attribute e: List; }"; - var ast = parse(model); - createSt(ast); - var errors = check(ast); - assertThat(errors).hasSize(0); - } - - 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 check(ASTSysMLModel ast) { - var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new SpecializationExists()); - Log.enableFailQuick(false); - checker.checkAll(ast); - return Log.getFindings().stream().filter(f -> f.isError()).collect(Collectors.toList()); - } - - @AfterEach - void clearLog() { - Log.clearFindings(); - Log.enableFailQuick(true); - } - -} diff --git a/language/src/test/java/cocos/spesml/SpesMLTest.java b/language/src/test/java/cocos/SpesMLTest.java similarity index 99% rename from language/src/test/java/cocos/spesml/SpesMLTest.java rename to language/src/test/java/cocos/SpesMLTest.java index 5af7616d..bcb84938 100644 --- a/language/src/test/java/cocos/spesml/SpesMLTest.java +++ b/language/src/test/java/cocos/SpesMLTest.java @@ -1,5 +1,5 @@ /* (c) https://github.com/MontiCore/monticore */ -package cocos.spesml; +package cocos; import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; diff --git a/language/src/test/java/symboltable/SymTabTest.java b/language/src/test/java/symboltable/SymTabTest.java index 6751b319..823dd564 100644 --- a/language/src/test/java/symboltable/SymTabTest.java +++ b/language/src/test/java/symboltable/SymTabTest.java @@ -6,7 +6,7 @@ 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.cocos.ConstraintIsBoolean; +import de.monticore.lang.sysmlv2.cocos.ConstraintIsBooleanTC3; import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.LogStub; import org.junit.jupiter.api.Assertions; @@ -45,7 +45,7 @@ public void testStream() throws IOException { Assertions.assertTrue(streamSymOpt.isPresent(), "Stream symbol should be resolvable!"); var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new ConstraintIsBoolean()); + checker.addCoCo(new ConstraintIsBooleanTC3()); checker.checkAll(ast); tool.runDefaultCoCos(ast); tool.runAdditionalCoCos(ast); diff --git a/language/src/test/java/types3/FieldAccessExpressionInConstraintUsageTest.java b/language/src/test/java/typecheck/FieldAccessExpressionInConstraintUsageTest.java similarity index 91% rename from language/src/test/java/types3/FieldAccessExpressionInConstraintUsageTest.java rename to language/src/test/java/typecheck/FieldAccessExpressionInConstraintUsageTest.java index fa96a73b..d77c27c4 100644 --- a/language/src/test/java/types3/FieldAccessExpressionInConstraintUsageTest.java +++ b/language/src/test/java/typecheck/FieldAccessExpressionInConstraintUsageTest.java @@ -1,4 +1,4 @@ -package types3; +package typecheck; import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; @@ -8,7 +8,6 @@ import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; @@ -23,13 +22,10 @@ import de.monticore.types3.Type4Ast; import de.monticore.types3.TypeCheck3; import de.monticore.types3.streams.StreamSymTypeRelations; -import de.monticore.types3.util.MapBasedTypeCheck3; 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.Disabled; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -107,10 +103,8 @@ public void reset() { @ParameterizedTest @ValueSource(strings = { "port def F { attribute a: boolean[2]; } part s { port f: F; constraint e { f.a[1] } }", - "port def F { attribute a: boolean; } part s { port f: F[1]; constraint e { f[1].a } }", + "port def F { attribute a: boolean; } part s { port f: F[1]; constraint e { f[1].a } }" - "port def F { attribute a: boolean[2]; } part s { port f: F; constraint e { f[1] } }", - "port def F { attribute a: boolean; } part s { port f: F[1]; constraint e { f[1] } }" }) public void test4ValidExpr1(String model) throws IOException { var ast = parser.parse_String(model); assertThat(ast).isPresent(); @@ -148,9 +142,8 @@ public void test4InvalidExpr(String model) throws IOException { var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); var type = TypeCheck3.typeOf(expr); - assertTrue(type.isObscureType() || - !Log.getFindings().isEmpty() || - !type.printFullName().equals("EventStream.EventStream")); + + assertFalse(type.printFullName().equals("EventStream.EventStream")); } } diff --git a/language/src/test/java/typecheck/FieldAccessExpressionInStateUsageTest.java b/language/src/test/java/typecheck/FieldAccessExpressionInStateUsageTest.java index e9ad4304..91785613 100644 --- a/language/src/test/java/typecheck/FieldAccessExpressionInStateUsageTest.java +++ b/language/src/test/java/typecheck/FieldAccessExpressionInStateUsageTest.java @@ -1,22 +1,36 @@ package typecheck; +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; -import de.monticore.lang.sysmlparts._ast.ASTAttributeUsage; import de.monticore.lang.sysmlparts._ast.ASTPartDef; -import de.monticore.lang.sysmlparts._ast.ASTPortDef; import de.monticore.lang.sysmlstates._ast.ASTStateUsage; import de.monticore.lang.sysmlstates._ast.ASTSysMLTransition; import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; -import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.LogStub; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -25,18 +39,14 @@ import java.util.stream.Stream; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** - *

This test is about TypeCheck.

+ *

This test is about TypeCheck3 deriving the types of FieldAccessExpressions in StateUsages.

* - *

In this test, the expression is calculated by creating SysMLExpressionsDeriver with a boolean parameter.

- * - *

When ASTFieldAccessExpression and ASTOCLArrayQualification are in StateUsage, this parameter - * is set to false and we test whether they are not calculated as Stream.

- * - *

For comparison, we set this parameter is set to true (This is the same as creating - * SysMLExpressionsDeriver without parameter) for ASTFieldAccessExpression in ConstraintUsage, - * we test whether ASTFieldAccessExpression will still be calculated as Stream.

+ *

When ASTFieldAccessExpression and ASTOCLArrayQualification are in StateUsage + * we test whether they are not calculated as Stream such as in constraints.

*/ public class FieldAccessExpressionInStateUsageTest { @@ -52,38 +62,120 @@ public static void init() { public void reset() { Log.getFindings().clear(); tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); } static Stream createInputs() { return Stream.of( Arguments.of( "port def F { attribute a: boolean; }" + - "part def X { port f: F; state s { transition first S if f.a then S; } }", - false), - Arguments.of( + "part def X { port f: F; state s { transition first S if f.a then S; } }") + ,Arguments.of( "port def F { attribute a: boolean[3]; }" + - "part def X { port f: F; state s { transition first S if f.a[1] then S; } }", - false), - Arguments.of( + "part def X { port f: F; state s { transition first S if f.a[1] then S; } }") + ,Arguments.of( "port def F { attribute a: boolean; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a then S; } }", - false), - Arguments.of( + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a then S; } }") + ,Arguments.of( "port def F { attribute a: boolean[3]; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a[1] then S; } }", - false), + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; } part def X { port f: F; constraint e { f.a } }") + ,Arguments.of( + "port def F { attribute a: boolean; } part def X { port f: F[3]; constraint e { f[1].a } }") + + + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; }" + + "part def X { port f: F; state s { transition first S if f.a then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; }" + + "part def X { port f: F; state s { transition first S if f.a[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F; constraint e { f.a } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F[3]; constraint e { f[1].a } }") + ); + } + + static Stream createInvalidInputs() { + return Stream.of( Arguments.of( - "port def F { attribute a: boolean; } part def X { port f: F; constraint e { f.a } }", - true) + "port def F { attribute a: boolean; attribute b: nat; }" + + "part def X { port f: F; state s { transition first S if f then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; }" + + "part def X { port f: F; state s { transition first S if f[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; attribute b: nat; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean[3]; attribute b: nat[3]; } " + + "part def X { port f: F[3]; exhibit state s { transition first S if f[1][1] then S; } }") + ,Arguments.of( + "port def F { attribute a: boolean; } part def X { port f: F; constraint e { f } }") ); } @ParameterizedTest @MethodSource({ "createInputs" }) - public void test(String model, boolean isStream) throws IOException { + public void test(String model) throws IOException { var ast = parser.parse_String(model); assertThat(ast).isPresent(); - var deriver = new SysMLDeriver(isStream); var astSysmlmodel = ast.get(); SysMLv2Mill.scopesGenitorDelegator().createFromAST(astSysmlmodel); tool.completeSymbolTable(astSysmlmodel); @@ -92,37 +184,46 @@ public void test(String model, boolean isStream) throws IOException { if (astSysmlelement instanceof ASTStateUsage) { var astTransition = ((ASTStateUsage) astSysmlelement).getSysMLElement(0); var expr = ((ASTSysMLTransition) astTransition).getGuard(); - var type = deriver.deriveType(expr); - assertThat(type.getResult().printFullName()).isEqualTo("boolean"); + var type = TypeCheck3.typeOf(expr); + assertThat(type.printFullName()).isEqualTo("boolean"); } else if (astSysmlelement instanceof ASTConstraintUsage) { var expr = ((ASTConstraintUsage) astSysmlelement).getExpression(); - var type = deriver.deriveType(expr); - assertThat(type.getResult().printFullName()).isEqualTo("EventStream.EventStream"); - } else { - // TODO The test is too complex - Assertions.fail("ASTSysMLElement should here be ASTStateUsage or ASTConstraintUsage"); + var type = TypeCheck3.typeOf(expr); + assertThat(type.printFullName()).isEqualTo( + "EventStream.EventStream"); + } + else { + Assertions.fail("ASTSysMLElement should here be ASTStateUsage"); } } - @Test - public void testProblem() throws IOException { - var ast = parser.parse_String("attribute a: boolean;"); + @ParameterizedTest + @MethodSource({ "createInvalidInputs" }) + public void testInvalid(String model) throws IOException { + var ast = parser.parse_String(model); assertThat(ast).isPresent(); var astSysmlmodel = ast.get(); SysMLv2Mill.scopesGenitorDelegator().createFromAST(astSysmlmodel); tool.completeSymbolTable(astSysmlmodel); - ASTAttributeUsage attr = (ASTAttributeUsage) astSysmlmodel.getSysMLElementList().get(0); - assertThat(attr.getEnclosingScope().resolveVariable("a").get().getType().printFullName()).isEqualTo("boolean"); - } + var astPartdef = astSysmlmodel.getSysMLElementList().get(1); + var astSysmlelement = ((ASTPartDef) astPartdef).getSysMLElement(1); + SymTypeExpression type = SymTypeExpressionFactory.createObscureType(); - @Test - public void testProblem2() throws IOException { - var ast = parser.parse_String("port def P { attribute a: boolean; }"); - assertThat(ast).isPresent(); - var astSysmlmodel = ast.get(); - SysMLv2Mill.scopesGenitorDelegator().createFromAST(astSysmlmodel); - tool.completeSymbolTable(astSysmlmodel); - var attr = (ASTPortDef) astSysmlmodel.getSysMLElementList().get(0); - assertThat(attr.getSpannedScope().resolveVariable("a").get().getType().printFullName()).isEqualTo("boolean"); + Log.enableFailQuick(false); + + if (astSysmlelement instanceof ASTStateUsage) { + var astTransition = ((ASTStateUsage) astSysmlelement).getSysMLElement(0); + var expr = ((ASTSysMLTransition) astTransition).getGuard(); + type = TypeCheck3.typeOf(expr); + } else if (astSysmlelement instanceof ASTConstraintUsage) { + var expr = ((ASTConstraintUsage) astSysmlelement).getExpression(); + type = TypeCheck3.typeOf(expr); + } + else { + Assertions.fail("ASTSysMLElement should here be ASTStateUsage"); + } + + assertTrue(!type.isPrimitive() || !type.asPrimitive().getPrimitiveName().equals("boolean")); + Log.enableFailQuick(true); } } diff --git a/language/src/test/java/typecheck/NegationTest.java b/language/src/test/java/typecheck/NegationTest.java index 1b101de6..6c52f112 100644 --- a/language/src/test/java/typecheck/NegationTest.java +++ b/language/src/test/java/typecheck/NegationTest.java @@ -1,13 +1,29 @@ package typecheck; import de.monticore.expressions.commonexpressions._ast.ASTEqualsExpression; -import de.monticore.expressions.commonexpressions._ast.ASTLogicalNotExpression; +import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; import de.monticore.lang.sysmlparts._ast.ASTPartUsage; +import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; +import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; +import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; +import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; +import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; +import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; +import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; import de.monticore.ocl.oclexpressions._ast.ASTForallExpression; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; +import de.monticore.types3.Type4Ast; +import de.monticore.types3.TypeCheck3; +import de.monticore.types3.streams.StreamSymTypeRelations; import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.LogStub; import org.junit.jupiter.api.BeforeAll; @@ -18,6 +34,7 @@ import java.io.IOException; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; public class NegationTest { @@ -34,6 +51,55 @@ public static void init() { public void reset() { Log.getFindings().clear(); tool.init(); + + var type4Ast = new Type4Ast(); + var typeTraverser = SysMLv2Mill.inheritanceTraverser(); + + var forBasis = new ExpressionBasisTypeVisitor(); + forBasis.setType4Ast(type4Ast); + typeTraverser.add4ExpressionsBasis(forBasis); + + var forLiterals = new MCCommonLiteralsTypeVisitor(); + forLiterals.setType4Ast(type4Ast); + typeTraverser.add4MCCommonLiterals(forLiterals); + + var forCommon = new SysMLCommonExpressionsTypeVisitor(); + forCommon.setType4Ast(type4Ast); + typeTraverser.add4CommonExpressions(forCommon); + typeTraverser.setCommonExpressionsHandler(forCommon); + typeTraverser.add4SysMLExpressions(forCommon); + typeTraverser.setSysMLExpressionsHandler(forCommon); + + var forOcl = new SysMLOCLExpressionsTypeVisitor(); + forOcl.setType4Ast(type4Ast); + typeTraverser.add4OCLExpressions(forOcl); + typeTraverser.add4SysMLExpressions(forOcl); + + var forStreams = new StreamExpressionsTypeVisitor(); + forStreams.setType4Ast(type4Ast); + typeTraverser.add4StreamExpressions(forStreams); + + var forSets = new SysMLSetExpressionsTypeVisitor(); + forSets.setType4Ast(type4Ast); + typeTraverser.add4SetExpressions(forSets); + + var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); + forBasicTypes.setType4Ast(type4Ast); + typeTraverser.add4MCBasicTypes(forBasicTypes); + typeTraverser.add4SysMLExpressions(forBasicTypes); + + var forCollectionTypes = new MCCollectionTypesTypeVisitor(); + forCollectionTypes.setType4Ast(type4Ast); + typeTraverser.add4MCCollectionTypes(forCollectionTypes); + + StreamSymTypeRelations.init(); + SysMLWithinScopeBasicSymbolResolver.init(); + SysMLTypeVisitorOperatorCalculator.init(); + CommonExpressionsLValueRelations.init(); + MCCollectionSymTypeRelations.init(); + SysMLSymTypeRelations.init(); + + new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); } @ParameterizedTest @@ -54,12 +120,11 @@ public void testNotBooleanStream(String model) throws IOException { var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); var forAllExpr = (ASTForallExpression)(((ASTConstraintUsage) constraintUsage).getExpression()); var equalsExpr = (ASTEqualsExpression) forAllExpr.getExpression(); - var deriver = new SysMLDeriver(); - var rightType = deriver.deriveType(equalsExpr.getRight()); - var leftType = deriver.deriveType(equalsExpr.getLeft()); - assertTrue(rightType.isPresentResult()); - assertThat(rightType.getResult().printFullName()).isEqualTo("UntimedStream.UntimedStream"); - assertThat(rightType.getResult().equals(leftType.getResult())); + var rightType = TypeCheck3.typeOf(equalsExpr.getRight()); + var leftType = TypeCheck3.typeOf(equalsExpr.getLeft()); + assertFalse(rightType.isObscureType()); + assertThat(rightType.printFullName()).isEqualTo("UntimedStream.UntimedStream"); + assertTrue(rightType.deepEquals(leftType)); } @ParameterizedTest @@ -80,11 +145,10 @@ public void testNotBoolean(String model) throws IOException { var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(0); var forAllExpr = (ASTForallExpression)(((ASTConstraintUsage) constraintUsage).getExpression()); var equalsExpr = (ASTEqualsExpression) forAllExpr.getExpression(); - var deriver = new SysMLDeriver(); - var rightType = deriver.deriveType(equalsExpr.getRight()); - var leftType = deriver.deriveType(equalsExpr.getLeft()); - assertTrue(rightType.isPresentResult()); - assertThat(rightType.getResult().printFullName()).isEqualTo("boolean"); - assertThat(rightType.getResult().equals(leftType.getResult())); + var rightType = TypeCheck3.typeOf(equalsExpr.getRight()); + var leftType = TypeCheck3.typeOf(equalsExpr.getLeft()); + assertFalse(rightType.isObscureType()); + assertThat(rightType.printFullName()).isEqualTo("boolean"); + assertTrue(rightType.deepEquals(leftType)); } } diff --git a/language/src/test/java/types3/StreamConstructorExpressionsTest.java b/language/src/test/java/typecheck/StreamConstructorExpressionsTest.java similarity index 98% rename from language/src/test/java/types3/StreamConstructorExpressionsTest.java rename to language/src/test/java/typecheck/StreamConstructorExpressionsTest.java index 276c7697..21812d28 100644 --- a/language/src/test/java/types3/StreamConstructorExpressionsTest.java +++ b/language/src/test/java/typecheck/StreamConstructorExpressionsTest.java @@ -1,4 +1,4 @@ -package types3; +package typecheck; import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; @@ -8,7 +8,6 @@ import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; @@ -25,7 +24,6 @@ import de.monticore.types3.Type4Ast; import de.monticore.types3.TypeCheck3; import de.monticore.types3.streams.StreamSymTypeRelations; -import de.monticore.types3.util.MapBasedTypeCheck3; import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.LogStub; import org.junit.jupiter.api.BeforeAll; diff --git a/language/src/test/java/types3/TC3FieldAccessInteroperabilityTest.java b/language/src/test/java/typecheck/TC3FieldAccessInteroperabilityTest.java similarity index 98% rename from language/src/test/java/types3/TC3FieldAccessInteroperabilityTest.java rename to language/src/test/java/typecheck/TC3FieldAccessInteroperabilityTest.java index bf4b6185..2e57a2f4 100644 --- a/language/src/test/java/types3/TC3FieldAccessInteroperabilityTest.java +++ b/language/src/test/java/typecheck/TC3FieldAccessInteroperabilityTest.java @@ -1,4 +1,4 @@ -package types3; +package typecheck; import de.monticore.expressions.commonexpressions._ast.ASTEqualsExpression; import de.monticore.expressions.commonexpressions._ast.ASTFieldAccessExpression; @@ -11,8 +11,6 @@ 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.cocos.ConstraintIsBooleanTC3; import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; diff --git a/language/src/test/java/typecheck/TypeCheck4CardinalExpressionsTest.java b/language/src/test/java/typecheck/TypeCheck4CardinalExpressionsTest.java deleted file mode 100644 index 58c46888..00000000 --- a/language/src/test/java/typecheck/TypeCheck4CardinalExpressionsTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package typecheck; - -import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; -import de.monticore.lang.sysmlparts._ast.ASTPartUsage; -import de.monticore.lang.sysmlv2.SysMLv2Mill; -import de.monticore.lang.sysmlv2.SysMLv2Tool; -import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; -import de.monticore.symbols.basicsymbols.BasicSymbolsMill; -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.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.io.IOException; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class TypeCheck4CardinalExpressionsTest { - - private final SysMLv2Parser parser = new SysMLv2Parser(); - private final SysMLv2Tool tool = new SysMLv2Tool(); - - @BeforeAll - public static void init() { - LogStub.init(); - } - - @BeforeEach - public void reset() { - Log.getFindings().clear(); - tool.init(); - } - - @ParameterizedTest - @ValueSource(strings = { - "port def F { attribute a: boolean[2]; } part s { port f: F; constraint e { f.a[1] } }", - "port def F { attribute a: boolean; } part s { port f: F[1]; constraint e { f[1].a } }" - }) public void test4ValidExpr1(String model) throws IOException { - var ast = parser.parse_String(model); - assertThat(ast).isPresent(); - var astSysMLModel = ast.get(); - - tool.createSymbolTable(astSysMLModel); - tool.completeSymbolTable(astSysMLModel); - tool.finalizeSymbolTable(astSysMLModel); - - var sysmlelements = astSysMLModel.getSysMLElementList(); - var astPartUsage = sysmlelements.get(1); - var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); - var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); - var deriver = new SysMLDeriver(); - var type = deriver.deriveType(expr); - assertTrue(type.isPresentResult()); - assertThat(type.getResult().printFullName()).isEqualTo("EventStream.EventStream"); - } - - @Test - @Disabled - public void test4InvalidExpr() throws IOException { - var model = "port def F { attribute a: boolean; } part s { port f: F[2]; constraint e { f.a } }"; - var ast = parser.parse_String(model); - assertThat(ast).isPresent(); - var astSysMLModel = ast.get(); - - tool.createSymbolTable(astSysMLModel); - tool.completeSymbolTable(astSysMLModel); - tool.finalizeSymbolTable(astSysMLModel); - - var sysmlelements = astSysMLModel.getSysMLElementList(); - var astPartUsage = sysmlelements.get(1); - var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); - var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); - var deriver = new SysMLDeriver(); - var type = deriver.deriveType(expr); - assertTrue(type.getResult().isObscureType()); - assertTrue(!Log.getFindings().isEmpty()); - } -} - - diff --git a/language/src/test/java/typecheck/TypeCheck4StreamConstructorExpressionsTest.java b/language/src/test/java/typecheck/TypeCheck4StreamConstructorExpressionsTest.java deleted file mode 100644 index 450f8bb9..00000000 --- a/language/src/test/java/typecheck/TypeCheck4StreamConstructorExpressionsTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package typecheck; - -import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; -import de.monticore.lang.sysmlparts._ast.ASTPartUsage; -import de.monticore.lang.sysmlv2.SysMLv2Mill; -import de.monticore.lang.sysmlv2.SysMLv2Tool; -import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; -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.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.io.IOException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class TypeCheck4StreamConstructorExpressionsTest { - - private final SysMLv2Parser parser = new SysMLv2Parser(); - private final SysMLv2Tool tool = new SysMLv2Tool(); - - @BeforeAll - public static void setup() { - LogStub.init(); - SysMLv2Mill.init(); - } - - @BeforeEach - public void clear() { - Log.clearFindings(); - tool.init(); - } - - @ParameterizedTest - @ValueSource(strings = { - "port def F { attribute a: boolean; } part s { port f: F; constraint e {} }", - "port def F { attribute a: boolean; } part s { port f: F; constraint e {} }" - }) - public void test4validStream(String model) throws IOException { - var ast = parser.parse_String(model); - - assertThat(ast).isPresent(); - assertThat(Log.getFindings()).isEmpty(); - var astSysMLModel = ast.get(); - - tool.createSymbolTable(astSysMLModel); - tool.completeSymbolTable(astSysMLModel); - tool.finalizeSymbolTable(astSysMLModel); - - var sysmlelements = astSysMLModel.getSysMLElementList(); - var astPartUsage = sysmlelements.get(1); - var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); - var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); - var deriver = new SysMLDeriver(); - var type = deriver.deriveType(expr); - assertTrue(type.isPresentResult()); - assertThat(type.getResult().printFullName()).isEqualTo("Stream.Stream"); - } - - @ParameterizedTest - @ValueSource(strings = { - "port def F { attribute a: boolean; } part s { port f: F; constraint e {} }", - "port def F { attribute a: boolean; } part s { port f: F; constraint e { >} }" - }) - public void test4invalidStream(String model) throws IOException { - var ast = parser.parse_String(model); - - assertThat(ast).isPresent(); - assertThat(Log.getFindings()).isEmpty(); - var astSysMLModel = ast.get(); - - tool.createSymbolTable(astSysMLModel); - tool.completeSymbolTable(astSysMLModel); - tool.finalizeSymbolTable(astSysMLModel); - - var sysmlelements = astSysMLModel.getSysMLElementList(); - var astPartUsage = sysmlelements.get(1); - var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); - var expr = ((ASTConstraintUsage) constraintUsage).getExpression(); - var deriver = new SysMLDeriver(); - var type = deriver.deriveType(expr); - assertTrue(type.isPresentResult()); - assertFalse(Log.getFindings().isEmpty()); - assertThat(type.getResult().printFullName()).isEqualTo("Stream.Stream"); - } -} diff --git a/language/src/test/java/types3/ConstraintCoCoTest.java b/language/src/test/java/types3/ConstraintCoCoTest.java deleted file mode 100644 index b033bf3e..00000000 --- a/language/src/test/java/types3/ConstraintCoCoTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package types3; - -import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; -import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; -import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; -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.cocos.ConstraintIsBooleanTC3; -import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; -import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; -import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; -import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; -import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; -import de.monticore.ocl.types3.OCLSymTypeRelations; -import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; -import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; -import de.monticore.types3.Type4Ast; -import de.monticore.types3.streams.StreamSymTypeRelations; -import de.monticore.types3.util.MapBasedTypeCheck3; -import de.monticore.types3.util.WithinScopeBasicSymbolsResolver; -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.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.io.IOException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class ConstraintCoCoTest { - - private static final String MODEL_PATH = "src/test/resources/cocos/constraints"; - - private SysMLv2Tool tool; - - @BeforeAll public static void init() { - LogStub.init(); - } - - @BeforeEach public void reset() { - Log.getFindings().clear(); - tool = new SysMLv2Tool(); - tool.init(); - - var type4Ast = new Type4Ast(); - var typeTraverser = SysMLv2Mill.inheritanceTraverser(); - - var forBasis = new ExpressionBasisTypeVisitor(); - forBasis.setType4Ast(type4Ast); - typeTraverser.add4ExpressionsBasis(forBasis); - - var forLiterals = new MCCommonLiteralsTypeVisitor(); - forLiterals.setType4Ast(type4Ast); - typeTraverser.add4MCCommonLiterals(forLiterals); - - var forCommon = new SysMLCommonExpressionsTypeVisitor(); - forCommon.setType4Ast(type4Ast); - typeTraverser.add4CommonExpressions(forCommon); - typeTraverser.setCommonExpressionsHandler(forCommon); - typeTraverser.add4SysMLExpressions(forCommon); - typeTraverser.setSysMLExpressionsHandler(forCommon); - - var forOcl = new SysMLOCLExpressionsTypeVisitor(); - forOcl.setType4Ast(type4Ast); - typeTraverser.add4OCLExpressions(forOcl); - typeTraverser.add4SysMLExpressions(forOcl); - - var forStreams = new StreamExpressionsTypeVisitor(); - forStreams.setType4Ast(type4Ast); - typeTraverser.add4StreamExpressions(forStreams); - - var forSets = new SysMLSetExpressionsTypeVisitor(); - forSets.setType4Ast(type4Ast); - typeTraverser.add4SetExpressions(forSets); - - var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); - forBasicTypes.setType4Ast(type4Ast); - typeTraverser.add4MCBasicTypes(forBasicTypes); - typeTraverser.add4SysMLExpressions(forBasicTypes); - - var forCollectionTypes = new MCCollectionTypesTypeVisitor(); - forCollectionTypes.setType4Ast(type4Ast); - typeTraverser.add4MCCollectionTypes(forCollectionTypes); - - StreamSymTypeRelations.init(); - SysMLWithinScopeBasicSymbolResolver.init(); - SysMLTypeVisitorOperatorCalculator.init(); - CommonExpressionsLValueRelations.init(); - MCCollectionSymTypeRelations.init(); - SysMLSymTypeRelations.init(); - - new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); - } - - @ParameterizedTest(name = "{index} - {0} does pass all checks w/o errors") - @ValueSource(strings = { "1_valid.sysml", - // boolean operator with literals - "2_valid.sysml", // resolve & compare ports - "3_valid.sysml", // resolve & compare channels - "4_valid.sysml", // stream snth - "5_valid.sysml", // port::channel-syntax with comparison - //"6_valid.sysml", // port::channel-syntax with literal - "7_valid.sysml", // INF literal - "8_valid.sysml", // forall construct - "9_valid.sysml", // constraint with literal - //"10_valid.sysml", // attribute definition without port - "11_valid.sysml", // stream length - "12_valid.sysml", // constraint with parameter - "13_valid.sysml", // OCL exists expression - "14_valid.sysml", // StreamConstructor Expression - "15_valid.sysml", //Times function for StreamConstructor Expression - "16_valid.sysml", //Inftimes and takes function - "17_valid.sysml", // user defined type - "18_valid.sysml", // user defined type channels - - "implicitFieldAccess/2_valid.sysml", // resolve & compare ports - "implicitFieldAccess/4_valid.sysml", // stream snth - "implicitFieldAccess/11_valid.sysml", // stream length - "implicitFieldAccess/14_valid.sysml", // StreamConstructor Expression - "implicitFieldAccess/15_valid.sysml", //Times function for StreamConstructor Expression - "implicitFieldAccess/17_valid.sysml", // user defined type - "implicitFieldAccess/18_valid.sysml", // user defined type channels - "implicitFieldAccess/19_valid.sysml", // interoperability between implicit and explicit - - }) - public void testValid(String modelName) throws IOException { - var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); - assertThat(optAst).isPresent(); - - ASTSysMLModel ast = optAst.get(); - - tool.createSymbolTable(ast); - tool.completeSymbolTable(ast); - tool.finalizeSymbolTable(ast); - - var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new ConstraintIsBooleanTC3()); - checker.checkAll(ast); - - assertTrue(Log.getFindings().isEmpty(), () -> Log.getFindings().toString()); - } - - @ParameterizedTest(name = "{index} - {0} does pass all checks w/o errors") - @ValueSource(strings = { "1_invalid.sysml", - // boolean operator with literals - "2_invalid.sysml", // resolve & compare ports - "3_invalid.sysml", // resolve & compare channels - "4_invalid.sysml", // stream snth - "5_invalid.sysml", // port::channel-syntax with comparison - "6_invalid.sysml", // port::channel-syntax with literal - "7_invalid.sysml", // INF literal - "8_invalid.sysml", // forall construct - "9_invalid.sysml", // constraint with literal - //"10_invalid.sysml", // attribute definition without port - "11_invalid.sysml", // stream length - //"12_invalid.sysml", // constraint with parameter - "13_invalid.sysml", // OCL exists expression - "14_invalid.sysml", // StreamConstructor Expression - "15_invalid.sysml", //Times function for StreamConstructor Expression - "16_invalid.sysml", //Inftimes and takes function - "17_invalid.sysml", // user defined type - "18_invalid.sysml", // user defined type channels - - "implicitFieldAccess/2_invalid.sysml", // resolve & compare ports - "implicitFieldAccess/4_invalid.sysml", // stream snth - "implicitFieldAccess/11_invalid.sysml", // stream length - "implicitFieldAccess/14_invalid.sysml", // StreamConstructor Expression - "implicitFieldAccess/15_invalid.sysml", //Times function for StreamConstructor Expression - "implicitFieldAccess/17_invalid.sysml", // user defined type - "implicitFieldAccess/18_invalid.sysml", // user defined type channels - "implicitFieldAccess/19_invalid.sysml", // interoperability between implicit and explicit - }) - public void testInvalid(String modelName) throws IOException { - var optAst = SysMLv2Mill.parser().parse(MODEL_PATH + "/" + modelName); - assertThat(optAst).isPresent(); - - ASTSysMLModel ast = optAst.get(); - - tool.createSymbolTable(ast); - tool.completeSymbolTable(ast); - tool.finalizeSymbolTable(ast); - - var checker = new SysMLv2CoCoChecker(); - checker.addCoCo(new ConstraintIsBooleanTC3()); - Log.enableFailQuick(false); - checker.checkAll(ast); - assertFalse(Log.getFindings().isEmpty()); - Log.clearFindings(); - Log.enableFailQuick(true); - } -} diff --git a/language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java b/language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java deleted file mode 100644 index 28f5b240..00000000 --- a/language/src/test/java/types3/FieldAccessExpressionInStateUsageTest.java +++ /dev/null @@ -1,251 +0,0 @@ -package types3; - -import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; -import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; -import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; -import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; -import de.monticore.lang.sysmlparts._ast.ASTAttributeUsage; -import de.monticore.lang.sysmlparts._ast.ASTPartDef; -import de.monticore.lang.sysmlparts._ast.ASTPortDef; -import de.monticore.lang.sysmlstates._ast.ASTStateUsage; -import de.monticore.lang.sysmlstates._ast.ASTSysMLTransition; -import de.monticore.lang.sysmlv2.SysMLv2Mill; -import de.monticore.lang.sysmlv2.SysMLv2Tool; -import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types.SysMLDeriver; -import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; -import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; -import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; -import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; -import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionFactory; -import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; -import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; -import de.monticore.types3.Type4Ast; -import de.monticore.types3.TypeCheck3; -import de.monticore.types3.streams.StreamSymTypeRelations; -import de.monticore.types3.util.MapBasedTypeCheck3; -import de.se_rwth.commons.logging.Log; -import de.se_rwth.commons.logging.LogStub; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.IOException; -import java.util.stream.Stream; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -/** - *

This test is about TypeCheck3 deriving the types of FieldAccessExpressions in StateUsages.

- * - *

When ASTFieldAccessExpression and ASTOCLArrayQualification are in StateUsage - * we test whether they are not calculated as Stream such as in constraints.

- */ -public class FieldAccessExpressionInStateUsageTest { - - private final SysMLv2Parser parser = new SysMLv2Parser(); - private final SysMLv2Tool tool = new SysMLv2Tool(); - - @BeforeAll - public static void init() { - LogStub.init(); - } - - @BeforeEach - public void reset() { - Log.getFindings().clear(); - tool.init(); - - var type4Ast = new Type4Ast(); - var typeTraverser = SysMLv2Mill.inheritanceTraverser(); - - var forBasis = new ExpressionBasisTypeVisitor(); - forBasis.setType4Ast(type4Ast); - typeTraverser.add4ExpressionsBasis(forBasis); - - var forLiterals = new MCCommonLiteralsTypeVisitor(); - forLiterals.setType4Ast(type4Ast); - typeTraverser.add4MCCommonLiterals(forLiterals); - - var forCommon = new SysMLCommonExpressionsTypeVisitor(); - forCommon.setType4Ast(type4Ast); - typeTraverser.add4CommonExpressions(forCommon); - typeTraverser.setCommonExpressionsHandler(forCommon); - typeTraverser.add4SysMLExpressions(forCommon); - typeTraverser.setSysMLExpressionsHandler(forCommon); - - var forOcl = new SysMLOCLExpressionsTypeVisitor(); - forOcl.setType4Ast(type4Ast); - typeTraverser.add4OCLExpressions(forOcl); - typeTraverser.add4SysMLExpressions(forOcl); - - var forStreams = new StreamExpressionsTypeVisitor(); - forStreams.setType4Ast(type4Ast); - typeTraverser.add4StreamExpressions(forStreams); - - var forSets = new SysMLSetExpressionsTypeVisitor(); - forSets.setType4Ast(type4Ast); - typeTraverser.add4SetExpressions(forSets); - - var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); - forBasicTypes.setType4Ast(type4Ast); - typeTraverser.add4MCBasicTypes(forBasicTypes); - typeTraverser.add4SysMLExpressions(forBasicTypes); - - var forCollectionTypes = new MCCollectionTypesTypeVisitor(); - forCollectionTypes.setType4Ast(type4Ast); - typeTraverser.add4MCCollectionTypes(forCollectionTypes); - - StreamSymTypeRelations.init(); - SysMLWithinScopeBasicSymbolResolver.init(); - SysMLTypeVisitorOperatorCalculator.init(); - CommonExpressionsLValueRelations.init(); - MCCollectionSymTypeRelations.init(); - SysMLSymTypeRelations.init(); - - new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); - } - - static Stream createInputs() { - return Stream.of( - Arguments.of( - "port def F { attribute a: boolean; }" + - "part def X { port f: F; state s { transition first S if f then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; }" + - "part def X { port f: F; state s { transition first S if f[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1][1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; } part def X { port f: F; constraint e { f } }") - - - ,Arguments.of( - "port def F { attribute a: boolean; }" + - "part def X { port f: F; state s { transition first S if f.a then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; }" + - "part def X { port f: F; state s { transition first S if f.a[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; } part def X { port f: F; constraint e { f.a } }") - ,Arguments.of( - "port def F { attribute a: boolean; } part def X { port f: F[3]; constraint e { f[1].a } }") - - - ,Arguments.of( - "port def F { attribute a: boolean; attribute b: nat; }" + - "part def X { port f: F; state s { transition first S if f.a then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; attribute b: nat[3]; }" + - "part def X { port f: F; state s { transition first S if f.a[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; attribute b: nat; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; attribute b: nat[3]; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1].a[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F; constraint e { f.a } }") - ,Arguments.of( - "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F[3]; constraint e { f[1].a } }") - ); - } - - static Stream createInvalidInputs() { - return Stream.of( - Arguments.of( - "port def F { attribute a: boolean; attribute b: nat; }" + - "part def X { port f: F; state s { transition first S if f then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; attribute b: nat[3]; }" + - "part def X { port f: F; state s { transition first S if f[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; attribute b: nat; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean[3]; attribute b: nat[3]; } " + - "part def X { port f: F[3]; exhibit state s { transition first S if f[1][1] then S; } }") - ,Arguments.of( - "port def F { attribute a: boolean; attribute b: nat; } part def X { port f: F; constraint e { f } }") - // TODO one field access with a stream method - ); - } - - @ParameterizedTest - @MethodSource({ "createInputs" }) - public void test(String model) throws IOException { - var ast = parser.parse_String(model); - assertThat(ast).isPresent(); - var astSysmlmodel = ast.get(); - SysMLv2Mill.scopesGenitorDelegator().createFromAST(astSysmlmodel); - tool.completeSymbolTable(astSysmlmodel); - var astPartdef = astSysmlmodel.getSysMLElementList().get(1); - var astSysmlelement = ((ASTPartDef) astPartdef).getSysMLElement(1); - if (astSysmlelement instanceof ASTStateUsage) { - var astTransition = ((ASTStateUsage) astSysmlelement).getSysMLElement(0); - var expr = ((ASTSysMLTransition) astTransition).getGuard(); - var type = TypeCheck3.typeOf(expr); - assertThat(type.printFullName()).isEqualTo("boolean"); - } else if (astSysmlelement instanceof ASTConstraintUsage) { - var expr = ((ASTConstraintUsage) astSysmlelement).getExpression(); - var type = TypeCheck3.typeOf(expr); - assertThat(type.printFullName()).isEqualTo( - "EventStream.EventStream"); - } - else { - Assertions.fail("ASTSysMLElement should here be ASTStateUsage"); - } - } - - @ParameterizedTest - @MethodSource({ "createInvalidInputs" }) - public void testInvalid(String model) throws IOException { - var ast = parser.parse_String(model); - assertThat(ast).isPresent(); - var astSysmlmodel = ast.get(); - SysMLv2Mill.scopesGenitorDelegator().createFromAST(astSysmlmodel); - tool.completeSymbolTable(astSysmlmodel); - var astPartdef = astSysmlmodel.getSysMLElementList().get(1); - var astSysmlelement = ((ASTPartDef) astPartdef).getSysMLElement(1); - SymTypeExpression type = SymTypeExpressionFactory.createObscureType(); - - Log.enableFailQuick(false); - - if (astSysmlelement instanceof ASTStateUsage) { - var astTransition = ((ASTStateUsage) astSysmlelement).getSysMLElement(0); - var expr = ((ASTSysMLTransition) astTransition).getGuard(); - type = TypeCheck3.typeOf(expr); - } else if (astSysmlelement instanceof ASTConstraintUsage) { - var expr = ((ASTConstraintUsage) astSysmlelement).getExpression(); - type = TypeCheck3.typeOf(expr); - } - else { - Assertions.fail("ASTSysMLElement should here be ASTStateUsage"); - } - - assertTrue(!type.isPrimitive() || !type.asPrimitive().getPrimitiveName().equals("boolean")); - Log.enableFailQuick(true); - } -} diff --git a/language/src/test/java/types3/NegationTest.java b/language/src/test/java/types3/NegationTest.java deleted file mode 100644 index 0e90be87..00000000 --- a/language/src/test/java/types3/NegationTest.java +++ /dev/null @@ -1,156 +0,0 @@ -package types3; - -import de.monticore.expressions.commonexpressions._ast.ASTEqualsExpression; -import de.monticore.expressions.commonexpressions.types3.util.CommonExpressionsLValueRelations; -import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; -import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; -import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; -import de.monticore.lang.sysmlparts._ast.ASTPartUsage; -import de.monticore.lang.sysmlv2.SysMLv2Mill; -import de.monticore.lang.sysmlv2.SysMLv2Tool; -import de.monticore.lang.sysmlv2._parser.SysMLv2Parser; -import de.monticore.lang.sysmlv2.types3.SysMLCommonExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLMCBasicTypesTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLOCLExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLSetExpressionsTypeVisitor; -import de.monticore.lang.sysmlv2.types3.SysMLSymTypeRelations; -import de.monticore.lang.sysmlv2.types3.SysMLTypeCheck3; -import de.monticore.lang.sysmlv2.types3.SysMLTypeVisitorOperatorCalculator; -import de.monticore.lang.sysmlv2.types3.SysMLWithinScopeBasicSymbolResolver; -import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; -import de.monticore.ocl.oclexpressions._ast.ASTForallExpression; -import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; -import de.monticore.types.mccollectiontypes.types3.MCCollectionTypesTypeVisitor; -import de.monticore.types3.Type4Ast; -import de.monticore.types3.TypeCheck3; -import de.monticore.types3.streams.StreamSymTypeRelations; -import de.monticore.types3.util.MapBasedTypeCheck3; -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.Disabled; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.io.IOException; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class NegationTest { - - private final SysMLv2Parser parser = new SysMLv2Parser(); - private final SysMLv2Tool tool = new SysMLv2Tool(); - - @BeforeAll - public static void init() { - LogStub.init(); - } - - @BeforeEach - public void reset() { - Log.getFindings().clear(); - tool.init(); - - var type4Ast = new Type4Ast(); - var typeTraverser = SysMLv2Mill.inheritanceTraverser(); - - var forBasis = new ExpressionBasisTypeVisitor(); - forBasis.setType4Ast(type4Ast); - typeTraverser.add4ExpressionsBasis(forBasis); - - var forLiterals = new MCCommonLiteralsTypeVisitor(); - forLiterals.setType4Ast(type4Ast); - typeTraverser.add4MCCommonLiterals(forLiterals); - - var forCommon = new SysMLCommonExpressionsTypeVisitor(); - forCommon.setType4Ast(type4Ast); - typeTraverser.add4CommonExpressions(forCommon); - typeTraverser.setCommonExpressionsHandler(forCommon); - typeTraverser.add4SysMLExpressions(forCommon); - typeTraverser.setSysMLExpressionsHandler(forCommon); - - var forOcl = new SysMLOCLExpressionsTypeVisitor(); - forOcl.setType4Ast(type4Ast); - typeTraverser.add4OCLExpressions(forOcl); - typeTraverser.add4SysMLExpressions(forOcl); - - var forStreams = new StreamExpressionsTypeVisitor(); - forStreams.setType4Ast(type4Ast); - typeTraverser.add4StreamExpressions(forStreams); - - var forSets = new SysMLSetExpressionsTypeVisitor(); - forSets.setType4Ast(type4Ast); - typeTraverser.add4SetExpressions(forSets); - - var forBasicTypes = new SysMLMCBasicTypesTypeVisitor(); - forBasicTypes.setType4Ast(type4Ast); - typeTraverser.add4MCBasicTypes(forBasicTypes); - typeTraverser.add4SysMLExpressions(forBasicTypes); - - var forCollectionTypes = new MCCollectionTypesTypeVisitor(); - forCollectionTypes.setType4Ast(type4Ast); - typeTraverser.add4MCCollectionTypes(forCollectionTypes); - - StreamSymTypeRelations.init(); - SysMLWithinScopeBasicSymbolResolver.init(); - SysMLTypeVisitorOperatorCalculator.init(); - CommonExpressionsLValueRelations.init(); - MCCollectionSymTypeRelations.init(); - SysMLSymTypeRelations.init(); - - new SysMLTypeCheck3(typeTraverser, type4Ast).setThisAsDelegate(); - } - - @ParameterizedTest - @ValueSource(strings = { - "port def F { in attribute val: boolean; } part s { port f: F; constraint e { forall long t: f.val.nth(t) == !f.val.nth(t) } }" - }) - public void testNotBooleanStream(String model) throws IOException { - var ast = parser.parse_String(model); - assertThat(ast).isPresent(); - var astSysMLModel = ast.get(); - - tool.createSymbolTable(astSysMLModel); - tool.completeSymbolTable(astSysMLModel); - tool.finalizeSymbolTable(astSysMLModel); - - var sysmlelements = astSysMLModel.getSysMLElementList(); - var astPartUsage = sysmlelements.get(1); - var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(1); - var forAllExpr = (ASTForallExpression)(((ASTConstraintUsage) constraintUsage).getExpression()); - var equalsExpr = (ASTEqualsExpression) forAllExpr.getExpression(); - var rightType = TypeCheck3.typeOf(equalsExpr.getRight()); - var leftType = TypeCheck3.typeOf(equalsExpr.getLeft()); - assertFalse(rightType.isObscureType()); - assertThat(rightType.printFullName()).isEqualTo("UntimedStream.UntimedStream"); - assertTrue(rightType.deepEquals(leftType)); - } - - @ParameterizedTest - @ValueSource(strings = { - "part s { constraint e { forall nat t: true == !false } }" - }) - public void testNotBoolean(String model) throws IOException { - var ast = parser.parse_String(model); - assertThat(ast).isPresent(); - var astSysMLModel = ast.get(); - - tool.createSymbolTable(astSysMLModel); - tool.completeSymbolTable(astSysMLModel); - tool.finalizeSymbolTable(astSysMLModel); - - var sysmlelements = astSysMLModel.getSysMLElementList(); - var astPartUsage = sysmlelements.get(0); - var constraintUsage = ((ASTPartUsage) astPartUsage).getSysMLElement(0); - var forAllExpr = (ASTForallExpression)(((ASTConstraintUsage) constraintUsage).getExpression()); - var equalsExpr = (ASTEqualsExpression) forAllExpr.getExpression(); - var rightType = TypeCheck3.typeOf(equalsExpr.getRight()); - var leftType = TypeCheck3.typeOf(equalsExpr.getLeft()); - assertFalse(rightType.isObscureType()); - assertThat(rightType.printFullName()).isEqualTo("boolean"); - assertTrue(rightType.deepEquals(leftType)); - } -} From 30b322a5518c9c8eb3b36a6f21b33c35f22d146b Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Tue, 24 Feb 2026 12:39:17 +0100 Subject: [PATCH 18/29] 7.8.17: COmplete refinements from Specialization too --- gradle.properties | 2 +- .../completers/DirectRefinementCompleter.java | 39 ++++++++++++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index 03e261a4..5d394dc6 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.16 +version = 7.8.17 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/DirectRefinementCompleter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/DirectRefinementCompleter.java index 05d23f53..a0ce4819 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/DirectRefinementCompleter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/DirectRefinementCompleter.java @@ -1,6 +1,7 @@ package de.monticore.lang.sysmlv2.symboltable.completers; import de.monticore.lang.sysmlbasis._ast.ASTSysMLRefinement; +import de.monticore.lang.sysmlbasis._ast.ASTSysMLSpecialization; import de.monticore.lang.sysmlparts._ast.ASTPartDef; import de.monticore.lang.sysmlparts._visitor.SysMLPartsVisitor2; import de.monticore.lang.sysmlv2.SysMLv2Mill; @@ -11,27 +12,53 @@ import java.util.ArrayList; import java.util.stream.Collectors; +/** + * Adds specializations and refinements to the list of direct refinements. + * Example: + * "part def Specific specializes Abstract" + * Results in the "Specific"-PartDefSymbol to contain "Abstract" in the list of + * "directRefinements". + */ public class DirectRefinementCompleter implements SysMLPartsVisitor2 { @Override public void visit(ASTPartDef node) { + var syn = new SysMLSynthesizer(); + + node.getSymbol().setDirectRefinementsList( + new ArrayList() + ); + var refinementTypes = node.getSpecializationList().stream() .filter(r -> r instanceof ASTSysMLRefinement) .flatMap(r -> r.getSuperTypesList().stream()).collect(Collectors.toList()); - var syn = new SysMLSynthesizer(); - - var validRefinementExpressions = new ArrayList(); for (var refinementType : refinementTypes) { - // Check existince of refinement before actually synthesizing it to avoid FATAL errors thrown by the synthesizer + // Check existence of refinement before actually synthesizing it to avoid + // FATAL errors thrown by the synthesizer if (refinementType.getDefiningSymbol().isEmpty()) { continue; } var result = syn.synthesizeType(refinementType); if (result.isPresentResult()) { - validRefinementExpressions.add(result.getResult()); + node.getSymbol().addDirectRefinements(result.getResult()); + } + } + + var specializationTypes = node.getSpecializationList().stream() + .filter(r -> r instanceof ASTSysMLSpecialization) + .flatMap(r -> r.getSuperTypesList().stream()).collect(Collectors.toList()); + + for (var specializationType : specializationTypes) { + // Check existence of refinement before actually synthesizing it to avoid + // FATAL errors thrown by the synthesizer + if (specializationType.getDefiningSymbol().isEmpty()) { + continue; + } + var result = syn.synthesizeType(specializationType); + if (result.isPresentResult()) { + node.getSymbol().addDirectRefinements(result.getResult()); } } - node.getSymbol().setDirectRefinementsList(validRefinementExpressions); } } From 128a0108c033abbac44712fd93bc832d6bcc12e4 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Tue, 24 Feb 2026 14:41:01 +0100 Subject: [PATCH 19/29] 7.8.18: Port-CoCos dont behave properly and try to access AST instead of ST --- gradle.properties | 2 +- .../src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5d394dc6..216e6a78 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.17 +version = 7.8.18 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 2f3bded0..c5d98df8 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -120,8 +120,6 @@ public void runDefaultCoCos(ASTSysMLModel ast) { // Connection CoCos checker.addCoCo(new SubPartNamesInConnectionExistCoCo()); checker.addCoCo(new QualifiedPortNameExistsCoCo()); - checker.addCoCo(new SubcomponentOutputConnectionDirectionCoCo()); - checker.addCoCo(new ParentComponentInputConnectionDirectionCoCo()); // Check ambiguous names checker.addCoCo(new UniqueSubPartNamesInParentCoCo()); From 8cefc64647934c817f0fdf53eaa143e2d37c17f2 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Mon, 2 Mar 2026 17:51:40 +0100 Subject: [PATCH 20/29] =?UTF-8?q?7.8.19:=20TypeVisitor=20f=C3=BCr=20Condit?= =?UTF-8?q?ionAndExpression2q?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- .../SysMLOCLExpressionsTypeVisitor.java | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 216e6a78..3a60b6d8 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.18 +version = 7.8.19 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java index 00571202..bb40eaf3 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java @@ -1,8 +1,16 @@ package de.monticore.lang.sysmlv2.types3; +import de.monticore.lang.sysmlexpressions._ast.ASTConditionalAndExpression2; import de.monticore.lang.sysmlexpressions._ast.ASTExistsExpression; import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsVisitor2; import de.monticore.ocl.oclexpressions.types3.OCLExpressionsTypeVisitor; +import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; +import de.monticore.types3.SymTypeRelations; +import de.monticore.types3.util.TypeVisitorLifting; +import de.se_rwth.commons.logging.Log; public class SysMLOCLExpressionsTypeVisitor extends OCLExpressionsTypeVisitor implements SysMLExpressionsVisitor2 { @@ -10,4 +18,28 @@ public class SysMLOCLExpressionsTypeVisitor extends OCLExpressionsTypeVisitor im public void endVisit(ASTExistsExpression node) { endVisit((de.monticore.ocl.oclexpressions._ast.ASTExistsExpression) node); } + + @Override + public void endVisit(ASTConditionalAndExpression2 expr) { + SymTypeExpression left = getType4Ast().getPartialTypeOfExpr(expr.getLeft()); + SymTypeExpression right = getType4Ast().getPartialTypeOfExpr(expr.getRight()); + + SymTypeExpression result = + TypeVisitorLifting.liftDefault( + this::calculateAndExpression) + .apply(left, right); + getType4Ast().setTypeOfExpression(expr, result); + } + + protected SymTypeExpression calculateAndExpression( + SymTypeExpression left, SymTypeExpression right) { + + if (SymTypeRelations.isCompatible(left, right) + && left.isPrimitive() + && left.asPrimitive().getPrimitiveName().equals("boolean")) { + return SymTypeExpressionFactory.createPrimitive(BasicSymbolsMill.BOOLEAN); + } + return SymTypeExpressionFactory.createObscureType(); + } + } From 54e2767b7485388346fd126cb736e7b35e0380d7 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Fri, 6 Mar 2026 09:37:09 +0100 Subject: [PATCH 21/29] 7.8.20: Fixed Resolving for Relative ModelPaths (#27, upate mclsg_version to 7.8.3) --- gradle.properties | 4 ++-- .../lang/sysmlv2/_lsp/SysMLv2LanguageServer.java | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3a60b6d8..3c366e3f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,10 +19,10 @@ sysmlGitlab = https://git.rwth-aachen.de/api/v4/projects/37093/packages/m # Dependencies mc_version = 7.8.0 -mclsg_version = 7.8.1 +mclsg_version = 7.8.3 se_commons_version = 7.8.0 assertj_version = 3.21.0 junit_version = 5.8.2 # Version of published artifacts -version = 7.8.19 +version = 7.8.20 diff --git a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/SysMLv2LanguageServer.java b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/SysMLv2LanguageServer.java index 2fedde56..99eedd99 100644 --- a/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/SysMLv2LanguageServer.java +++ b/language-server/src/main/java/de/monticore/lang/sysmlv2/_lsp/SysMLv2LanguageServer.java @@ -5,6 +5,7 @@ import de.mclsg.lsp.document_management.DocumentManager; import de.mclsg.lsp.modelpath.multiproject.ProjectLayoutBuilder; import de.monticore.lang.sysmlv2._lsp.language_access.SysMLv2ScopeManager; +import org.eclipse.lsp4j.InitializedParams; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.MessageType; import org.slf4j.Logger; @@ -17,6 +18,21 @@ public class SysMLv2LanguageServer extends SysMLv2LanguageServerTOP { private static final Logger logger = LoggerFactory.getLogger(SysMLv2LanguageServer.class); + @Override + public void initialized(InitializedParams params) { + if (options != null) { + // Re-resolve layout with correct workspace path + ProjectLayout newLayout = new ProjectLayoutBuilder() + .projectpath(options.getWorkspacePath()) + .symbolPath(options.getSymbolPaths()) + .resources(options.getModelPaths()) + .build(); + + resetContent(newLayout); + } + super.initialized(params); + } + /** Convenience: Wir modifizieren aktuell eigentlich nur den ModelPath */ public SysMLv2LanguageServer(ProjectLayout layout) { this( From 209cd00a9a018f9a81955afafa62e18f014ceb37 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Fri, 6 Mar 2026 09:37:50 +0100 Subject: [PATCH 22/29] =?UTF-8?q?7.8.21:=20TypeVisitor=20f=C3=BCr=20Condit?= =?UTF-8?q?ionalOrExpression2=20(#70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- .../SysMLOCLExpressionsTypeVisitor.java | 17 ++++- .../test/java/typecheck/TypeCheck3Test.java | 66 +++++++++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3c366e3f..6abf99eb 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.20 +version = 7.8.21 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java index bb40eaf3..b5c8247e 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLOCLExpressionsTypeVisitor.java @@ -1,6 +1,7 @@ package de.monticore.lang.sysmlv2.types3; import de.monticore.lang.sysmlexpressions._ast.ASTConditionalAndExpression2; +import de.monticore.lang.sysmlexpressions._ast.ASTConditionalOrExpression2; import de.monticore.lang.sysmlexpressions._ast.ASTExistsExpression; import de.monticore.lang.sysmlexpressions._visitor.SysMLExpressionsVisitor2; import de.monticore.ocl.oclexpressions.types3.OCLExpressionsTypeVisitor; @@ -26,12 +27,24 @@ public void endVisit(ASTConditionalAndExpression2 expr) { SymTypeExpression result = TypeVisitorLifting.liftDefault( - this::calculateAndExpression) + this::calculateBooleanBinaryExpression) .apply(left, right); getType4Ast().setTypeOfExpression(expr, result); } - protected SymTypeExpression calculateAndExpression( + @Override + public void endVisit(ASTConditionalOrExpression2 expr) { + SymTypeExpression left = getType4Ast().getPartialTypeOfExpr(expr.getLeft()); + SymTypeExpression right = getType4Ast().getPartialTypeOfExpr(expr.getRight()); + + SymTypeExpression result = + TypeVisitorLifting.liftDefault( + this::calculateBooleanBinaryExpression) + .apply(left, right); + getType4Ast().setTypeOfExpression(expr, result); + } + + protected SymTypeExpression calculateBooleanBinaryExpression( SymTypeExpression left, SymTypeExpression right) { if (SymTypeRelations.isCompatible(left, right) diff --git a/language/src/test/java/typecheck/TypeCheck3Test.java b/language/src/test/java/typecheck/TypeCheck3Test.java index 21d64edc..940847e8 100644 --- a/language/src/test/java/typecheck/TypeCheck3Test.java +++ b/language/src/test/java/typecheck/TypeCheck3Test.java @@ -4,14 +4,17 @@ import de.monticore.expressions.commonexpressions._visitor.CommonExpressionsVisitor2; import de.monticore.expressions.commonexpressions.types3.CommonExpressionsTypeVisitor; import de.monticore.expressions.streamexpressions.types3.StreamExpressionsTypeVisitor; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; import de.monticore.lang.sysmlv2.SysMLv2Mill; import de.monticore.lang.sysmlv2.SysMLv2Tool; import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor; import de.monticore.ocl.oclexpressions.types3.OCLExpressionsTypeVisitor; +import de.monticore.types.check.SymTypeExpression; import de.monticore.types.mcbasictypes.types3.MCBasicTypesTypeVisitor; import de.monticore.types3.Type4Ast; import de.monticore.types3.TypeCheck3; import de.monticore.types3.util.MapBasedTypeCheck3; +import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -95,4 +98,67 @@ void testTypeCheck3() throws IOException { assertThat(printer.content).isEqualTo("Übersetzung der length-Funktion"); } + @Test + public void testConditionalAnd2Type() throws IOException { + var tool = new SysMLv2Tool(); + Log.getFindings().clear(); + tool.init(); + + var astExp = SysMLv2Mill.parser().parse_String("constraint { true & false }").get(); + tool.createSymbolTable(astExp); + tool.completeSymbolTable(astExp); + + SymTypeExpression type = TypeCheck3.typeOf(((ASTConstraintUsage)astExp.getSysMLElement(0)).getExpression()); + + assertThat(Log.getFindings().isEmpty()).isTrue(); + assertThat(type.isPrimitive()).isTrue(); + assertThat(type.asPrimitive().getPrimitiveName()).isEqualTo("boolean"); + } + + @Test + public void testConditionalAnd2TypeExpressionOnly() throws IOException { + var tool = new SysMLv2Tool(); + Log.getFindings().clear(); + tool.init(); + + var astExp = SysMLv2Mill.parser().parse_StringExpression("true & false").get(); + + SymTypeExpression type = TypeCheck3.typeOf(astExp); + + assertThat(Log.getFindings().isEmpty()).isTrue(); + assertThat(type.isPrimitive()).isTrue(); + assertThat(type.asPrimitive().getPrimitiveName()).isEqualTo("boolean"); + } + + @Test + public void testConditionalOr2Type() throws IOException { + var tool = new SysMLv2Tool(); + Log.getFindings().clear(); + tool.init(); + + var astExp = SysMLv2Mill.parser().parse_String("constraint { true | false }").get(); + tool.createSymbolTable(astExp); + tool.completeSymbolTable(astExp); + + SymTypeExpression type = TypeCheck3.typeOf(((ASTConstraintUsage)astExp.getSysMLElement(0)).getExpression()); + + assertThat(Log.getFindings().isEmpty()).isTrue(); + assertThat(type.isPrimitive()).isTrue(); + assertThat(type.asPrimitive().getPrimitiveName()).isEqualTo("boolean"); + } + + @Test + public void testConditionalOr2TypeExpressionOnly() throws IOException { + var tool = new SysMLv2Tool(); + Log.getFindings().clear(); + tool.init(); + + var astExp = SysMLv2Mill.parser().parse_StringExpression("true | false").get(); + + SymTypeExpression type = TypeCheck3.typeOf(astExp); + + assertThat(Log.getFindings().isEmpty()).isTrue(); + assertThat(type.isPrimitive()).isTrue(); + assertThat(type.asPrimitive().getPrimitiveName()).isEqualTo("boolean"); + } } From f6017732ccbfeed1ecc0ca853dc970b7d7f70386 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Fri, 6 Mar 2026 09:50:59 +0100 Subject: [PATCH 23/29] 7.8.22: CoCo for AcceptAction in Event-Transitions --- gradle.properties | 2 +- .../monticore/lang/sysmlv2/SysMLv2Tool.java | 2 + .../cocos/EventTransitionRequiresAccept.java | 38 ++++++ .../EventTransitionRequiresAcceptTest.java | 108 ++++++++++++++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/EventTransitionRequiresAccept.java create mode 100644 language/src/test/java/cocos/EventTransitionRequiresAcceptTest.java diff --git a/gradle.properties b/gradle.properties index 6abf99eb..5af3d3ae 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.21 +version = 7.8.22 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 c5d98df8..1096b91e 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/SysMLv2Tool.java @@ -24,6 +24,7 @@ import de.monticore.lang.sysmlv2._symboltable.SysMLv2Symbols2Json; import de.monticore.lang.sysmlv2._visitor.SysMLv2Traverser; import de.monticore.lang.sysmlv2.cocos.AssignActionTypeCheck3; +import de.monticore.lang.sysmlv2.cocos.EventTransitionRequiresAccept; import de.monticore.lang.sysmlv2.cocos.FlowCheckCoCo; import de.monticore.lang.sysmlv2.cocos.NameCompatible4Isabelle; import de.monticore.lang.sysmlv2.cocos.OneCardinality; @@ -167,6 +168,7 @@ public void runAdditionalCoCos( checker.addCoCo(new FlowCheckCoCo()); checker.addCoCo(new PortDefinitionExistsCoCo()); checker.addCoCo(new PartBehaviorCoCo()); + checker.addCoCo(new EventTransitionRequiresAccept()); checker.checkAll(ast); } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/cocos/EventTransitionRequiresAccept.java b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/EventTransitionRequiresAccept.java new file mode 100644 index 00000000..34353602 --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/cocos/EventTransitionRequiresAccept.java @@ -0,0 +1,38 @@ +package de.monticore.lang.sysmlv2.cocos; + +import de.monticore.lang.componentconnector._symboltable.EventAutomatonSymbol; +import de.monticore.lang.sysmlstates._ast.ASTSysMLTransition; +import de.monticore.lang.sysmlstates._cocos.SysMLStatesASTSysMLTransitionCoCo; +import de.se_rwth.commons.logging.Log; + +/** + * All transitions in an Event-Automaton need AcceptActions + */ +public class EventTransitionRequiresAccept implements + SysMLStatesASTSysMLTransitionCoCo { + + @Override + public void check(ASTSysMLTransition node) { + if (!isInEventAutomaton(node)) return; + + if (!node.isPresentInlineAcceptActionUsage()) { + Log.error("EventAutomaton transition must contain an AcceptAction.", + node.get_SourcePositionStart(), + node.get_SourcePositionEnd()); + } + } + + private boolean isInEventAutomaton(ASTSysMLTransition node) { + var scope = node.getEnclosingScope(); + + while (scope != null) { + if (scope.isPresentSpanningSymbol()) { + var sym = scope.getSpanningSymbol(); + if (sym instanceof EventAutomatonSymbol) return true; + } + scope = scope.getEnclosingScope(); + } + return false; + } + +} diff --git a/language/src/test/java/cocos/EventTransitionRequiresAcceptTest.java b/language/src/test/java/cocos/EventTransitionRequiresAcceptTest.java new file mode 100644 index 00000000..84c80924 --- /dev/null +++ b/language/src/test/java/cocos/EventTransitionRequiresAcceptTest.java @@ -0,0 +1,108 @@ +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.cocos.EventTransitionRequiresAccept; +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.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +public class EventTransitionRequiresAcceptTest { + + @BeforeAll + public static void init() { + LogStub.init(); + } + + @BeforeEach + public void clear() { + Log.clearFindings(); + } + + @Test + void eventAutomaton_withAccept_mustNotLogError() { + parseAndCheck(valid); + var errors = Log.getFindings().stream() + .filter(s -> s.isError()) + .collect(Collectors.toList()); + assertTrue(errors.isEmpty(), + "Expected no errors, but got:\n" + errors); + } + + @Test + void eventAutomaton_withoutAccept_mustLogError() { + parseAndCheck(invalid); + assertFalse(Log.getFindings().isEmpty()); + } + + void parseAndCheck(String model) { + var tool = new SysMLv2Tool(); + tool.init(); + ASTSysMLModel ast = null; + try { + ast = SysMLv2Mill.parser().parse_String(model).get(); + } + catch (Exception e) { + fail("Model was not parsable"); + } + + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + var checker = new SysMLv2CoCoChecker(); + checker.addCoCo(new EventTransitionRequiresAccept()); + checker.checkAll(ast); + } + + String valid = "part def TestWithAccept {\n" + + " port input: Booleans;\n" + + " port output: ~Booleans;\n" + + "\n" + + " exhibit state behavior {\n" + + " entry;\n" + + " then S;\n" + + "\n" + + " state S;\n" + + "\n" + + " transition\n" + + " first S\n" + + " accept input.val\n" + + " if input.val == true\n" + + " do action {\n" + + " send false to output.val;\n" + + " }\n" + + " then S;\n" + + " }\n" + + "}"; + + String invalid = "part def TestWithoutAccept {\n" + + " port input: Booleans;\n" + + "\n" + + " exhibit state behavior {\n" + + " entry; then S;\n" + + "\n" + + " state S;\n" + + "\n" + + " transition ok\n" + + " first S\n" + + " accept input.val\n" + + " then S;\n" + + "\n" + + " transition bad\n" + + " first S\n" + + " then S;\n" + + " }\n" + + "}"; + +} From e617df166ce9b8e2c67c9a71750f52da559e00c0 Mon Sep 17 00:00:00 2001 From: Jana Nefedova <116279327+JanaNefedova@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:46:01 +0100 Subject: [PATCH 24/29] In/accept dataport (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Übergänge mit „accept … via …“ werden jetzt korrekt erkannt * update version --- gradle.properties | 2 +- .../adapters/StateUsage2AutomatonAdapter.java | 29 +++++++++++++++--- .../StateUsage2EventAutomatonAdapter.java | 15 ++++++---- .../EventAutomatonSymbolAdapterTest.java | 30 +++++++++++++++++++ 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5af3d3ae..7886dac0 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.22 +version = 7.8.23 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2AutomatonAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2AutomatonAdapter.java index 874e6eec..8cfd8784 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2AutomatonAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2AutomatonAdapter.java @@ -11,6 +11,7 @@ import de.monticore.lang.sysmlstates._symboltable.StateUsageSymbol; import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; import de.monticore.types.mcbasictypes._ast.ASTMCQualifiedType; +import de.se_rwth.commons.logging.Log; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -93,10 +94,30 @@ public List getInitialConfigurationList() { return initialConfiguration; } - private String getTrigger(ASTSysMLTransition transition) { - var trigger = transition.getInlineAcceptActionUsage(); + public static String getAcceptTrigger(ASTSysMLTransition transition) { + if (transition == null || !transition.isPresentInlineAcceptActionUsage()) { + return ""; + } + var accept = transition.getInlineAcceptActionUsage(); + var payload = accept.getPayload(); + if (accept.isPresentReceiver() && payload.isPresentPayloadHandle()) { + return accept.getReceiver().getQName() + "." + payload.getPayloadHandle(); + } + if (payload.isPresentPayloadType() && payload.getPayloadType() instanceof ASTMCQualifiedType) { + return String.join(".", ((ASTMCQualifiedType) payload.getPayloadType()) + .getMCQualifiedName().getPartsList()); + } + return ""; + } - return String.join(".", ((ASTMCQualifiedType)trigger.getPayload() - .getPayloadType()).getMCQualifiedName().getPartsList()); + private String getTrigger(ASTSysMLTransition transition) { + String trigger = getAcceptTrigger(transition); + if (trigger.isEmpty()) { + Log.error( + "0xB0003 Missing or unsupported transition trigger (expected an 'accept' clause).", + transition.get_SourcePositionStart(), + transition.get_SourcePositionEnd()); + } + return trigger; } } diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2EventAutomatonAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2EventAutomatonAdapter.java index 3bd4cec4..cbb8c8dc 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2EventAutomatonAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/StateUsage2EventAutomatonAdapter.java @@ -6,9 +6,11 @@ import de.monticore.lang.sysmlactions._ast.ASTSysMLSuccession; import de.monticore.lang.sysmlparts._symboltable.PartDefSymbol; import de.monticore.lang.sysmlstates._ast.ASTSysMLTransition; +import static de.monticore.lang.sysmlv2.symboltable.adapters.StateUsage2AutomatonAdapter.getAcceptTrigger; import de.monticore.lang.sysmlstates._symboltable.StateUsageSymbol; import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; import de.monticore.types.mcbasictypes._ast.ASTMCQualifiedType; +import de.se_rwth.commons.logging.Log; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -115,10 +117,13 @@ public List getInitialConfigurationList() { } private String getTrigger(ASTSysMLTransition transition) { - //TODO nochmal richtig machen - var trigger = transition.getInlineAcceptActionUsage(); - - return String.join(".", - ((ASTMCQualifiedType)trigger.getPayload().getPayloadType()).getMCQualifiedName().getPartsList()); + String trigger = getAcceptTrigger(transition); + if (trigger.isEmpty()) { + Log.error( + "0xB0002 Unsupported or missing transition trigger (expected 'accept ' or 'accept : via ').", + transition.get_SourcePositionStart(), + transition.get_SourcePositionEnd()); + } + return trigger; } } diff --git a/language/src/test/java/symboltable/EventAutomatonSymbolAdapterTest.java b/language/src/test/java/symboltable/EventAutomatonSymbolAdapterTest.java index 92202cb7..74e77603 100644 --- a/language/src/test/java/symboltable/EventAutomatonSymbolAdapterTest.java +++ b/language/src/test/java/symboltable/EventAutomatonSymbolAdapterTest.java @@ -143,4 +143,34 @@ public void testEventTransition() throws IOException { assertThat(output.getPortSymbol().getName()).isEqualTo("o.val"); assertThat(output.getValue()).isInstanceOf(ASTLogicalNotExpression.class); } + + @Test + public void testEventTransition_TypedAcceptViaMapsToPort() throws IOException { + var as = process("port def B {\n" + + " in attribute val: boolean;\n" + + "}\n" + + "\n" + + "part def A {\n" + + " port i: B;\n" + + " port o: ~B;\n" + + "\n" + + " exhibit state aut {\n" + + " state S;\n" + + " transition t\n" + + " first S\n" + + " accept val: boolean via i\n" + + " if true\n" + + " do action { send !i.val to o.val; }\n" + + " then S;\n" + + " }\n" + + "}"); + + var aut = as.resolveEventAutomaton("A").get(); + + var evTransitions = aut.getEventTransitionsList(); + assertThat(evTransitions).isNotEmpty(); + + var trans = evTransitions.get(0); + assertThat(trans.getPortSymbol().getName()).isEqualTo("i.val"); + } } From 74c921f7e0993d06414b84f991cd7898e00c7468 Mon Sep 17 00:00:00 2001 From: Jana Nefedova <116279327+JanaNefedova@users.noreply.github.com> Date: Sun, 8 Mar 2026 00:41:46 +0100 Subject: [PATCH 25/29] Grammatik angepasst, damit 'metadata def delayed' erlaubt wird (#72) * Grammatik angepasst, damit 'metadata def delayed' erlaubt wird * update version --- gradle.properties | 2 +- .../lang/SysMLImportsAndPackages.mc4 | 2 +- .../grammars/de/monticore/lang/SysMLParts.mc4 | 2 +- .../monticore/lang/sysmlv2/SysMLv2Tool.java | 2 + .../sysmlv2/_symboltable/ISysMLv2Scope.java | 8 +++ .../cocos/ValidCausalityTimingCoCo.java | 24 ++++++++ .../MetadataDef2TypeSymbolAdapter.java | 53 ++++++++++++++++ .../completers/CausalityCompleter.java | 6 +- .../cocos/ValidCausalityTimingCoCoTest.java | 60 +++++++++++++++++++ .../MetadataDefinitionSymbolTest.java | 47 +++++++++++++++ 10 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/cocos/ValidCausalityTimingCoCo.java create mode 100644 language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/MetadataDef2TypeSymbolAdapter.java create mode 100644 language/src/test/java/cocos/ValidCausalityTimingCoCoTest.java create mode 100644 language/src/test/java/symboltable/MetadataDefinitionSymbolTest.java 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(); + } +} From ed060ecdab3b000a9505b09ba93a57815ca04ab2 Mon Sep 17 00:00:00 2001 From: Mathias Pfeiffer Date: Sun, 8 Mar 2026 22:48:39 +0100 Subject: [PATCH 26/29] 7.8.25: Implemented MildComponentSymbol.isHistoryBased() --- gradle.properties | 2 +- .../adapters/PartDef2ComponentAdapter.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c5eb4f77..a178dd01 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.24 +version = 7.8.25 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/PartDef2ComponentAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/PartDef2ComponentAdapter.java index c6333124..97a5c6d1 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/PartDef2ComponentAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/PartDef2ComponentAdapter.java @@ -144,6 +144,23 @@ public List getConnectorsList() { } } + @Override + public boolean isHistoryBased() { + if(!getSpannedScope().getLocalMildSpecificationSymbols().isEmpty()) { + return true; + } + // TODO only "require" + else if(!getSpannedScope().getLocalRequirementUsageSymbols().isEmpty()) { + return true; + } + // TODO only "assert" + else if(!getSpannedScope().getLocalConstraintUsageSymbols().isEmpty()) { + return true; + } + else { + return false; + } + } /** * Since we might not know the name of the constraint or requirement, and thus From 0e5ed612f7be0b32726a36380de155c5942af0ab Mon Sep 17 00:00:00 2001 From: Dovydas Skauranskas <109866625+DovydasSkauranskas@users.noreply.github.com> Date: Thu, 12 Mar 2026 13:43:29 +0200 Subject: [PATCH 27/29] =?UTF-8?q?7.8.26:=20TypesCompleter=20f=C3=BCr=20MCT?= =?UTF-8?q?uples=20(#73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SymTypeExpression fuer MCTupleType * type.hasTypeInfo() check * Version erhoeht --- gradle.properties | 2 +- .../symboltable/completers/TypesCompleter.java | 13 ++++++++++++- .../SysMLv2DeriveSymTypeOfCommonExpressions.java | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index a178dd01..631a7c8b 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.25 +version = 7.8.26 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java index 0c1f1baa..8b9247a5 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/completers/TypesCompleter.java @@ -25,6 +25,7 @@ import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionFactory; import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType; +import de.monticore.types.mcstructuraltypes._ast.ASTMCTupleType; import de.se_rwth.commons.logging.Log; import java.util.ArrayList; @@ -47,7 +48,17 @@ private List getTypeCompletion(List specia for(var mcType: astTyping.getSuperTypesList()) { SymTypeExpression res = null; - if(mcType instanceof ASTMCGenericType) { + if(mcType instanceof ASTMCTupleType) { + var tupleType = (ASTMCTupleType) mcType; + List componentTypes = new ArrayList<>(); + for(var componentMcType : tupleType.getMCTypeList()) { + componentTypes.add(SymTypeExpressionFactory.createTypeExpression( + componentMcType.printType(), + (IBasicSymbolsScope) componentMcType.getEnclosingScope())); + } + res = SymTypeExpressionFactory.createTuple(componentTypes); + } + else if(mcType instanceof ASTMCGenericType) { // We still have to print when the type is generic because the defining symbol does not give info about the // instantiation with type arguments res = SymTypeExpressionFactory.createTypeExpression( diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java index 2cbd75bb..cbacad46 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types/SysMLv2DeriveSymTypeOfCommonExpressions.java @@ -69,7 +69,7 @@ public boolean isIntegralType(SymTypeExpression type) { protected void calculateFieldAccessAboutPortUsage(SymTypeExpression type) { if (this.isStream) { //case for isStream == true - if (type.getTypeInfo().getName().contains("Stream")) { + if (type.hasTypeInfo() && type.getTypeInfo().getName().contains("Stream")) { //type is already Stream, set TypeCheckResult getTypeCheckResult().setResult(type); } else { From 0a0150266d67fc73ff7f150e36f68bf12946f18e Mon Sep 17 00:00:00 2001 From: Dovydas Skauranskas <109866625+DovydasSkauranskas@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:43:45 +0200 Subject: [PATCH 28/29] #201 tsyn Flag von dem Part Def ablesen (#74) * #201 tsyn Flag von dem Part Def ablesen * #201 Check if present AST node * #201 PartDefSymbol Type check --- .../adapters/AttributeUsage2PortSymbolAdapter.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java index 4350c499..d0efcb49 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/symboltable/adapters/AttributeUsage2PortSymbolAdapter.java @@ -1,6 +1,7 @@ package de.monticore.lang.sysmlv2.symboltable.adapters; import de.monticore.lang.componentconnector._symboltable.MildPortSymbol; +import de.monticore.lang.sysmlparts._ast.ASTPartDef; import de.monticore.lang.sysmlparts._symboltable.AttributeUsageSymbol; import de.monticore.lang.sysmlparts._symboltable.PartDefSymbol; import de.monticore.lang.sysmlparts._symboltable.PortUsageSymbol; @@ -75,7 +76,11 @@ private Timing determineTiming(PortUsageSymbol container) { var scope = (ISysMLv2Scope) container.getEnclosingScope(); boolean hasTsyn = scope.getLocalStateUsageSymbols().stream() - .anyMatch(sym -> sym.getUserDefinedKeywordsList().contains("tsyn")); + .anyMatch(sym -> sym.getUserDefinedKeywordsList().contains("tsyn")) + || scope.getSpanningSymbol() instanceof PartDefSymbol && scope.getSpanningSymbol().isPresentAstNode() && + ((ASTPartDef) scope.getSpanningSymbol().getAstNode()) + .getUserDefinedKeywordList().stream() + .anyMatch(kw -> kw.getMCQualifiedName().getQName().equals("tsyn")); return hasTsyn ? Timing.TIMED_SYNC : Timing.TIMED; } From 7706f920ebe558b0815c1a376bb903ccca39b180 Mon Sep 17 00:00:00 2001 From: Dovydas Skauranskas <109866625+DovydasSkauranskas@users.noreply.github.com> Date: Mon, 16 Mar 2026 18:59:36 +0200 Subject: [PATCH 29/29] Version erhoeht --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 631a7c8b..fa0e56fe 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.26 +version = 7.8.27