diff --git a/src/Microsoft.ComponentDetection.Detectors/dotnet/DotNetComponentDetector.cs b/src/Microsoft.ComponentDetection.Detectors/dotnet/DotNetComponentDetector.cs index 3161372f4..8770ce3bb 100644 --- a/src/Microsoft.ComponentDetection.Detectors/dotnet/DotNetComponentDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/dotnet/DotNetComponentDetector.cs @@ -25,7 +25,9 @@ public class DotNetComponentDetector : FileComponentDetector private readonly IPathUtilityService pathUtilityService; private readonly LockFileFormat lockFileFormat = new(); private readonly ConcurrentDictionary sdkVersionCache = []; - private readonly JsonDocumentOptions jsonDocumentOptions = new() { CommentHandling = JsonCommentHandling.Skip }; + private readonly JsonDocumentOptions jsonDocumentOptions = + new() { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true }; + private string? sourceDirectory; private string? sourceFileRootDirectory; diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/DotNetComponentDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/DotNetComponentDetectorTests.cs index 4b3455ef6..d4941512a 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/DotNetComponentDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/DotNetComponentDetectorTests.cs @@ -304,6 +304,38 @@ public async Task TestDotNetDetectorGlobalJsonWithComments_ReturnsSDKVersion() discoveredComponents.Where(component => component.Component.Id == "8.2.100 net8.0 unknown - DotNet").Should().ContainSingle(); } + [TestMethod] + public async Task TestDotNetDetectorGlobalJsonWithTrailingCommas_ReturnsSDKVersion() + { + var projectPath = Path.Combine(RootDir, "path", "to", "project"); + var projectAssets = ProjectAssets("projectName", "does-not-exist", projectPath, "net8.0"); + + // Trailing commas after version property and after sdk object + var globalJson = StreamFromString(""" + { + "sdk": { + "version": "9.9.900", + }, + } + """); + this.AddFile(projectPath, null); + this.AddFile(Path.Combine(RootDir, "path", "global.json"), globalJson); + this.SetCommandResult(-1); // force reading from file instead of dotnet --version + + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile("project.assets.json", projectAssets) + .ExecuteDetectorAsync(); + + scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().HaveCount(2); + + var discoveredComponents = detectedComponents.ToArray(); + discoveredComponents.Where(component => component.Component.Id == "9.9.900 unknown unknown - DotNet").Should().ContainSingle(); + discoveredComponents.Where(component => component.Component.Id == "9.9.900 net8.0 unknown - DotNet").Should().ContainSingle(); + } + [TestMethod] public async Task TestDotNetDetectorGlobalJsonWithoutVersion() {