diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index f2b7542ce..b758f4efa 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -50,7 +50,7 @@ This fix ensure that imported models containing, for example, a top-level `Libra - https://github.com/eclipse-syson/syson/issues/1799[#1799] During export, `Element` with a name that conflicts with SysML Keyword should be escaped. - https://github.com/eclipse-syson/syson/issues/1825[#1825] `LiteralRational` value wrongly rounded during textual export. - https://github.com/eclipse-syson/syson/issues/1784[#1784] Error while exporting `FeatureValue` using enumeration literals. - +- https://github.com/eclipse-syson/syson/issues/1838[#1838] [metamodel] Invalid computation of `Usage.getType`: The subsetted features should be taken into account. === Improvements diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVConnectionUsageEdgeTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVConnectionUsageEdgeTests.java index 6d0b02ce1..eefaeba2f 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVConnectionUsageEdgeTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVConnectionUsageEdgeTests.java @@ -361,7 +361,8 @@ public void directEditFeatureTyping() { this.directEditTester.checkDirectEditCenteredEdgeLabel(this.verifier, this.diagram, EdgeConnectionUsageTestProjectData.GraphicalIds.CONNECTION_0_ID, "connection0 : ConnectionDefinition1", "connection0 : ConnectionDefinition1"); this.semanticCheckerService.checkElement(this.verifier, ConnectionUsage.class, () -> EdgeConnectionUsageTestProjectData.SemanticIds.CONNECTION_0_ID, connectionUsage -> { - assertThat(connectionUsage.getType()).hasSize(1).allMatch(type -> "ConnectionDefinition1".equals(type.getName())); + assertThat(connectionUsage.getType()).hasSize(2) + .allMatch(type -> "ConnectionDefinition1".equals(type.getName()) || "BinaryLinkObject".equals(type.getName())); }); } diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/imports/MutationInsertTextualSysMLv2DataFetcherTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/imports/MutationInsertTextualSysMLv2DataFetcherTests.java index e3d1427e6..1b177830c 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/imports/MutationInsertTextualSysMLv2DataFetcherTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/imports/MutationInsertTextualSysMLv2DataFetcherTests.java @@ -41,6 +41,7 @@ import org.eclipse.syson.sysml.AttributeUsage; import org.eclipse.syson.sysml.Element; import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.FeatureTyping; import org.eclipse.syson.sysml.FlowUsage; import org.eclipse.syson.sysml.Import; import org.eclipse.syson.sysml.NamespaceImport; @@ -207,9 +208,9 @@ public void testCreateRealAttributeWithResolutionProblem() { if (p.getOwnedFeature().size() == 1) { Feature f1 = p.getOwnedFeature().get(0); if (f1 instanceof AttributeUsage xAttr) { - EList types = xAttr.getType(); + EList typing = xAttr.getOwnedTyping(); // The FeatureTyping is created but the type is unresolved - return types.size() == 1 && types.get(0) == null && "x".equals(f1.getDeclaredName()); + return typing.size() == 1 && typing.get(0).getType() == null && "x".equals(f1.getDeclaredName()); } } return false; diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/libraries/update/SysONLibraryUpdateTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/libraries/update/SysONLibraryUpdateTests.java index a443db1d3..3061b4b94 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/libraries/update/SysONLibraryUpdateTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/libraries/update/SysONLibraryUpdateTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2025 Obeo. + * Copyright (c) 2025, 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 @@ -216,9 +216,7 @@ public void testProjectContentsHaveBeenUpdated() { // So the type should be null. final AttributeUsage attribute1 = Streams.of(mainResource.getAllContents()).filter(AttributeUsage.class::isInstance).map(AttributeUsage.class::cast) .filter(attribute -> attribute.getDeclaredName().equals("attribute1")).findFirst().get(); - assertThat(attribute1.getType()).hasSize(1); - final Type attribute1Type = attribute1.getType().get(0); - assertThat(attribute1Type).isNull(); + assertThat(attribute1.getType()).isEmpty(); // LibraryResource2 is unchanged, so our assumptions should still hold. final AttributeUsage attribute2 = Streams.of(mainResource.getAllContents()).filter(AttributeUsage.class::isInstance).map(AttributeUsage.class::cast) @@ -232,9 +230,7 @@ public void testProjectContentsHaveBeenUpdated() { // AttributeDefinition3 has been removed, so the type should be null now. final AttributeUsage attribute3 = Streams.of(mainResource.getAllContents()).filter(AttributeUsage.class::isInstance).map(AttributeUsage.class::cast) .filter(attribute -> attribute.getDeclaredName().equals("attribute3")).findFirst().get(); - assertThat(attribute3.getType()).hasSize(1); - final Type attribute3Type = attribute3.getType().get(0); - assertThat(attribute3Type).isNull(); + assertThat(attribute3.getType()).isEmpty(); } protected Library loadMyLibraryV1() { diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/metamodel/helper/ElementInitializerSwitchIntegrationTest.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/metamodel/helper/ElementInitializerSwitchIntegrationTest.java new file mode 100644 index 000000000..7073f73b9 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/metamodel/helper/ElementInitializerSwitchIntegrationTest.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * 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.metamodel.helper; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput; +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload; +import org.eclipse.sirius.components.core.api.IObjectSearchService; +import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; +import org.eclipse.syson.AbstractIntegrationTests; +import org.eclipse.syson.application.controller.editingContext.checkers.ISemanticChecker; +import org.eclipse.syson.application.controller.editingContext.checkers.SemanticCheckerService; +import org.eclipse.syson.application.data.GeneralViewWithTopNodesTestProjectData; +import org.eclipse.syson.services.SemanticRunnableFactory; +import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription; +import org.eclipse.syson.sysml.Package; +import org.eclipse.syson.sysml.SysmlFactory; +import org.eclipse.syson.sysml.ViewDefinition; +import org.eclipse.syson.sysml.ViewUsage; +import org.eclipse.syson.sysml.metamodel.services.ElementInitializerSwitch; +import org.eclipse.syson.sysml.metamodel.services.MetamodelMutationElementService; +import org.eclipse.syson.sysml.util.ElementUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.transaction.annotation.Transactional; + +import reactor.test.StepVerifier; + +/** + * Integration test for {@link org.eclipse.syson.sysml.metamodel.services.ElementInitializerSwitch}. Mostly used to test element initialization in a context where the standard libraries are required. + * + * @author Arthur Daussy + */ +@Transactional +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ElementInitializerSwitchIntegrationTest extends AbstractIntegrationTests { + + @Autowired + private IGivenInitialServerState givenInitialServerState; + + @Autowired + private IGivenDiagramSubscription givenDiagramSubscription; + + @Autowired + private IObjectSearchService objectSearchService; + + @Autowired + private SemanticRunnableFactory semanticRunnableFactory; + + private StepVerifier.Step verifier; + + private SemanticCheckerService semanticCheckerService; + + private ElementInitializerSwitch elementInitializerSwitch; + + private ElementUtil elementUtil; + + @BeforeEach + public void setUp() { + this.elementInitializerSwitch = new ElementInitializerSwitch(); + this.elementUtil = new ElementUtil(); + this.givenInitialServerState.initialize(); + var diagramEventInput = new DiagramEventInput(UUID.randomUUID(), + GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, + GeneralViewWithTopNodesTestProjectData.GraphicalIds.DIAGRAM_ID); + var flux = this.givenDiagramSubscription.subscribe(diagramEventInput); + this.verifier = StepVerifier.create(flux); + this.semanticCheckerService = new SemanticCheckerService(this.semanticRunnableFactory, this.objectSearchService, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, + GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID); + } + + @AfterEach + public void tearDown() { + if (this.verifier != null) { + this.verifier.thenCancel() + .verify(Duration.ofSeconds(10)); + } + } + + @DisplayName("GIVEN a ViewUsage, WHEN it is initialized, THEN it's typed by default with the GeneralView ViewDefinition") + @Sql(scripts = { GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void testViewUsageDefaultType() { + ISemanticChecker semanticChecker = (editingContext) -> { + Package semanticRootObject = (Package) this.objectSearchService.getObject(editingContext, GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID).orElseThrow(); + var view1 = SysmlFactory.eINSTANCE.createViewUsage(); + new MetamodelMutationElementService().addChildInParent(semanticRootObject, view1); + var initializedView1 = this.elementInitializerSwitch.doSwitch(view1); + var generalViewViewDef = this.elementUtil.findByNameAndType(view1, "StandardViewDefinitions::GeneralView", ViewDefinition.class); + assertThat(((ViewUsage) initializedView1).getType()).contains(generalViewViewDef); + }; + this.semanticCheckerService.checkEditingContext(semanticChecker, this.verifier); + } + +} 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 8b63141a6..d9c643d59 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 @@ -13,10 +13,16 @@ package org.eclipse.syson.sysml.impl; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.BasicEList; @@ -868,14 +874,10 @@ public Type basicGetOwningType() { */ @Override public EList getType() { - List types = new ArrayList<>(); - 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()); + Collection allTypingFeatures = this.collectTypingFeatures(); + List types = this.collectTypes(allTypingFeatures); + List filtered = this.reduceToMostSpecializeTypes(types); + return new EcoreEList.UnmodifiableEList<>(this, SysmlPackage.eINSTANCE.getFeature_Type(), filtered.size(), filtered.toArray()); } /** @@ -1130,8 +1132,7 @@ public EList typingFeatures() { if (!this.isIsConjugated()) { var subsettedFeatures = this.getOwnedSubsetting().stream() .filter(s -> !(s instanceof CrossSubsetting)) - .map(Subsetting::getSubsettedFeature) - .toList(); + .map(Subsetting::getSubsettedFeature).collect(Collectors.toList()); var chainingFeature = this.getChainingFeature(); if (chainingFeature.isEmpty() || subsettedFeatures.contains(chainingFeature.get(chainingFeature.size() - 1))) { typingFeatures.addAll(subsettedFeatures); @@ -1496,4 +1497,46 @@ public String toString() { return result.toString(); } + /** + * @generated NOT + */ + private List reduceToMostSpecializeTypes(List types) { + return types.stream() + .filter(t1 -> types.stream().noneMatch(t2 -> t2 != t1 && t2.specializes(t1))) + .toList(); + } + + /** + * @generated NOT + */ + private List collectTypes(Collection features) { + return features.stream() + .flatMap(feature -> feature.getOwnedTyping().stream() + .map(FeatureTyping::getType) + .filter(Objects::nonNull)) + .distinct() + .toList(); + } + + /** + * @generated NOT + */ + private Collection collectTypingFeatures() { + Deque typingFeatureQueue = new ArrayDeque<>(); + typingFeatureQueue.push(this); + Set featureCollector = new LinkedHashSet<>(); + featureCollector.add(this); + + // Collect all features providing a type for this feature + while (!typingFeatureQueue.isEmpty()) { + Feature current = typingFeatureQueue.pop(); + // Collect all features providing typing + for (Feature next : current.typingFeatures()) { + if (next != null && featureCollector.add(next)) { + typingFeatureQueue.addLast(next); + } + } + } + return featureCollector; + } } // FeatureImpl 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 index dbe1d14ae..054dd4a46 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2025 Obeo. + * Copyright (c) 2025, 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 @@ -17,6 +17,9 @@ import java.util.List; import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.ItemDefinition; +import org.eclipse.syson.sysml.ItemUsage; +import org.eclipse.syson.sysml.Package; import org.eclipse.syson.sysml.Type; import org.eclipse.syson.sysml.util.ModelBuilder; import org.junit.jupiter.api.DisplayName; @@ -56,4 +59,156 @@ public void checkFeatureChainTypeAndFeatrures() { assertThat(featureChain.getFeature()).isEqualTo(List.of(t3f1)); } + @DisplayName("Given some Features, WHEN computing their types, THEN the computation account subsetted feature") + @Test + public void checkType() { + var model = new FeatureTypeTestModel(); + + assertThat(model.item1.getType()) + .hasSize(1) + .first().isEqualTo(model.subItemDef1); + + assertThat(model.item2.getType()) + .hasSize(1) + .first().isEqualTo(model.subItemDef1); + + assertThat(model.item3.getType()) + .hasSize(2) + .contains(model.subItemDef1, model.itemDef2); + + assertThat(model.item3.getType()) + .hasSize(2) + .contains(model.subItemDef1, model.itemDef2); + + assertThat(model.item4.getType()) + .hasSize(2) + .contains(model.subItemDef1, model.itemDef2); + } + + @DisplayName("Given some Features in a subsetting loop, WHEN computing their types, THEN the computation do not run into stackoverflow") + @Test + public void checkTypeWithTypeLoop() { + var model = new FeatureTypeTestModel(); + + assertThat(model.itemLoop1.getType()) + .hasSize(2) + .contains(model.subItemDef1, model.itemDef2); + + assertThat(model.itemLoop2.getType()) + .hasSize(2) + .contains(model.subItemDef1, model.itemDef2); + + assertThat(model.itemLoop3.getType()) + .hasSize(2) + .contains(model.subItemDef1, model.itemDef2); + } + + @DisplayName("Given some Features, WHEN computing their typingFeatures, THEN the computation account subsetted feature") + @Test + public void checkTypingFeatures() { + var model = new FeatureTypeTestModel(); + + assertThat(model.item1.typingFeatures()) + .isEmpty(); + assertThat(model.item2.typingFeatures()) + .hasSize(1) + .first().isEqualTo(model.item1); + } + + @DisplayName("Given some Features in a subsetting loop, WHEN computing their typingFeatures, THEN the computation do not run into stackoverflow") + @Test + public void checkFeaturingTypesLoop() { + var model = new FeatureTypeTestModel(); + + assertThat(model.itemLoop3.typingFeatures()) + .hasSize(1) + .first().isEqualTo(model.itemLoop2); + assertThat(model.itemLoop2.typingFeatures()) + .hasSize(1) + .first().isEqualTo(model.itemLoop1); + assertThat(model.itemLoop1.typingFeatures()) + .hasSize(1) + .first().isEqualTo(model.itemLoop3); + } + + /** + * Test model use to test geType method. + * + *

+ *

+     * package root {
+     *  item def SuperItemDef1;
+     *  item def SubItemDef1 :>SuperItemDef1;
+     *  item def ItemDef2;
+     *
+     *  item item1 : SubItemDef1;
+     *  item item2 :> item1;
+     *  item item3 :> item1 : ItemDef2;
+     *
+     *  item itemLoop1 :> itemLoop3 : SubItemDef1;
+     *  item itemLoop2 :> itemLoop1 : ItemDef2;
+     *  item itemLoop3 :> itemLoop2 : SuperItemDef1;
+     *  item item4 : SubItemDef1, SuperItemDef1, ItemDef2
+     *
+     * }
+     * 
+ *

+ * + * @author Arthur Daussy + */ + private static class FeatureTypeTestModel { + + private final ModelBuilder builder = new ModelBuilder(); + private Package root; + private ItemDefinition superItemDef1; + private ItemDefinition subItemDef1; + private ItemUsage item1; + private ItemUsage item2; + private ItemUsage itemLoop1; + private ItemUsage itemLoop2; + private ItemUsage itemLoop3; + private ItemDefinition itemDef2; + private ItemUsage item3; + private ItemUsage item4; + + public FeatureTypeTestModel() { + this.build(); + } + + private void build() { + this.root = this.builder.createWithName(Package.class, "root"); + + this.superItemDef1 = this.builder.createInWithName(ItemDefinition.class, this.root, "SuperItemDef1"); + this.subItemDef1 = this.builder.createInWithName(ItemDefinition.class, this.root, "SubItemDef1"); + this.itemDef2 = this.builder.createInWithName(ItemDefinition.class, this.root, "ItemDef2"); + this.builder.addSubclassification(this.subItemDef1, this.superItemDef1); + + this.item1 = this.builder.createInWithName(ItemUsage.class, this.root, "item1"); + this.builder.setType(this.item1, this.subItemDef1); + this.item2 = this.builder.createInWithName(ItemUsage.class, this.root, "item2"); + this.builder.addSubsetting(this.item2, this.item1); + this.item3 = this.builder.createInWithName(ItemUsage.class, this.root, "item3"); + this.builder.addSubsetting(this.item3, this.item2); + this.builder.setType(this.item3, this.itemDef2); + + this.itemLoop1 = this.builder.createInWithName(ItemUsage.class, this.root, "itemLoop1"); + this.builder.setType(this.itemLoop1, this.subItemDef1); + this.itemLoop2 = this.builder.createInWithName(ItemUsage.class, this.root, "itemLoop2"); + this.builder.setType(this.itemLoop2, this.itemDef2); + this.itemLoop3 = this.builder.createInWithName(ItemUsage.class, this.root, "itemLoop3"); + this.builder.setType(this.itemLoop3, this.superItemDef1); + + this.builder.addSubsetting(this.itemLoop1, this.itemLoop3); + this.builder.addSubsetting(this.itemLoop2, this.itemLoop1); + this.builder.addSubsetting(this.itemLoop3, this.itemLoop2); + + this.item4 = this.builder.createInWithName(ItemUsage.class, this.root, "item4"); + this.builder.setType(this.item4, this.subItemDef1); + this.builder.setType(this.item4, this.superItemDef1); + this.builder.setType(this.item4, this.itemDef2); + + + } + } + } diff --git a/backend/services/syson-sysml-metamodel-services/src/test/java/org/eclipse/syson/sysml/metamodel/services/ElementInitializerSwitchTest.java b/backend/services/syson-sysml-metamodel-services/src/test/java/org/eclipse/syson/sysml/metamodel/services/ElementInitializerSwitchTest.java index fa01ccaed..97f12bfe7 100644 --- a/backend/services/syson-sysml-metamodel-services/src/test/java/org/eclipse/syson/sysml/metamodel/services/ElementInitializerSwitchTest.java +++ b/backend/services/syson-sysml-metamodel-services/src/test/java/org/eclipse/syson/sysml/metamodel/services/ElementInitializerSwitchTest.java @@ -26,8 +26,6 @@ import org.eclipse.syson.sysml.Relationship; import org.eclipse.syson.sysml.SysmlFactory; import org.eclipse.syson.sysml.SysmlPackage; -import org.eclipse.syson.sysml.ViewDefinition; -import org.eclipse.syson.sysml.ViewUsage; import org.eclipse.syson.sysml.VisibilityKind; import org.eclipse.syson.sysml.util.ElementUtil; import org.junit.jupiter.api.BeforeEach; @@ -179,21 +177,6 @@ public void testStakeholderDefaultName() { assertThat(initializedS2.getDeclaredName()).isEqualTo("stakeholder2"); } - @DisplayName("GIVEN a ViewUsage, WHEN it is initialized, THEN it's typed by default with the GeneralView ViewDefinition") - @Test - public void testViewUsageDefaultType() { - var root = SysmlFactory.eINSTANCE.createPackage(); - this.resource.getContents().add(root); - root.setDeclaredName(ROOT); - var view1 = SysmlFactory.eINSTANCE.createViewUsage(); - this.addInParent(view1, root); - var initializedView1 = this.elementInitializerSwitch.doSwitch(view1); - assertThat(initializedView1).isInstanceOf(ViewUsage.class); - var generalViewViewDef = this.elementUtil.findByNameAndType(view1, "StandardViewDefinitions::GeneralView", ViewDefinition.class); - assertThat(((ViewUsage) initializedView1).getType()).contains(generalViewViewDef); - - } - private void addInParent(Element element, Element parent) { OwningMembership owningMembership = SysmlFactory.eINSTANCE.createOwningMembership(); parent.getOwnedRelationship().add(owningMembership); diff --git a/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc index adcc8719c..15e6b58bc 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc @@ -87,6 +87,7 @@ package root { * Miscellaneous: ** New `Expose` elements now have `visibility` set to _protected_ and have `isImportAll` set to _true_, as required by the SysMLv2 specification. +** Correct the computation of a `Feature`'s types to properly account for subsetted features. == Improvements