diff --git a/ba/doc/conformance.md b/ba/doc/conformance.md index 83e443b12c..9fc17065b6 100644 --- a/ba/doc/conformance.md +++ b/ba/doc/conformance.md @@ -140,6 +140,8 @@ The AST precedence error and the strict-model flattening error must be assessed **Implemented for [#3178](https://github.com/osate/osate2/issues/3178):** for a subclause without an `in modes` statement, translation now binds each complete state to a visible same-named mode case-insensitively. A subclause with an `in modes` statement does not create those bindings. The validator enforces D.3's all-or-none rule before strict checking, so a non-mode complete state is reported when another complete state represents a mode. `Issue3178Test` exercises source and destination bindings, matching and mismatching transition triggers, every source of a multi-source transition, the all-or-none diagnostic, and the `in modes` boundary through embedded AADL models without mutating the strict model. +**External trigger validation and context ([#3232](https://github.com/osate/osate2/issues/3232)):** external conditions require incoming event or event data ports of the containing component. OSATE also deliberately accepts outgoing event or event data ports of direct subcomponents; bidirectional ports satisfy either direction. The validator reports invalid trigger kinds, directions, unresolved names, and paths that the strict model cannot represent, and keeps the strict checkers out of an incomplete condition. `ActualPortHolder.context` retains the subcomponent separately from the port and its feature-group path. Mode-refinement comparisons include the context, so `first.p` and `second.p` remain distinct even when both subcomponents share a classifier. `Issue3232Test` covers these checks, nested expressions, feature groups, and strict-model serialization. + ### G15 — Multiple final states in subprogram behavior are always rejected **Standard:** D.3's description explicitly allows several final states when specifying intended behavior; a deterministic implementation representation is distinguished as requiring one final state. diff --git a/ba/org.osate.ba.edit/plugin.properties b/ba/org.osate.ba.edit/plugin.properties index 148a88c684..8eb02d0377 100644 --- a/ba/org.osate.ba.edit/plugin.properties +++ b/ba/org.osate.ba.edit/plugin.properties @@ -366,3 +366,4 @@ _UI_BehaviorArraySize_integerValue_feature = Integer Value _UI_PortUpdatedValue_type = Port Updated Value _UI_ModeSwitchTriggerLogicalExpression_logicalOperators_feature = Logical Operators _UI_ModeSwitchConjunction_logicalOperators_feature = Logical Operators +_UI_ActualPortHolder_context_feature = Context diff --git a/ba/org.osate.ba.edit/src/org/osate/ba/aadlba/provider/ActualPortHolderItemProvider.java b/ba/org.osate.ba.edit/src/org/osate/ba/aadlba/provider/ActualPortHolderItemProvider.java index d49f80cb7b..d8f31acfbf 100644 --- a/ba/org.osate.ba.edit/src/org/osate/ba/aadlba/provider/ActualPortHolderItemProvider.java +++ b/ba/org.osate.ba.edit/src/org/osate/ba/aadlba/provider/ActualPortHolderItemProvider.java @@ -1,12 +1,12 @@ /** * AADL-BA-FrontEnd - * + * * Copyright (c) 2011-2021 TELECOM ParisTech and CNRS - * + * * TELECOM ParisTech/LTCI - * + * * Authors: see AUTHORS - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the Eclipse Public License as published by Eclipse, either * version 2.0 of the License, or (at your option) any later version. This @@ -24,7 +24,9 @@ import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.edit.provider.ComposeableAdapterFactory; import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; +import org.osate.ba.aadlba.AadlBaPackage; /** * This is the item provider adapter for a {@link org.osate.ba.aadlba.ActualPortHolder} object. @@ -54,10 +56,26 @@ public List getPropertyDescriptors(Object object) { if (itemPropertyDescriptors == null) { super.getPropertyDescriptors(object); + addContextPropertyDescriptor(object); } return itemPropertyDescriptors; } + /** + * This adds a property descriptor for the Context feature. + * + * + * @generated + */ + protected void addContextPropertyDescriptor(Object object) { + itemPropertyDescriptors + .add(createItemPropertyDescriptor(((ComposeableAdapterFactory) adapterFactory).getRootAdapterFactory(), + getResourceLocator(), getString("_UI_ActualPortHolder_context_feature"), + getString("_UI_PropertyDescriptor_description", "_UI_ActualPortHolder_context_feature", + "_UI_ActualPortHolder_type"), + AadlBaPackage.Literals.ACTUAL_PORT_HOLDER__CONTEXT, true, false, true, null, null, null)); + } + /** * This returns the label text for the adapted class. * diff --git a/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3186_SubprogramExternalCondition.txt b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3186_SubprogramExternalCondition.txt index e7a554bf9b..5620093910 100644 --- a/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3186_SubprogramExternalCondition.txt +++ b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3186_SubprogramExternalCondition.txt @@ -1 +1,2 @@ error | semantic | 37 | 10 | 5 | subprogram components cannot use an external condition: an execute or internal condition must be used instead: Behavior Annex D.3 consistency rule failed. +error | semantic | 37 | 13 | 2 | 'go' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent diff --git a/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt new file mode 100644 index 0000000000..933cada57f --- /dev/null +++ b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt @@ -0,0 +1,9 @@ +error | semantic | 53 | 15 | 5 | 'value' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 53 | 38 | 6 | 'stored' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 53 | 49 | 11 | 'local_value' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 54 | 15 | 8 | 'outgoing' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 54 | 27 | 13 | 'outgoing_data' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 55 | 15 | 14 | 'child.incoming' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 55 | 34 | 19 | 'child.incoming_data' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 55 | 57 | 11 | 'child.value' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent +error | semantic | 56 | 15 | 7 | 'unknown' is not an external-condition trigger: expected an incoming event or event data port of the component, or an outgoing event or event data port of a subcomponent diff --git a/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_Issue3232.txt b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_Issue3232.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_ModeTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_ModeTriggers.txt new file mode 100644 index 0000000000..2a06866cfd --- /dev/null +++ b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_ModeTriggers.txt @@ -0,0 +1 @@ +error | semantic | 63 | 9 | 18 | The behavior transition tries to refine a transition mode but it is not consisting with any transition mode of ModeTriggers::controller.mismatching component: Behavior Annex D.3.(C4) consistency rule failed. diff --git a/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics-validated/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_Issue3232.txt b/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_Issue3232.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_ModeTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_ModeTriggers.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt b/ba/org.osate.ba.tests/expected/diagnostics/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt new file mode 100644 index 0000000000..cf98179d6e --- /dev/null +++ b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt @@ -0,0 +1,27 @@ +annex[0] owner=GroupedTriggers::controller.impl + (BehaviorAnnex, behavior_specification, 2222, 159) + (BehaviorCondition, , 2302, 67) + (BehaviorState, running, 2256, 7) + (BehaviorState, waiting, 2230, 7) + (BehaviorStateGroup, , 2230, 24) + (BehaviorStateGroup, , 2256, 22) + (BehaviorTransition, , 2292, 89) + (ModeSwitchCondition, , 2305, 64) + (ModeSwitchConjunction, , 2305, 64) + (ModeSwitchTrigger, , 2305, 17) + (ModeSwitchTrigger, , 2327, 24) + (ModeSwitchTrigger, , 2356, 13) + (Reference, , 2305, 17) + (Reference, , 2327, 24) + (Reference, , 2356, 13) + (ReferenceSegment, child, 2327, 5) + (ReferenceSegment, grouped, 2356, 7) + (ReferenceSegment, input_group, 2305, 11) + (ReferenceSegment, output_group, 2333, 12) + (ReferenceSegment, ready, 2317, 5) + (ReferenceSegment, ready, 2346, 5) + (ReferenceSegment, ready, 2364, 5) + (ReferenceTail, , 2316, 6) + (ReferenceTail, , 2332, 13) + (ReferenceTail, , 2345, 6) + (ReferenceTail, , 2363, 6) diff --git a/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt new file mode 100644 index 0000000000..09874722a5 --- /dev/null +++ b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt @@ -0,0 +1,66 @@ +annex[0] owner=InvalidTriggers::controller.impl + (BehaviorAnnex, behavior_specification, 2302, 347) + (BehaviorCondition, , 2422, 49) + (BehaviorCondition, , 2495, 28) + (BehaviorCondition, , 2547, 56) + (BehaviorCondition, , 2627, 10) + (BehaviorState, running, 2382, 7) + (BehaviorState, waiting, 2356, 7) + (BehaviorStateGroup, , 2356, 24) + (BehaviorStateGroup, , 2382, 16) + (BehaviorTransition, , 2412, 71) + (BehaviorTransition, , 2485, 50) + (BehaviorTransition, , 2537, 78) + (BehaviorTransition, , 2617, 32) + (BehaviorVariable, local_value, 2313, 11) + (BehaviorVariableGroup, , 2313, 34) + (ModeSwitchCondition, , 2425, 46) + (ModeSwitchCondition, , 2448, 22) + (ModeSwitchCondition, , 2498, 25) + (ModeSwitchCondition, , 2550, 53) + (ModeSwitchCondition, , 2630, 7) + (ModeSwitchConjunction, , 2425, 18) + (ModeSwitchConjunction, , 2447, 24) + (ModeSwitchConjunction, , 2448, 22) + (ModeSwitchConjunction, , 2498, 8) + (ModeSwitchConjunction, , 2510, 13) + (ModeSwitchConjunction, , 2550, 38) + (ModeSwitchConjunction, , 2592, 11) + (ModeSwitchConjunction, , 2630, 7) + (ModeSwitchTrigger, , 2425, 5) + (ModeSwitchTrigger, , 2435, 8) + (ModeSwitchTrigger, , 2447, 24) + (ModeSwitchTrigger, , 2448, 6) + (ModeSwitchTrigger, , 2459, 11) + (ModeSwitchTrigger, , 2498, 8) + (ModeSwitchTrigger, , 2510, 13) + (ModeSwitchTrigger, , 2550, 14) + (ModeSwitchTrigger, , 2569, 19) + (ModeSwitchTrigger, , 2592, 11) + (ModeSwitchTrigger, , 2630, 7) + (Reference, , 2425, 5) + (Reference, , 2435, 8) + (Reference, , 2448, 6) + (Reference, , 2459, 11) + (Reference, , 2498, 8) + (Reference, , 2510, 13) + (Reference, , 2550, 14) + (Reference, , 2569, 19) + (Reference, , 2592, 11) + (Reference, , 2630, 7) + (ReferenceSegment, child, 2550, 5) + (ReferenceSegment, child, 2569, 5) + (ReferenceSegment, child, 2592, 5) + (ReferenceSegment, incoming, 2435, 8) + (ReferenceSegment, incoming, 2556, 8) + (ReferenceSegment, incoming_data, 2575, 13) + (ReferenceSegment, local_value, 2459, 11) + (ReferenceSegment, outgoing, 2498, 8) + (ReferenceSegment, outgoing_data, 2510, 13) + (ReferenceSegment, stored, 2448, 6) + (ReferenceSegment, unknown, 2630, 7) + (ReferenceSegment, value, 2425, 5) + (ReferenceSegment, value, 2598, 5) + (ReferenceTail, , 2555, 9) + (ReferenceTail, , 2574, 14) + (ReferenceTail, , 2597, 6) diff --git a/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_Issue3232.txt b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_Issue3232.txt new file mode 100644 index 0000000000..099ff7028d --- /dev/null +++ b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_Issue3232.txt @@ -0,0 +1,26 @@ +annex[0] owner=Issue3232::controller.impl + (BehaviorAnnex, behavior_specification, 2088, 163) + (BehaviorCondition, , 2168, 71) + (BehaviorState, running, 2122, 7) + (BehaviorState, waiting, 2096, 7) + (BehaviorStateGroup, , 2096, 24) + (BehaviorStateGroup, , 2122, 22) + (BehaviorTransition, , 2158, 93) + (ModeSwitchCondition, , 2171, 68) + (ModeSwitchCondition, , 2202, 36) + (ModeSwitchConjunction, , 2171, 26) + (ModeSwitchConjunction, , 2201, 38) + (ModeSwitchConjunction, , 2202, 36) + (ModeSwitchTrigger, , 2171, 8) + (ModeSwitchTrigger, , 2184, 13) + (ModeSwitchTrigger, , 2201, 38) + (ModeSwitchTrigger, , 2202, 13) + (ModeSwitchTrigger, , 2220, 18) + (Reference, , 2171, 8) + (Reference, , 2184, 13) + (Reference, , 2202, 13) + (Reference, , 2220, 18) + (ReferenceSegment, bidirectional, 2202, 13) + (ReferenceSegment, bidirectional_data, 2220, 18) + (ReferenceSegment, incoming, 2171, 8) + (ReferenceSegment, incoming_data, 2184, 13) diff --git a/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_ModeTriggers.txt b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_ModeTriggers.txt new file mode 100644 index 0000000000..14ed95392a --- /dev/null +++ b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_ModeTriggers.txt @@ -0,0 +1,30 @@ +annex[0] owner=ModeTriggers::controller.matching + (BehaviorAnnex, behavior_specification, 2086, 113) + (BehaviorCondition, , 2171, 17) + (BehaviorState, active, 2126, 6) + (BehaviorState, idle, 2094, 4) + (BehaviorStateGroup, , 2094, 30) + (BehaviorStateGroup, , 2126, 24) + (BehaviorTransition, , 2164, 35) + (ModeSwitchCondition, , 2174, 14) + (ModeSwitchConjunction, , 2174, 14) + (ModeSwitchTrigger, , 2174, 14) + (Reference, , 2174, 14) + (ReferenceSegment, first, 2174, 5) + (ReferenceSegment, outgoing, 2180, 8) + (ReferenceTail, , 2179, 9) +annex[1] owner=ModeTriggers::controller.mismatching + (BehaviorAnnex, behavior_specification, 2451, 114) + (BehaviorCondition, , 2536, 18) + (BehaviorState, active, 2491, 6) + (BehaviorState, idle, 2459, 4) + (BehaviorStateGroup, , 2459, 30) + (BehaviorStateGroup, , 2491, 24) + (BehaviorTransition, , 2529, 36) + (ModeSwitchCondition, , 2539, 15) + (ModeSwitchConjunction, , 2539, 15) + (ModeSwitchTrigger, , 2539, 15) + (Reference, , 2539, 15) + (ReferenceSegment, outgoing, 2546, 8) + (ReferenceSegment, second, 2539, 6) + (ReferenceTail, , 2545, 9) diff --git a/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt new file mode 100644 index 0000000000..8e2a99377a --- /dev/null +++ b/ba/org.osate.ba.tests/expected/positions/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt @@ -0,0 +1,48 @@ +annex[0] owner=SubcomponentTriggers::controller.impl + (BehaviorAnnex, behavior_specification, 2191, 238) + (BehaviorCondition, , 2271, 146) + (BehaviorState, running, 2225, 7) + (BehaviorState, waiting, 2199, 7) + (BehaviorStateGroup, , 2199, 24) + (BehaviorStateGroup, , 2225, 22) + (BehaviorTransition, , 2261, 168) + (ModeSwitchCondition, , 2274, 143) + (ModeSwitchCondition, , 2315, 44) + (ModeSwitchCondition, , 2367, 49) + (ModeSwitchConjunction, , 2274, 34) + (ModeSwitchConjunction, , 2314, 46) + (ModeSwitchConjunction, , 2315, 44) + (ModeSwitchConjunction, , 2366, 51) + (ModeSwitchConjunction, , 2367, 49) + (ModeSwitchTrigger, , 2274, 14) + (ModeSwitchTrigger, , 2293, 15) + (ModeSwitchTrigger, , 2314, 46) + (ModeSwitchTrigger, , 2315, 19) + (ModeSwitchTrigger, , 2339, 20) + (ModeSwitchTrigger, , 2366, 51) + (ModeSwitchTrigger, , 2367, 19) + (ModeSwitchTrigger, , 2391, 25) + (Reference, , 2274, 14) + (Reference, , 2293, 15) + (Reference, , 2315, 19) + (Reference, , 2339, 20) + (Reference, , 2367, 19) + (Reference, , 2391, 25) + (ReferenceSegment, bidirectional, 2373, 13) + (ReferenceSegment, bidirectional_data, 2398, 18) + (ReferenceSegment, first, 2274, 5) + (ReferenceSegment, first, 2315, 5) + (ReferenceSegment, first, 2367, 5) + (ReferenceSegment, outgoing, 2280, 8) + (ReferenceSegment, outgoing, 2300, 8) + (ReferenceSegment, outgoing_data, 2321, 13) + (ReferenceSegment, outgoing_data, 2346, 13) + (ReferenceSegment, second, 2293, 6) + (ReferenceSegment, second, 2339, 6) + (ReferenceSegment, second, 2391, 6) + (ReferenceTail, , 2279, 9) + (ReferenceTail, , 2299, 9) + (ReferenceTail, , 2320, 14) + (ReferenceTail, , 2345, 14) + (ReferenceTail, , 2372, 14) + (ReferenceTail, , 2397, 19) diff --git a/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt new file mode 100644 index 0000000000..745911508f --- /dev/null +++ b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt @@ -0,0 +1,12 @@ +annex[0] owner=GroupedTriggers::controller.impl + parsedAnnexSubclause : BehaviorAnnex name=behavior_specification + states[0] : BehaviorState name=waiting + states[1] : BehaviorState name=running + transitions[0] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=GroupedTriggers::signals.ready [EventPort] + groupHolders[0] : GroupHolder element=GroupedTriggers::controller.input_group [FeatureGroup] + modeSwitchTriggers[1] : EventPortHolder element=GroupedTriggers::signals.ready [EventPort] context=GroupedTriggers::controller.impl.child + groupHolders[0] : GroupHolder element=GroupedTriggers::worker.output_group [FeatureGroup] + modeSwitchTriggers[2] : EventPortHolder element=GroupedTriggers::workers.ready [EventPort] context=GroupedTriggers::controller.impl.grouped diff --git a/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt new file mode 100644 index 0000000000..a3c5a68ea3 --- /dev/null +++ b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt @@ -0,0 +1,27 @@ +annex[0] owner=InvalidTriggers::controller.impl + parsedAnnexSubclause : BehaviorAnnex name=behavior_specification + variables[0] : BehaviorVariable name=local_value + states[0] : BehaviorState name=waiting + states[1] : BehaviorState name=running + transitions[0] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=InvalidTriggers::controller.incoming [EventPort] + modeSwitchConjunctions[1] : ModeSwitchConjunction + modeSwitchTriggers[0] : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + transitions[1] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=InvalidTriggers::controller.outgoing [EventPort] + modeSwitchConjunctions[1] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventDataPortHolder element=InvalidTriggers::controller.outgoing_data [EventDataPort] + transitions[2] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=InvalidTriggers::worker.incoming [EventPort] context=InvalidTriggers::controller.impl.child + modeSwitchTriggers[1] : EventDataPortHolder element=InvalidTriggers::worker.incoming_data [EventDataPort] context=InvalidTriggers::controller.impl.child + modeSwitchConjunctions[1] : ModeSwitchConjunction + transitions[3] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction diff --git a/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_Issue3232.txt b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_Issue3232.txt new file mode 100644 index 0000000000..6568516503 --- /dev/null +++ b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_Issue3232.txt @@ -0,0 +1,14 @@ +annex[0] owner=Issue3232::controller.impl + parsedAnnexSubclause : BehaviorAnnex name=behavior_specification + states[0] : BehaviorState name=waiting + states[1] : BehaviorState name=running + transitions[0] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=Issue3232::controller.incoming [EventPort] + modeSwitchTriggers[1] : EventDataPortHolder element=Issue3232::controller.incoming_data [EventDataPort] + modeSwitchConjunctions[1] : ModeSwitchConjunction + modeSwitchTriggers[0] : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=Issue3232::controller.bidirectional [EventPort] + modeSwitchTriggers[1] : EventDataPortHolder element=Issue3232::controller.bidirectional_data [EventDataPort] diff --git a/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_ModeTriggers.txt b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_ModeTriggers.txt new file mode 100644 index 0000000000..d7a8ae89b6 --- /dev/null +++ b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_ModeTriggers.txt @@ -0,0 +1,16 @@ +annex[0] owner=ModeTriggers::controller.matching + parsedAnnexSubclause : BehaviorAnnex name=behavior_specification + states[0] : BehaviorState name=idle + states[1] : BehaviorState name=active + transitions[0] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=ModeTriggers::worker.outgoing [EventPort] context=ModeTriggers::controller.matching.first +annex[1] owner=ModeTriggers::controller.mismatching + parsedAnnexSubclause : BehaviorAnnex name=behavior_specification + states[0] : BehaviorState name=idle + states[1] : BehaviorState name=active + transitions[0] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=ModeTriggers::worker.outgoing [EventPort] context=ModeTriggers::controller.mismatching.second diff --git a/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt new file mode 100644 index 0000000000..a7fd5ce75d --- /dev/null +++ b/ba/org.osate.ba.tests/expected/resolved-model/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt @@ -0,0 +1,19 @@ +annex[0] owner=SubcomponentTriggers::controller.impl + parsedAnnexSubclause : BehaviorAnnex name=behavior_specification + states[0] : BehaviorState name=waiting + states[1] : BehaviorState name=running + transitions[0] : BehaviorTransition + condition : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=SubcomponentTriggers::worker.outgoing [EventPort] context=SubcomponentTriggers::controller.impl.first + modeSwitchTriggers[1] : EventPortHolder element=SubcomponentTriggers::worker.outgoing [EventPort] context=SubcomponentTriggers::controller.impl.second + modeSwitchConjunctions[1] : ModeSwitchConjunction + modeSwitchTriggers[0] : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventDataPortHolder element=SubcomponentTriggers::worker.outgoing_data [EventDataPort] context=SubcomponentTriggers::controller.impl.first + modeSwitchTriggers[1] : EventDataPortHolder element=SubcomponentTriggers::worker.outgoing_data [EventDataPort] context=SubcomponentTriggers::controller.impl.second + modeSwitchConjunctions[2] : ModeSwitchConjunction + modeSwitchTriggers[0] : ModeSwitchTriggerLogicalExpression + modeSwitchConjunctions[0] : ModeSwitchConjunction + modeSwitchTriggers[0] : EventPortHolder element=SubcomponentTriggers::worker.bidirectional [EventPort] context=SubcomponentTriggers::controller.impl.first + modeSwitchTriggers[1] : EventDataPortHolder element=SubcomponentTriggers::worker.bidirectional_data [EventDataPort] context=SubcomponentTriggers::controller.impl.second diff --git a/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt new file mode 100644 index 0000000000..7e10788e79 --- /dev/null +++ b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_GroupedTriggers.txt @@ -0,0 +1,9 @@ +===== annex[0] owner=GroupedTriggers::controller.impl ===== + +states +\twaiting : initial state; +\trunning : final state; +transitions +\twaiting -[on input_group.ready and child.output_group.ready and grouped.ready]-> running; +----- Xtext reparse ----- +reparsed diff --git a/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt new file mode 100644 index 0000000000..bc7beb415b --- /dev/null +++ b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_InvalidTriggers.txt @@ -0,0 +1,14 @@ +===== annex[0] owner=InvalidTriggers::controller.impl ===== + +variables +\tlocal_value : Base_Types::Integer; +states +\twaiting : initial state; +\trunning : state; +transitions +\twaiting -[on value and incoming or (stored and local_value)]-> running; +\twaiting -[on outgoing or outgoing_data]-> running; +\twaiting -[on child.incoming and child.incoming_data or child.value]-> running; +\twaiting -[on unknown]-> running; +----- Xtext reparse ----- +reparsed diff --git a/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_Issue3232.txt b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_Issue3232.txt new file mode 100644 index 0000000000..03dc4f5714 --- /dev/null +++ b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_Issue3232.txt @@ -0,0 +1,9 @@ +===== annex[0] owner=Issue3232::controller.impl ===== + +states +\twaiting : initial state; +\trunning : final state; +transitions +\twaiting -[on incoming and incoming_data or (bidirectional and bidirectional_data)]-> running; +----- Xtext reparse ----- +reparsed diff --git a/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_ModeTriggers.txt b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_ModeTriggers.txt new file mode 100644 index 0000000000..2c0dfed45b --- /dev/null +++ b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_ModeTriggers.txt @@ -0,0 +1,18 @@ +===== annex[0] owner=ModeTriggers::controller.matching ===== + +states +\tidle : initial complete state; +\tactive : complete state; +transitions +\tidle -[on first.outgoing]-> active; +----- Xtext reparse ----- +reparsed +===== annex[1] owner=ModeTriggers::controller.mismatching ===== + +states +\tidle : initial complete state; +\tactive : complete state; +transitions +\tidle -[on second.outgoing]-> active; +----- Xtext reparse ----- +reparsed diff --git a/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt new file mode 100644 index 0000000000..415caabc51 --- /dev/null +++ b/ba/org.osate.ba.tests/expected/unparse/org.osate.ba.tests_models_issue3232_SubcomponentTriggers.txt @@ -0,0 +1,11 @@ +===== annex[0] owner=SubcomponentTriggers::controller.impl ===== + +states +\twaiting : initial state; +\trunning : final state; +transitions +\twaiting -[on first.outgoing and second.outgoing or +\t\t(first.outgoing_data and second.outgoing_data) or +\t\t(first.bidirectional and second.bidirectional_data)]-> running; +----- Xtext reparse ----- +reparsed diff --git a/ba/org.osate.ba.tests/models/issue3232/.gitignore b/ba/org.osate.ba.tests/models/issue3232/.gitignore new file mode 100644 index 0000000000..afce51184c --- /dev/null +++ b/ba/org.osate.ba.tests/models/issue3232/.gitignore @@ -0,0 +1,2 @@ +/.aadlbin-gen/ +/instances/ diff --git a/ba/org.osate.ba.tests/models/issue3232/.project b/ba/org.osate.ba.tests/models/issue3232/.project new file mode 100644 index 0000000000..969b352329 --- /dev/null +++ b/ba/org.osate.ba.tests/models/issue3232/.project @@ -0,0 +1,18 @@ + + + issue3232 + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + + org.osate.core.aadlnature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/ba/org.osate.ba.tests/models/issue3232/GroupedTriggers.aadl b/ba/org.osate.ba.tests/models/issue3232/GroupedTriggers.aadl new file mode 100644 index 0000000000..c9e01eab84 --- /dev/null +++ b/ba/org.osate.ba.tests/models/issue3232/GroupedTriggers.aadl @@ -0,0 +1,57 @@ +-- Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file). +-- All Rights Reserved. +-- +-- NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY +-- KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE +-- OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT +-- MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. +-- +-- This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 +-- which is available at https://www.eclipse.org/legal/epl-2.0/ +-- SPDX-License-Identifier: EPL-2.0 +-- +-- Created, in part, with funding and support from the United States Government. (see Acknowledgments file). +-- +-- This program includes and/or can make use of certain third party source code, object code, documentation and other +-- files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system +-- configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and +-- conditions contained in any such Third Party Software or separate license file distributed with such Third Party +-- Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici- +-- aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li- +-- censes only apply to the Third Party Software and not any other portion of this program or this program as a whole. + +package GroupedTriggers +public +feature group signals +features + ready : in event port; +end signals; + +thread worker +features + output_group : feature group inverse of signals; +end worker; + +thread group workers +features + ready : out event port; +end workers; + +process controller +features + input_group : feature group signals; +end controller; + +process implementation controller.impl +subcomponents + child : thread worker; + grouped : thread group workers; +annex behavior_specification {** +states + waiting : initial state; + running : final state; +transitions + waiting -[on input_group.ready and child.output_group.ready and grouped.ready]-> running; +**}; +end controller.impl; +end GroupedTriggers; diff --git a/ba/org.osate.ba.tests/models/issue3232/InvalidTriggers.aadl b/ba/org.osate.ba.tests/models/issue3232/InvalidTriggers.aadl new file mode 100644 index 0000000000..b27b31ad8f --- /dev/null +++ b/ba/org.osate.ba.tests/models/issue3232/InvalidTriggers.aadl @@ -0,0 +1,59 @@ +-- Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file). +-- All Rights Reserved. +-- +-- NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY +-- KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE +-- OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT +-- MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. +-- +-- This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 +-- which is available at https://www.eclipse.org/legal/epl-2.0/ +-- SPDX-License-Identifier: EPL-2.0 +-- +-- Created, in part, with funding and support from the United States Government. (see Acknowledgments file). +-- +-- This program includes and/or can make use of certain third party source code, object code, documentation and other +-- files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system +-- configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and +-- conditions contained in any such Third Party Software or separate license file distributed with such Third Party +-- Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici- +-- aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li- +-- censes only apply to the Third Party Software and not any other portion of this program or this program as a whole. + +package InvalidTriggers +public + with Base_Types; + +thread worker +features + incoming : in event port; + incoming_data : in event data port Base_Types::Integer; + value : out data port Base_Types::Integer; +end worker; + +process controller +features + incoming : in event port; + value : in data port Base_Types::Integer; + outgoing : out event port; + outgoing_data : out event data port Base_Types::Integer; +end controller; + +process implementation controller.impl +subcomponents + child : thread worker; + stored : data Base_Types::Integer; +annex behavior_specification {** +variables + local_value : Base_Types::Integer; +states + waiting : initial state; + running : state; +transitions + waiting -[on value and incoming or (stored and local_value)]-> running; + waiting -[on outgoing or outgoing_data]-> running; + waiting -[on child.incoming and child.incoming_data or child.value]-> running; + waiting -[on unknown]-> running; +**}; +end controller.impl; +end InvalidTriggers; diff --git a/ba/org.osate.ba.tests/models/issue3232/Issue3232.aadl b/ba/org.osate.ba.tests/models/issue3232/Issue3232.aadl new file mode 100644 index 0000000000..ad3889ae2b --- /dev/null +++ b/ba/org.osate.ba.tests/models/issue3232/Issue3232.aadl @@ -0,0 +1,44 @@ +-- Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file). +-- All Rights Reserved. +-- +-- NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY +-- KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE +-- OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT +-- MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. +-- +-- This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 +-- which is available at https://www.eclipse.org/legal/epl-2.0/ +-- SPDX-License-Identifier: EPL-2.0 +-- +-- Created, in part, with funding and support from the United States Government. (see Acknowledgments file). +-- +-- This program includes and/or can make use of certain third party source code, object code, documentation and other +-- files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system +-- configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and +-- conditions contained in any such Third Party Software or separate license file distributed with such Third Party +-- Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici- +-- aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li- +-- censes only apply to the Third Party Software and not any other portion of this program or this program as a whole. + +package Issue3232 +public + with Base_Types; + +process controller +features + incoming : in event port; + incoming_data : in event data port Base_Types::Integer; + bidirectional : in out event port; + bidirectional_data : in out event data port Base_Types::Integer; +end controller; + +process implementation controller.impl +annex behavior_specification {** +states + waiting : initial state; + running : final state; +transitions + waiting -[on incoming and incoming_data or (bidirectional and bidirectional_data)]-> running; +**}; +end controller.impl; +end Issue3232; diff --git a/ba/org.osate.ba.tests/models/issue3232/ModeTriggers.aadl b/ba/org.osate.ba.tests/models/issue3232/ModeTriggers.aadl new file mode 100644 index 0000000000..8889849db3 --- /dev/null +++ b/ba/org.osate.ba.tests/models/issue3232/ModeTriggers.aadl @@ -0,0 +1,66 @@ +-- Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file). +-- All Rights Reserved. +-- +-- NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY +-- KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE +-- OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT +-- MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. +-- +-- This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 +-- which is available at https://www.eclipse.org/legal/epl-2.0/ +-- SPDX-License-Identifier: EPL-2.0 +-- +-- Created, in part, with funding and support from the United States Government. (see Acknowledgments file). +-- +-- This program includes and/or can make use of certain third party source code, object code, documentation and other +-- files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system +-- configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and +-- conditions contained in any such Third Party Software or separate license file distributed with such Third Party +-- Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici- +-- aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li- +-- censes only apply to the Third Party Software and not any other portion of this program or this program as a whole. + +package ModeTriggers +public +thread worker +features + outgoing : out event port; +end worker; + +process controller +end controller; + +process implementation controller.matching +subcomponents + first : thread worker; + second : thread worker; +modes + idle : initial mode; + active : mode; + idle -[first.outgoing]-> active; +annex behavior_specification {** +states + idle : initial complete state; + active : complete state; +transitions + idle -[on first.outgoing]-> active; +**}; +end controller.matching; + +process implementation controller.mismatching +subcomponents + first : thread worker; + second : thread worker; +modes + idle : initial mode; + active : mode; + idle -[first.outgoing]-> active; +annex behavior_specification {** +states + idle : initial complete state; + active : complete state; +transitions + idle -[on second.outgoing]-> active; +**}; +end controller.mismatching; +end ModeTriggers; diff --git a/ba/org.osate.ba.tests/models/issue3232/SubcomponentTriggers.aadl b/ba/org.osate.ba.tests/models/issue3232/SubcomponentTriggers.aadl new file mode 100644 index 0000000000..4e4b1847d8 --- /dev/null +++ b/ba/org.osate.ba.tests/models/issue3232/SubcomponentTriggers.aadl @@ -0,0 +1,52 @@ +-- Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file). +-- All Rights Reserved. +-- +-- NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY +-- KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE +-- OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT +-- MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. +-- +-- This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 +-- which is available at https://www.eclipse.org/legal/epl-2.0/ +-- SPDX-License-Identifier: EPL-2.0 +-- +-- Created, in part, with funding and support from the United States Government. (see Acknowledgments file). +-- +-- This program includes and/or can make use of certain third party source code, object code, documentation and other +-- files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system +-- configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and +-- conditions contained in any such Third Party Software or separate license file distributed with such Third Party +-- Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici- +-- aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li- +-- censes only apply to the Third Party Software and not any other portion of this program or this program as a whole. + +package SubcomponentTriggers +public + with Base_Types; + +thread worker +features + outgoing : out event port; + outgoing_data : out event data port Base_Types::Integer; + bidirectional : in out event port; + bidirectional_data : in out event data port Base_Types::Integer; +end worker; + +process controller +end controller; + +process implementation controller.impl +subcomponents + first : thread worker; + second : thread worker; +annex behavior_specification {** +states + waiting : initial state; + running : final state; +transitions + waiting -[on first.outgoing and second.outgoing or + (first.outgoing_data and second.outgoing_data) or + (first.bidirectional and second.bidirectional_data)]-> running; +**}; +end controller.impl; +end SubcomponentTriggers; diff --git a/ba/org.osate.ba.tests/src/org/osate/ba/tests/Issue3186Test.java b/ba/org.osate.ba.tests/src/org/osate/ba/tests/Issue3186Test.java index 6f64aa1e20..662726b28b 100644 --- a/ba/org.osate.ba.tests/src/org/osate/ba/tests/Issue3186Test.java +++ b/ba/org.osate.ba.tests/src/org/osate/ba/tests/Issue3186Test.java @@ -79,13 +79,16 @@ public void threadCannotUseAnExternalCondition() throws Exception { /** * The fixture's trigger is an outgoing event port because core AADL admits no other event port on a subprogram, * so no subprogram can name the incoming port the D.3 event_trigger production asks for. The rule constrains the - * form of the condition rather than its triggers, which is what makes it worth reporting anyway. + * form of the condition rather than its triggers, so it is reported alongside the trigger-direction error. */ @Test public void subprogramCannotUseAnExternalCondition() throws Exception { assertDiagnostics("SubprogramExternalCondition", List.of(new Expected("on go", CHECKER, "subprogram components cannot use an external condition: an execute or internal condition must be used" - + " instead: Behavior Annex D.3 consistency rule failed."))); + + " instead: Behavior Annex D.3 consistency rule failed."), + new Expected("go", "org.osate.xtext.aadl2.ba.externalConditionTrigger", + "'go' is not an external-condition trigger: expected an incoming event or event data port" + + " of the component, or an outgoing event or event data port of a subcomponent"))); } /** Only external conditions leave the complete state, so the device rule has nothing to reject. */ diff --git a/ba/org.osate.ba.tests/src/org/osate/ba/tests/Issue3232Test.java b/ba/org.osate.ba.tests/src/org/osate/ba/tests/Issue3232Test.java new file mode 100644 index 0000000000..4be1fc951b --- /dev/null +++ b/ba/org.osate.ba.tests/src/org/osate/ba/tests/Issue3232Test.java @@ -0,0 +1,202 @@ +/** + * Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file). + * All Rights Reserved. + * + * NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE + * OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT + * MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. + * + * This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * SPDX-License-Identifier: EPL-2.0 + * + * Created, in part, with funding and support from the United States Government. (see Acknowledgments file). + * + * This program includes and/or can make use of certain third party source code, object code, documentation and other + * files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system + * configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and + * conditions contained in any such Third Party Software or separate license file distributed with such Third Party + * Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici- + * aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li- + * censes only apply to the Third Party Software and not any other portion of this program or this program as a whole. + */ +package org.osate.ba.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; +import org.eclipse.xtext.diagnostics.Severity; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.eclipse.xtext.testing.InjectWith; +import org.eclipse.xtext.testing.XtextRunner; +import org.eclipse.xtext.testing.validation.ValidationTestHelper; +import org.eclipse.xtext.validation.Issue; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.osate.aadl2.AadlPackage; +import org.osate.aadl2.ComponentImplementation; +import org.osate.annexsupport.AnnexUtil; +import org.osate.ba.aadlba.AadlBaPackage; +import org.osate.ba.aadlba.ActualPortHolder; +import org.osate.ba.aadlba.BehaviorAnnex; +import org.osate.ba.aadlba.ModeSwitchTriggerLogicalExpression; +import org.osate.testsupport.TestHelper; +import org.osate.xtext.aadl2.ba.util.BehaviorAnnexUtil; + +import com.google.inject.Inject; +import com.itemis.xtext.testing.XtextTest; + +/** Exercises external-condition trigger validation and preservation through ordinary embedded AADL models. */ +@RunWith(XtextRunner.class) +@InjectWith(BehaviorAnnexInjectorProvider.class) +public class Issue3232Test extends XtextTest { + private static final String PATH = "org.osate.ba.tests/models/issue3232/"; + private static final String EXTERNAL_CONDITION_TRIGGER = "org.osate.xtext.aadl2.ba.externalConditionTrigger"; + + @Inject + private TestHelper testHelper; + + @Inject + private ValidationTestHelper validationHelper; + + @Test + public void incomingOwnerPortsRemainTriggersInNestedExpressions() throws Exception { + var root = testHelper.parseFile(PATH + "Issue3232.aadl"); + validationHelper.assertNoIssues(root); + var ports = triggers(root); + assertEquals(List.of("incoming", "incoming_data", "bidirectional", "bidirectional_data"), + ports.stream().map(port -> port.getPort().getName()).toList()); + for (var port : ports) { + assertNull(port.getContext()); + } + } + + @Test + public void outgoingSubcomponentPortsRetainTheirContexts() throws Exception { + var root = testHelper.parseFile(PATH + "SubcomponentTriggers.aadl"); + validationHelper.assertNoIssues(root); + var annex = AnnexUtil.getAllDefaultAnnexSubclauses(root).getFirst(); + var owner = (ComponentImplementation) annex.getContainingClassifier(); + var first = owner.getAllSubcomponents().stream().filter(s -> "first".equals(s.getName())).findFirst().orElseThrow(); + var second = owner.getAllSubcomponents().stream().filter(s -> "second".equals(s.getName())).findFirst().orElseThrow(); + var ports = triggers(root); + assertEquals(List.of("outgoing", "outgoing", "outgoing_data", "outgoing_data", "bidirectional", + "bidirectional_data"), ports.stream().map(port -> port.getPort().getName()).toList()); + assertSame(ports.get(0).getPort(), ports.get(1).getPort()); + for (var i = 0; i < ports.size(); i++) { + assertSame(i % 2 == 0 ? first : second, ports.get(i).getContext()); + } + } + + @Test + public void strictSerializationPreservesSubcomponentContexts() throws Exception { + var root = testHelper.parseFile(PATH + "SubcomponentTriggers.aadl"); + validationHelper.assertNoIssues(root); + var strict = BehaviorAnnexUtil.getStrictModel(AnnexUtil.getAllDefaultAnnexSubclauses(root).getFirst()); + var original = triggers(strict); + root.eResource().setURI(URI.createURI("memory:/issue3232.aadl")); + var resource = new XMIResourceImpl(URI.createURI("memory:/issue3232.aadlba")); + root.eResource().getResourceSet().getPackageRegistry().put(AadlBaPackage.eNS_URI, AadlBaPackage.eINSTANCE); + root.eResource().getResourceSet().getResources().add(resource); + try { + resource.getContents().add(EcoreUtil.copy(strict)); + var bytes = new ByteArrayOutputStream(); + resource.save(bytes, Map.of()); + resource.unload(); + resource.load(new ByteArrayInputStream(bytes.toByteArray()), Map.of()); + EcoreUtil.resolveAll(resource); + var reloaded = triggers((BehaviorAnnex) resource.getContents().getFirst()); + assertEquals(original.size(), reloaded.size()); + for (var i = 0; i < original.size(); i++) { + assertSame(original.get(i).getPort(), reloaded.get(i).getPort()); + assertSame(original.get(i).getContext(), reloaded.get(i).getContext()); + } + } finally { + root.eResource().getResourceSet().getResources().remove(resource); + } + } + + @Test + public void featureGroupsAndThreadGroupContextsRemainDistinct() throws Exception { + var root = testHelper.parseFile(PATH + "GroupedTriggers.aadl"); + validationHelper.assertNoIssues(root); + var ports = triggers(root); + assertEquals(3, ports.size()); + assertNull(ports.get(0).getContext()); + assertEquals("child", ports.get(1).getContext().getName()); + assertEquals("grouped", ports.get(2).getContext().getName()); + assertEquals(List.of(List.of("input_group"), List.of("output_group"), List.of()), + ports.stream().map(port -> port.getGroupHolders().stream() + .map(group -> group.getElement().getName()).toList()).toList()); + } + + @Test + public void invalidKindsDirectionsAndNamesAreReportedOnEveryWrittenTrigger() throws Exception { + var root = testHelper.parseFile(PATH + "InvalidTriggers.aadl"); + var names = List.of("value", "stored", "local_value", "outgoing", "outgoing_data", "child.incoming", + "child.incoming_data", "child.value", "unknown"); + assertDiagnostics(root, names.stream().map(name -> new Expected(name, EXTERNAL_CONDITION_TRIGGER, + "'" + name + "' is not an external-condition trigger: expected an incoming event or event data port" + + " of the component, or an outgoing event or event data port of a subcomponent")).toList()); + } + + @Test + public void modeRefinementDistinguishesSubcomponentsOfTheSameClassifier() throws Exception { + var root = testHelper.parseFile(PATH + "ModeTriggers.aadl"); + assertDiagnostics(root, List.of(new Expected("on second.outgoing", "org.osate.xtext.aadl2.ba.checker", + "The behavior transition tries to refine a transition mode but it is not consisting with any " + + "transition mode of ModeTriggers::controller.mismatching component: Behavior Annex D.3.(C4) " + + "consistency rule failed."))); + } + + private static List triggers(AadlPackage root) { + var annex = AnnexUtil.getAllDefaultAnnexSubclauses(root).getFirst(); + return triggers(BehaviorAnnexUtil.getStrictModel(annex)); + } + + private static List triggers(BehaviorAnnex strict) { + var result = new ArrayList(); + collectTriggers((ModeSwitchTriggerLogicalExpression) strict.getTransitions().getFirst().getCondition(), result); + return result; + } + + private static void collectTriggers(ModeSwitchTriggerLogicalExpression expression, List result) { + for (var conjunction : expression.getModeSwitchConjunctions()) { + for (var trigger : conjunction.getModeSwitchTriggers()) { + if (trigger instanceof ModeSwitchTriggerLogicalExpression group) { + collectTriggers(group, result); + } else { + assertTrue(trigger instanceof ActualPortHolder); + result.add((ActualPortHolder) trigger); + } + } + } + } + + private void assertDiagnostics(AadlPackage root, List expected) { + var source = NodeModelUtils.getNode(root).getRootNode().getText(); + var issues = validationHelper.validate(root).stream().sorted(Comparator.comparing(Issue::getOffset)).toList(); + assertEquals(issues.toString(), expected.size(), issues.size()); + assertEquals(expected, issues.stream().map(issue -> { + assertEquals(Severity.ERROR, issue.getSeverity()); + var target = source.substring(issue.getOffset(), issue.getOffset() + issue.getLength()); + return new Expected(target, issue.getCode(), issue.getMessage()); + }).toList()); + } + + private record Expected(String target, String code, String message) { + } +} diff --git a/ba/org.osate.ba.tests/src/org/osate/ba/tests/characterization/BehaviorAnnexCharacterizationTest.java b/ba/org.osate.ba.tests/src/org/osate/ba/tests/characterization/BehaviorAnnexCharacterizationTest.java index 5f51e197fb..5051e5b7a9 100644 --- a/ba/org.osate.ba.tests/src/org/osate/ba/tests/characterization/BehaviorAnnexCharacterizationTest.java +++ b/ba/org.osate.ba.tests/src/org/osate/ba/tests/characterization/BehaviorAnnexCharacterizationTest.java @@ -60,6 +60,7 @@ import org.osate.annexsupport.AnnexUnparserRegistry; import org.osate.annexsupport.AnnexUtil; import org.osate.ba.aadlba.AadlBaPackage; +import org.osate.ba.aadlba.ActualPortHolder; import org.osate.testsupport.Aadl2InjectorProvider; import org.osate.testsupport.TestHelper; import org.osate.xtext.aadl2.ba.BehaviorAnnexStandaloneSetup; @@ -310,6 +311,9 @@ private static void appendModel(final StringBuilder result, final EObject object } } } + if (object instanceof ActualPortHolder port && port.getContext() != null) { + result.append(" context=").append(qualifiedName(port.getContext())); + } result.append('\n'); final var indexes = new HashMap(); diff --git a/ba/org.osate.ba/model/aadlba.ecore b/ba/org.osate.ba/model/aadlba.ecore index 183b5e8d96..a33a400a35 100644 --- a/ba/org.osate.ba/model/aadlba.ecore +++ b/ba/org.osate.ba/model/aadlba.ecore @@ -14,6 +14,12 @@
+ + +
+ + + diff --git a/ba/org.osate.ba/src/org/osate/ba/aadlba/AadlBaPackage.java b/ba/org.osate.ba/src/org/osate/ba/aadlba/AadlBaPackage.java index b586e594f2..bf348aef23 100644 --- a/ba/org.osate.ba/src/org/osate/ba/aadlba/AadlBaPackage.java +++ b/ba/org.osate.ba/src/org/osate/ba/aadlba/AadlBaPackage.java @@ -1215,6 +1215,15 @@ public interface AadlBaPackage extends EPackage { */ int ACTUAL_PORT_HOLDER__GROUP_HOLDERS = PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int ACTUAL_PORT_HOLDER__CONTEXT = PORT_HOLDER_FEATURE_COUNT + 0; + /** * The number of structural features of the 'Actual Port Holder' class. * @@ -1222,7 +1231,7 @@ public interface AadlBaPackage extends EPackage { * @generated * @ordered */ - int ACTUAL_PORT_HOLDER_FEATURE_COUNT = PORT_HOLDER_FEATURE_COUNT + 0; + int ACTUAL_PORT_HOLDER_FEATURE_COUNT = PORT_HOLDER_FEATURE_COUNT + 1; /** * The feature id for the 'Owned Element' reference list. @@ -3315,6 +3324,15 @@ public interface AadlBaPackage extends EPackage { */ int DATA_PORT_HOLDER__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int DATA_PORT_HOLDER__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Data Port Holder' class. * @@ -3739,6 +3757,15 @@ public interface AadlBaPackage extends EPackage { */ int EVENT_DATA_PORT_HOLDER__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int EVENT_DATA_PORT_HOLDER__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Event Data Port Holder' class. * @@ -3793,6 +3820,15 @@ public interface AadlBaPackage extends EPackage { */ int EVENT_PORT_HOLDER__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int EVENT_PORT_HOLDER__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Event Port Holder' class. * @@ -4975,6 +5011,15 @@ public interface AadlBaPackage extends EPackage { */ int PORT_COUNT_VALUE__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int PORT_COUNT_VALUE__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Port Count Value' class. * @@ -5074,6 +5119,15 @@ public interface AadlBaPackage extends EPackage { */ int PORT_DEQUEUE_VALUE__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int PORT_DEQUEUE_VALUE__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Port Dequeue Value' class. * @@ -5128,6 +5182,15 @@ public interface AadlBaPackage extends EPackage { */ int PORT_FREEZE_ACTION__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int PORT_FREEZE_ACTION__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Port Freeze Action' class. * @@ -5182,6 +5245,15 @@ public interface AadlBaPackage extends EPackage { */ int PORT_FRESH_VALUE__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int PORT_FRESH_VALUE__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Port Fresh Value' class. * @@ -6971,6 +7043,15 @@ public interface AadlBaPackage extends EPackage { */ int PORT_UPDATED_VALUE__GROUP_HOLDERS = ACTUAL_PORT_HOLDER__GROUP_HOLDERS; + /** + * The feature id for the 'Context' reference. + * + * + * @generated + * @ordered + */ + int PORT_UPDATED_VALUE__CONTEXT = ACTUAL_PORT_HOLDER__CONTEXT; + /** * The number of structural features of the 'Port Updated Value' class. * @@ -7137,6 +7218,17 @@ public interface AadlBaPackage extends EPackage { */ EClass getActualPortHolder(); + /** + * Returns the meta object for the reference '{@link org.osate.ba.aadlba.ActualPortHolder#getContext Context}'. + * + * + * @return the meta object for the reference 'Context'. + * @see org.osate.ba.aadlba.ActualPortHolder#getContext() + * @see #getActualPortHolder() + * @generated + */ + EReference getActualPortHolder_Context(); + /** * Returns the meta object for class '{@link org.osate.ba.aadlba.AssignmentAction Assignment Action}'. * @@ -9629,6 +9721,14 @@ interface Literals { */ EClass ACTUAL_PORT_HOLDER = eINSTANCE.getActualPortHolder(); + /** + * The meta object literal for the 'Context' reference feature. + * + * + * @generated + */ + EReference ACTUAL_PORT_HOLDER__CONTEXT = eINSTANCE.getActualPortHolder_Context(); + /** * The meta object literal for the '{@link org.osate.ba.aadlba.impl.AssignmentActionImpl Assignment Action}' class. * diff --git a/ba/org.osate.ba/src/org/osate/ba/aadlba/ActualPortHolder.java b/ba/org.osate.ba/src/org/osate/ba/aadlba/ActualPortHolder.java index 4624011520..1613164608 100644 --- a/ba/org.osate.ba/src/org/osate/ba/aadlba/ActualPortHolder.java +++ b/ba/org.osate.ba/src/org/osate/ba/aadlba/ActualPortHolder.java @@ -1,12 +1,12 @@ /** * AADL-BA-FrontEnd - * + * * Copyright (c) 2011-2021 TELECOM ParisTech and CNRS - * + * * TELECOM ParisTech/LTCI - * + * * Authors: see AUTHORS - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the Eclipse Public License as published by Eclipse, either * version 2.0 of the License, or (at your option) any later version. This @@ -20,18 +20,50 @@ package org.osate.ba.aadlba; import org.osate.aadl2.Port; +import org.osate.aadl2.Subcomponent; /** * * A representation of the model object 'Actual Port Holder'. * * + *

+ * The following features are supported: + *

+ *
    + *
  • {@link org.osate.ba.aadlba.ActualPortHolder#getContext Context}
  • + *
* * @see org.osate.ba.aadlba.AadlBaPackage#getActualPortHolder() * @model abstract="true" * @generated */ public interface ActualPortHolder extends PortHolder { + /** + * Returns the value of the 'Context' reference. + * + * + * + * The subcomponent whose port is referenced by an external-condition trigger. Absent for a port of the component containing the Behavior Annex. + * + * @return the value of the 'Context' reference. + * @see #setContext(Subcomponent) + * @see org.osate.ba.aadlba.AadlBaPackage#getActualPortHolder_Context() + * @model + * @generated + */ + Subcomponent getContext(); + + /** + * Sets the value of the '{@link org.osate.ba.aadlba.ActualPortHolder#getContext Context}' reference. + * + * + * @param value the new value of the 'Context' reference. + * @see #getContext() + * @generated + */ + void setContext(Subcomponent value); + /** * * diff --git a/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/AadlBaPackageImpl.java b/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/AadlBaPackageImpl.java index 1b48779e4f..146f418974 100644 --- a/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/AadlBaPackageImpl.java +++ b/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/AadlBaPackageImpl.java @@ -1109,6 +1109,16 @@ public EClass getActualPortHolder() { return actualPortHolderEClass; } + /** + * + * + * @generated + */ + @Override + public EReference getActualPortHolder_Context() { + return (EReference) actualPortHolderEClass.getEStructuralFeatures().get(0); + } + /** * * @@ -3501,6 +3511,7 @@ public void createPackageContents() { // Create classes and their features actualPortHolderEClass = createEClass(ACTUAL_PORT_HOLDER); + createEReference(actualPortHolderEClass, ACTUAL_PORT_HOLDER__CONTEXT); assignmentActionEClass = createEClass(ASSIGNMENT_ACTION); createEReference(assignmentActionEClass, ASSIGNMENT_ACTION__TARGET); @@ -4119,6 +4130,9 @@ public void initializePackageContents() { // Initialize classes and features; add operations and parameters initEClass(actualPortHolderEClass, ActualPortHolder.class, "ActualPortHolder", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getActualPortHolder_Context(), theAadl2Package.getSubcomponent(), null, "context", null, 0, 1, + ActualPortHolder.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, + !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); EOperation op = addEOperation(actualPortHolderEClass, null, "setPort", 1, 1, IS_UNIQUE, IS_ORDERED); addEParameter(op, theAadl2Package.getPort(), "port", 1, 1, IS_UNIQUE, IS_ORDERED); diff --git a/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/ActualPortHolderImpl.java b/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/ActualPortHolderImpl.java index 4831b2a7df..0b8e9579ca 100644 --- a/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/ActualPortHolderImpl.java +++ b/ba/org.osate.ba/src/org/osate/ba/aadlba/impl/ActualPortHolderImpl.java @@ -1,12 +1,12 @@ /** * AADL-BA-FrontEnd - * + * * Copyright (c) 2011-2021 TELECOM ParisTech and CNRS - * + * * TELECOM ParisTech/LTCI - * + * * Authors: see AUTHORS - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the Eclipse Public License as published by Eclipse, either * version 2.0 of the License, or (at your option) any later version. This @@ -19,8 +19,12 @@ */ package org.osate.ba.aadlba.impl; +import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.InternalEObject; +import org.eclipse.emf.ecore.impl.ENotificationImpl; import org.osate.aadl2.Port; +import org.osate.aadl2.Subcomponent; import org.osate.ba.aadlba.AadlBaPackage; import org.osate.ba.aadlba.ActualPortHolder; import org.osate.ba.utils.visitor.IBAVisitor; @@ -29,10 +33,26 @@ * * An implementation of the model object 'Actual Port Holder'. * + *

+ * The following features are implemented: + *

+ *
    + *
  • {@link org.osate.ba.aadlba.impl.ActualPortHolderImpl#getContext Context}
  • + *
* * @generated */ public abstract class ActualPortHolderImpl extends PortHolderImpl implements ActualPortHolder { + /** + * The cached value of the '{@link #getContext() Context}' reference. + * + * + * @see #getContext() + * @generated + * @ordered + */ + protected Subcomponent context; + /** * * @@ -52,6 +72,50 @@ protected EClass eStaticClass() { return AadlBaPackage.Literals.ACTUAL_PORT_HOLDER; } + /** + * + * + * @generated + */ + @Override + public Subcomponent getContext() { + if (context != null && context.eIsProxy()) { + InternalEObject oldContext = (InternalEObject) context; + context = (Subcomponent) eResolveProxy(oldContext); + if (context != oldContext) { + if (eNotificationRequired()) { + eNotify(new ENotificationImpl(this, Notification.RESOLVE, AadlBaPackage.ACTUAL_PORT_HOLDER__CONTEXT, + oldContext, context)); + } + } + } + return context; + } + + /** + * + * + * @generated + */ + public Subcomponent basicGetContext() { + return context; + } + + /** + * + * + * @generated + */ + @Override + public void setContext(Subcomponent newContext) { + Subcomponent oldContext = context; + context = newContext; + if (eNotificationRequired()) { + eNotify(new ENotificationImpl(this, Notification.SET, AadlBaPackage.ACTUAL_PORT_HOLDER__CONTEXT, oldContext, + context)); + } + } + /** * * @@ -72,6 +136,68 @@ public Port getPort() { return (Port) element; } + /** + * + * + * @generated + */ + @Override + public Object eGet(int featureID, boolean resolve, boolean coreType) { + switch (featureID) { + case AadlBaPackage.ACTUAL_PORT_HOLDER__CONTEXT: + if (resolve) { + return getContext(); + } + return basicGetContext(); + } + return super.eGet(featureID, resolve, coreType); + } + + /** + * + * + * @generated + */ + @Override + public void eSet(int featureID, Object newValue) { + switch (featureID) { + case AadlBaPackage.ACTUAL_PORT_HOLDER__CONTEXT: + setContext((Subcomponent) newValue); + return; + } + super.eSet(featureID, newValue); + } + + /** + * + * + * @generated + */ + @Override + public void eUnset(int featureID) { + switch (featureID) { + case AadlBaPackage.ACTUAL_PORT_HOLDER__CONTEXT: + setContext((Subcomponent) null); + return; + } + super.eUnset(featureID); + } + + /** + * + * + * @generated + */ + @Override + public boolean eIsSet(int featureID) { + switch (featureID) { + case AadlBaPackage.ACTUAL_PORT_HOLDER__CONTEXT: + return context != null; + } + return super.eIsSet(featureID); + } + + @Override public void accept(IBAVisitor visitor) { visitor.visit(this); } diff --git a/ba/org.osate.ba/src/org/osate/ba/analyzers/AadlBaConsistencyRulesChecker.java b/ba/org.osate.ba/src/org/osate/ba/analyzers/AadlBaConsistencyRulesChecker.java index 690cdc2e35..4e2ebb5b58 100644 --- a/ba/org.osate.ba/src/org/osate/ba/analyzers/AadlBaConsistencyRulesChecker.java +++ b/ba/org.osate.ba/src/org/osate/ba/analyzers/AadlBaConsistencyRulesChecker.java @@ -25,6 +25,7 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import java.util.StringJoiner; import org.eclipse.emf.common.util.EList; import org.osate.aadl2.ComponentCategory; @@ -251,12 +252,12 @@ public boolean D_3_C4_Check(BehaviorTransition btOwner, BehaviorState srcState) } triggerOwner = expression; for (var trigg : AadlBaVisitors.getDispatchTriggers(expression)) { - lCondTriggs.add(((ActualPortHolder) trigg).getPort().getName()); + lCondTriggs.add(triggerName((ActualPortHolder) trigg)); } } else if (btOwner.getCondition() instanceof ModeSwitchTriggerLogicalExpression expression) { triggerOwner = expression; for (var trigg : getExternalConditionTriggers(expression)) { - lCondTriggs.add(trigg.getPort().getName()); + lCondTriggs.add(triggerName(trigg)); } } else { // D.3.(L6) and D.3(L7) error case. Do not report error but @@ -289,7 +290,8 @@ public boolean D_3_C4_Check(BehaviorTransition btOwner, BehaviorState srcState) if (mTrans.getSource().getName().equalsIgnoreCase(mode.getName())) { // Fetches mode transition trigger names. for (var mtt : mTrans.getOwnedTriggers()) { - lModeTriggs.add(AadlBaUtils.getName(mtt)); + lModeTriggs.add(mtt.getContext() == null ? mtt.getTriggerPort().getName() + : mtt.getContext().getName() + "." + mtt.getTriggerPort().getName()); } // Checks consistency between the two triggers lists without @@ -409,6 +411,17 @@ private static List getExternalConditionTriggers( return result; } + private static String triggerName(ActualPortHolder port) { + var name = new StringJoiner("."); + if (port.getContext() != null) { + name.add(port.getContext().getName()); + } + for (var group : port.getGroupHolders()) { + name.add(group.getElement().getName()); + } + return name.add(port.getPort().getName()).toString(); + } + private static void collectExternalConditionTriggers(ModeSwitchTriggerLogicalExpression expression, List result) { for (ModeSwitchConjunction conjunction : expression.getModeSwitchConjunctions()) { diff --git a/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/translation/DeclarativeToStrictTranslator.java b/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/translation/DeclarativeToStrictTranslator.java index 9ea50ac174..18e7320381 100644 --- a/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/translation/DeclarativeToStrictTranslator.java +++ b/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/translation/DeclarativeToStrictTranslator.java @@ -578,6 +578,15 @@ private org.osate.ba.aadlba.ModeSwitchTriggerLogicalExpression toModeSwitchExpre strictTrigger = resolvedTrigger instanceof org.osate.ba.aadlba.ModeSwitchTrigger modeSwitchTrigger ? modeSwitchTrigger : null; + if (resolvedTrigger instanceof ActualPortHolder port + && !sourceTrigger.getReference().getSegments().isEmpty() + && resolvedReferences.get(sourceTrigger.getReference().getSegments().getFirst()) + instanceof org.osate.aadl2.Subcomponent context) { + port.setContext(context); + // A thread group is also represented as a GroupHolder by the generic resolver. Its + // subcomponent identity belongs in context, not in the feature-group path as well. + port.getGroupHolders().removeIf(group -> group.getElement() == context); + } } else { strictTrigger = toModeSwitchExpression(sourceTrigger.getExpression(), sourceTrigger); } diff --git a/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java b/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java index d340977d16..473b2679e5 100644 --- a/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java +++ b/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java @@ -50,9 +50,11 @@ import org.osate.aadl2.Element; import org.osate.aadl2.EventDataPort; import org.osate.aadl2.EventPort; +import org.osate.aadl2.FeatureGroup; import org.osate.aadl2.InternalFeature; import org.osate.aadl2.Port; import org.osate.aadl2.Property; +import org.osate.aadl2.Subcomponent; import org.osate.aadl2.modelsupport.errorreporting.AbstractAnalysisErrorReporter; import org.osate.aadl2.modelsupport.errorreporting.AnalysisErrorReporterManager; import org.osate.aadl2.parsesupport.ParseUtil; @@ -74,8 +76,10 @@ import org.osate.xtext.aadl2.ba.behaviorAnnex.DispatchTriggerCondition; import org.osate.xtext.aadl2.ba.behaviorAnnex.ForStatement; import org.osate.xtext.aadl2.ba.behaviorAnnex.InternalCondition; +import org.osate.xtext.aadl2.ba.behaviorAnnex.ModeSwitchTrigger; import org.osate.xtext.aadl2.ba.behaviorAnnex.Reference; import org.osate.xtext.aadl2.ba.behaviorAnnex.ReferenceExpression; +import org.osate.xtext.aadl2.ba.behaviorAnnex.ReferenceSegment; import org.osate.xtext.aadl2.ba.behaviorAnnex.UnaryExpression; import org.osate.xtext.aadl2.ba.behaviorAnnex.UnindexedReferenceExpression; import org.osate.xtext.aadl2.ba.translation.DeclarativeToStrictTranslator; @@ -95,6 +99,7 @@ public final class BehaviorAnnexValidator extends AbstractBehaviorAnnexValidator public static final String UNREPRESENTABLE_LITERAL = "org.osate.xtext.aadl2.ba.unrepresentableLiteral"; public static final String INTERNAL_PORT_USE = "org.osate.xtext.aadl2.ba.internalPortUse"; public static final String INTERNAL_CONDITION_PORT = "org.osate.xtext.aadl2.ba.internalConditionPort"; + public static final String EXTERNAL_CONDITION_TRIGGER = "org.osate.xtext.aadl2.ba.externalConditionTrigger"; public static final String TIMEOUT_RESET_PORT = "org.osate.xtext.aadl2.ba.timeoutResetPort"; public static final String TIMEOUT_RESET_PORT_TIME = "org.osate.xtext.aadl2.ba.timeoutResetPortTime"; public static final String ITERATIVE_VARIABLE_TARGET = "org.osate.xtext.aadl2.ba.iterativeVariableTarget"; @@ -137,6 +142,7 @@ public void checkBehaviorAnnex(final BehaviorAnnex source) { representable &= checkIteratorClassifiers(source); representable &= checkInternalPortUses(source, translation); representable &= checkInternalConditionPorts(source, translation); + representable &= checkExternalConditionTriggers(source, translation); representable &= checkTimeoutResetPorts(source, translation); representable &= checkIteratorTargets(source, translation); representable &= checkIteratedValues(source, translation); @@ -341,6 +347,72 @@ private boolean checkInternalConditionPorts(final BehaviorAnnex source, final Tr return accepted; } + /** + * D.3 external conditions name incoming event or event data ports. Also admit outgoing ports of a direct + * subcomponent, retaining that subcomponent as the strict port holder's context. Invalid names and reference + * paths cannot be represented faithfully, so report every written trigger and gate the strict checkers. + */ + private boolean checkExternalConditionTriggers(final BehaviorAnnex source, final TranslationResult translation) { + var representable = true; + for (var contents = source.eAllContents(); contents.hasNext();) { + if (!(contents.next() instanceof ModeSwitchTrigger trigger) || trigger.getReference() == null) { + continue; + } + var reference = trigger.getReference(); + var kind = externalConditionTriggerKind(reference, translation); + if (kind != ExternalTriggerKind.VALID) { + error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(reference)) + + "' is not an external-condition trigger: expected an incoming event or event data port" + + " of the component, or an outgoing event or event data port of a subcomponent", + reference, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, EXTERNAL_CONDITION_TRIGGER); + // A wrong-direction port is still represented completely. Keep independent strict diagnostics, + // including the prohibition on external conditions in subprograms, whose event ports are all out. + representable &= kind != ExternalTriggerKind.UNREPRESENTABLE; + } + } + return representable; + } + + private enum ExternalTriggerKind { + VALID, WRONG_DIRECTION, UNREPRESENTABLE + } + + private static ExternalTriggerKind externalConditionTriggerKind(Reference reference, TranslationResult translation) { + var resolved = translation.getResolvedReference(reference); + if (!(resolved instanceof EventPort) && !(resolved instanceof EventDataPort)) { + return ExternalTriggerKind.UNREPRESENTABLE; + } + var segments = new ArrayList(reference.getSegments()); + for (var tail : reference.getTails()) { + if (!".".equals(tail.getSeparator())) { + return ExternalTriggerKind.UNREPRESENTABLE; + } + segments.add(tail.getSegment()); + } + var subcomponent = false; + var inverse = false; + for (var i = 0; i < segments.size() - 1; i++) { + var segment = segments.get(i); + var prefix = translation.getResolvedReference(segment); + if (i == 0 && prefix instanceof Subcomponent) { + // A context identifies a direct subcomponent, not an array element or a nested subcomponent path. + if (!segment.getIndexes().isEmpty()) { + return ExternalTriggerKind.UNREPRESENTABLE; + } + subcomponent = true; + } else if (prefix instanceof FeatureGroup group) { + inverse ^= group.isInverse(); + var type = group.getAllFeatureGroupType(); + inverse ^= type != null && type.getInverse() != null; + } else { + return ExternalTriggerKind.UNREPRESENTABLE; + } + } + var port = (Port) resolved; + var incoming = subcomponent ^ inverse ? port.isOut() : port.isIn(); + return incoming ? ExternalTriggerKind.VALID : ExternalTriggerKind.WRONG_DIRECTION; + } + /** * The AS5506/3 Rev A D.4 timeout_reset_port production names an event port or an event data port, and the * production that takes the list, completion_relative_timeout_catch, requires a behavior time; the bare