diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 460c890f0..5b2551929 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -29,6 +29,7 @@ - https://github.com/eclipse-syson/syson/issues/1398[#1398] [explorer] Fix an issue where a d'n'd of an `Element` in a diagram exposed the `Element` twice in the `ViewUsage` associated to the diagram. - https://github.com/eclipse-syson/syson/issues/1411[#1411] [syson] Fix an issue where model and diagrams referencing standard libraries elements might not correctly loaded. - https://github.com/eclipse-syson/syson/issues/1411[#1411] [syson] Fix an issue where model and diagrams referencing standard libraries elements might not correctly saved. +- https://github.com/eclipse-syson/syson/issues/1407[#1407] [metamodel] Fix an issue where a `Feature` containing a `ChainingFeature` was not typed with the type of the last `ChainingFeature`. === Improvements diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/helper/ImplicitSpecializationSwitch.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/helper/ImplicitSpecializationSwitch.java index d77a7cb5c..1a527e7e6 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/helper/ImplicitSpecializationSwitch.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/helper/ImplicitSpecializationSwitch.java @@ -661,6 +661,25 @@ public List caseFeature(Feature object) { if (!this.hasRedefinition(object)) { implicitSpecializations.addAll(this.handleImplicitParameterRedefinition(object)); } + // The specification states that "If the Feature has chainingFeatures, then the union also includes the types of + // the last chainingFeature".We need to implement this here in order to make inherited Feature resolvable. + // If we only implement this in "getType" of the Feature implementation the general mechanism of name resolution + // that relies on "getMembership" would fail. + // Normally the implicit typing would be present in the model (either with an implicit inheritance + // or implicit typing). But since in SysON we choose to add those "implicit" element virtually when the derived + // feature are called, we needed to find a place where this 'implicit' typing would impact both Feature.getType + // and Namespace.getMembership. implementations. + + EList chainingFeature = object.getChainingFeature(); + if (!chainingFeature.isEmpty()) { + Feature lastFeature = chainingFeature.get(chainingFeature.size() - 1); + for (Type type : lastFeature.getType()) { + FeatureTyping featureTyping = SysmlFactory.eINSTANCE.createFeatureTyping(); + implicitSpecializations.add(featureTyping); + featureTyping.setType(type); + featureTyping.setTypedFeature(object); + } + } return implicitSpecializations; } @@ -1666,8 +1685,6 @@ private List handleImplicitParameterRedefinition(Feature feature) return implicitRedefinitions; } - - private List handleImplicitParameterRedefinition(Feature feature, Step owner) { List implicitRedefinitions = new ArrayList<>(); int parameterIndex = owner.getParameter().indexOf(feature); diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java index 9aebb97ab..b88b1b9e2 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java @@ -810,18 +810,22 @@ public Type basicGetOwningType() { } /** - * + * Types that restrict the values of this Feature, such that the values must be instances of + * all the types. The types of a Feature are derived from its typings and the types of its subsettings. If the + * Feature is chained, then the types of the last Feature in the chain are also types of the chained Feature. * * @generated NOT */ @Override public EList getType() { List types = new ArrayList<>(); - this.getOwnedRelationship().stream() + this.getOwnedSpecialization().stream() .filter(FeatureTyping.class::isInstance) .map(FeatureTyping.class::cast) .map(typing -> typing.getType()) .forEach(types::add); + return new EcoreEList.UnmodifiableEList<>(this, SysmlPackage.eINSTANCE.getFeature_Type(), types.size(), types.toArray()); } diff --git a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionDefinitionImplTest.java b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionDefinitionImplTest.java index 6f016cf0f..13a48be31 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionDefinitionImplTest.java +++ b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionDefinitionImplTest.java @@ -47,6 +47,7 @@ public void setUp() { end1.getOwnedRelationship().add(featureTypingEnd1); this.partDef1 = SysmlFactory.eINSTANCE.createPartDefinition(); featureTypingEnd1.setType(this.partDef1); + featureTypingEnd1.setTypedFeature(end1); var end2 = SysmlFactory.eINSTANCE.createReferenceUsage(); end2.setIsEnd(true); membershipEnd2.getOwnedRelatedElement().add(end2); @@ -54,6 +55,7 @@ public void setUp() { end2.getOwnedRelationship().add(featureTypingEnd2); this.partDef2 = SysmlFactory.eINSTANCE.createPartDefinition(); featureTypingEnd2.setType(this.partDef2); + featureTypingEnd2.setTypedFeature(end2); } @Test diff --git a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionUsageImplTest.java b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionUsageImplTest.java index b3ff62a68..b1220c22d 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionUsageImplTest.java +++ b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConnectionUsageImplTest.java @@ -58,10 +58,12 @@ public void setUp() { end2.getOwnedRelationship().add(featureTypingEnd2); this.partDef2 = SysmlFactory.eINSTANCE.createPartDefinition(); featureTypingEnd2.setType(this.partDef2); + featureTypingEnd2.setTypedFeature(end2); this.connectionUsage = SysmlFactory.eINSTANCE.createConnectionUsage(); var featureTypingConnectionUsage = SysmlFactory.eINSTANCE.createFeatureTyping(); featureTypingConnectionUsage.setType(this.connectionDefinition); + featureTypingConnectionUsage.setTypedFeature(this.connectionUsage); this.connectionUsage.getOwnedRelationship().add(featureTypingConnectionUsage); var membershipEnd3 = SysmlFactory.eINSTANCE.createFeatureMembership(); var membershipEnd4 = SysmlFactory.eINSTANCE.createFeatureMembership(); diff --git a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/FeatureTest.java b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/FeatureTest.java new file mode 100644 index 000000000..dbe1d14ae --- /dev/null +++ b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/FeatureTest.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sysml.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.Type; +import org.eclipse.syson.sysml.util.ModelBuilder; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Test class for {@link FeatureImpl}. + * + * @author Arthur Daussy + */ +public class FeatureTest { + + @DisplayName("GIVEN a Feature with FeatureChain, WHEN computing its features and type, THEN check that type of last ChainingFeature is taking into account for computeing feature type and accessible features.") + @Test + public void checkFeatureChainTypeAndFeatrures() { + + ModelBuilder builder = new ModelBuilder(); + + // Create a Type with features + Type t1 = builder.createWithName(Type.class, "t1"); + Feature t1f1 = builder.createInWithName(Feature.class, t1, "t1Feature"); + Type t2 = builder.createWithName(Type.class, "t2"); + Feature t2f1 = builder.createInWithName(Feature.class, t2, "t2Feature"); + Type t3 = builder.createWithName(Type.class, "t3"); + Feature t3f1 = builder.createInWithName(Feature.class, t3, "t1Feature"); + + builder.setType(t1f1, t2); + builder.setType(t2f1, t3); + + // Create a Feature Chain + + Feature featureChain = builder.createFeatureChaining(t1f1, t2f1); + + assertThat(featureChain.getFeatureTarget()).isEqualTo(t2f1); + assertThat(featureChain.getType()).contains(t3); + + assertThat(featureChain.getFeature()).isEqualTo(List.of(t3f1)); + } + +} diff --git a/doc/content/modules/user-manual/pages/release-notes/2025.8.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2025.8.0.adoc index 93e500aac..388fe5310 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2025.8.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2025.8.0.adoc @@ -39,6 +39,25 @@ Moreover, the tooling has been improved to: - Fix an issue where model and diagrams referencing standard libraries elements might not correctly loaded. - Fix an issue where model and diagrams referencing standard libraries elements might not correctly saved. +- Fix an issue where the type property of `Feature` that owns `FeatureChaining` was not correctly set. +The type of the last `FeatureChaining` is now added to the list of type of the owning feature. + +For example in: + +``` +Type T1 { + feature t1Feature : T2; +} +Type T2 { + feature t2Feature : T3; +} +Type T3 { + feature t3Feature ; +} +``` + +The `FeatureChain` _t1Feature.t2Feature_ is now typed with _T3_. + == Improvements == Dependency update