diff --git a/SysML2.NET.Tests/Extend/ConstructorExpressionExtensionsTestFixture.cs b/SysML2.NET.Tests/Extend/ConstructorExpressionExtensionsTestFixture.cs
new file mode 100644
index 00000000..dcf61555
--- /dev/null
+++ b/SysML2.NET.Tests/Extend/ConstructorExpressionExtensionsTestFixture.cs
@@ -0,0 +1,47 @@
+// -------------------------------------------------------------------------------------------------
+//
+//
+// Copyright 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// ------------------------------------------------------------------------------------------------
+
+namespace SysML2.NET.Tests.Extend
+{
+ using System;
+
+ using NUnit.Framework;
+
+ using SysML2.NET.Core.POCO.Kernel.Expressions;
+
+ [TestFixture]
+ public class ConstructorExpressionExtensionsTestFixture
+ {
+ [Test]
+ public void VerifyComputeRedefinedModelLevelEvaluableOperation()
+ {
+ Assert.That(
+ () => ((IConstructorExpression)null).ComputeRedefinedModelLevelEvaluableOperation([]),
+ Throws.TypeOf());
+
+ var subject = new ConstructorExpression();
+
+ // For later: populated case depends on ComputeArgument, still a stub (out of batch).
+ Assert.That(
+ () => subject.ComputeRedefinedModelLevelEvaluableOperation([]),
+ Throws.TypeOf());
+ }
+ }
+}
diff --git a/SysML2.NET.Tests/Extend/FeatureReferenceExpressionExtensionsTestFixture.cs b/SysML2.NET.Tests/Extend/FeatureReferenceExpressionExtensionsTestFixture.cs
index 1ec91c35..7e05af71 100644
--- a/SysML2.NET.Tests/Extend/FeatureReferenceExpressionExtensionsTestFixture.cs
+++ b/SysML2.NET.Tests/Extend/FeatureReferenceExpressionExtensionsTestFixture.cs
@@ -1,38 +1,210 @@
-// -------------------------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------------------------
//
-//
+//
// Copyright 2022-2026 Starion Group S.A.
-//
+//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
-//
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
+//
//
// ------------------------------------------------------------------------------------------------
namespace SysML2.NET.Tests.Extend
{
using System;
-
+
using NUnit.Framework;
-
+
+ using SysML2.NET.Core.POCO.Core.Features;
+ using SysML2.NET.Core.POCO.Core.Types;
+ using SysML2.NET.Core.POCO.Kernel.Behaviors;
using SysML2.NET.Core.POCO.Kernel.Expressions;
+ using SysML2.NET.Core.POCO.Kernel.FeatureValues;
+ using SysML2.NET.Core.POCO.Kernel.Metadata;
+ using SysML2.NET.Core.POCO.Root.Annotations;
+ using SysML2.NET.Core.POCO.Root.Namespaces;
+ using SysML2.NET.Extensions;
+
+ using Type = SysML2.NET.Core.POCO.Core.Types.Type;
[TestFixture]
public class FeatureReferenceExpressionExtensionsTestFixture
{
[Test]
- public void ComputeReferent_ThrowsNotSupportedException()
+ public void VerifyComputeReferent()
+ {
+ // Branch 1: null subject → ArgumentNullException.
+ Assert.That(
+ () => ((IFeatureReferenceExpression)null).ComputeReferent(),
+ Throws.TypeOf());
+
+ // Branch 2: no ownedMembership at all → null.
+ var subject = new FeatureReferenceExpression();
+
+ Assert.That(subject.ComputeReferent(), Is.Null);
+
+ // Branch 3: only a ParameterMembership → rejected by the reject(ParameterMembership) filter → null.
+ var parameterFeature = new Feature();
+ var parameterMembership = new ParameterMembership();
+ subject.AssignOwnership(parameterMembership, parameterFeature);
+
+ Assert.That(subject.ComputeReferent(), Is.Null);
+
+ // Branch 4: first non-parameter membership whose MemberElement is NOT a Feature → null.
+ var nonFeatureSubject = new FeatureReferenceExpression();
+ var nonFeatureMembership = new Membership();
+ nonFeatureSubject.AssignOwnership(nonFeatureMembership);
+ nonFeatureMembership.MemberElement = new Namespace();
+
+ Assert.That(nonFeatureSubject.ComputeReferent(), Is.Null);
+
+ // Branch 5: first non-parameter membership whose MemberElement IS a Feature → returns that Feature.
+ var referentFeature = new Feature();
+ var featureMembership = new Membership();
+ var positiveSubject = new FeatureReferenceExpression();
+ positiveSubject.AssignOwnership(featureMembership);
+ featureMembership.MemberElement = referentFeature;
+
+ Assert.That(positiveSubject.ComputeReferent(), Is.SameAs(referentFeature));
+
+ // Branch 6: ParameterMembership first, then a plain Membership with a Feature → the
+ // ParameterMembership is rejected; the Membership is the first non-parameter one → its Feature.
+ var mixedSubject = new FeatureReferenceExpression();
+ var mixedParamFeature = new Feature();
+ var mixedParamMembership = new ParameterMembership();
+ mixedSubject.AssignOwnership(mixedParamMembership, mixedParamFeature);
+
+ var mixedReferentFeature = new Feature();
+ var mixedMembership = new Membership();
+ mixedSubject.AssignOwnership(mixedMembership);
+ mixedMembership.MemberElement = mixedReferentFeature;
+
+ Assert.That(mixedSubject.ComputeReferent(), Is.SameAs(mixedReferentFeature));
+ }
+
+ [Test]
+ public void VerifyComputeRedefinedModelLevelEvaluableOperation()
+ {
+ // Branch 1: null subject → ArgumentNullException.
+ Assert.That(
+ () => ((IFeatureReferenceExpression)null).ComputeRedefinedModelLevelEvaluableOperation([]),
+ Throws.TypeOf());
+
+ // Branch 2: referent == null (only a ParameterMembership, which ComputeReferent rejects) → true.
+ var noReferentSubject = new FeatureReferenceExpression();
+ var parameterFeature = new Feature();
+ var parameterMembership = new ParameterMembership();
+ noReferentSubject.AssignOwnership(parameterMembership, parameterFeature);
+
+ // Branch 3: referent is a plain Feature with no featuringType and no FeatureValue → falls through
+ // to "value expression is null → true".
+ var plainReferent = new Feature();
+ var plainMembership = new Membership();
+ var plainSubject = new FeatureReferenceExpression();
+ plainSubject.AssignOwnership(plainMembership);
+ plainMembership.MemberElement = plainReferent;
+
+ // Branch 4: visited already contains the referent → cycle guard → false.
+ var visitedReferent = new Feature();
+ var visitedMembership = new Membership();
+ var visitedSubject = new FeatureReferenceExpression();
+ visitedSubject.AssignOwnership(visitedMembership);
+ visitedMembership.MemberElement = visitedReferent;
+
+ // Branch 5: referent.owningType is a Metaclass → true.
+ var metaclassReferent = new Feature();
+ var metaclass = new Metaclass();
+ metaclass.AssignOwnership(new FeatureMembership(), metaclassReferent);
+ var metaclassRefMembership = new Membership();
+ var metaclassSubject = new FeatureReferenceExpression();
+ metaclassSubject.AssignOwnership(metaclassRefMembership);
+ metaclassRefMembership.MemberElement = metaclassReferent;
+
+ using (Assert.EnterMultipleScope())
+ {
+ Assert.That(noReferentSubject.ComputeRedefinedModelLevelEvaluableOperation([]), Is.True);
+ Assert.That(plainSubject.ComputeRedefinedModelLevelEvaluableOperation([]), Is.True);
+ Assert.That(visitedSubject.ComputeRedefinedModelLevelEvaluableOperation([visitedReferent]), Is.False);
+ Assert.That(metaclassSubject.ComputeRedefinedModelLevelEvaluableOperation([]), Is.True);
+ }
+ }
+
+ [Test]
+ public void VerifyComputeRedefinedEvaluateOperation()
{
- Assert.That(() => ((IFeatureReferenceExpression)null).ComputeReferent(), Throws.TypeOf());
+ // Branch 1: null subject → ArgumentNullException.
+ Assert.That(
+ () => ((IFeatureReferenceExpression)null).ComputeRedefinedEvaluateOperation(null),
+ Throws.TypeOf());
+
+ // Branch 2: target is null (not a Type) → empty sequence.
+ var subject = new FeatureReferenceExpression();
+
+ Assert.That(subject.ComputeRedefinedEvaluateOperation(null), Is.Empty);
+
+ // Branch 3: target is a non-Type element (a Comment) → empty sequence.
+ Assert.That(subject.ComputeRedefinedEvaluateOperation(new Comment()), Is.Empty);
+
+ // Branch 4: target IS a Type, but none of its features redefine the referent, and the
+ // referent has an empty featuringType → falls to else → returns [referent].
+ var referent = new Feature();
+ var referentMembership = new Membership();
+ var referentSubject = new FeatureReferenceExpression();
+ referentSubject.AssignOwnership(referentMembership);
+ referentMembership.MemberElement = referent;
+
+ var emptyType = new Type();
+ var referentResult = referentSubject.ComputeRedefinedEvaluateOperation(emptyType);
+
+ // Branch 5: target IS a Type, no feature redefines the referent, and the referent HAS a
+ // non-empty featuringType (via a TypeFeaturing) → falls to else → empty sequence.
+ var featuredReferent = new Feature();
+ var featuringType = new Type();
+ featuredReferent.AssignOwnership(new TypeFeaturing { FeatureOfType = featuredReferent, FeaturingType = featuringType });
+
+ var featuredMembership = new Membership();
+ var featuredSubject = new FeatureReferenceExpression();
+ featuredSubject.AssignOwnership(featuredMembership);
+ featuredMembership.MemberElement = featuredReferent;
+
+ // Branch 6 (recursion): target IS a Type whose feature redefines the referent and carries a
+ // FeatureValue whose value is a LiteralExpression. FeatureReferenceExpression.Evaluate
+ // recurses into the value Expression's Evaluate; LiteralExpression.Evaluate IS
+ // implemented (returns Sequence{self}), so this asserts the real evaluated result.
+ var recursionReferent = new Feature();
+ var recursionMembership = new Membership();
+ var recursionSubject = new FeatureReferenceExpression();
+ recursionSubject.AssignOwnership(recursionMembership);
+ recursionMembership.MemberElement = recursionReferent;
+
+ var redefiningFeature = new Feature();
+ redefiningFeature.AssignOwnership(new Redefinition { RedefinedFeature = recursionReferent });
+
+ var literalValue = new LiteralBoolean();
+ redefiningFeature.AssignOwnership(new FeatureValue(), literalValue);
+
+ var targetType = new Type();
+ targetType.AssignOwnership(new FeatureMembership(), redefiningFeature);
+
+ var recursionResult = recursionSubject.ComputeRedefinedEvaluateOperation(targetType);
+
+ using (Assert.EnterMultipleScope())
+ {
+ Assert.That(referentResult, Has.Count.EqualTo(1));
+ Assert.That(referentResult[0], Is.SameAs(referent));
+ Assert.That(featuredSubject.ComputeRedefinedEvaluateOperation(new Type()), Is.Empty);
+ Assert.That(recursionResult, Has.Count.EqualTo(1));
+ Assert.That(recursionResult[0], Is.SameAs(literalValue));
+ }
}
}
}
diff --git a/SysML2.NET.Tests/Extend/InvocationExpressionExtensionsTestFixture.cs b/SysML2.NET.Tests/Extend/InvocationExpressionExtensionsTestFixture.cs
new file mode 100644
index 00000000..b4f38ff5
--- /dev/null
+++ b/SysML2.NET.Tests/Extend/InvocationExpressionExtensionsTestFixture.cs
@@ -0,0 +1,58 @@
+// -------------------------------------------------------------------------------------------------
+//
+//
+// Copyright 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// ------------------------------------------------------------------------------------------------
+
+namespace SysML2.NET.Tests.Extend
+{
+ using System;
+
+ using NUnit.Framework;
+
+ using SysML2.NET.Core.POCO.Kernel.Expressions;
+
+ [TestFixture]
+ public class InvocationExpressionExtensionsTestFixture
+ {
+ [Test]
+ public void VerifyComputeRedefinedModelLevelEvaluableOperation()
+ {
+ Assert.That(
+ () => ((IInvocationExpression)null).ComputeRedefinedModelLevelEvaluableOperation([]),
+ Throws.TypeOf());
+
+ var subject = new InvocationExpression();
+
+ // For later: populated case depends on ComputeArgument / Function.ComputeIsModelLevelEvaluable, still a stub (out of batch).
+ Assert.That(
+ () => subject.ComputeRedefinedModelLevelEvaluableOperation([]),
+ Throws.TypeOf());
+ }
+
+ [Test]
+ public void VerifyComputeRedefinedEvaluateOperation()
+ {
+ var subject = new InvocationExpression();
+
+ // For later: deferred — needs Function-application engine (no OCL).
+ Assert.That(
+ () => subject.ComputeRedefinedEvaluateOperation(null),
+ Throws.TypeOf());
+ }
+ }
+}
diff --git a/SysML2.NET.Tests/Extend/LiteralExpressionExtensionsTestFixture.cs b/SysML2.NET.Tests/Extend/LiteralExpressionExtensionsTestFixture.cs
new file mode 100644
index 00000000..6bfe194e
--- /dev/null
+++ b/SysML2.NET.Tests/Extend/LiteralExpressionExtensionsTestFixture.cs
@@ -0,0 +1,69 @@
+// -------------------------------------------------------------------------------------------------
+//
+//
+// Copyright 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// ------------------------------------------------------------------------------------------------
+
+namespace SysML2.NET.Tests.Extend
+{
+ using System;
+
+ using NUnit.Framework;
+
+ using SysML2.NET.Core.POCO.Kernel.Expressions;
+
+ [TestFixture]
+ public class LiteralExpressionExtensionsTestFixture
+ {
+ [Test]
+ public void VerifyComputeRedefinedModelLevelEvaluableOperation()
+ {
+ Assert.That(
+ () => ((ILiteralExpression)null).ComputeRedefinedModelLevelEvaluableOperation([]),
+ Throws.TypeOf());
+
+ var subject = new LiteralExpression();
+
+ using (Assert.EnterMultipleScope())
+ {
+ Assert.That(subject.ComputeRedefinedModelLevelEvaluableOperation([]), Is.True);
+
+ // visited is unused by the OCL body (`true`); a null visited must still return true.
+ Assert.That(subject.ComputeRedefinedModelLevelEvaluableOperation(null), Is.True);
+ }
+ }
+
+ [Test]
+ public void VerifyComputeRedefinedEvaluateOperation()
+ {
+ Assert.That(
+ () => ((ILiteralExpression)null).ComputeRedefinedEvaluateOperation(null),
+ Throws.TypeOf());
+
+ var subject = new LiteralExpression();
+
+ // target is unused by the OCL body (`Sequence{self}`); pass null.
+ var result = subject.ComputeRedefinedEvaluateOperation(null);
+
+ using (Assert.EnterMultipleScope())
+ {
+ Assert.That(result, Has.Count.EqualTo(1));
+ Assert.That(result[0], Is.SameAs(subject));
+ }
+ }
+ }
+}
diff --git a/SysML2.NET.Tests/Extend/NullExpressionExtensionsTestFixture.cs b/SysML2.NET.Tests/Extend/NullExpressionExtensionsTestFixture.cs
new file mode 100644
index 00000000..c7b56918
--- /dev/null
+++ b/SysML2.NET.Tests/Extend/NullExpressionExtensionsTestFixture.cs
@@ -0,0 +1,63 @@
+// -------------------------------------------------------------------------------------------------
+//
+//
+// Copyright 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// ------------------------------------------------------------------------------------------------
+
+namespace SysML2.NET.Tests.Extend
+{
+ using System;
+
+ using NUnit.Framework;
+
+ using SysML2.NET.Core.POCO.Kernel.Expressions;
+
+ [TestFixture]
+ public class NullExpressionExtensionsTestFixture
+ {
+ [Test]
+ public void VerifyComputeRedefinedModelLevelEvaluableOperation()
+ {
+ Assert.That(
+ () => ((INullExpression)null).ComputeRedefinedModelLevelEvaluableOperation([]),
+ Throws.TypeOf());
+
+ var subject = new NullExpression();
+
+ using (Assert.EnterMultipleScope())
+ {
+ Assert.That(subject.ComputeRedefinedModelLevelEvaluableOperation([]), Is.True);
+
+ // visited is unused by the OCL body (`true`); a null visited must still return true.
+ Assert.That(subject.ComputeRedefinedModelLevelEvaluableOperation(null), Is.True);
+ }
+ }
+
+ [Test]
+ public void VerifyComputeRedefinedEvaluateOperation()
+ {
+ Assert.That(
+ () => ((INullExpression)null).ComputeRedefinedEvaluateOperation(null),
+ Throws.TypeOf());
+
+ var subject = new NullExpression();
+
+ // target is unused by the OCL body (`Sequence{}`); pass null.
+ Assert.That(subject.ComputeRedefinedEvaluateOperation(null), Is.Empty);
+ }
+ }
+}
diff --git a/SysML2.NET/Extend/ConstructorExpressionExtensions.cs b/SysML2.NET/Extend/ConstructorExpressionExtensions.cs
index 2fd066ba..74ef8a3f 100644
--- a/SysML2.NET/Extend/ConstructorExpressionExtensions.cs
+++ b/SysML2.NET/Extend/ConstructorExpressionExtensions.cs
@@ -1,20 +1,20 @@
// -------------------------------------------------------------------------------------------------
//
-//
-// Copyright (C) 2022-2026 Starion Group S.A.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
+//
+// Copyright (C) 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
+//
//
// ------------------------------------------------------------------------------------------------
@@ -22,20 +22,13 @@ namespace SysML2.NET.Core.POCO.Kernel.Expressions
{
using System;
using System.Collections.Generic;
+ using System.Linq;
- using SysML2.NET.Core.Core.Types;
- using SysML2.NET.Core.Root.Namespaces;
using SysML2.NET.Core.POCO.Core.Features;
- using SysML2.NET.Core.POCO.Core.Types;
- using SysML2.NET.Core.POCO.Kernel.Behaviors;
- using SysML2.NET.Core.POCO.Kernel.Functions;
- using SysML2.NET.Core.POCO.Root.Annotations;
- using SysML2.NET.Core.POCO.Root.Elements;
- using SysML2.NET.Core.POCO.Root.Namespaces;
///
- /// The class provides extensions methods for
- /// the interface
+ /// The class provides extensions methods for
+ /// the interface
///
internal static class ConstructorExpressionExtensions
{
@@ -50,7 +43,7 @@ internal static class ConstructorExpressionExtensions
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -58,10 +51,14 @@ internal static class ConstructorExpressionExtensions
///
/// The expected
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static bool ComputeRedefinedModelLevelEvaluableOperation(this IConstructorExpression constructorExpressionSubject, List visited)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (constructorExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(constructorExpressionSubject));
+ }
+
+ return constructorExpressionSubject.argument.All(argument => argument.ModelLevelEvaluable(visited));
}
}
}
diff --git a/SysML2.NET/Extend/FeatureReferenceExpressionExtensions.cs b/SysML2.NET/Extend/FeatureReferenceExpressionExtensions.cs
index 16b4a8eb..b62b3558 100644
--- a/SysML2.NET/Extend/FeatureReferenceExpressionExtensions.cs
+++ b/SysML2.NET/Extend/FeatureReferenceExpressionExtensions.cs
@@ -1,20 +1,20 @@
// -------------------------------------------------------------------------------------------------
//
-//
-// Copyright (C) 2022-2026 Starion Group S.A.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
+//
+// Copyright (C) 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
+//
//
// ------------------------------------------------------------------------------------------------
@@ -22,20 +22,19 @@ namespace SysML2.NET.Core.POCO.Kernel.Expressions
{
using System;
using System.Collections.Generic;
+ using System.Linq;
- using SysML2.NET.Core.Core.Types;
- using SysML2.NET.Core.Root.Namespaces;
using SysML2.NET.Core.POCO.Core.Features;
using SysML2.NET.Core.POCO.Core.Types;
using SysML2.NET.Core.POCO.Kernel.Behaviors;
+ using SysML2.NET.Core.POCO.Kernel.FeatureValues;
using SysML2.NET.Core.POCO.Kernel.Functions;
- using SysML2.NET.Core.POCO.Root.Annotations;
+ using SysML2.NET.Core.POCO.Kernel.Metadata;
using SysML2.NET.Core.POCO.Root.Elements;
- using SysML2.NET.Core.POCO.Root.Namespaces;
///
- /// The class provides extensions methods for
- /// the interface
+ /// The class provides extensions methods for
+ /// the interface
///
internal static class FeatureReferenceExpressionExtensions
{
@@ -56,24 +55,35 @@ internal static class FeatureReferenceExpressionExtensions
///
///
///
- /// The subject
+ /// The subject
///
///
/// the computed result
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static IFeature ComputeReferent(this IFeatureReferenceExpression featureReferenceExpressionSubject)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (featureReferenceExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(featureReferenceExpressionSubject));
+ }
+
+ var nonParameterMembership = featureReferenceExpressionSubject.ownedMembership
+ .FirstOrDefault(membership => membership is not IParameterMembership);
+
+ return nonParameterMembership?.MemberElement as IFeature;
}
///
- /// A FeatureReferenceExpression is model-level evaluable if it's referent
- /// - conforms to the self-reference feature Anything::self;
- /// - is an Expression that is model-level evaluable;
- /// - has an owningType that is a Metaclass or MetadataFeature; or
- /// - has no featuringTypes and, if it has a FeatureValue, the value Expression is model-level
- /// evaluable.
+ /// A FeatureReferenceExpression is model-level evaluable if it's referent
+ ///
+ /// - conforms to the self-reference feature Anything::self;
+ /// - is an Expression that is model-level evaluable;
+ /// - has an owningType that is a Metaclass or MetadataFeature; or
+ /// -
+ /// has no featuringTypes and, if it has a FeatureValue, the value Expression is model-level
+ /// evaluable.
+ ///
+ ///
///
///
/// OCL2.0:
@@ -91,7 +101,7 @@ internal static IFeature ComputeReferent(this IFeatureReferenceExpression featur
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -99,22 +109,69 @@ internal static IFeature ComputeReferent(this IFeatureReferenceExpression featur
///
/// The expected
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static bool ComputeRedefinedModelLevelEvaluableOperation(this IFeatureReferenceExpression featureReferenceExpressionSubject, List visited)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (featureReferenceExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(featureReferenceExpressionSubject));
+ }
+
+ var referent = featureReferenceExpressionSubject.referent;
+
+ if (referent == null || referent.SpecializesFromLibrary("Anything::self"))
+ {
+ return true;
+ }
+
+ if (visited.Contains(referent))
+ {
+ return false;
+ }
+
+ var next = new List(visited) { referent };
+
+ if (referent is IExpression referentExpression && referentExpression.ModelLevelEvaluable(next))
+ {
+ return true;
+ }
+
+ if (referent.owningType is IMetaclass or IMetadataFeature)
+ {
+ return true;
+ }
+
+ if (referent.featuringType.Count != 0)
+ {
+ return false;
+ }
+
+ var valueExpression = referent.ownedMembership.OfType().FirstOrDefault()?.value;
+
+ return valueExpression == null || valueExpression.ModelLevelEvaluable(next);
}
///
- /// First, determine a value Expression for the referent:
- /// - If the target Element is a Type that has a feature that is the referent or (directly
- /// or indirectly) redefines it, then the value Expression of the FeatureValue for that feature (if
- /// any).
- Else, if the referent has no featuringTypes, the value
- /// Expression of the FeatureValue for the referent (if any).
- /// Then: - If such a
- /// value Expression exists, return the result of evaluating that Expression on the target.
- /// - Else, if the referent is not an Expression, return the referent.
- /// - Else return the empty sequence.
+ /// First, determine a value Expression for the referent:
+ ///
+ /// -
+ /// If the target Element is a Type that has a feature that is the referent or (directly
+ /// or indirectly) redefines it, then the value Expression of the FeatureValue for that feature (if
+ /// any).
+ ///
+ /// -
+ /// Else, if the referent has no featuringTypes, the value
+ /// Expression of the FeatureValue for the referent (if any).
+ ///
+ ///
+ /// Then:
+ ///
+ /// -
+ /// If such a
+ /// value Expression exists, return the result of evaluating that Expression on the target.
+ ///
+ /// - Else, if the referent is not an Expression, return the referent.
+ /// - Else return the empty sequence.
+ ///
///
///
/// OCL2.0:
@@ -135,7 +192,7 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this IFeatureR
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -143,10 +200,36 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this IFeatureR
///
/// The expected collection of
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static List ComputeRedefinedEvaluateOperation(this IFeatureReferenceExpression featureReferenceExpressionSubject, IElement target)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (featureReferenceExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(featureReferenceExpressionSubject));
+ }
+
+ if (target is not IType targetType)
+ {
+ return [];
+ }
+
+ var referent = featureReferenceExpressionSubject.referent;
+
+ var redefiningFeatures = targetType.feature
+ .Where(feature => feature.ownedRedefinition.Any(redefinition => redefinition.RedefinedFeature == referent))
+ .ToList();
+
+ if (redefiningFeatures.Count != 0)
+ {
+ return
+ [
+ .. redefiningFeatures
+ .Select(feature => feature.ownedMembership.OfType().FirstOrDefault()?.value)
+ .Where(valueExpression => valueExpression != null)
+ .SelectMany(valueExpression => valueExpression.Evaluate(target))
+ ];
+ }
+
+ return referent != null && referent.featuringType.Count == 0 ? [referent] : [];
}
}
}
diff --git a/SysML2.NET/Extend/InvocationExpressionExtensions.cs b/SysML2.NET/Extend/InvocationExpressionExtensions.cs
index b004aad5..ebcdd8e3 100644
--- a/SysML2.NET/Extend/InvocationExpressionExtensions.cs
+++ b/SysML2.NET/Extend/InvocationExpressionExtensions.cs
@@ -1,20 +1,20 @@
// -------------------------------------------------------------------------------------------------
//
-//
-// Copyright (C) 2022-2026 Starion Group S.A.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
+//
+// Copyright (C) 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
+//
//
// ------------------------------------------------------------------------------------------------
@@ -22,20 +22,15 @@ namespace SysML2.NET.Core.POCO.Kernel.Expressions
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Linq;
- using SysML2.NET.Core.Core.Types;
- using SysML2.NET.Core.Root.Namespaces;
using SysML2.NET.Core.POCO.Core.Features;
- using SysML2.NET.Core.POCO.Core.Types;
- using SysML2.NET.Core.POCO.Kernel.Behaviors;
- using SysML2.NET.Core.POCO.Kernel.Functions;
- using SysML2.NET.Core.POCO.Root.Annotations;
using SysML2.NET.Core.POCO.Root.Elements;
- using SysML2.NET.Core.POCO.Root.Namespaces;
///
- /// The class provides extensions methods for
- /// the interface
+ /// The class provides extensions methods for
+ /// the interface
///
internal static class InvocationExpressionExtensions
{
@@ -51,7 +46,7 @@ internal static class InvocationExpressionExtensions
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -59,10 +54,15 @@ internal static class InvocationExpressionExtensions
///
/// The expected
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static bool ComputeRedefinedModelLevelEvaluableOperation(this IInvocationExpression invocationExpressionSubject, List visited)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (invocationExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(invocationExpressionSubject));
+ }
+
+ return invocationExpressionSubject.argument.All(argument => argument.ModelLevelEvaluable(visited))
+ && invocationExpressionSubject.function.isModelLevelEvaluable;
}
///
@@ -71,7 +71,7 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this IInvocati
/// possible, then return an empty sequence.
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -79,7 +79,7 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this IInvocati
///
/// The expected collection of
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
internal static List ComputeRedefinedEvaluateOperation(this IInvocationExpression invocationExpressionSubject, IElement target)
{
throw new NotSupportedException("Create a GitHub issue when this method is required");
diff --git a/SysML2.NET/Extend/LiteralExpressionExtensions.cs b/SysML2.NET/Extend/LiteralExpressionExtensions.cs
index d3924913..efdfcf49 100644
--- a/SysML2.NET/Extend/LiteralExpressionExtensions.cs
+++ b/SysML2.NET/Extend/LiteralExpressionExtensions.cs
@@ -1,20 +1,20 @@
// -------------------------------------------------------------------------------------------------
//
-//
-// Copyright (C) 2022-2026 Starion Group S.A.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
+//
+// Copyright (C) 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
+//
//
// ------------------------------------------------------------------------------------------------
@@ -23,19 +23,12 @@ namespace SysML2.NET.Core.POCO.Kernel.Expressions
using System;
using System.Collections.Generic;
- using SysML2.NET.Core.Core.Types;
- using SysML2.NET.Core.Root.Namespaces;
using SysML2.NET.Core.POCO.Core.Features;
- using SysML2.NET.Core.POCO.Core.Types;
- using SysML2.NET.Core.POCO.Kernel.Behaviors;
- using SysML2.NET.Core.POCO.Kernel.Functions;
- using SysML2.NET.Core.POCO.Root.Annotations;
using SysML2.NET.Core.POCO.Root.Elements;
- using SysML2.NET.Core.POCO.Root.Namespaces;
///
- /// The class provides extensions methods for
- /// the interface
+ /// The class provides extensions methods for
+ /// the interface
///
internal static class LiteralExpressionExtensions
{
@@ -49,7 +42,7 @@ internal static class LiteralExpressionExtensions
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -57,10 +50,14 @@ internal static class LiteralExpressionExtensions
///
/// The expected
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static bool ComputeRedefinedModelLevelEvaluableOperation(this ILiteralExpression literalExpressionSubject, List visited)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (literalExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(literalExpressionSubject));
+ }
+
+ return true;
}
///
@@ -73,7 +70,7 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this ILiteralE
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -81,10 +78,14 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this ILiteralE
///
/// The expected collection of
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static List ComputeRedefinedEvaluateOperation(this ILiteralExpression literalExpressionSubject, IElement target)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (literalExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(literalExpressionSubject));
+ }
+
+ return [literalExpressionSubject];
}
}
}
diff --git a/SysML2.NET/Extend/NullExpressionExtensions.cs b/SysML2.NET/Extend/NullExpressionExtensions.cs
index bbfde5e9..e2f8ea47 100644
--- a/SysML2.NET/Extend/NullExpressionExtensions.cs
+++ b/SysML2.NET/Extend/NullExpressionExtensions.cs
@@ -1,20 +1,20 @@
// -------------------------------------------------------------------------------------------------
//
-//
-// Copyright (C) 2022-2026 Starion Group S.A.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
+//
+// Copyright (C) 2022-2026 Starion Group S.A.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
+//
//
// ------------------------------------------------------------------------------------------------
@@ -23,19 +23,12 @@ namespace SysML2.NET.Core.POCO.Kernel.Expressions
using System;
using System.Collections.Generic;
- using SysML2.NET.Core.Core.Types;
- using SysML2.NET.Core.Root.Namespaces;
using SysML2.NET.Core.POCO.Core.Features;
- using SysML2.NET.Core.POCO.Core.Types;
- using SysML2.NET.Core.POCO.Kernel.Behaviors;
- using SysML2.NET.Core.POCO.Kernel.Functions;
- using SysML2.NET.Core.POCO.Root.Annotations;
using SysML2.NET.Core.POCO.Root.Elements;
- using SysML2.NET.Core.POCO.Root.Namespaces;
///
- /// The class provides extensions methods for
- /// the interface
+ /// The class provides extensions methods for
+ /// the interface
///
internal static class NullExpressionExtensions
{
@@ -49,7 +42,7 @@ internal static class NullExpressionExtensions
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -57,10 +50,14 @@ internal static class NullExpressionExtensions
///
/// The expected
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static bool ComputeRedefinedModelLevelEvaluableOperation(this INullExpression nullExpressionSubject, List visited)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (nullExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(nullExpressionSubject));
+ }
+
+ return true;
}
///
@@ -73,7 +70,7 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this INullExpr
///
///
///
- /// The subject
+ /// The subject
///
///
/// No documentation provided
@@ -81,10 +78,14 @@ internal static bool ComputeRedefinedModelLevelEvaluableOperation(this INullExpr
///
/// The expected collection of
///
- [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static List ComputeRedefinedEvaluateOperation(this INullExpression nullExpressionSubject, IElement target)
{
- throw new NotSupportedException("Create a GitHub issue when this method is required");
+ if (nullExpressionSubject == null)
+ {
+ throw new ArgumentNullException(nameof(nullExpressionSubject));
+ }
+
+ return [];
}
}
}