From b8fcef7f6e13e9e1717fd18bdcc46017fba78cda Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 19:11:11 +0000
Subject: [PATCH 01/10] Initial plan
From 7dd264bed7938d914334dc703b4c4e169266f53f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 19:32:40 +0000
Subject: [PATCH 02/10] Apply TemplateDotNetLibrary updates: Polyfill,
LangVersion=latest, netstandard2.0 support
- Add netstandard2.0 to TargetFrameworks in library project
- Add Polyfill 9.12.0 package with PolyArgumentExceptions=true
- Update LangVersion from 12 to latest in both projects
- Update SonarAnalyzer.CSharp from 10.19.0.132793 to 10.20.0.135146
- Update Microsoft.NET.Test.Sdk from 18.0.1 to 18.3.0
- Add System.Text.Json conditional references (9.0.5 for netstandard2.0, 10.0.3 for net8+)
- Add HashCodePolyfill.cs for System.HashCode on netstandard2.0
- Add #if NET7_0_OR_GREATER guard in SpdxHelpers.cs for [GeneratedRegex]
- Add InternalsVisibleTo for test project
- Reorganize ItemGroups with template-style section comments
- Add REQ-PLAT-004 for .NET Standard 2.0 target framework support
---
requirements.yaml | 19 ++++
.../DemaConsulting.SpdxModel.csproj | 33 +++++-
.../HashCodePolyfill.cs | 100 ++++++++++++++++++
src/DemaConsulting.SpdxModel/SpdxHelpers.cs | 16 ++-
.../DemaConsulting.SpdxModel.Tests.csproj | 91 +++++++++-------
5 files changed, 215 insertions(+), 44 deletions(-)
create mode 100644 src/DemaConsulting.SpdxModel/HashCodePolyfill.cs
diff --git a/requirements.yaml b/requirements.yaml
index 578681c..9fb3766 100644
--- a/requirements.yaml
+++ b/requirements.yaml
@@ -314,3 +314,22 @@ sections:
tests:
- net10.0@Spdx2JsonDeserializer_Deserialize_ValidSpdx22JsonReturnsExpectedDocument
- net10.0@Spdx2JsonSerializer_SerializeDocument_CorrectResults
+
+ - id: REQ-PLAT-004
+ title: The library shall support the .NET Standard 2.0 target framework.
+ tags:
+ - platform
+ justification: |
+ .NET Standard 2.0 is a formal API surface specification that enables the library to be
+ consumed by a wide range of project types, including .NET Framework 4.6.1+ projects,
+ .NET Core 2.0+ projects, Xamarin, Unity, MSBuild extensions, and other tools that
+ require .NET Standard compatibility. Publishing a netstandard2.0 target maximizes
+ adoption across the .NET ecosystem without requiring consumers to upgrade to a modern
+ runtime. The build system validates successful compilation against the netstandard2.0
+ target for every change. The net8.0 test results below serve as provisional functional
+ evidence since .NET 8 fully implements the .NET Standard 2.0 API surface; dedicated
+ net481 test targets would provide direct runtime evidence and are tracked as a future
+ enhancement.
+ tests:
+ - net8.0@Spdx2JsonDeserializer_Deserialize_ValidSpdx22JsonReturnsExpectedDocument
+ - net8.0@Spdx2JsonSerializer_SerializeDocument_CorrectResults
diff --git a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
index a191bcb..982679b 100644
--- a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
+++ b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
@@ -1,8 +1,8 @@
- net8.0;net9.0;net10.0
- 12
+ netstandard2.0;net8.0;net9.0;net10.0
+ latest
enable
enable
@@ -31,11 +31,14 @@
true
- true
+ True
true
true
latest
+
+ true
+
true
$(PackageId)
@@ -43,20 +46,40 @@
Organization: $(Company)
+
-
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DemaConsulting.SpdxModel/HashCodePolyfill.cs b/src/DemaConsulting.SpdxModel/HashCodePolyfill.cs
new file mode 100644
index 0000000..e74c6c1
--- /dev/null
+++ b/src/DemaConsulting.SpdxModel/HashCodePolyfill.cs
@@ -0,0 +1,100 @@
+// Copyright(c) 2024 DEMA Consulting
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#if NETSTANDARD2_0
+
+// Provide a minimal HashCode.Combine polyfill for netstandard2.0, which does not
+// have System.HashCode. The implementation uses prime-based accumulation to
+// produce reasonably well-distributed hash codes from multiple values, matching
+// the public API surface used in this library.
+namespace System;
+
+///
+/// Polyfill for System.HashCode on netstandard2.0 targets.
+///
+///
+/// System.HashCode was introduced in .NET Core 2.1 / netstandard2.1 and is not
+/// available in netstandard2.0. This internal struct provides the Combine overloads
+/// used by this library so that no conditional compilation is needed in calling code.
+///
+internal struct HashCode
+{
+ ///
+ /// Combines two values into a hash code using prime-based accumulation.
+ ///
+ /// Type of the first value
+ /// Type of the second value
+ /// First value
+ /// Second value
+ /// Combined hash code
+ public static int Combine(T1 value1, T2 value2)
+ {
+ // Accumulate hash codes using a prime multiplier to reduce collisions
+ var hash = 17;
+ hash = hash * 31 + (value1?.GetHashCode() ?? 0);
+ hash = hash * 31 + (value2?.GetHashCode() ?? 0);
+ return hash;
+ }
+
+ ///
+ /// Combines three values into a hash code using prime-based accumulation.
+ ///
+ /// Type of the first value
+ /// Type of the second value
+ /// Type of the third value
+ /// First value
+ /// Second value
+ /// Third value
+ /// Combined hash code
+ public static int Combine(T1 value1, T2 value2, T3 value3)
+ {
+ // Accumulate hash codes using a prime multiplier to reduce collisions
+ var hash = 17;
+ hash = hash * 31 + (value1?.GetHashCode() ?? 0);
+ hash = hash * 31 + (value2?.GetHashCode() ?? 0);
+ hash = hash * 31 + (value3?.GetHashCode() ?? 0);
+ return hash;
+ }
+
+ ///
+ /// Combines four values into a hash code using prime-based accumulation.
+ ///
+ /// Type of the first value
+ /// Type of the second value
+ /// Type of the third value
+ /// Type of the fourth value
+ /// First value
+ /// Second value
+ /// Third value
+ /// Fourth value
+ /// Combined hash code
+ public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4)
+ {
+ // Accumulate hash codes using a prime multiplier to reduce collisions
+ var hash = 17;
+ hash = hash * 31 + (value1?.GetHashCode() ?? 0);
+ hash = hash * 31 + (value2?.GetHashCode() ?? 0);
+ hash = hash * 31 + (value3?.GetHashCode() ?? 0);
+ hash = hash * 31 + (value4?.GetHashCode() ?? 0);
+ return hash;
+ }
+}
+
+#endif
diff --git a/src/DemaConsulting.SpdxModel/SpdxHelpers.cs b/src/DemaConsulting.SpdxModel/SpdxHelpers.cs
index acb10a1..c6bbbb2 100644
--- a/src/DemaConsulting.SpdxModel/SpdxHelpers.cs
+++ b/src/DemaConsulting.SpdxModel/SpdxHelpers.cs
@@ -24,11 +24,25 @@ namespace DemaConsulting.SpdxModel;
internal static partial class SpdxHelpers
{
+#if NET7_0_OR_GREATER
///
- /// Regular expression for checking date/time formats
+ /// Regular expression for checking date/time formats (source-generated for .NET 7+)
///
[GeneratedRegex(@"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$", RegexOptions.None, 100)]
private static partial Regex DateTimeRegex();
+#else
+ ///
+ /// Cached regular expression instance for checking date/time formats (netstandard2.0 fallback)
+ ///
+ private static readonly Regex DateTimeRegexInstance =
+ new Regex(@"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$", RegexOptions.None, TimeSpan.FromMilliseconds(100));
+
+ ///
+ /// Regular expression for checking date/time formats
+ ///
+ /// Compiled instance
+ private static Regex DateTimeRegex() => DateTimeRegexInstance;
+#endif
///
/// Test if a string is a valid SPDX date/time field (which include null/empty)
diff --git a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
index 912a018..14bb554 100644
--- a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
+++ b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
@@ -2,7 +2,7 @@
net8.0;net9.0;net10.0
- 12
+ latest
enable
enable
@@ -12,47 +12,62 @@
true
- true
+ True
true
true
latest
-
-
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 5971af5bf9ec02656a898e108c7827af342a9586 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 19:34:29 +0000
Subject: [PATCH 03/10] Add net481 Windows test target and update REQ-PLAT-004
to use net481 evidence
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
requirements.yaml | 20 ++++++++-----------
.../DemaConsulting.SpdxModel.Tests.csproj | 3 ++-
2 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/requirements.yaml b/requirements.yaml
index 9fb3766..e816f79 100644
--- a/requirements.yaml
+++ b/requirements.yaml
@@ -320,16 +320,12 @@ sections:
tags:
- platform
justification: |
- .NET Standard 2.0 is a formal API surface specification that enables the library to be
- consumed by a wide range of project types, including .NET Framework 4.6.1+ projects,
- .NET Core 2.0+ projects, Xamarin, Unity, MSBuild extensions, and other tools that
- require .NET Standard compatibility. Publishing a netstandard2.0 target maximizes
- adoption across the .NET ecosystem without requiring consumers to upgrade to a modern
- runtime. The build system validates successful compilation against the netstandard2.0
- target for every change. The net8.0 test results below serve as provisional functional
- evidence since .NET 8 fully implements the .NET Standard 2.0 API surface; dedicated
- net481 test targets would provide direct runtime evidence and are tracked as a future
- enhancement.
+ .NET Standard 2.0 is a widely-supported target framework that enables the library to
+ be used in MSBuild extensions and other tooling that requires .NET Standard compatibility.
+ Supporting this target framework ensures the library can be integrated into a broader
+ range of .NET projects, including those targeting .NET Framework and older .NET Core versions.
+ The net481 test target on Windows provides direct runtime evidence of .NET Standard 2.0
+ compatibility, as .NET Framework 4.8.1 fully implements the .NET Standard 2.0 API surface.
tests:
- - net8.0@Spdx2JsonDeserializer_Deserialize_ValidSpdx22JsonReturnsExpectedDocument
- - net8.0@Spdx2JsonSerializer_SerializeDocument_CorrectResults
+ - "net481@Spdx2JsonDeserializer_Deserialize_ValidSpdx22JsonReturnsExpectedDocument"
+ - "net481@Spdx2JsonSerializer_SerializeDocument_CorrectResults"
diff --git a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
index 14bb554..f093aa5 100644
--- a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
+++ b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
@@ -1,7 +1,8 @@
- net8.0;net9.0;net10.0
+ net481;net8.0;net9.0;net10.0
+ net8.0;net9.0;net10.0
latest
enable
enable
From 076adf0c0745998513c28041383c973e1ca7d8c9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 19:43:46 +0000
Subject: [PATCH 04/10] Simplify System.Text.Json to single version and restore
lowercase GenerateDocumentationFile
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj | 3 +--
.../DemaConsulting.SpdxModel.Tests.csproj | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
index 982679b..1a378be 100644
--- a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
+++ b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
@@ -72,8 +72,7 @@
-
-
+
diff --git a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
index f093aa5..4ba4393 100644
--- a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
+++ b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
@@ -13,7 +13,7 @@
true
- True
+ true
true
true
latest
From 7a8e86f323922cdc10f8b9b1589875f7810740b6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 19:47:56 +0000
Subject: [PATCH 05/10] Restore GenerateDocumentationFile to lowercase true in
library project
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
index 1a378be..cdfc6d2 100644
--- a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
+++ b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
@@ -31,7 +31,7 @@
true
- True
+ true
true
true
latest
From d4430a2346b04198c98784c19086b71424c10b65 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 19:54:01 +0000
Subject: [PATCH 06/10] Replace HashCodePolyfill with Microsoft.Bcl.HashCode
6.0.0; fix spell-check failures
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
.../DemaConsulting.SpdxModel.csproj | 1 +
.../HashCodePolyfill.cs | 100 ------------------
src/DemaConsulting.SpdxModel/SpdxHelpers.cs | 2 +-
3 files changed, 2 insertions(+), 101 deletions(-)
delete mode 100644 src/DemaConsulting.SpdxModel/HashCodePolyfill.cs
diff --git a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
index cdfc6d2..38c459d 100644
--- a/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
+++ b/src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
@@ -72,6 +72,7 @@
+
diff --git a/src/DemaConsulting.SpdxModel/HashCodePolyfill.cs b/src/DemaConsulting.SpdxModel/HashCodePolyfill.cs
deleted file mode 100644
index e74c6c1..0000000
--- a/src/DemaConsulting.SpdxModel/HashCodePolyfill.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright(c) 2024 DEMA Consulting
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if NETSTANDARD2_0
-
-// Provide a minimal HashCode.Combine polyfill for netstandard2.0, which does not
-// have System.HashCode. The implementation uses prime-based accumulation to
-// produce reasonably well-distributed hash codes from multiple values, matching
-// the public API surface used in this library.
-namespace System;
-
-///
-/// Polyfill for System.HashCode on netstandard2.0 targets.
-///
-///
-/// System.HashCode was introduced in .NET Core 2.1 / netstandard2.1 and is not
-/// available in netstandard2.0. This internal struct provides the Combine overloads
-/// used by this library so that no conditional compilation is needed in calling code.
-///
-internal struct HashCode
-{
- ///
- /// Combines two values into a hash code using prime-based accumulation.
- ///
- /// Type of the first value
- /// Type of the second value
- /// First value
- /// Second value
- /// Combined hash code
- public static int Combine(T1 value1, T2 value2)
- {
- // Accumulate hash codes using a prime multiplier to reduce collisions
- var hash = 17;
- hash = hash * 31 + (value1?.GetHashCode() ?? 0);
- hash = hash * 31 + (value2?.GetHashCode() ?? 0);
- return hash;
- }
-
- ///
- /// Combines three values into a hash code using prime-based accumulation.
- ///
- /// Type of the first value
- /// Type of the second value
- /// Type of the third value
- /// First value
- /// Second value
- /// Third value
- /// Combined hash code
- public static int Combine(T1 value1, T2 value2, T3 value3)
- {
- // Accumulate hash codes using a prime multiplier to reduce collisions
- var hash = 17;
- hash = hash * 31 + (value1?.GetHashCode() ?? 0);
- hash = hash * 31 + (value2?.GetHashCode() ?? 0);
- hash = hash * 31 + (value3?.GetHashCode() ?? 0);
- return hash;
- }
-
- ///
- /// Combines four values into a hash code using prime-based accumulation.
- ///
- /// Type of the first value
- /// Type of the second value
- /// Type of the third value
- /// Type of the fourth value
- /// First value
- /// Second value
- /// Third value
- /// Fourth value
- /// Combined hash code
- public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4)
- {
- // Accumulate hash codes using a prime multiplier to reduce collisions
- var hash = 17;
- hash = hash * 31 + (value1?.GetHashCode() ?? 0);
- hash = hash * 31 + (value2?.GetHashCode() ?? 0);
- hash = hash * 31 + (value3?.GetHashCode() ?? 0);
- hash = hash * 31 + (value4?.GetHashCode() ?? 0);
- return hash;
- }
-}
-
-#endif
diff --git a/src/DemaConsulting.SpdxModel/SpdxHelpers.cs b/src/DemaConsulting.SpdxModel/SpdxHelpers.cs
index c6bbbb2..9d5d9cf 100644
--- a/src/DemaConsulting.SpdxModel/SpdxHelpers.cs
+++ b/src/DemaConsulting.SpdxModel/SpdxHelpers.cs
@@ -32,7 +32,7 @@ internal static partial class SpdxHelpers
private static partial Regex DateTimeRegex();
#else
///
- /// Cached regular expression instance for checking date/time formats (netstandard2.0 fallback)
+ /// Cached regular expression instance for checking date/time formats (pre-.NET 7 fallback)
///
private static readonly Regex DateTimeRegexInstance =
new Regex(@"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$", RegexOptions.None, TimeSpan.FromMilliseconds(100));
From b7119eb4d51e6681bef170dea2604b76e1bfa686 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 20:03:43 +0000
Subject: [PATCH 07/10] Fix net481 build: guard ReplaceLineEndings behind
NET6_0_OR_GREATER in TestHelpers.cs
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs b/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs
index d3d0482..b6008ed 100644
--- a/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs
+++ b/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs
@@ -41,6 +41,10 @@ public static string GetEmbeddedResource(string resourceName)
// Read the resource
using var reader = new StreamReader(stream);
+#if NET6_0_OR_GREATER
return reader.ReadToEnd().ReplaceLineEndings();
+#else
+ return reader.ReadToEnd().Replace("\r\n", "\n").Replace("\r", "\n");
+#endif
}
}
From dadaa1ba80d2ebb26fe19a3ac3ba42cde32aaa34 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 20:10:25 +0000
Subject: [PATCH 08/10] Use library's Polyfill via global using Polyfills;
instead of #if guard in TestHelpers.cs
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
.../DemaConsulting.SpdxModel.Tests.csproj | 1 +
test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs | 4 ----
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
index 4ba4393..4e50a1a 100644
--- a/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
+++ b/test/DemaConsulting.SpdxModel.Tests/DemaConsulting.SpdxModel.Tests.csproj
@@ -69,6 +69,7 @@
+
\ No newline at end of file
diff --git a/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs b/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs
index b6008ed..d3d0482 100644
--- a/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs
+++ b/test/DemaConsulting.SpdxModel.Tests/TestHelpers.cs
@@ -41,10 +41,6 @@ public static string GetEmbeddedResource(string resourceName)
// Read the resource
using var reader = new StreamReader(stream);
-#if NET6_0_OR_GREATER
return reader.ReadToEnd().ReplaceLineEndings();
-#else
- return reader.ReadToEnd().Replace("\r\n", "\n").Replace("\r", "\n");
-#endif
}
}
From 2e2bab3b52ada7725da6470a81974b8a4ac60efe Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 20:19:38 +0000
Subject: [PATCH 09/10] Fix ArgumentException message assertions to be portable
across .NET Framework and modern .NET
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
.../Transforms/SpdxRelationshipsTests.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs b/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs
index f240d37..ff63d60 100644
--- a/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs
+++ b/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs
@@ -69,8 +69,8 @@ public void SpdxRelationships_AddSingle_MissingId()
});
// Assert: Verify the exception message and that no relationships were added
- Assert.AreEqual("Element SPDXRef-Package-Missing not found in SPDX document (Parameter 'relationship')",
- ex.Message);
+ Assert.IsTrue(ex.Message.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document"));
+ Assert.AreEqual("relationship", ex.ParamName);
Assert.IsEmpty(document.Relationships);
}
@@ -97,8 +97,8 @@ public void SpdxRelationships_AddSingle_MissingRelatedElement()
});
// Assert: Verify the exception message and that no relationships were added
- Assert.AreEqual("Element SPDXRef-Package-Missing not found in SPDX document (Parameter 'relationship')",
- ex.Message);
+ Assert.IsTrue(ex.Message.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document"));
+ Assert.AreEqual("relationship", ex.ParamName);
Assert.IsEmpty(document.Relationships);
}
From 63da66141473be715c9010f2db9851b359053781 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 20:22:29 +0000
Subject: [PATCH 10/10] Replace Assert.IsTrue(x.StartsWith) antipattern with
Assert.StartsWith
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
.../Transforms/SpdxRelationshipsTests.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs b/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs
index ff63d60..930d7b1 100644
--- a/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs
+++ b/test/DemaConsulting.SpdxModel.Tests/Transforms/SpdxRelationshipsTests.cs
@@ -69,7 +69,7 @@ public void SpdxRelationships_AddSingle_MissingId()
});
// Assert: Verify the exception message and that no relationships were added
- Assert.IsTrue(ex.Message.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document"));
+ Assert.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document", ex.Message);
Assert.AreEqual("relationship", ex.ParamName);
Assert.IsEmpty(document.Relationships);
}
@@ -97,7 +97,7 @@ public void SpdxRelationships_AddSingle_MissingRelatedElement()
});
// Assert: Verify the exception message and that no relationships were added
- Assert.IsTrue(ex.Message.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document"));
+ Assert.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document", ex.Message);
Assert.AreEqual("relationship", ex.ParamName);
Assert.IsEmpty(document.Relationships);
}