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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
= Changelog

== v2026.9.0 (work in progress)

=== Shapes

=== Architectural decision records

=== Breaking changes

=== Dependency update

=== Bug fixes

=== Improvements

=== New features

- https://github.com/eclipse-syson/syson/issues/2316[#2316] [diagrams] Add support for list item inheritance in _perform actions_ compartments
s

== v2026.7.0

=== Breaking changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,55 @@ public void checkStateUsageExhibitStatesInheritanceWithRedefinition() {
.run();
}

@DisplayName("GIVEN a base ActionDefinition with a perform action, WHEN another ActionDefinition is subclassing the base ActionDefinition, THEN the base ActionDefinition perform actions are inherited by the other ActionDefinition")
@Test
public void checkActionDefinitionPerformActionsInheritanceWithSubclassification() {
new ElementSpecializationInheritanceTestRunner()
.baseElementToInheritFromEClass(SysmlPackage.eINSTANCE.getActionDefinition())
.baseElementToInheritFromNodeId(GeneralViewWithTopNodesTestProjectData.GraphicalIds.ACTION_DEFINITION_ID)
.elementToInheritCreationToolName("New Perform action")
.withEdgeExpected()
.withSelectedElementId("")
.elementToInheritExpectedListItemLabelText("ref ")
.compartmentName("perform actions")
.elementThatInheritFromBaseElementCreationToolName("New Action Definition")
.elementThatInheritFromBaseElementEClass(SysmlPackage.eINSTANCE.getActionDefinition())
.specializationToolName("New Subclassification")
.run();
}

@DisplayName("GIVEN a StateDefinition with a do action, WHEN a StateUsage is typed by the StateDefinition, THEN the StateDefinition perform actions are inherited by the StateUsage")
@Test
public void checkStateDefinitionPerformActionsInheritanceWithFeatureTyping() {
new ElementSpecializationInheritanceTestRunner()
.baseElementToInheritFromEClass(SysmlPackage.eINSTANCE.getStateDefinition())
.baseElementToInheritFromNodeId(GeneralViewWithTopNodesTestProjectData.GraphicalIds.STATE_DEFINITION_ID)
.elementToInheritCreationToolName("New Do Action")
.withSelectedElementId(GeneralViewWithTopNodesTestProjectData.SemanticIds.ACTION_USAGE_ID)
.elementToInheritExpectedListItemLabelText("ref do ::> action")
.compartmentName("perform actions")
.elementThatInheritFromBaseElementCreationToolName("New State")
.elementThatInheritFromBaseElementEClass(SysmlPackage.eINSTANCE.getStateUsage())
.specializationToolName("New Feature Typing")
.run();
}

@DisplayName("GIVEN a StateUsage with an entry action, WHEN a PartUsage is subsetting by reference the StateUsage, THEN the StateUsage perform actions are inherited by the PartUsage")
@Test
public void checkStateUsagePerformActionsInheritanceWithReferenceSubsetting() {
new ElementSpecializationInheritanceTestRunner()
.baseElementToInheritFromEClass(SysmlPackage.eINSTANCE.getStateUsage())
.baseElementToInheritFromNodeId(GeneralViewWithTopNodesTestProjectData.GraphicalIds.STATE_USAGE_ID)
.elementToInheritCreationToolName("New Entry Action")
.withSelectedElementId(GeneralViewWithTopNodesTestProjectData.SemanticIds.ACTION_USAGE_ID)
.elementToInheritExpectedListItemLabelText("ref entry ::> action")
.compartmentName("perform actions")
.elementThatInheritFromBaseElementCreationToolName("New Part")
.elementThatInheritFromBaseElementEClass(SysmlPackage.eINSTANCE.getPartUsage())
.specializationToolName("New Reference Subsetting")
.run();
}

