From 0b56006ac06ce5eecbcccab432292fb1ea0b210f Mon Sep 17 00:00:00 2001 From: atheate Date: Mon, 31 Aug 2026 14:08:07 +0200 Subject: [PATCH 1/2] Fix #304 --- .../Expected/18-Use Case/18-Use Case.sysml | 76 +++++++++++++++++++ .../TextualNotationValidationTestFixture.cs | 1 + .../Writers/NameResolutionCache.cs | 28 ++++++- 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 SysML2.NET.Serializer.TextualNotation.Tests/Expected/18-Use Case/18-Use Case.sysml diff --git a/SysML2.NET.Serializer.TextualNotation.Tests/Expected/18-Use Case/18-Use Case.sysml b/SysML2.NET.Serializer.TextualNotation.Tests/Expected/18-Use Case/18-Use Case.sysml new file mode 100644 index 00000000..8eee106b --- /dev/null +++ b/SysML2.NET.Serializer.TextualNotation.Tests/Expected/18-Use Case/18-Use Case.sysml @@ -0,0 +1,76 @@ +package '18-Use Case' { + part def Vehicle; + part def Person; + part def Environment; + part def 'Fuel Station'; + use case 'provide transportation' { + subject vehicle: Vehicle; + actor driver: Person; + actor passengers: Person[0..4]; + actor environment: Environment; + objective { + doc + /* + * Satisfy mission requirements to transport driver and passengers + * from starting location to ending location in conformance with + * the driving profile and meet the mission requirements for safety, + * reliability, comfort, and affordability. + */ + + } + :>> start { + doc + /* Mock-up of a pre-condition. */ + assert constraint { doc /* Vehicle at starting location */ } + } + first start; + then include 'enter vehicle' { + subject; + actor :>> driver = 'provide transportation'::driver; + actor :>> passengers = 'provide transportation'::passengers; + } + then use case 'drive vehicle' { + include 'add fuel'[0..*] { + doc + /* + * Mock-up of an extension point. + * (But reference to 'add fuel' is in the wrong direction, and it doesn't + * make the extension condition sufficient to trigger the behavior.) + */ + + subject; + actor :>> fueler = driver; + :>> start { + doc + /* Fuel level < 10% max fuel */ + } + } + } + then include 'exit vehicle' { + subject; + actor :>> driver = 'provide transportation'::driver; + actor :>> passengers = 'provide transportation'::passengers; + } + then done; + :>> done { + doc + /* Mock-up of a post-condition. */ + assert constraint { doc /* Vehicle at ending location */ } + } + } + use case 'enter vehicle' { + subject vehicle: Vehicle; + actor driver: Person; + actor passengers: Person[0..4]; + } + use case 'exit vehicle' { + subject vehicle: Vehicle; + actor driver: Person; + actor passengers: Person[0..4]; + } + use case 'add fuel' { + subject vehicle: Vehicle; + actor fueler: Person; + actor 'fuel station': 'Fuel Station'; + } +} diff --git a/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs b/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs index 5ec197dd..84f02604 100644 --- a/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs +++ b/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs @@ -136,6 +136,7 @@ public void OneTimeTearDown() [TestCase("15-Properties-Values-Expressions", "15_19a-Materials with Properties.sysmlx")] [TestCase("17-Sequence Modeling", "17a-Sequence-Modeling.sysmlx")] [TestCase("17-Sequence Modeling", "17b-Sequence-Modeling.sysmlx")] + [TestCase("18-Use Case", "18-Use Case.sysmlx")] public async Task VerifyValidationTextualNotationXmi(string folderName, string fileName) { var loggerFactory = LoggerFactory.Create(builder => diff --git a/SysML2.NET.Serializer.TextualNotation/Writers/NameResolutionCache.cs b/SysML2.NET.Serializer.TextualNotation/Writers/NameResolutionCache.cs index 0340093c..b5c81676 100644 --- a/SysML2.NET.Serializer.TextualNotation/Writers/NameResolutionCache.cs +++ b/SysML2.NET.Serializer.TextualNotation/Writers/NameResolutionCache.cs @@ -2346,7 +2346,7 @@ private void BuildInheritedEntries(IType type, Dictionary QueryImpliedGeneralClosure(IType type, List declaredS /// /// Indexes, for lookup only, the members an implied general contributes. /// + /// The Type that reaches the general through an implied Specialization. /// The Type reached through an implied Specialization. /// The destination index. /// Whether the owning scope is reached through the global namespace. - private static void AddImpliedLookupEntries(IType impliedGeneral, Dictionary> index, bool isGlobal) + /// + /// The contribution is filtered through Type::removeRedefinedFeatures, because a member the + /// inheriting Type REDEFINES is not one of that Type's Memberships. KerML §8.3.3.1.10 derives + /// inheritedMemberships as removeRedefinedFeatures(inheritableMemberships(…)), whose + /// second condition rejects a Membership one of whose redefined Features is a directly + /// redefinedFeature of an ownedFeature of the Type. + /// Without the filter the redefined library member and the local redefinition both land in the + /// same simple-name bucket, so the name reads as shadowed and a reference that should be bare is + /// emitted fully qualified — first 'provide transportation'::start for first start. + /// The declared-supertype path needs no such filter: it reads inheritedMembership, which + /// has already applied it. Only this path bypasses that derivation, because an implied Specialization + /// is detached and its members have to be gathered directly. + /// + private static void AddImpliedLookupEntries(IType inheritingType, IType impliedGeneral, Dictionary> index, bool isGlobal) { if (impliedGeneral == null) { @@ -2500,6 +2514,16 @@ private static void AddImpliedLookupEntries(IType impliedGeneral, Dictionary PassesVisibilityFilter(member, isGlobal))) { AddLookupOnlyEntry(index, member); From 8932c631b4f5d42181e79b3834fa01317b0e8881 Mon Sep 17 00:00:00 2001 From: atheate Date: Mon, 31 Aug 2026 14:46:01 +0200 Subject: [PATCH 2/2] textual notation performance on test --- .../SysML2.NET.Serializer.TextualNotation.Tests.csproj | 6 ++++++ .../Writers/TextualNotationValidationTestFixture.cs | 1 + 2 files changed, 7 insertions(+) diff --git a/SysML2.NET.Serializer.TextualNotation.Tests/SysML2.NET.Serializer.TextualNotation.Tests.csproj b/SysML2.NET.Serializer.TextualNotation.Tests/SysML2.NET.Serializer.TextualNotation.Tests.csproj index 0a0f680b..080d52cc 100644 --- a/SysML2.NET.Serializer.TextualNotation.Tests/SysML2.NET.Serializer.TextualNotation.Tests.csproj +++ b/SysML2.NET.Serializer.TextualNotation.Tests/SysML2.NET.Serializer.TextualNotation.Tests.csproj @@ -15,6 +15,12 @@ false true en-US + + true + true diff --git a/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs b/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs index 84f02604..76f49c4d 100644 --- a/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs +++ b/SysML2.NET.Serializer.TextualNotation.Tests/Writers/TextualNotationValidationTestFixture.cs @@ -36,6 +36,7 @@ namespace SysML2.NET.Serializer.TextualNotation.Tests.Writers using SysML2.NET.Serializer.Xmi; [TestFixture] + [Parallelizable(ParallelScope.Children)] public class TextualNotationValidationTestFixture { ///