Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions requirements.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,18 @@ 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 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:
- "net481@Spdx2JsonDeserializer_Deserialize_ValidSpdx22JsonReturnsExpectedDocument"
- "net481@Spdx2JsonSerializer_SerializeDocument_CorrectResults"
31 changes: 27 additions & 4 deletions src/DemaConsulting.SpdxModel/DemaConsulting.SpdxModel.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>12</LangVersion>
<TargetFrameworks>netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand Down Expand Up @@ -36,27 +36,50 @@
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest</AnalysisLevel>

<!-- Polyfill Configuration -->
<PolyArgumentExceptions>true</PolyArgumentExceptions>

<!-- SBOM Configuration -->
<GenerateSBOM>true</GenerateSBOM>
<SBOMPackageName>$(PackageId)</SBOMPackageName>
<SBOMPackageVersion>$(Version)</SBOMPackageVersion>
<SBOMPackageSupplier>Organization: $(Company)</SBOMPackageSupplier>
</PropertyGroup>

<!-- Build Tool Dependencies -->
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="10.0.3" />
<PackageReference Include="Microsoft.Sbom.Targets" Version="4.1.5" PrivateAssets="All" />
<PackageReference Include="Polyfill" Version="9.12.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.103" PrivateAssets="All" />
</ItemGroup>

<!-- Code Analysis Dependencies -->
<ItemGroup>
<!-- Analyzer packages use child-element form to configure both PrivateAssets and IncludeAssets:
- PrivateAssets="all" prevents these build-time analyzers from becoming transitive dependencies
in packages that consume this library.
- IncludeAssets lists all asset types (including 'analyzers' and 'buildtransitive') to ensure
Roslyn analyzers and MSBuild targets are fully activated during the build. -->
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.103">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.19.0.132793">
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.20.0.135146">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<!-- Library Dependencies -->
<ItemGroup>
<PackageReference Include="Microsoft.Bcl.HashCode" Version="6.0.0" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
<PackageReference Include="System.Text.Json" Version="10.0.3" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="DemaConsulting.SpdxModel.Tests" />
</ItemGroup>

<ItemGroup>
<None Remove="DemaConsulting.SpdxModel.csproj.DotSettings" />
</ItemGroup>
Expand Down
16 changes: 15 additions & 1 deletion src/DemaConsulting.SpdxModel/SpdxHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,25 @@ namespace DemaConsulting.SpdxModel;

internal static partial class SpdxHelpers
{
#if NET7_0_OR_GREATER
/// <summary>
/// Regular expression for checking date/time formats
/// Regular expression for checking date/time formats (source-generated for .NET 7+)
/// </summary>
[GeneratedRegex(@"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$", RegexOptions.None, 100)]
private static partial Regex DateTimeRegex();
#else
/// <summary>
/// Cached regular expression instance for checking date/time formats (pre-.NET 7 fallback)
/// </summary>
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));

/// <summary>
/// Regular expression for checking date/time formats
/// </summary>
/// <returns>Compiled <see cref="Regex"/> instance</returns>
private static Regex DateTimeRegex() => DateTimeRegexInstance;
#endif

/// <summary>
/// Test if a string is a valid SPDX date/time field (which include null/empty)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>12</LangVersion>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('Windows'))">net481;net8.0;net9.0;net10.0</TargetFrameworks>
<TargetFrameworks Condition="!$([MSBuild]::IsOSPlatform('Windows'))">net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand All @@ -18,41 +19,57 @@
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>

<ItemGroup>
<None Remove="DemaConsulting.SpdxModel.Tests.csproj.DotSettings" />
<None Remove="IO\Examples\SPDXJSONExample-v2.2.spdx.json" />
<None Remove="IO\Examples\SPDXJSONExample-v2.3.spdx.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="IO\Examples\SPDXJSONExample-v2.2.spdx.json" />
<EmbeddedResource Include="IO\Examples\SPDXJSONExample-v2.3.spdx.json" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="MSTest.TestAdapter" Version="4.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.103">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.19.0.132793">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\DemaConsulting.SpdxModel\DemaConsulting.SpdxModel.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<!-- Test Framework Dependencies -->
<ItemGroup>
<!-- coverlet.collector uses child-element form to configure both PrivateAssets and IncludeAssets:
- PrivateAssets="all" keeps this test-coverage tool out of any consuming project's dependencies.
- IncludeAssets lists all asset types (including 'build' and 'buildtransitive') to ensure the
data collector MSBuild targets are activated so coverage is collected during test runs. -->
<PackageReference Include="coverlet.collector" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="4.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="4.1.0" />
</ItemGroup>

<!-- Code Analysis Dependencies -->
<ItemGroup>
<!-- Analyzer packages use child-element form to configure both PrivateAssets and IncludeAssets:
- PrivateAssets="all" prevents these build-time analyzers from becoming transitive dependencies
in any project that references this test project.
- IncludeAssets lists all asset types (including 'analyzers' and 'buildtransitive') to ensure
Roslyn analyzers and MSBuild targets are fully activated during the build. -->
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.103">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.20.0.135146">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<!-- Project References -->
<ItemGroup>
<ProjectReference Include="..\..\src\DemaConsulting.SpdxModel\DemaConsulting.SpdxModel.csproj" />
</ItemGroup>

<ItemGroup>
<None Remove="DemaConsulting.SpdxModel.Tests.csproj.DotSettings" />
<None Remove="IO\Examples\SPDXJSONExample-v2.2.spdx.json" />
<None Remove="IO\Examples\SPDXJSONExample-v2.3.spdx.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="IO\Examples\SPDXJSONExample-v2.2.spdx.json" />
<EmbeddedResource Include="IO\Examples\SPDXJSONExample-v2.3.spdx.json" />
</ItemGroup>

<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
<Using Include="Polyfills" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -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.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document", ex.Message);
Assert.AreEqual("relationship", ex.ParamName);
Assert.IsEmpty(document.Relationships);
}

Expand All @@ -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.StartsWith("Element SPDXRef-Package-Missing not found in SPDX document", ex.Message);
Assert.AreEqual("relationship", ex.ParamName);
Assert.IsEmpty(document.Relationships);
}

Expand Down