/**
* This test runner verifies that creating a specializing relationship create inherited elements.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.syson.sysml.ActionUsage;
import org.eclipse.syson.sysml.Behavior;
import org.eclipse.syson.sysml.ConstraintUsage;
import org.eclipse.syson.sysml.Definition;
import org.eclipse.syson.sysml.ExhibitStateUsage;
import org.eclipse.syson.sysml.Feature;
import org.eclipse.syson.sysml.OwningMembership;
import org.eclipse.syson.sysml.PartUsage;
import org.eclipse.syson.sysml.PerformActionUsage;
import org.eclipse.syson.sysml.ReferenceUsage;
import org.eclipse.syson.sysml.RequirementConstraintKind;
import org.eclipse.syson.sysml.RequirementConstraintMembership;
Expand Down Expand Up @@ -79,13 +81,11 @@ public Boolean caseExhibitStateUsage(ExhibitStateUsage object) {
// Add this behavior parameter check for each caseXXXUsage.
// In this case, we want to display inherited parameters (directed feature) but not all features with the same
// type.
if (!shouldKeep && this.shouldConsiderParameter(object)) {
if (this.shouldConsiderParameter(object)) {
shouldKeep = this.isInheritedParameter(object);
}
if (!shouldKeep && this.shouldConsiderExhibitState(object)) {
} else if (this.shouldConsiderExhibitState(object)) {
shouldKeep = this.isInheritedState(object);
}
if (!shouldKeep) {
} else {
shouldKeep = super.caseExhibitStateUsage(object);
}
return shouldKeep;
Expand Down Expand Up @@ -115,6 +115,22 @@ public Boolean casePartUsage(PartUsage object) {
return eType.equals(eClass) || (eType instanceof EClass eTypeEClass && eTypeEClass.isSuperTypeOf(eClass));
}

@Override
public Boolean casePerformActionUsage(PerformActionUsage object) {
Boolean shouldKeep = Boolean.FALSE;
// Add this behavior parameter check for each caseXXXUsage.
// In this case, we want to display inherited parameters (directed feature) but not all features with the same
// type.
if (this.shouldConsiderParameter(object)) {
shouldKeep = this.isInheritedParameter(object);
} else if (this.shouldConsiderPerformUsage(object)) {
shouldKeep = this.isInheritedAction(object);
} else {
shouldKeep = super.casePerformActionUsage(object);
}
return shouldKeep;
}

@Override
public Boolean caseReferenceUsage(ReferenceUsage object) {
// Add this behavior parameter check for each caseXXXUsage.
Expand Down Expand Up @@ -162,4 +178,23 @@ private boolean isInheritedState(Feature feature) {
};
return featureState.contains(feature);
}

private boolean shouldConsiderPerformUsage(Feature feature) {
if (!(feature instanceof PerformActionUsage)) {
return false;
}

EClassifier eType = this.eReference.getEType();
EClass eClass = feature.eClass();
return eType.equals(eClass) || (eType instanceof EClass eTypeEClass && eTypeEClass.isSuperTypeOf(eClass));
}

private boolean isInheritedAction(Feature feature) {
List< ActionUsage> featureActions = switch (feature.getOwner()) {
case Definition definition -> definition.getOwnedAction();
case Usage usage -> usage.getNestedAction();
default -> List.of();
};
return featureActions.contains(feature);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
import org.eclipse.syson.standard.diagrams.view.nodes.ObjectiveDocumentationCompartmentItemNodeDescription;
import org.eclipse.syson.standard.diagrams.view.nodes.PerformActionsCompartmentItemNodeDescriptionProvider;
import org.eclipse.syson.standard.diagrams.view.nodes.PerformActionsCompartmentNodeDescriptionProvider;
import org.eclipse.syson.standard.diagrams.view.nodes.PerformActionsInheritedCompartmentItemNodeDescriptionProvider;
import org.eclipse.syson.standard.diagrams.view.nodes.PortDefinitionOwnedItemBorderNodeDescriptionProvider;
import org.eclipse.syson.standard.diagrams.view.nodes.PortDefinitionOwnedItemCompartmentItemNodeDescriptionProvider;
import org.eclipse.syson.standard.diagrams.view.nodes.PortUsageBorderNodeDescriptionProvider;
Expand Down Expand Up @@ -639,13 +640,15 @@ private List<IDiagramElementDescriptionProvider<?>> createCompartmentsForListIte
compartmentNodeDescriptionProviders.add(new CompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new CompartmentNodeDescriptionProvider(eClass, eReference, colorProvider));
compartmentNodeDescriptionProviders.add(new InheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsInheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
} else if ((SysmlPackage.eINSTANCE.getPartUsage().equals(eClass) && SysmlPackage.eINSTANCE.getUsage_NestedAction().equals(eReference))
|| (SysmlPackage.eINSTANCE.getPartDefinition().equals(eClass) && SysmlPackage.eINSTANCE.getDefinition_OwnedAction().equals(eReference))) {
compartmentNodeDescriptionProviders.add(new ActionItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new CompartmentNodeDescriptionProvider(eClass, eReference, colorProvider));
compartmentNodeDescriptionProviders.add(new InheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsInheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
} else if ((SysmlPackage.eINSTANCE.getPartUsage().equals(eClass) && SysmlPackage.eINSTANCE.getUsage_NestedState().equals(eReference))
Expand All @@ -661,6 +664,7 @@ private List<IDiagramElementDescriptionProvider<?>> createCompartmentsForListIte
compartmentNodeDescriptionProviders.add(new CompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new CompartmentNodeDescriptionProvider(eClass, eReference, colorProvider));
compartmentNodeDescriptionProviders.add(new InheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsInheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator()));
} else if (SysmlPackage.eINSTANCE.getPortDefinition().equals(eClass) && SysmlPackage.eINSTANCE.getDefinition_OwnedItem().equals(eReference)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ protected List<NodeDescription> getDroppableNodes(IViewDiagramElementFinder cach
public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) {
cache.getNodeDescription(this.getDescriptionNameGenerator().getCompartmentName(this.eClass, this.eReference) + PERFORM_ACTIONS_COMPARTMENT_NAME).ifPresent(nd -> {
cache.getNodeDescription(this.getDescriptionNameGenerator().getCompartmentItemName(this.eClass, this.eReference) + PERFORM_ACTIONS_COMPARTMENT_NAME).ifPresent(nd.getChildrenDescriptions()::add);
cache.getNodeDescription(this.getDescriptionNameGenerator().getInheritedCompartmentItemName(this.eClass, this.eReference) + PERFORM_ACTIONS_COMPARTMENT_NAME).ifPresent(nd.getChildrenDescriptions()::add);
nd.setPalette(this.createCompartmentPalette(cache));
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2026 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.standard.diagrams.view.nodes;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.sirius.components.view.builder.providers.IColorProvider;
import org.eclipse.sirius.components.view.diagram.NodeDescription;
import org.eclipse.syson.diagram.common.view.nodes.InheritedCompartmentItemNodeDescriptionProvider;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.util.AQLConstants;
import org.eclipse.syson.util.IDescriptionNameGenerator;
import org.eclipse.syson.util.SysMLMetamodelHelper;

/**
* The inherited perform action compartment list item node description provider.
*
* @author gcoutable
*/
public class PerformActionsInheritedCompartmentItemNodeDescriptionProvider extends InheritedCompartmentItemNodeDescriptionProvider {

public PerformActionsInheritedCompartmentItemNodeDescriptionProvider(EClass eClass, EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) {
super(eClass, eReference, colorProvider, descriptionNameGenerator);
}

@Override
public NodeDescription create() {
NodeDescription nd = super.create();
var qualifiedName = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getPerformActionUsage());
nd.setName(this.descriptionNameGenerator.getInheritedCompartmentItemName(this.eClass, this.eReference) + PerformActionsCompartmentNodeDescriptionProvider.PERFORM_ACTIONS_COMPARTMENT_NAME);
nd.setDomainType(qualifiedName);
nd.setPreconditionExpression(AQLConstants.AQL_SELF + ".oclIsTypeOf(" + qualifiedName + ")");
return nd;
}
}
29 changes: 29 additions & 0 deletions doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
= 2026.9.0 (work in progress)

== Key highlights

== New features

* In diagrams:

** Add support for list item inheritance in _perform actions_ compartments.

* In textual import/export:

== Bug fixes

* In diagrams:

* In textual import/export:


== Improvements

* In diagrams:

* In textual import/export:


== Technical details

* For technical details on this {product} release, including breaking changes, please refer to the https://github.com/eclipse-syson/syson/blob/main/CHANGELOG.adoc[changelog].
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

:sectnums!:

include::user-manual:release-notes/2026.9.0.adoc[leveloffset=+1]
include::user-manual:release-notes/2026.7.0.adoc[leveloffset=+1]
include::user-manual:release-notes/2026.5.0.adoc[leveloffset=+1]
include::user-manual:release-notes/2026.3.0.adoc[leveloffset=+1]
Expand Down
2 changes: 1 addition & 1 deletion doc/docs-site/antora-playbook.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
site:
title: SysON Docs
start_page: v2026.5.0@syson::index.adoc
start_page: v2026.7.0@syson::index.adoc

output:
clean: true
Expand Down
Loading