From 81ae0f7f53d68645355b4b012f117c84f6226cf3 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 09:08:28 +0200 Subject: [PATCH 1/8] update nuget packages --- src/NuGetLicense/NuGetLicense.csproj | 4 ++-- src/NuGetUtility/NuGetUtility.csproj | 10 ++++++---- .../FileLicenseMatcher.Test.csproj | 2 +- tests/NuGetLicense.Test/NuGetLicense.Test.csproj | 2 +- tests/NuGetUtility.Test/NuGetUtility.Test.csproj | 2 +- .../NuGetUtility.UrlToLicenseMapping.Test.csproj | 4 ++-- .../MultiTargetProjectWithDifferentDependencies.csproj | 4 ++-- .../PackageReferenceProject.csproj | 2 +- .../VersionRangesProject/VersionRangesProject.csproj | 2 +- 9 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/NuGetLicense/NuGetLicense.csproj b/src/NuGetLicense/NuGetLicense.csproj index 51969f08..ce7e2d38 100644 --- a/src/NuGetLicense/NuGetLicense.csproj +++ b/src/NuGetLicense/NuGetLicense.csproj @@ -27,8 +27,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/NuGetUtility/NuGetUtility.csproj b/src/NuGetUtility/NuGetUtility.csproj index c8387deb..d6e58eeb 100644 --- a/src/NuGetUtility/NuGetUtility.csproj +++ b/src/NuGetUtility/NuGetUtility.csproj @@ -20,8 +20,10 @@ - - + + + compile; build; native; contentfiles; analyzers; buildtransitive + @@ -39,8 +41,8 @@ - - + + all diff --git a/tests/FileLicenseMatcher.Test/FileLicenseMatcher.Test.csproj b/tests/FileLicenseMatcher.Test/FileLicenseMatcher.Test.csproj index 2383df1a..831dfc00 100644 --- a/tests/FileLicenseMatcher.Test/FileLicenseMatcher.Test.csproj +++ b/tests/FileLicenseMatcher.Test/FileLicenseMatcher.Test.csproj @@ -16,7 +16,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/NuGetLicense.Test/NuGetLicense.Test.csproj b/tests/NuGetLicense.Test/NuGetLicense.Test.csproj index 5ef98e69..a5d0bce1 100644 --- a/tests/NuGetLicense.Test/NuGetLicense.Test.csproj +++ b/tests/NuGetLicense.Test/NuGetLicense.Test.csproj @@ -29,7 +29,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/NuGetUtility.Test/NuGetUtility.Test.csproj b/tests/NuGetUtility.Test/NuGetUtility.Test.csproj index 64f93566..818c5e13 100644 --- a/tests/NuGetUtility.Test/NuGetUtility.Test.csproj +++ b/tests/NuGetUtility.Test/NuGetUtility.Test.csproj @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/NuGetUtility.UrlToLicenseMapping.Test/NuGetUtility.UrlToLicenseMapping.Test.csproj b/tests/NuGetUtility.UrlToLicenseMapping.Test/NuGetUtility.UrlToLicenseMapping.Test.csproj index 2f6eff9c..ac9bcc55 100644 --- a/tests/NuGetUtility.UrlToLicenseMapping.Test/NuGetUtility.UrlToLicenseMapping.Test.csproj +++ b/tests/NuGetUtility.UrlToLicenseMapping.Test/NuGetUtility.UrlToLicenseMapping.Test.csproj @@ -16,12 +16,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/targets/MultiTargetProjectWithDifferentDependencies/MultiTargetProjectWithDifferentDependencies.csproj b/tests/targets/MultiTargetProjectWithDifferentDependencies/MultiTargetProjectWithDifferentDependencies.csproj index a6ae65fc..17d0faba 100644 --- a/tests/targets/MultiTargetProjectWithDifferentDependencies/MultiTargetProjectWithDifferentDependencies.csproj +++ b/tests/targets/MultiTargetProjectWithDifferentDependencies/MultiTargetProjectWithDifferentDependencies.csproj @@ -5,9 +5,9 @@ - + - + diff --git a/tests/targets/PackageReferenceProject/PackageReferenceProject.csproj b/tests/targets/PackageReferenceProject/PackageReferenceProject.csproj index 22c33b17..6f105564 100644 --- a/tests/targets/PackageReferenceProject/PackageReferenceProject.csproj +++ b/tests/targets/PackageReferenceProject/PackageReferenceProject.csproj @@ -9,7 +9,7 @@ - + diff --git a/tests/targets/VersionRangesProject/VersionRangesProject.csproj b/tests/targets/VersionRangesProject/VersionRangesProject.csproj index 0a110cde..2c6b6ed6 100644 --- a/tests/targets/VersionRangesProject/VersionRangesProject.csproj +++ b/tests/targets/VersionRangesProject/VersionRangesProject.csproj @@ -5,7 +5,7 @@ - + \ No newline at end of file From 475d00f7783c0beead9485952ff0e94b1b8e7ee3 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 17:37:26 +0200 Subject: [PATCH 2/8] a few fixes --- .../Compare/LicenseMatcherTest.cs | 27 +++++++++++++------ .../CommandLineOptionsParserTest.cs | 2 +- .../UrlToLicenseMappingTest.cs | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/FileLicenseMatcher.Test/Compare/LicenseMatcherTest.cs b/tests/FileLicenseMatcher.Test/Compare/LicenseMatcherTest.cs index 9e0946c1..7c2f1e8b 100644 --- a/tests/FileLicenseMatcher.Test/Compare/LicenseMatcherTest.cs +++ b/tests/FileLicenseMatcher.Test/Compare/LicenseMatcherTest.cs @@ -9,14 +9,8 @@ namespace FileLicenseMatcher.Test.Compare { public class LicenseMatcherTest { - private readonly IFileSystem _fileSystem; + private readonly IFileSystem _fileSystem = Substitute.For(); - public LicenseMatcherTest() - { - _fileSystem = Substitute.For(); - } - -#pragma warning disable S6966 //Awaitable method should be used [Test] public async Task Match_Should_Return_Empty_When_Map_Is_Empty() { @@ -44,7 +38,9 @@ public async Task Match_Should_Return_Empty_When_File_Does_Not_Exist() string result = uut.Match("license contents"); await Assert.That(result).IsEmpty(); +#pragma warning disable S6966 //Awaitable method should be used file.DidNotReceive().ReadAllText(Arg.Any()); +#pragma warning restore S6966 //Awaitable method should be used S6966 } [Test] @@ -62,14 +58,18 @@ public async Task Match_Should_Return_Mapped_Id_When_Content_Equals() IFile file = Substitute.For(); _fileSystem.File.Returns(file); file.Exists(path).Returns(true); +#pragma warning disable S6966 //Awaitable method should be used file.ReadAllText(path).Returns(content); +#pragma warning restore S6966 //Awaitable method should be used var uut = new LicenseMatcher(_fileSystem, map); string result = uut.Match(content); await Assert.That(result).EqualTo(mappedId); +#pragma warning disable S6966 //Awaitable method should be used file.Received(1).ReadAllText(path); +#pragma warning restore S6966 //Awaitable method should be used } [Test] @@ -90,15 +90,19 @@ public async Task Match_Should_Skip_Files_That_Do_Not_Exist_And_Return_When_Foun _fileSystem.File.Returns(file); file.Exists(firstPath).Returns(false); file.Exists(secondPath).Returns(true); +#pragma warning disable S6966 //Awaitable method should be used file.ReadAllText(secondPath).Returns(licenseText); +#pragma warning restore S6966 //Awaitable method should be used var uut = new LicenseMatcher(_fileSystem, map); string result = uut.Match(licenseText); await Assert.That(result).EqualTo(secondId); +#pragma warning disable S6966 //Awaitable method should be used file.DidNotReceive().ReadAllText(firstPath); file.Received(1).ReadAllText(secondPath); +#pragma warning restore S6966 //Awaitable method should be used } [Test] @@ -114,14 +118,18 @@ public async Task Match_Should_Return_Empty_When_No_File_Matches_Content() IFile file = Substitute.For(); _fileSystem.File.Returns(file); file.Exists(path).Returns(true); +#pragma warning disable S6966 //Awaitable method should be used file.ReadAllText(path).Returns("different content"); +#pragma warning restore S6966 //Awaitable method should be used var uut = new LicenseMatcher(_fileSystem, map); string result = uut.Match("license contents"); await Assert.That(result).IsEmpty(); +#pragma warning disable S6966 //Awaitable method should be used file.Received(1).ReadAllText(path); +#pragma warning restore S6966 //Awaitable method should be used } [Test] @@ -140,15 +148,18 @@ public async Task Match_Should_Ignore_Whitespace_Differences() IFile file = Substitute.For(); _fileSystem.File.Returns(file); file.Exists(path).Returns(true); +#pragma warning disable S6966 //Awaitable method should be used file.ReadAllText(path).Returns(fileContent); +#pragma warning restore S6966 //Awaitable method should be used var uut = new LicenseMatcher(_fileSystem, map); string result = uut.Match(inputContent); await Assert.That(result).EqualTo(mappedId); +#pragma warning disable S6966 //Awaitable method should be used file.Received(1).ReadAllText(path); - } #pragma warning restore S6966 //Awaitable method should be used + } } } diff --git a/tests/NuGetLicense.Test/CommandLineOptionsParserTest.cs b/tests/NuGetLicense.Test/CommandLineOptionsParserTest.cs index 3de5bedb..76f258fa 100644 --- a/tests/NuGetLicense.Test/CommandLineOptionsParserTest.cs +++ b/tests/NuGetLicense.Test/CommandLineOptionsParserTest.cs @@ -324,7 +324,7 @@ public async Task GetLicenseMatcher_WithFile_ReturnsCombinedMatcher() string mappingFile = "/test/dir/license-mappings.json"; string licenseFile = "/test/dir/LICENSE.txt"; _fileSystem.AddFile(licenseFile, new MockFileData("MIT License content")); - _fileSystem.AddFile(mappingFile, new MockFileData($"{{\"LICENSE.txt\":\"MIT\"}}")); + _fileSystem.AddFile(mappingFile, new MockFileData("{\"LICENSE.txt\":\"MIT\"}")); // Act IFileLicenseMatcher result = _parser.GetLicenseMatcher(mappingFile); diff --git a/tests/NuGetUtility.UrlToLicenseMapping.Test/UrlToLicenseMappingTest.cs b/tests/NuGetUtility.UrlToLicenseMapping.Test/UrlToLicenseMappingTest.cs index 5c8ed54b..2968ce31 100644 --- a/tests/NuGetUtility.UrlToLicenseMapping.Test/UrlToLicenseMappingTest.cs +++ b/tests/NuGetUtility.UrlToLicenseMapping.Test/UrlToLicenseMappingTest.cs @@ -71,7 +71,7 @@ public async Task License_Should_Be_Available_And_Match_Expected_License(KeyValu retryCount++; Console.WriteLine($"Failed to check license. Retry count: {retryCount}\n\n"); - Console.WriteLine($"Error:"); + Console.WriteLine("Error:"); Console.WriteLine(licenseResult.Error); Console.WriteLine($"\n\nRetrying after {retryTimeout}ms\n\n"); From ef6d6f27294bb0ea14cded12fac004cae0522b4b Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 20:03:13 +0200 Subject: [PATCH 3/8] Fix nullability --- .../NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs | 6 ++++-- .../Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs index c593b23a..04f6e64a 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs @@ -5,6 +5,7 @@ using NuGet.Packaging; using NuGet.Protocol.Core.Types; using NuGet.Versioning; +using NuGetUtility.Wrapper.NuGetWrapper.Versioning; using IWrappedPackageMetadata = NuGetUtility.Wrapper.NuGetWrapper.Packaging.IPackageMetadata; using OriginalGlobalPackagesFolderUtility = NuGet.Protocol.GlobalPackagesFolderUtility; using OriginalPackageIdentity = NuGet.Packaging.Core.PackageIdentity; @@ -32,7 +33,8 @@ public GlobalPackagesFolderUtility(ISettings settings) using PackageReaderBase pkgStream = cachedPackage.PackageReader; var manifest = Manifest.ReadFrom(pkgStream.GetNuspec(), true); - if (manifest.Metadata.Version.Equals(identity.Version)) + if (manifest.Metadata.Version is not { } manifestVersion || + !new WrappedNuGetVersion(manifestVersion).Equals(identity.Version)) { return null; } @@ -40,7 +42,7 @@ public GlobalPackagesFolderUtility(ISettings settings) var result = new WrappedPackageMetadata(manifest.Metadata); if (result.LicenseMetadata?.Type == Packaging.LicenseType.File) { - string normalizedPath = NuGet.Common.PathUtility.GetPathWithDirectorySeparator(manifest.Metadata.LicenseMetadata.License); + string normalizedPath = NuGet.Common.PathUtility.GetPathWithDirectorySeparator(result.LicenseMetadata.License); using Stream licenseStream = pkgStream.GetStream(normalizedPath); using var reader = new StreamReader(licenseStream); return new LicenseAugmentedPackageMetadata(result, reader.ReadToEnd()); diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs index e7b2660c..33a04832 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs @@ -14,7 +14,8 @@ internal class WrappedPackageMetadata : IWrappedPackageMetadata public WrappedPackageMetadata(ManifestMetadata metadata) { - Identity = new PackageIdentity(metadata.Id, new WrappedNuGetVersion(metadata.Version)); + Identity = new PackageIdentity(metadata.Id ?? throw new ArgumentNullException(nameof(metadata.Id)), + new WrappedNuGetVersion(metadata.Version ?? throw new ArgumentNullException(nameof(metadata.Version)))); LicenseMetadata = metadata.LicenseMetadata; _metadata = metadata; } From 6a0949db7cbd669082961aa8c83838356c82503f Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 21:00:28 +0200 Subject: [PATCH 4/8] Code cleanup --- .../Combine/LicenseMatcher.cs | 9 +- .../Compare/LicenseMatcher.cs | 18 +- .../SPDX/FastLicenseMatcher.cs | 16 +- .../SPDX/JavaCore/LicenseTemplateRule.cs | 10 +- .../SPDX/JavaCore/LicenseTextHelper.cs | 124 ++-------- .../JavaCore/SpdxLicenseTemplateHelper.cs | 12 +- .../CompareTemplateOutputHandler.cs | 24 +- .../SPDX/JavaLibrary/LicenseCompareHelper.cs | 14 +- .../SPDX/JavaLibrary/ParseInstruction.cs | 8 +- src/NuGetLicense/CommandLineOptionsParser.cs | 39 ++- .../LicenseValidationOrchestrator.cs | 138 +++++------ .../LicenseDownloadException.cs | 11 +- .../LicenseValidationResult.cs | 2 +- .../LicenseValidator/LicenseValidator.cs | 232 ++++++++---------- .../Output/Csv/CsvOutputFormatter.cs | 21 +- .../Output/Json/JsonOutputFormatter.cs | 23 +- .../Output/Table/TableOutputFormatter.cs | 38 ++- src/NuGetLicense/Program.cs | 2 +- src/NuGetUtility/Output/Table/TablePrinter.cs | 2 +- .../PackageInformationReader.cs | 36 +-- .../ProjectsCollector.cs | 18 +- .../ReferencedPackageReader.cs | 129 +++++----- .../DownloadFailedException.cs | 7 +- .../HttpClientWrapper/FileDownloader.cs | 23 +- .../Wrapper/MsBuildWrapper/ProjectWrapper.cs | 27 +- .../Frameworks/WrappedNuGetFramework.cs | 9 +- .../NuGetWrapper/NugetWrapperException.cs | 6 +- .../Core/PackagesConfigReaderException.cs | 5 +- .../Core/WrappedPackageDependency.cs | 8 +- .../AssetsPackageDependencyReader.cs | 2 +- .../ProjectModel/WrappedLibraryDependency.cs | 10 +- .../ProjectModel/WrappedLockFile.cs | 19 +- .../ProjectModel/WrappedLockFileLibrary.cs | 15 +- .../ProjectModel/WrappedLockFileTarget.cs | 13 +- .../ProjectModel/WrappedPackageSpec.cs | 13 +- .../WrappedTargetFrameworkInformation.cs | 15 +- .../CachingDisposableSourceRepository.cs | 18 +- .../Types/CachingPackageMetadataResource.cs | 47 ++-- .../Protocol/GlobalPackagesFolderUtility.cs | 9 +- .../LicenseAugmentedPackageMetadata.cs | 2 +- .../Protocol/WrappedPackageMetadata.cs | 34 +-- ...pper.cs => ISolutionPersistenceWrapper.cs} | 2 +- ...apper.cs => SolutionPersistenceWrapper.cs} | 2 +- .../Combine/LicenseMatcherTest.cs | 10 +- .../SPDX/LicenseMatcherTest.cs | 25 +- .../LicenseValidationOrchestratorTest.cs | 33 ++- .../Output/Csv/CsvOutputFormatterTests.cs | 16 +- .../Output/Helper/NuGetVersion.cs | 11 +- .../Output/Json/JsonOutputFormatterTest.cs | 20 +- .../Table/MarkdownTableOutputFormatterTest.cs | 17 +- .../Output/Table/TableOutputFormatterTest.cs | 17 +- .../AsyncEnumerable.cs | 13 +- .../AsyncEnumerator.cs | 15 +- .../NuGet/Versioning/NuGetVersionBuilder.cs | 13 +- .../Architecture/ArchitectureTest.cs | 8 +- .../Architecture/ConditionsExtensions.cs | 2 +- .../Extensions/HashSetExtensionsTest.cs | 13 +- .../Extensions/ProjectExtensionsTest.cs | 21 +- .../PackageInformationReaderTest.cs | 2 +- .../ProjectFiltering/ProjectFiltererTest.cs | 44 ++-- .../ProjectsCollectorTest.cs | 36 +-- .../ReferencedPackageReaderTest.cs | 18 +- 62 files changed, 562 insertions(+), 984 deletions(-) rename src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/{ISolutionPersistanceWrapper.cs => ISolutionPersistenceWrapper.cs} (85%) rename src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/{SolutionPersistanceWrapper.cs => SolutionPersistenceWrapper.cs} (93%) diff --git a/src/FileLicenseMatcher/Combine/LicenseMatcher.cs b/src/FileLicenseMatcher/Combine/LicenseMatcher.cs index d4496393..e7063f96 100644 --- a/src/FileLicenseMatcher/Combine/LicenseMatcher.cs +++ b/src/FileLicenseMatcher/Combine/LicenseMatcher.cs @@ -5,14 +5,9 @@ namespace FileLicenseMatcher.Combine { - public class LicenseMatcher : IFileLicenseMatcher + public class LicenseMatcher(IReadOnlyList matchers) : IFileLicenseMatcher { - private readonly IReadOnlyCollection _matchers; - - public LicenseMatcher(IReadOnlyList matchers) - { - _matchers = matchers; - } + private readonly IReadOnlyCollection _matchers = matchers; public string Match(string licenseText) { diff --git a/src/FileLicenseMatcher/Compare/LicenseMatcher.cs b/src/FileLicenseMatcher/Compare/LicenseMatcher.cs index 9428de5d..d94e4896 100644 --- a/src/FileLicenseMatcher/Compare/LicenseMatcher.cs +++ b/src/FileLicenseMatcher/Compare/LicenseMatcher.cs @@ -8,27 +8,19 @@ namespace FileLicenseMatcher.Compare { - public class LicenseMatcher : IFileLicenseMatcher + public class LicenseMatcher(IFileSystem fileSystem, IDictionary fileLicenseMap) + : IFileLicenseMatcher { - private readonly IFileSystem _fileSystem; - private readonly IDictionary _fileLicenseMap; - - public LicenseMatcher(IFileSystem fileSystem, IDictionary fileLicenseMap) - { - _fileSystem = fileSystem; - _fileLicenseMap = fileLicenseMap; - } - public string Match(string licenseText) { string[] licenseContent = licenseText.Split(Array.Empty(), StringSplitOptions.RemoveEmptyEntries); - foreach (KeyValuePair kvp in _fileLicenseMap) + foreach (KeyValuePair kvp in fileLicenseMap) { - if (!_fileSystem.File.Exists(kvp.Key)) + if (!fileSystem.File.Exists(kvp.Key)) { continue; } - IEnumerable fileContent = _fileSystem.File.ReadAllText(kvp.Key).Split(Array.Empty(), StringSplitOptions.RemoveEmptyEntries); + IEnumerable fileContent = fileSystem.File.ReadAllText(kvp.Key).Split(Array.Empty(), StringSplitOptions.RemoveEmptyEntries); if (licenseContent.SequenceEqual(fileContent)) { return kvp.Value; diff --git a/src/FileLicenseMatcher/SPDX/FastLicenseMatcher.cs b/src/FileLicenseMatcher/SPDX/FastLicenseMatcher.cs index dcd91099..78609de0 100644 --- a/src/FileLicenseMatcher/SPDX/FastLicenseMatcher.cs +++ b/src/FileLicenseMatcher/SPDX/FastLicenseMatcher.cs @@ -25,11 +25,11 @@ public class FastLicenseMatcher : IFileLicenseMatcher private const string START_COMMENT_CHAR_PATTERN = "(//|/\\*|\\*|#|' |REM ||-}|\\*\\)|\\s\\*)\\s*$", RegexOptions.Compiled); - private static readonly Regex START_COMMENT_PATTERN = new Regex("^\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); - private static readonly Regex BEGIN_OPTIONAL_COMMENT_PATTERN = new Regex("^\\s*<>\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); + private static readonly Regex RULE_PATTERN = new(START_RULE + "\\s*(beginOptional|endOptional|var)", RegexOptions.Compiled); + private static readonly Regex END_RULE_PATTERN = new(END_RULE, RegexOptions.Compiled); + private static readonly Regex END_COMMENT_PATTERN = new("(\\*/|-->|-}|\\*\\)|\\s\\*)\\s*$", RegexOptions.Compiled); + private static readonly Regex START_COMMENT_PATTERN = new("^\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); + private static readonly Regex BEGIN_OPTIONAL_COMMENT_PATTERN = new("^\\s*<>\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); #pragma warning restore IDE1006 private readonly IImmutableDictionary _templateInstructions; @@ -94,7 +94,7 @@ private static ParseInstruction ParseTemplate(ILicense license) end = endMatch.Index + endMatch.Length; string ruleString = licenseTemplate.Substring(ruleMatches.Current.Index + START_RULE.Length, end - END_RULE.Length - ruleMatches.Current.Index - START_RULE.Length); - LicenseTemplateRule rule = new LicenseTemplateRule(ruleString); + LicenseTemplateRule rule = new(ruleString); if (rule.Type == LicenseTemplateRule.RuleType.VARIABLE) { instructionStack.Peek().addSubInstruction(new ParseInstruction(rule, null)); @@ -116,7 +116,7 @@ private static ParseInstruction ParseTemplate(ILicense license) else { throw new LicenseTemplateRuleException( - "Unrecognized rule: " + rule.Type.ToString() + " after text '" + upToTheFind + "'"); + "Unrecognized rule: " + rule.Type + " after text '" + upToTheFind + "'"); } } if (instructionStack.Count > 1) @@ -147,7 +147,7 @@ private static string removeCommentChars(string s) { return ""; } - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); using var reader = new StringReader(s); try { diff --git a/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTemplateRule.cs b/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTemplateRule.cs index d7c3a0e3..83e4507c 100644 --- a/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTemplateRule.cs +++ b/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTemplateRule.cs @@ -22,13 +22,13 @@ public class LicenseTemplateRule public enum RuleType { VARIABLE, BEGIN_OPTIONAL, END_OPTIONAL } public RuleType? Type { get; set; } - public string? Original { get; set; } = null; + public string? Original { get; set; } public string? Name { get; set; } - public string? Example { get; set; } = null; - public string? Match { get; set; } = null; + public string? Example { get; set; } + public string? Match { get; set; } #pragma warning disable IDE1006 - static readonly Regex SPLIT_REGEX = new Regex("[^\\\\];", RegexOptions.Compiled); + static readonly Regex SPLIT_REGEX = new("[^\\\\];", RegexOptions.Compiled); #pragma warning restore IDE1006 private const string EXAMPLE_KEYWORD = "example"; private const string NAME_KEYWORD = "name"; @@ -144,7 +144,7 @@ public void parseLicenseTemplateRule(string parseableLicenseTemplateRule) string typeStr; if (rulePartMatcher.Count > 0) { - typeStr = parseableLicenseTemplateRule.Substring(start, rulePartMatcher[0].Index + 1 - start).Trim(); + typeStr = parseableLicenseTemplateRule.Substring(start, rulePartMatcher[0].Index + 1).Trim(); start = rulePartMatcher[0].Index + rulePartMatcher[0].Length; } else diff --git a/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTextHelper.cs b/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTextHelper.cs index cdd9a316..5162f867 100644 --- a/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTextHelper.cs +++ b/src/FileLicenseMatcher/SPDX/JavaCore/LicenseTextHelper.cs @@ -24,25 +24,25 @@ public static class LicenseTextHelper { private const string TOKEN_SPLIT_REGEX = "(^|[^\\s.,?'();:\"/\\[\\]<>]{1,100})((\\s|\\.|,|\\?|'|\"|\\(|\\)|;|:|/|\\[|]|<|>|$){1,100})"; - public static readonly Regex TOKEN_SPLIT_PATTERN = new Regex(TOKEN_SPLIT_REGEX, RegexOptions.Compiled); + public static readonly Regex TOKEN_SPLIT_PATTERN = new(TOKEN_SPLIT_REGEX, RegexOptions.Compiled); #pragma warning disable IDE1006 private static readonly ImmutableHashSet PUNCTUATION = [".", ",", "?", "\"", "'", "(", ")", ";", ":", "/", "[", "]", "<", ">"]; // most of these are comments for common programming languages (C style, Java, Ruby, Python) private static readonly ImmutableHashSet SKIPPABLE_TOKENS = ["//", "/*", "*/", "/**", "#", "##", "*", "**", "\"\"\"", "/", "=begin", "=end"]; - static readonly Regex DASHES_REGEX = new Regex("[\\u2010\\u2011\\u2012\\u2013\\u2014\\u2015\\uFE58\\uFF0D\\-]{1,2}", RegexOptions.Compiled); - static readonly Regex SPACE_PATTERN = new Regex("[\\u202F\\u2007\\u2060\\u2009]", RegexOptions.Compiled); - static readonly Regex COMMA_PATTERN = new Regex("[\\uFF0C\\uFE10\\uFE50]"); - static readonly Regex PER_CENT_PATTERN = new Regex("per cent", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_HOLDER_PATTERN = new Regex("copyright holder", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_HOLDERS_PATTERN = new Regex("copyright holders", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_OWNERS_PATTERN = new Regex("copyright owners", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_OWNER_PATTERN = new Regex("copyright owner", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex PER_CENT_PATTERN_LF = new Regex("per\\s{0,100}\\n{1,10}\\s{0,100}cent", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_HOLDERS_PATTERN_LF = new Regex("copyright\\s{0,100}\\n{1,10}\\s{0,100}holders", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_HOLDER_PATTERN_LF = new Regex("copyright\\s{0,100}\\n{1,10}\\s{0,100}holder", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_OWNERS_PATTERN_LF = new Regex("copyright\\s{0,100}\\n{1,10}\\s{0,100}owners", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_OWNER_PATTERN_LF = new Regex("copyright\\s{0,100}\\n{1,10}\\s{0,100}owner", RegexOptions.IgnoreCase | RegexOptions.Compiled); - static readonly Regex COPYRIGHT_SYMBOL_PATTERN = new Regex("\\(c\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex DASHES_REGEX = new("[\\u2010\\u2011\\u2012\\u2013\\u2014\\u2015\\uFE58\\uFF0D\\-]{1,2}", RegexOptions.Compiled); + static readonly Regex SPACE_PATTERN = new("[\\u202F\\u2007\\u2060\\u2009]", RegexOptions.Compiled); + static readonly Regex COMMA_PATTERN = new("[\\uFF0C\\uFE10\\uFE50]"); + static readonly Regex PER_CENT_PATTERN = new("per cent", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_HOLDER_PATTERN = new("copyright holder", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_HOLDERS_PATTERN = new("copyright holders", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_OWNERS_PATTERN = new("copyright owners", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_OWNER_PATTERN = new("copyright owner", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex PER_CENT_PATTERN_LF = new("per\\s{0,100}\\n{1,10}\\s{0,100}cent", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_HOLDERS_PATTERN_LF = new("copyright\\s{0,100}\\n{1,10}\\s{0,100}holders", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_HOLDER_PATTERN_LF = new("copyright\\s{0,100}\\n{1,10}\\s{0,100}holder", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_OWNERS_PATTERN_LF = new("copyright\\s{0,100}\\n{1,10}\\s{0,100}owners", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_OWNER_PATTERN_LF = new("copyright\\s{0,100}\\n{1,10}\\s{0,100}owner", RegexOptions.IgnoreCase | RegexOptions.Compiled); + static readonly Regex COPYRIGHT_SYMBOL_PATTERN = new("\\(c\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled); #pragma warning restore IDE1006 public static readonly IImmutableDictionary NORMALIZE_TOKENS = ImmutableDictionary.CreateRange( [ @@ -96,90 +96,6 @@ public static class LicenseTextHelper ] ); - /** - * Returns true if two sets of license text is considered a match per - * the SPDX License matching guidelines documented at spdx.org (currently license matching guidelines) - * There are 2 unimplemented features - bullets/numbering is not considered and comments with no whitespace between text is not skipped - * @param licenseTextA text to compare - * @param licenseTextB text to compare - * @return true if the license text is equivalent - */ - public static bool isLicenseTextEquivalent(string licenseTextA, string licenseTextB) - { - // Need to take care of multi-word equivalent words - convert to single words with hyphens - - // tokenize each of the strings - if (licenseTextA == null) - { - return string.IsNullOrEmpty(licenseTextB); - } - if (licenseTextB == null) - { - return string.IsNullOrEmpty(licenseTextA); - } - if (licenseTextA.Equals(licenseTextB)) - { - return true; - } - IDictionary tokenToLocationA = new Dictionary(); - IDictionary tokenToLocationB = new Dictionary(); - IReadOnlyList licenseATokens = tokenizeLicenseText(licenseTextA, tokenToLocationA); - IReadOnlyList licenseBTokens = tokenizeLicenseText(licenseTextB, tokenToLocationB); - int bTokenCounter = 0; - int aTokenCounter = 0; - string? nextAToken = getTokenAt(licenseATokens, aTokenCounter++); - string? nextBToken = getTokenAt(licenseBTokens, bTokenCounter++); - while (nextAToken != null) - { - if (nextBToken == null) - { - // end of b stream - while (canSkip(nextAToken)) - { - nextAToken = getTokenAt(licenseATokens, aTokenCounter++); - } - if (nextAToken != null) - { - return false; // there is more stuff in the license text B, so not equal - } - } - else if (tokensEquivalent(nextAToken, nextBToken)) - { - // just move onto the next set of tokens - nextAToken = getTokenAt(licenseATokens, aTokenCounter++); - nextBToken = getTokenAt(licenseBTokens, bTokenCounter++); - } - else - { - // see if we can skip through some B tokens to find a match - while (canSkip(nextBToken)) - { - nextBToken = getTokenAt(licenseBTokens, bTokenCounter++); - } - // just to be sure, skip forward on the A license - while (canSkip(nextAToken)) - { - nextAToken = getTokenAt(licenseATokens, aTokenCounter++); - } - if (!tokensEquivalent(nextAToken, nextBToken)) - { - return false; - } - else - { - nextAToken = getTokenAt(licenseATokens, aTokenCounter++); - nextBToken = getTokenAt(licenseBTokens, bTokenCounter++); - } - } - } - // need to make sure B is at the end - while (canSkip(nextBToken)) - { - nextBToken = getTokenAt(licenseBTokens, bTokenCounter++); - } - return nextBToken == null; - } - /** * Tokenizes the license text, normalizes quotes, lowercases and converts * multi-words for better equiv. comparisons @@ -231,7 +147,7 @@ public static IReadOnlyList tokenizeLicenseText(string licenseText, IDic { // Don't fill in the lines, take a simpler approach MatchCollection m = TOKEN_SPLIT_PATTERN.Matches(textToTokenize); - foreach (GroupCollection groups in m.Cast().Select(m => m.Groups)) + foreach (GroupCollection groups in m.Cast().Select(match => match.Groups)) { string word = groups[1].Value.Trim(); string separator = groups[2].Value.Trim(); @@ -357,9 +273,9 @@ public static string replaceMultWord(string s) * @param s String to normalize * @return String normalized for comparison */ - private static readonly Regex s_singleQuotePattern = new Regex("[‘’‛‚`]", RegexOptions.Compiled); - private static readonly Regex s_doubleQuotePattern = new Regex("[“”‟„]", RegexOptions.Compiled); - private static readonly Regex s_dashPattern = new Regex("[—–]", RegexOptions.Compiled); + private static readonly Regex s_singleQuotePattern = new("[‘’‛‚`]", RegexOptions.Compiled); + private static readonly Regex s_doubleQuotePattern = new("[“”‟„]", RegexOptions.Compiled); + private static readonly Regex s_dashPattern = new("[—–]", RegexOptions.Compiled); public static string normalizeText(string s) { // First normalize single quotes, then normalize two single quotes to a double quote, normalize double quotes @@ -377,7 +293,7 @@ public static string normalizeText(string s) * @param s Input string * @return s without any line separators (---, ***, ===) */ - private static readonly Regex s_removeLineSeparatorsRegex = new Regex("[-=*]{3,}\\s*$", RegexOptions.Compiled); + private static readonly Regex s_removeLineSeparatorsRegex = new("[-=*]{3,}\\s*$", RegexOptions.Compiled); public static string removeLineSeparators(string s) { return s_removeLineSeparatorsRegex.Replace(s, ""); // Remove ----, ***, and ==== diff --git a/src/FileLicenseMatcher/SPDX/JavaCore/SpdxLicenseTemplateHelper.cs b/src/FileLicenseMatcher/SPDX/JavaCore/SpdxLicenseTemplateHelper.cs index 26256845..b96f1076 100644 --- a/src/FileLicenseMatcher/SPDX/JavaCore/SpdxLicenseTemplateHelper.cs +++ b/src/FileLicenseMatcher/SPDX/JavaCore/SpdxLicenseTemplateHelper.cs @@ -21,8 +21,8 @@ public static class SpdxLicenseTemplateHelper { private const string START_RULE = "<<"; private const string END_RULE = ">>"; - public static readonly Regex RULE_PATTERN = new Regex(START_RULE + "\\s*(beginOptional|endOptional|var)", RegexOptions.Compiled); - public static readonly Regex END_RULE_PATTERN = new Regex(END_RULE, RegexOptions.Compiled); + public static readonly Regex RULE_PATTERN = new(START_RULE + "\\s*(beginOptional|endOptional|var)", RegexOptions.Compiled); + public static readonly Regex END_RULE_PATTERN = new(END_RULE, RegexOptions.Compiled); /** * Parses the license template calling the templateOutputHandler for any text @@ -36,13 +36,13 @@ public static class SpdxLicenseTemplateHelper */ public static void parseTemplate(string licenseTemplate, ILicenseTemplateOutputHandler templateOutputHandler) { - IEnumerator ruleMatcher = RULE_PATTERN.Matches(licenseTemplate).Cast().GetEnumerator(); + using IEnumerator ruleMatcher = RULE_PATTERN.Matches(licenseTemplate).Cast().GetEnumerator(); int end = 0; int optionalNestLevel = 0; while (ruleMatcher.MoveNext()) { // copy everything up to the start of the find - string upToTheFind = licenseTemplate.Substring(end, ruleMatcher.Current.Index - end); + string upToTheFind = licenseTemplate.Substring(end, ruleMatcher.Current!.Index - end); if (!string.IsNullOrWhiteSpace(upToTheFind)) { templateOutputHandler.text(upToTheFind); @@ -55,7 +55,7 @@ public static void parseTemplate(string licenseTemplate, ILicenseTemplateOutputH end = endMatch.Index + endMatch.Length; string ruleString = licenseTemplate.Substring(ruleMatcher.Current.Index + START_RULE.Length, end - END_RULE.Length - ruleMatcher.Current.Index - START_RULE.Length); - LicenseTemplateRule rule = new LicenseTemplateRule(ruleString); + LicenseTemplateRule rule = new(ruleString); if (rule.Type == LicenseTemplateRule.RuleType.VARIABLE) { templateOutputHandler.variableRule(rule); @@ -78,7 +78,7 @@ public static void parseTemplate(string licenseTemplate, ILicenseTemplateOutputH else { throw new LicenseTemplateRuleException( - "Unrecognized rule: " + rule.Type.ToString() + " after text '" + upToTheFind + "'"); + "Unrecognized rule: " + rule.Type + " after text '" + upToTheFind + "'"); } } if (optionalNestLevel > 0) diff --git a/src/FileLicenseMatcher/SPDX/JavaLibrary/CompareTemplateOutputHandler.cs b/src/FileLicenseMatcher/SPDX/JavaLibrary/CompareTemplateOutputHandler.cs index 3363ae4b..095c6f86 100644 --- a/src/FileLicenseMatcher/SPDX/JavaLibrary/CompareTemplateOutputHandler.cs +++ b/src/FileLicenseMatcher/SPDX/JavaLibrary/CompareTemplateOutputHandler.cs @@ -35,10 +35,10 @@ public class CompareTemplateOutputHandler : ILicenseTemplateOutputHandler private readonly IReadOnlyList _compareTokens; private readonly string _compareText; private readonly IDictionary _tokenToLocation = new Dictionary(); - private readonly ParseInstruction _topLevelInstruction = new ParseInstruction(null, null); - public DifferenceDescription Differences { get; } = new DifferenceDescription(); - private ParseInstruction? _currentOptionalInstruction = null; - private bool _parsingComplete = false; + private readonly ParseInstruction _topLevelInstruction = new(null, null); + public DifferenceDescription Differences { get; } = new(); + private ParseInstruction? _currentOptionalInstruction; + private bool _parsingComplete; /** * Construct a new {@link CompareTemplateOutputHandler} with the specified text to compare @@ -199,7 +199,7 @@ public void variableRule(LicenseTemplateRule rule) */ public void beginOptional(LicenseTemplateRule rule) { - ParseInstruction optionalInstruction = new ParseInstruction(rule, null); + ParseInstruction optionalInstruction = new(rule, null); if (_currentOptionalInstruction != null) { _currentOptionalInstruction.addSubInstruction(optionalInstruction); @@ -257,18 +257,4 @@ public void completeParsing() } _parsingComplete = true; } - - /** - * Compares the text against the compareText - * - * @param text text to compare - * @param startToken token of the compareText to being the comparison - * @return next token index (positive) if there is a match, negative first token where this is a miss-match if no match - */ - public int textEquivalent(string text, int startToken) - { - IDictionary textLocations = new Dictionary(); - IReadOnlyList textTokens = LicenseTextHelper.tokenizeLicenseText(text, textLocations); - return compareText(textTokens, _compareTokens, startToken, null, _compareTokens); - } } diff --git a/src/FileLicenseMatcher/SPDX/JavaLibrary/LicenseCompareHelper.cs b/src/FileLicenseMatcher/SPDX/JavaLibrary/LicenseCompareHelper.cs index 71d7bfdb..8af967ed 100644 --- a/src/FileLicenseMatcher/SPDX/JavaLibrary/LicenseCompareHelper.cs +++ b/src/FileLicenseMatcher/SPDX/JavaLibrary/LicenseCompareHelper.cs @@ -17,9 +17,9 @@ internal static class LicenseCompareHelper private const string START_COMMENT_CHAR_PATTERN = "(//|/\\*|\\*|#|' |REM ||-}|\\*\\)|\\s\\*)\\s*$", RegexOptions.Compiled); - private static readonly Regex START_COMMENT_PATTERN = new Regex("^\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); - private static readonly Regex BEGIN_OPTIONAL_COMMENT_PATTERN = new Regex("^\\s*<>\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); + private static readonly Regex END_COMMENT_PATTERN = new("(\\*/|-->|-}|\\*\\)|\\s\\*)\\s*$", RegexOptions.Compiled); + private static readonly Regex START_COMMENT_PATTERN = new("^\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); + private static readonly Regex BEGIN_OPTIONAL_COMMENT_PATTERN = new("^\\s*<>\\s*" + START_COMMENT_CHAR_PATTERN, RegexOptions.Compiled); #pragma warning restore IDE1006 #region Additions to optimize matching performance (not available in the original java code) @@ -155,7 +155,7 @@ public static string locateOriginalText(string fullLicenseText, int startToken, if (end == null) { // read until the end of the stream - StringBuilder sb = new StringBuilder(line.Substring(start.Column)); + StringBuilder sb = new(line.Substring(start.Column)); currentLine++; line = reader.ReadLine(); while (line != null) @@ -172,7 +172,7 @@ public static string locateOriginalText(string fullLicenseText, int startToken, } else { - StringBuilder sb = new StringBuilder(line.Substring(start.Column)); + StringBuilder sb = new(line.Substring(start.Column)); currentLine++; line = reader.ReadLine(); while (line != null && currentLine < end.Line) @@ -193,7 +193,7 @@ public static string locateOriginalText(string fullLicenseText, int startToken, catch (IOException) { // just build with spaces - not ideal, but close enough most of the time - StringBuilder sb = new StringBuilder(tokens[startToken]); + StringBuilder sb = new(tokens[startToken]); for (int i = startToken + 1; i <= endToken; i++) { sb.Append(' '); @@ -252,7 +252,7 @@ public static string removeCommentChars(string s) { return ""; } - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); using var reader = new StringReader(s); try { diff --git a/src/FileLicenseMatcher/SPDX/JavaLibrary/ParseInstruction.cs b/src/FileLicenseMatcher/SPDX/JavaLibrary/ParseInstruction.cs index 4dcf9ea1..3365eb74 100644 --- a/src/FileLicenseMatcher/SPDX/JavaLibrary/ParseInstruction.cs +++ b/src/FileLicenseMatcher/SPDX/JavaLibrary/ParseInstruction.cs @@ -215,7 +215,7 @@ public int match(IReadOnlyList matchTokens, int startToken, int endToken // optimization, don't go through the effort to subset the text foreach (ParseInstruction sub in _subInstructions) { - DifferenceDescription optionalDifference = new DifferenceDescription(); + DifferenceDescription optionalDifference = new(); nextToken = sub.match(matchTokens, nextToken, endToken, originalText, optionalDifference, tokenToLocation, compareTokens); if (nextToken < 0) @@ -268,7 +268,7 @@ private int matchOptional(IReadOnlyList matchingStartTokens, { foreach (int matchingStartToken in matchingStartTokens) { - DifferenceDescription matchDifferences = new DifferenceDescription(); + DifferenceDescription matchDifferences = new(); int matchLocation = startToken; foreach (ParseInstruction sub in _subInstructions) { @@ -346,7 +346,7 @@ private IReadOnlyList findNextNonVarTextStartTokens(ParseInstruction afterC // Go through the preceding optional rules. If there is enough token matches, add it to the result list foreach (int optionalSub in leadingOptionalSubInstructions) { - DifferenceDescription tempDiffDescription = new DifferenceDescription(); + DifferenceDescription tempDiffDescription = new(); int nextOptMatchingStart = nextMatchingStart; int optTokenAfterMatch = _subInstructions[optionalSub].match(matchTokens, nextOptMatchingStart, endToken, originalText, tempDiffDescription, tokenToLocation, true, compareTokens); while (optTokenAfterMatch <= nextOptMatchingStart && -optTokenAfterMatch <= endToken @@ -417,7 +417,7 @@ private IReadOnlyList findNextNonVarTextStartTokens(ParseInstruction afterC else { // Not enough text tokens, we need to make sure everything matches beyond this point - DifferenceDescription tempDiffDescription = new DifferenceDescription(); + DifferenceDescription tempDiffDescription = new(); int nextCheckToken = _subInstructions[firstNormalTextIndex].match(matchTokens, nextMatchingStart, endToken, originalText, tempDiffDescription, tokenToLocation, true, compareTokens); int nextCheckSubInstruction = firstNormalTextIndex + 1; while (nextCheckToken > 0 && diff --git a/src/NuGetLicense/CommandLineOptionsParser.cs b/src/NuGetLicense/CommandLineOptionsParser.cs index 5c591080..b3a3756a 100644 --- a/src/NuGetLicense/CommandLineOptionsParser.cs +++ b/src/NuGetLicense/CommandLineOptionsParser.cs @@ -21,17 +21,8 @@ namespace NuGetLicense /// /// Parses and transforms command line options into the format required by the license validation orchestrator. /// - public class CommandLineOptionsParser : ICommandLineOptionsParser + public class CommandLineOptionsParser(IFileSystem fileSystem, HttpClient httpClient) : ICommandLineOptionsParser { - private readonly IFileSystem _fileSystem; - private readonly HttpClient _httpClient; - - public CommandLineOptionsParser(IFileSystem fileSystem, HttpClient httpClient) - { - _fileSystem = fileSystem; - _httpClient = httpClient; - } - public string[] GetInputFiles(string? inputFile, string? inputJsonFile) { if (inputFile is not null) @@ -41,7 +32,7 @@ public string[] GetInputFiles(string? inputFile, string? inputJsonFile) if (inputJsonFile is not null) { - return JsonSerializer.Deserialize(_fileSystem.File.ReadAllText(inputJsonFile))!; + return JsonSerializer.Deserialize(fileSystem.File.ReadAllText(inputJsonFile))!; } // Defensive check: validation should already be done at command line parsing level, @@ -71,7 +62,7 @@ public IImmutableDictionary GetLicenseMappings(string? licenseMappi return UrlToLicenseMapping.Default; } - Dictionary userDictionary = JsonSerializer.Deserialize>(_fileSystem.File.ReadAllText(licenseMapping))!; + Dictionary userDictionary = JsonSerializer.Deserialize>(fileSystem.File.ReadAllText(licenseMapping))!; return UrlToLicenseMapping.Default.SetItems(userDictionary); } @@ -80,12 +71,12 @@ public CustomPackageInformation[] GetOverridePackageInformation(string? override { if (overridePackageInformation is null) { - return Array.Empty(); + return []; } try { - string fileContent = _fileSystem.File.ReadAllText(overridePackageInformation); + string fileContent = fileSystem.File.ReadAllText(overridePackageInformation); var serializerOptions = new JsonSerializerOptions(); serializerOptions.Converters.Add(new NuGetVersionJsonConverter()); CustomPackageInformation[]? result = JsonSerializer.Deserialize(fileContent, serializerOptions); @@ -105,12 +96,12 @@ public IFileLicenseMatcher GetLicenseMatcher(string? licenseFileMappings) return spdxLicenseMatcher; } - string containingDirectory = _fileSystem.Path.GetDirectoryName(_fileSystem.Path.GetFullPath(licenseFileMappings))!; - Dictionary rawMappings = JsonSerializer.Deserialize>(_fileSystem.File.ReadAllText(licenseFileMappings))!; - var fullPathMappings = rawMappings.ToDictionary(kvp => _fileSystem.Path.GetFullPath(_fileSystem.Path.Combine(containingDirectory, kvp.Key)), kvp => kvp.Value); + string containingDirectory = fileSystem.Path.GetDirectoryName(fileSystem.Path.GetFullPath(licenseFileMappings))!; + Dictionary rawMappings = JsonSerializer.Deserialize>(fileSystem.File.ReadAllText(licenseFileMappings))!; + var fullPathMappings = rawMappings.ToDictionary(kvp => fileSystem.Path.GetFullPath(fileSystem.Path.Combine(containingDirectory, kvp.Key)), kvp => kvp.Value); return new FileLicenseMatcher.Combine.LicenseMatcher([ - new FileLicenseMatcher.Compare.LicenseMatcher(_fileSystem, fullPathMappings), + new FileLicenseMatcher.Compare.LicenseMatcher(fileSystem, fullPathMappings), spdxLicenseMatcher ]); } @@ -122,12 +113,12 @@ public IFileDownloader GetFileDownloader(string? downloadLicenseInformation) return new NopFileDownloader(); } - if (!_fileSystem.Directory.Exists(downloadLicenseInformation)) + if (!fileSystem.Directory.Exists(downloadLicenseInformation)) { - _fileSystem.Directory.CreateDirectory(downloadLicenseInformation); + fileSystem.Directory.CreateDirectory(downloadLicenseInformation); } - return new FileDownloader(_httpClient, downloadLicenseInformation); + return new FileDownloader(httpClient, downloadLicenseInformation); } public IOutputFormatter GetOutputFormatter(OutputType outputType, bool returnErrorsOnly, bool includeIgnoredPackages) @@ -147,15 +138,15 @@ private string[] ParseStringArrayOrFile(string? value) { if (value is null) { - return Array.Empty(); + return []; } // Check if the value is a path to an existing file - if (_fileSystem.File.Exists(value)) + if (fileSystem.File.Exists(value)) { try { - string fileContent = _fileSystem.File.ReadAllText(value); + string fileContent = fileSystem.File.ReadAllText(value); string[]? result = JsonSerializer.Deserialize(fileContent); return result ?? throw new ArgumentException($"File '{value}' contains invalid JSON: expected an array of strings but got null."); } diff --git a/src/NuGetLicense/LicenseValidationOrchestrator.cs b/src/NuGetLicense/LicenseValidationOrchestrator.cs index 6c3ef79e..d0351a32 100644 --- a/src/NuGetLicense/LicenseValidationOrchestrator.cs +++ b/src/NuGetLicense/LicenseValidationOrchestrator.cs @@ -24,62 +24,48 @@ namespace NuGetLicense /// /// Orchestrates the license validation process. /// - public class LicenseValidationOrchestrator : ILicenseValidationOrchestrator + public class LicenseValidationOrchestrator(IFileSystem fileSystem, + ISolutionPersistenceWrapper solutionPersistence, + IMsBuildAbstraction msBuild, + IPackagesConfigReader packagesConfigReader, + ICommandLineOptionsParser optionsParser, + Stream outputStream, + Stream errorStream) + : ILicenseValidationOrchestrator { - private readonly IFileSystem _fileSystem; - private readonly ISolutionPersistanceWrapper _solutionPersistance; - private readonly IMsBuildAbstraction _msBuild; - private readonly IPackagesConfigReader _packagesConfigReader; - private readonly ICommandLineOptionsParser _optionsParser; - private readonly Stream _outputStream; - private readonly Stream _errorStream; - - public LicenseValidationOrchestrator( - IFileSystem fileSystem, - ISolutionPersistanceWrapper solutionPersistance, - IMsBuildAbstraction msBuild, - IPackagesConfigReader packagesConfigReader, - ICommandLineOptionsParser optionsParser, - Stream outputStream, - Stream errorStream) - { - _fileSystem = fileSystem; - _solutionPersistance = solutionPersistance; - _msBuild = msBuild; - _packagesConfigReader = packagesConfigReader; - _optionsParser = optionsParser; - _outputStream = outputStream; - _errorStream = errorStream; - } - public async Task ValidateAsync(ICommandLineOptions options, CancellationToken cancellationToken = default) { - string[] inputFiles = _optionsParser.GetInputFiles(options.InputFile, options.InputJsonFile); - string[] ignoredPackagesArray = _optionsParser.GetIgnoredPackages(options.IgnoredPackages); - IImmutableDictionary licenseMappings = _optionsParser.GetLicenseMappings(options.LicenseMapping); - string[] allowedLicensesArray = _optionsParser.GetAllowedLicenses(options.AllowedLicenses); - CustomPackageInformation[] overridePackageInformationArray = _optionsParser.GetOverridePackageInformation(options.OverridePackageInformation); - IFileDownloader licenseDownloader = _optionsParser.GetFileDownloader(options.DownloadLicenseInformation); - IOutputFormatter output = _optionsParser.GetOutputFormatter(options.OutputType, options.ReturnErrorsOnly, options.IncludeIgnoredPackages); - - var projectCollector = new ProjectsCollector(_solutionPersistance, _fileSystem); - var projectReader = new ReferencedPackageReader( - _msBuild, - new LockFileFactory(), - new NuGetFrameworkUtility(), - new AssetsPackageDependencyReader(new NuGetFrameworkUtility()), - _packagesConfigReader); + string[] inputFiles = optionsParser.GetInputFiles(options.InputFile, options.InputJsonFile); + string[] ignoredPackagesArray = optionsParser.GetIgnoredPackages(options.IgnoredPackages); + IImmutableDictionary licenseMappings = optionsParser.GetLicenseMappings(options.LicenseMapping); + string[] allowedLicensesArray = optionsParser.GetAllowedLicenses(options.AllowedLicenses); + CustomPackageInformation[] overridePackageInformationArray = optionsParser.GetOverridePackageInformation(options.OverridePackageInformation); + IFileDownloader licenseDownloader = optionsParser.GetFileDownloader(options.DownloadLicenseInformation); + IOutputFormatter output = optionsParser.GetOutputFormatter(options.OutputType, options.ReturnErrorsOnly, options.IncludeIgnoredPackages); + + var projectCollector = new ProjectsCollector(solutionPersistence, fileSystem); + var projectReader = new ReferencedPackageReader(msBuild, + new LockFileFactory(), + new NuGetFrameworkUtility(), + new AssetsPackageDependencyReader(new NuGetFrameworkUtility()), + packagesConfigReader); var validator = new LicenseValidator.LicenseValidator(licenseMappings, - allowedLicensesArray, - licenseDownloader, - _optionsParser.GetLicenseMatcher(options.LicenseFileMappings), - ignoredPackagesArray); - - string[] excludedProjectsArray = _optionsParser.GetExcludedProjects(options.ExcludedProjects); - IEnumerable projects = (await inputFiles.SelectManyAsync(projectCollector.GetProjectsAsync)).Where(p => !Array.Exists(excludedProjectsArray, ignored => p.PathLike(ignored))); - IEnumerable packagesForProject = GetPackagesPerProject(projects, projectReader, options.IncludeTransitive, options.TargetFramework, options.ExcludePublishFalse, options.IncludeSharedProjects, out IReadOnlyCollection projectReaderExceptions); + allowedLicensesArray, + licenseDownloader, + optionsParser.GetLicenseMatcher(options.LicenseFileMappings), + ignoredPackagesArray); + + string[] excludedProjectsArray = optionsParser.GetExcludedProjects(options.ExcludedProjects); + IEnumerable projects = (await inputFiles.SelectManyAsync(projectCollector.GetProjectsAsync)).Where(p => !Array.Exists(excludedProjectsArray, p.PathLike)); + IEnumerable packagesForProject = GetPackagesPerProject(projects, + projectReader, + options.IncludeTransitive, + options.TargetFramework, + options.ExcludePublishFalse, + options.IncludeSharedProjects, + out IReadOnlyCollection projectReaderExceptions); IAsyncEnumerable downloadedLicenseInformation = - packagesForProject.SelectMany(p => GetPackageInformations(p, overridePackageInformationArray, cancellationToken)); + packagesForProject.SelectMany(p => GetPackageInformation(p, overridePackageInformationArray, cancellationToken)); var results = (await validator.Validate(downloadedLicenseInformation, cancellationToken)).ToList(); if (projectReaderExceptions.Count > 0) @@ -91,19 +77,19 @@ public async Task ValidateAsync(ICommandLineOptions options, CancellationTo try { - Stream outputStream = GetOutputStream(options.DestinationFile); + Stream os = GetOutputStream(options.DestinationFile); bool shouldDisposeStream = options.DestinationFile != null; try { - await output.Write(outputStream, results.OrderBy(r => r.PackageId).ThenBy(r => r.PackageVersion).ToList()); + await output.Write(os, results.OrderBy(r => r.PackageId).ThenBy(r => r.PackageVersion).ToList()); return results.Count(r => r.ValidationErrors.Any()); } finally { if (shouldDisposeStream) { - outputStream.Dispose(); + await os.DisposeAsync(); } } } @@ -118,17 +104,17 @@ private Stream GetOutputStream(string? destinationFile) { if (destinationFile is null) { - return _outputStream; + return outputStream; } - string fullPath = _fileSystem.Path.GetFullPath(destinationFile); - string? directoryName = _fileSystem.Path.GetDirectoryName(fullPath); - if (directoryName != null && !_fileSystem.Directory.Exists(directoryName)) + string fullPath = fileSystem.Path.GetFullPath(destinationFile); + string? directoryName = fileSystem.Path.GetDirectoryName(fullPath); + if (directoryName != null && !fileSystem.Directory.Exists(directoryName)) { - _fileSystem.Directory.CreateDirectory(directoryName); + fileSystem.Directory.CreateDirectory(directoryName); } - return _fileSystem.File.Open(fullPath, FileMode.Create, FileAccess.Write, FileShare.None); + return fileSystem.File.Open(fullPath, FileMode.Create, FileAccess.Write, FileShare.None); } private async Task WriteValidationExceptions(IReadOnlyCollection validationExceptions) @@ -142,24 +128,23 @@ private async Task WriteValidationExceptions(IReadOnlyCollection vali private async Task WriteToErrorStreamAsync(string message) { byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(message + Environment.NewLine); - await _errorStream.WriteAsync(messageBytes, 0, messageBytes.Length); - await _errorStream.FlushAsync(); + await errorStream.WriteAsync(messageBytes, 0, messageBytes.Length); + await errorStream.FlushAsync(); } - private static IReadOnlyCollection GetPackagesPerProject( - IEnumerable projects, - ReferencedPackageReader reader, - bool includeTransitive, - string? targetFramework, - bool excludePublishFalse, - bool includeSharedProjects, - out IReadOnlyCollection exceptions) + private static IReadOnlyCollection GetPackagesPerProject(IEnumerable projects, + ReferencedPackageReader reader, + bool includeTransitive, + string? targetFramework, + bool excludePublishFalse, + bool includeSharedProjects, + out IReadOnlyCollection exceptions) { var encounteredExceptions = new List(); var result = new List(); exceptions = encounteredExceptions; - ProjectFilter filter = new ProjectFilter(); + ProjectFilter filter = new(); foreach (string project in filter.FilterProjects(projects, includeSharedProjects)) { try @@ -176,10 +161,9 @@ private static IReadOnlyCollection GetPackagesPer return result; } - private static async IAsyncEnumerable GetPackageInformations( - ProjectWithReferencedPackages projectWithReferences, - IEnumerable overridePackageInformation, - [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellation) + private static async IAsyncEnumerable GetPackageInformation(ProjectWithReferencedPackages projectWithReferences, + IEnumerable overridePackageInformation, + [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellation) { ISettings settings = Settings.LoadDefaultSettings(projectWithReferences.Project); var sourceProvider = new PackageSourceProvider(settings); @@ -188,7 +172,9 @@ private static async IAsyncEnumerable GetPackageIn var globalPackagesFolderUtility = new GlobalPackagesFolderUtility(settings); var informationReader = new PackageInformationReader(sourceRepositoryProvider, globalPackagesFolderUtility, overridePackageInformation); - await foreach (ReferencedPackageWithContext package in informationReader.GetPackageInfo(new ProjectWithReferencedPackages(projectWithReferences.Project, projectWithReferences.ReferencedPackages), cancellation)) + await foreach (ReferencedPackageWithContext package in informationReader.GetPackageInfo(new ProjectWithReferencedPackages(projectWithReferences.Project, + projectWithReferences.ReferencedPackages), + cancellation)) { yield return package; } diff --git a/src/NuGetLicense/LicenseValidator/LicenseDownloadException.cs b/src/NuGetLicense/LicenseValidator/LicenseDownloadException.cs index 1602474c..10cdfd50 100644 --- a/src/NuGetLicense/LicenseValidator/LicenseDownloadException.cs +++ b/src/NuGetLicense/LicenseValidator/LicenseDownloadException.cs @@ -5,13 +5,6 @@ namespace NuGetLicense.LicenseValidator { - public class LicenseDownloadException : Exception - { - public LicenseDownloadException(Exception inner, string context, Uri url, PackageIdentity packageInfo) - : - base( - $"Failed to download license for package {packageInfo.Id} ({packageInfo.Version}) from url: {url}.\nContext: {context}", - inner) - { } - } + public class LicenseDownloadException(Exception inner, string context, Uri url, PackageIdentity packageInfo) + : Exception($"Failed to download license for package {packageInfo.Id} ({packageInfo.Version}) from url: {url}.\nContext: {context}", inner); } diff --git a/src/NuGetLicense/LicenseValidator/LicenseValidationResult.cs b/src/NuGetLicense/LicenseValidator/LicenseValidationResult.cs index 2b2b19c0..a2744c2c 100644 --- a/src/NuGetLicense/LicenseValidator/LicenseValidationResult.cs +++ b/src/NuGetLicense/LicenseValidator/LicenseValidationResult.cs @@ -17,7 +17,7 @@ public record LicenseValidationResult(string PackageId, LicenseInformationOrigin LicenseInformationOrigin, List? ValidationErrors = null) { - public List ValidationErrors { get; } = ValidationErrors ?? new List(); + public List ValidationErrors { get; } = ValidationErrors ?? []; public string? License { get; set; } = License; public string? LicenseUrl { get; set; } = LicenseUrl; diff --git a/src/NuGetLicense/LicenseValidator/LicenseValidator.cs b/src/NuGetLicense/LicenseValidator/LicenseValidator.cs index 887796d0..73aa5a4c 100644 --- a/src/NuGetLicense/LicenseValidator/LicenseValidator.cs +++ b/src/NuGetLicense/LicenseValidator/LicenseValidator.cs @@ -14,33 +14,17 @@ namespace NuGetLicense.LicenseValidator { - public class LicenseValidator + public class LicenseValidator(IImmutableDictionary licenseMapping, + IEnumerable allowedLicenses, + IFileDownloader fileDownloader, + IFileLicenseMatcher fileLicenseMatcher, + string[] ignoredPackages) { - private readonly IEnumerable _allowedLicenses; - private readonly IFileDownloader _fileDownloader; - private readonly IFileLicenseMatcher _fileLicenseMatcher; - private readonly string[] _ignoredPackages; - private readonly IImmutableDictionary _licenseMapping; - - public LicenseValidator(IImmutableDictionary licenseMapping, - IEnumerable allowedLicenses, - IFileDownloader fileDownloader, - IFileLicenseMatcher fileLicenseMatcher, - string[] ignoredPackages) - { - _licenseMapping = licenseMapping; - _allowedLicenses = allowedLicenses; - _fileDownloader = fileDownloader; - _fileLicenseMatcher = fileLicenseMatcher; - _ignoredPackages = ignoredPackages; - } - - public async Task> Validate( - IAsyncEnumerable packages, - CancellationToken token) + public async Task> Validate(IAsyncEnumerable packages, + CancellationToken token) { var result = new ConcurrentDictionary(); - await foreach (ReferencedPackageWithContext info in packages) + await foreach (ReferencedPackageWithContext info in packages.WithCancellation(token)) { if (IsIgnoredPackage(info.PackageInfo.Identity)) { @@ -69,57 +53,53 @@ public async Task> Validate( private bool IsIgnoredPackage(PackageIdentity identity) { - return Array.Exists(_ignoredPackages, ignored => identity.Id.Like(ignored)); + return Array.Exists(ignoredPackages, ignored => identity.Id.Like(ignored)); } - private static void AddOrUpdateLicense( - ConcurrentDictionary result, - IPackageMetadata info, - LicenseInformationOrigin origin, - ValidationError error, - string? license = null) + private static void AddOrUpdateLicense(ConcurrentDictionary result, + IPackageMetadata info, + LicenseInformationOrigin origin, + ValidationError error, + string? license = null) { - var newValue = new LicenseValidationResult( - info.Identity.Id, - info.Identity.Version, - info.ProjectUrl?.ToString(), - license, - info.LicenseUrl?.AbsoluteUri, - info.Copyright, - info.Authors, - info.Description, - info.Summary, - origin, - new List { error }); + var newValue = new LicenseValidationResult(info.Identity.Id, + info.Identity.Version, + info.ProjectUrl, + license, + info.LicenseUrl?.AbsoluteUri, + info.Copyright, + info.Authors, + info.Description, + info.Summary, + origin, + [error]); result.AddOrUpdate(new LicenseNameAndVersion(info.Identity.Id, info.Identity.Version), - newValue, - (key, oldValue) => UpdateResult(oldValue, newValue)); + newValue, + (key, oldValue) => UpdateResult(oldValue, newValue)); } - private static void AddOrUpdateLicense( - ConcurrentDictionary result, - IPackageMetadata info, - LicenseInformationOrigin origin, - string? license = null) + private static void AddOrUpdateLicense(ConcurrentDictionary result, + IPackageMetadata info, + LicenseInformationOrigin origin, + string? license = null) { - var newValue = new LicenseValidationResult( - info.Identity.Id, - info.Identity.Version, - info.ProjectUrl?.ToString(), - license, - info.LicenseUrl?.AbsoluteUri, - info.Copyright, - info.Authors, - info.Description, - info.Summary, - origin); + var newValue = new LicenseValidationResult(info.Identity.Id, + info.Identity.Version, + info.ProjectUrl, + license, + info.LicenseUrl?.AbsoluteUri, + info.Copyright, + info.Authors, + info.Description, + info.Summary, + origin); result.AddOrUpdate(new LicenseNameAndVersion(info.Identity.Id, info.Identity.Version), - newValue, - (key, oldValue) => UpdateResult(oldValue, newValue)); + newValue, + (key, oldValue) => UpdateResult(oldValue, newValue)); } private static LicenseValidationResult UpdateResult(LicenseValidationResult oldValue, - LicenseValidationResult newValue) + LicenseValidationResult newValue) { oldValue.ValidationErrors.AddRange(newValue.ValidationErrors); if (oldValue.License is null && newValue.License is not null) @@ -131,9 +111,9 @@ private static LicenseValidationResult UpdateResult(LicenseValidationResult oldV } private async Task ValidateLicenseByMetadataAsync(IPackageMetadata info, - string context, - ConcurrentDictionary result, - CancellationToken token) + string context, + ConcurrentDictionary result, + CancellationToken token) { switch (info.LicenseMetadata!.Type) { @@ -146,61 +126,60 @@ private async Task ValidateLicenseByMetadataAsync(IPackageMetadata info, { await DownloadLicenseAsync(GetLicenseUrl(licenseId), info.Identity, context, token); AddOrUpdateLicense(result, - info, - ToLicenseOrigin(info.LicenseMetadata.Type), - info.LicenseMetadata.License); + info, + ToLicenseOrigin(info.LicenseMetadata.Type), + info.LicenseMetadata.License); } else { AddOrUpdateLicense(result, - info, - ToLicenseOrigin(info.LicenseMetadata.Type), - new ValidationError(GetLicenseNotAllowedMessage(info.LicenseMetadata.License), context), - info.LicenseMetadata.License); + info, + ToLicenseOrigin(info.LicenseMetadata.Type), + new ValidationError(GetLicenseNotAllowedMessage(info.LicenseMetadata.License), context), + info.LicenseMetadata.License); } break; } case LicenseType.File: { - string matchedLicense = _fileLicenseMatcher.Match(info.LicenseMetadata.License); + string matchedLicense = fileLicenseMatcher.Match(info.LicenseMetadata.License); if (string.IsNullOrEmpty(matchedLicense)) { AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.File, - new ValidationError("Unable to determine license from the given license file", context), - info.LicenseMetadata.License); + info, + LicenseInformationOrigin.File, + new ValidationError("Unable to determine license from the given license file", context), + info.LicenseMetadata.License); break; } SpdxExpression? licenseExpression = ParseSpdxExpression(matchedLicense); if (IsValidLicenseExpression(licenseExpression)) { - await StoreLicenseAsync(info.LicenseMetadata.License, info.Identity, token); + await fileDownloader.StoreFileAsync(info.LicenseMetadata.License, GetFileName(info.Identity), token); AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.File, - matchedLicense); + info, + LicenseInformationOrigin.File, + matchedLicense); } else { AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.File, - new ValidationError(GetLicenseNotAllowedMessage(matchedLicense), context), - info.LicenseMetadata.License); + info, + LicenseInformationOrigin.File, + new ValidationError(GetLicenseNotAllowedMessage(matchedLicense), context), + info.LicenseMetadata.License); } break; } default: { AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.Unknown, - new ValidationError( - $"Validation for licenses of type {info.LicenseMetadata!.Type} not yet supported", - context)); + info, + LicenseInformationOrigin.Unknown, + new ValidationError($"Validation for licenses of type {info.LicenseMetadata!.Type} not yet supported", + context)); break; } } @@ -215,58 +194,56 @@ private async Task ValidateLicenseByMetadataAsync(IPackageMetadata info, }; private async Task ValidateLicenseByUrl(IPackageMetadata info, - string context, - ConcurrentDictionary result, - CancellationToken token) + string context, + ConcurrentDictionary result, + CancellationToken token) { if (info.LicenseUrl!.IsAbsoluteUri) { await DownloadLicenseAsync(info.LicenseUrl, info.Identity, context, token); } - if (_licenseMapping.TryGetValue(info.LicenseUrl, out string? licenseId)) + if (licenseMapping.TryGetValue(info.LicenseUrl, out string? licenseId)) { SpdxExpression? licenseExpression = ParseSpdxExpression(licenseId); if (IsValidLicenseExpression(licenseExpression)) { AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.Url, - licenseId); + info, + LicenseInformationOrigin.Url, + licenseId); } else { AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.Url, - new ValidationError(GetLicenseNotAllowedMessage(licenseId), context), - licenseId); + info, + LicenseInformationOrigin.Url, + new ValidationError(GetLicenseNotAllowedMessage(licenseId), context), + licenseId); } } - else if (!_allowedLicenses.Any()) + else if (!allowedLicenses.Any()) { AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.Url, - info.LicenseUrl.ToString()); + info, + LicenseInformationOrigin.Url, + info.LicenseUrl.ToString()); } else { AddOrUpdateLicense(result, - info, - LicenseInformationOrigin.Url, - new ValidationError($"Cannot determine License type for url {info.LicenseUrl}", context), - info.LicenseUrl.ToString()); + info, + LicenseInformationOrigin.Url, + new ValidationError($"Cannot determine License type for url {info.LicenseUrl}", context), + info.LicenseUrl.ToString()); } } private static Uri FixupLicenseUrl(Uri licenseUrl) { if ((licenseUrl.Host == "github.com" || licenseUrl.Host == "www.github.com") - && licenseUrl.Query == "" - && licenseUrl.Segments.Length >= 5 - && licenseUrl.Segments[3] == "blob/") + && licenseUrl is { Query: "", Segments: [_, _, _, "blob/", _, ..] }) { return new Uri($"{licenseUrl}?raw=true"); } @@ -278,9 +255,7 @@ private async Task DownloadLicenseAsync(Uri licenseUrl, PackageIdentity identity licenseUrl = FixupLicenseUrl(licenseUrl); try { - await _fileDownloader.DownloadFile(licenseUrl, - $"{identity.Id}__{identity.Version}", - token); + await fileDownloader.DownloadFile(licenseUrl, GetFileName(identity), token); } catch (OperationCanceledException) { @@ -292,32 +267,19 @@ await _fileDownloader.DownloadFile(licenseUrl, } } - private async Task StoreLicenseAsync(string licenseText, PackageIdentity identity, CancellationToken token) - { - await _fileDownloader.StoreFileAsync(licenseText, - $"{identity.Id}__{identity.Version}", - token); - } - private bool IsLicenseValid(string licenseId) { - if (!_allowedLicenses.Any()) + if (!allowedLicenses.Any()) { return true; } - return _allowedLicenses.Any(allowedLicense => allowedLicense.Equals(licenseId)); + return allowedLicenses.Any(allowedLicense => allowedLicense.Equals(licenseId)); } - private static string GetLicenseNotAllowedMessage(string license) - { - return $"License \"{license}\" not found in list of supported licenses"; - } + private static string GetLicenseNotAllowedMessage(string license) => $"License \"{license}\" not found in list of supported licenses"; - private static Uri GetLicenseUrl(string spdxIdentifier) - { - return new Uri($"https://licenses.nuget.org/({spdxIdentifier})"); - } + private static Uri GetLicenseUrl(string spdxIdentifier) => new($"https://licenses.nuget.org/({spdxIdentifier})"); private static LicenseInformationOrigin ToLicenseOrigin(LicenseType type) => type switch { @@ -326,6 +288,8 @@ private static Uri GetLicenseUrl(string spdxIdentifier) _ => throw new ArgumentOutOfRangeException(nameof(type), type, $"This conversion method only supports the {nameof(LicenseType.Overwrite)} and {nameof(LicenseType.Expression)} types for conversion") }; + private static string GetFileName(PackageIdentity identity) => $"{identity.Id}__{identity.Version}"; + private static SpdxExpression? ParseSpdxExpression(string expression) => SpdxExpressionParser.Parse(expression, _ => true, _ => true); private sealed record LicenseNameAndVersion(string LicenseName, INuGetVersion Version); diff --git a/src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs b/src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs index e49960ae..fec04a1a 100644 --- a/src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs +++ b/src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs @@ -6,25 +6,16 @@ namespace NuGetLicense.Output.Csv { - public class CsvOutputFormatter : IOutputFormatter + public class CsvOutputFormatter(bool printErrorsOnly, bool skipIgnoredPackages) : IOutputFormatter { - private readonly bool _printErrorsOnly; - private readonly bool _skipIgnoredPackages; - - public CsvOutputFormatter(bool printErrorsOnly, bool skipIgnoredPackages) - { - _printErrorsOnly = printErrorsOnly; - _skipIgnoredPackages = skipIgnoredPackages; - } - public async Task Write(Stream stream, IList results) { - if (_printErrorsOnly) + if (printErrorsOnly) { results = results.Where(r => r.ValidationErrors.Any()).ToList(); } - if (_skipIgnoredPackages) + if (skipIgnoredPackages) { results = results .Where(r => r.LicenseInformationOrigin != LicenseInformationOrigin.Ignored) @@ -38,8 +29,8 @@ await writer.WriteLineAsync( foreach (LicenseValidationResult license in results) { - string[] row = new[] - { + string[] row = + [ EscapeCsvValue(license.PackageId), EscapeCsvValue(license.PackageVersion.ToString()), EscapeCsvValue(license.LicenseInformationOrigin.ToString()), EscapeCsvValue(license.License ?? string.Empty), @@ -48,7 +39,7 @@ await writer.WriteLineAsync( EscapeCsvValue(license.Authors ?? string.Empty), EscapeCsvValue(license.PackageProjectUrl ?? string.Empty), GetValidationErrorsString(license.ValidationErrors) - }; + ]; await writer.WriteLineAsync(string.Join(",", row)); } diff --git a/src/NuGetLicense/Output/Json/JsonOutputFormatter.cs b/src/NuGetLicense/Output/Json/JsonOutputFormatter.cs index a2112698..cac14507 100644 --- a/src/NuGetLicense/Output/Json/JsonOutputFormatter.cs +++ b/src/NuGetLicense/Output/Json/JsonOutputFormatter.cs @@ -8,29 +8,22 @@ namespace NuGetLicense.Output.Json { - public class JsonOutputFormatter : IOutputFormatter + public class JsonOutputFormatter(bool prettyPrint, bool printErrorsOnly, bool skipIgnoredPackages) + : IOutputFormatter { - private readonly bool _printErrorsOnly; - private readonly bool _skipIgnoredPackages; - private readonly JsonSerializerOptions _options; - public JsonOutputFormatter(bool prettyPrint, bool printErrorsOnly, bool skipIgnoredPackages) + private readonly JsonSerializerOptions _options = new() { - _printErrorsOnly = printErrorsOnly; - _skipIgnoredPackages = skipIgnoredPackages; - _options = new JsonSerializerOptions - { - Converters = { new NuGetVersionJsonConverter(), new ValidatedLicenseJsonConverterWithOmittingEmptyErrorList() }, - WriteIndented = prettyPrint - }; - } + Converters = { new NuGetVersionJsonConverter(), new ValidatedLicenseJsonConverterWithOmittingEmptyErrorList() }, + WriteIndented = prettyPrint + }; public async Task Write(Stream stream, IList results) { - if (_printErrorsOnly) + if (printErrorsOnly) { results = results.Where(r => r.ValidationErrors.Any()).ToList(); } - else if (_skipIgnoredPackages) + else if (skipIgnoredPackages) { results = results.Where(r => r.LicenseInformationOrigin != LicenseInformationOrigin.Ignored).ToList(); } diff --git a/src/NuGetLicense/Output/Table/TableOutputFormatter.cs b/src/NuGetLicense/Output/Table/TableOutputFormatter.cs index 68ed8d83..36056073 100644 --- a/src/NuGetLicense/Output/Table/TableOutputFormatter.cs +++ b/src/NuGetLicense/Output/Table/TableOutputFormatter.cs @@ -6,34 +6,24 @@ namespace NuGetLicense.Output.Table { - public class TableOutputFormatter : IOutputFormatter + public class TableOutputFormatter(bool printErrorsOnly, bool skipIgnoredPackages, bool printMarkdown = false) + : IOutputFormatter { - private readonly bool _printErrorsOnly; - private readonly bool _skipIgnoredPackages; - private readonly bool _printMarkdown; - - public TableOutputFormatter(bool printErrorsOnly, bool skipIgnoredPackages, bool printMarkdown = false) - { - _printErrorsOnly = printErrorsOnly; - _skipIgnoredPackages = skipIgnoredPackages; - _printMarkdown = printMarkdown; - } - public async Task Write(Stream stream, IList results) { var errorColumnDefinition = new ColumnDefinition("Error", license => license.ValidationErrors.Select(e => e.Error), license => license.ValidationErrors.Any()); ColumnDefinition[] columnDefinitions = [ - new ColumnDefinition("Package", license => license.PackageId, license => true, true), - new ColumnDefinition("Version", license => license.PackageVersion, license => true, true), - new ColumnDefinition("License Information Origin", license => license.LicenseInformationOrigin, license => true, true), - new ColumnDefinition("License Expression", license => license.License?.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries), license => license.License != null), - new ColumnDefinition("License Url", license => license.LicenseUrl, license => license.LicenseUrl != null), - new ColumnDefinition("Copyright", license => license.Copyright, license => license.Copyright != null), - new ColumnDefinition("Authors", license => license.Authors, license => license.Authors != null), - new ColumnDefinition("Package Project Url",license => license.PackageProjectUrl, license => license.PackageProjectUrl != null), + new("Package", license => license.PackageId, license => true, true), + new("Version", license => license.PackageVersion, license => true, true), + new("License Information Origin", license => license.LicenseInformationOrigin, license => true, true), + new("License Expression", license => license.License?.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries), license => license.License != null), + new("License Url", license => license.LicenseUrl, license => license.LicenseUrl != null), + new("Copyright", license => license.Copyright, license => license.Copyright != null), + new("Authors", license => license.Authors, license => license.Authors != null), + new("Package Project Url",license => license.PackageProjectUrl, license => license.PackageProjectUrl != null), errorColumnDefinition, - new ColumnDefinition("Error Context", license => license.ValidationErrors.Select(e => e.Context), license => license.ValidationErrors.Any()), + new("Error Context", license => license.ValidationErrors.Select(e => e.Context), license => license.ValidationErrors.Any()), ]; foreach (LicenseValidationResult license in results) @@ -44,18 +34,18 @@ public async Task Write(Stream stream, IList results) } } - if (_printErrorsOnly) + if (printErrorsOnly) { results = results.Where(r => r.ValidationErrors.Any()).ToList(); } - else if (_skipIgnoredPackages) + else if (skipIgnoredPackages) { results = results.Where(r => r.LicenseInformationOrigin != LicenseInformationOrigin.Ignored).ToList(); } ColumnDefinition[] relevantColumns = columnDefinitions.Where(c => c.Enabled).ToArray(); await TablePrinterExtensions - .Create(stream, relevantColumns.Select(d => d.Title), _printMarkdown) + .Create(stream, relevantColumns.Select(d => d.Title), printMarkdown) .FromValues( results, license => relevantColumns.Select(d => d.PropertyAccessor(license))) diff --git a/src/NuGetLicense/Program.cs b/src/NuGetLicense/Program.cs index 8e64b0aa..39b024e8 100644 --- a/src/NuGetLicense/Program.cs +++ b/src/NuGetLicense/Program.cs @@ -81,7 +81,7 @@ public async Task OnExecuteAsync(CommandLineApplication app, CancellationTo using var httpClient = new HttpClient(); var fileSystem = new System.IO.Abstractions.FileSystem(); - var solutionPersistance = new SolutionPersistanceWrapper(); + var solutionPersistance = new SolutionPersistenceWrapper(); var msBuild = new MsBuildAbstraction(); IPackagesConfigReader packagesConfigReader = GetPackagesConfigReader(); diff --git a/src/NuGetUtility/Output/Table/TablePrinter.cs b/src/NuGetUtility/Output/Table/TablePrinter.cs index 4739c2f2..77ed7441 100644 --- a/src/NuGetUtility/Output/Table/TablePrinter.cs +++ b/src/NuGetUtility/Output/Table/TablePrinter.cs @@ -11,7 +11,7 @@ namespace NuGetUtility.Output.Table public class TablePrinter { private readonly int[] _lengths; - private readonly List _rows = new(); + private readonly List _rows = []; private readonly Stream _stream; private readonly string[] _titles; private readonly bool _printMarkdown; diff --git a/src/NuGetUtility/PackageInformationReader/PackageInformationReader.cs b/src/NuGetUtility/PackageInformationReader/PackageInformationReader.cs index 16fbbd24..113be2f4 100644 --- a/src/NuGetUtility/PackageInformationReader/PackageInformationReader.cs +++ b/src/NuGetUtility/PackageInformationReader/PackageInformationReader.cs @@ -9,24 +9,14 @@ namespace NuGetUtility.PackageInformationReader { - public class PackageInformationReader + public class PackageInformationReader(IWrappedSourceRepositoryProvider sourceRepositoryProvider, + IGlobalPackagesFolderUtility globalPackagesFolderUtility, + IEnumerable customPackageInformation) { - private readonly IGlobalPackagesFolderUtility _globalPackagesFolderUtility; - private readonly IEnumerable _customPackageInformation; - private readonly ISourceRepository[] _repositories; + private readonly ISourceRepository[] _repositories = sourceRepositoryProvider.GetRepositories(); - public PackageInformationReader(IWrappedSourceRepositoryProvider sourceRepositoryProvider, - IGlobalPackagesFolderUtility globalPackagesFolderUtility, - IEnumerable customPackageInformation) - { - _globalPackagesFolderUtility = globalPackagesFolderUtility; - _customPackageInformation = customPackageInformation; - _repositories = sourceRepositoryProvider.GetRepositories(); - } - - public async IAsyncEnumerable GetPackageInfo( - ProjectWithReferencedPackages projectWithReferencedPackages, - [EnumeratorCancellation] CancellationToken cancellation) + public async IAsyncEnumerable GetPackageInfo(ProjectWithReferencedPackages projectWithReferencedPackages, + [EnumeratorCancellation] CancellationToken cancellation) { foreach (PackageIdentity package in projectWithReferencedPackages.ReferencedPackages) { @@ -54,7 +44,7 @@ public async IAsyncEnumerable GetPackageInfo( } private PackageSearchResult TryGetPackageInformationFromGlobalPackageFolder(PackageIdentity package) { - IPackageMetadata? metadata = _globalPackagesFolderUtility.GetPackage(package); + IPackageMetadata? metadata = globalPackagesFolderUtility.GetPackage(package); if (metadata is not null) { return new PackageSearchResult(metadata); @@ -62,10 +52,9 @@ private PackageSearchResult TryGetPackageInformationFromGlobalPackageFolder(Pack return new PackageSearchResult(); } - private static async Task TryGetPackageInformationFromRepositories( - ISourceRepository[] repositories, - PackageIdentity package, - CancellationToken cancellation) + private static async Task TryGetPackageInformationFromRepositories(ISourceRepository[] repositories, + PackageIdentity package, + CancellationToken cancellation) { foreach (ISourceRepository repository in repositories) { @@ -83,7 +72,8 @@ private static async Task TryGetPackageInformationFromRepos IPackageDownloader? downloader = await TryGetPackageDownloaderAsync(repository, package, cancellation); if (downloader is not null) { - return new PackageSearchResult(new LicenseAugmentedPackageMetadata(updatedPackageMetadata, await downloader.ReadAsync(updatedPackageMetadata.LicenseMetadata.License, cancellation))); + return new PackageSearchResult(new LicenseAugmentedPackageMetadata(updatedPackageMetadata, + await downloader.ReadAsync(updatedPackageMetadata.LicenseMetadata.License, cancellation))); } return new PackageSearchResult(); } @@ -97,7 +87,7 @@ private static async Task TryGetPackageInformationFromRepos private PackageSearchResult TryGetPackageInfoFromCustomInformation(PackageIdentity package) { - CustomPackageInformation resolvedCustomInformation = _customPackageInformation.FirstOrDefault(info => + CustomPackageInformation resolvedCustomInformation = customPackageInformation.FirstOrDefault(info => info.Id.Equals(package.Id) && info.Version.Equals(package.Version)); if (resolvedCustomInformation == default) { diff --git a/src/NuGetUtility/ReferencedPackagesReader/ProjectsCollector.cs b/src/NuGetUtility/ReferencedPackagesReader/ProjectsCollector.cs index f1c00a41..4665765a 100644 --- a/src/NuGetUtility/ReferencedPackagesReader/ProjectsCollector.cs +++ b/src/NuGetUtility/ReferencedPackagesReader/ProjectsCollector.cs @@ -6,22 +6,14 @@ namespace NuGetUtility.ReferencedPackagesReader { - public class ProjectsCollector + public class ProjectsCollector(ISolutionPersistenceWrapper solutionPersistence, IFileSystem fileSystem) { - private readonly ISolutionPersistanceWrapper _solutionPersistance; - private readonly IFileSystem _fileSystem; - - public ProjectsCollector(ISolutionPersistanceWrapper solutionPersistance, IFileSystem fileSystem) - { - _solutionPersistance = solutionPersistance; - _fileSystem = fileSystem; - } - public async Task> GetProjectsAsync(string inputPath) { - return _fileSystem.Path.GetExtension(inputPath).StartsWith(".sln") - ? (await _solutionPersistance.GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(inputPath))).Where(_fileSystem.File.Exists).Select(_fileSystem.Path.GetFullPath) - : [_fileSystem.Path.GetFullPath(inputPath)]; + var extension = Path.GetExtension(inputPath); + return new[] { ".sln", ".slnx" }.Contains(extension) + ? (await solutionPersistence.GetProjectsFromSolutionAsync(fileSystem.Path.GetFullPath(inputPath))).Where(fileSystem.File.Exists).Select(fileSystem.Path.GetFullPath) + : [fileSystem.Path.GetFullPath(inputPath)]; } } } diff --git a/src/NuGetUtility/ReferencedPackagesReader/ReferencedPackageReader.cs b/src/NuGetUtility/ReferencedPackagesReader/ReferencedPackageReader.cs index 483b3354..db7d0a8a 100644 --- a/src/NuGetUtility/ReferencedPackagesReader/ReferencedPackageReader.cs +++ b/src/NuGetUtility/ReferencedPackagesReader/ReferencedPackageReader.cs @@ -10,27 +10,13 @@ namespace NuGetUtility.ReferencedPackagesReader { - public class ReferencedPackageReader + public class ReferencedPackageReader(IMsBuildAbstraction msBuild, + ILockFileFactory lockFileFactory, + INuGetFrameworkUtility nuGetFrameworkUtility, + IAssetsPackageDependencyReader assetsPackageDependencyReader, + IPackagesConfigReader packagesConfigReader) { private const string ProjectReferenceIdentifier = "project"; - private readonly ILockFileFactory _lockFileFactory; - private readonly INuGetFrameworkUtility _nuGetFrameworkUtility; - private readonly IAssetsPackageDependencyReader _assetsPackageDependencyReader; - private readonly IPackagesConfigReader _packagesConfigReader; - private readonly IMsBuildAbstraction _msBuild; - - public ReferencedPackageReader(IMsBuildAbstraction msBuild, - ILockFileFactory lockFileFactory, - INuGetFrameworkUtility nuGetFrameworkUtility, - IAssetsPackageDependencyReader assetsPackageDependencyReader, - IPackagesConfigReader packagesConfigReader) - { - _msBuild = msBuild; - _lockFileFactory = lockFileFactory; - _nuGetFrameworkUtility = nuGetFrameworkUtility; - _assetsPackageDependencyReader = assetsPackageDependencyReader; - _packagesConfigReader = packagesConfigReader; - } /// /// Gets installed NuGet packages for the specified project. @@ -47,7 +33,7 @@ public ReferencedPackageReader(IMsBuildAbstraction msBuild, /// Resolved package identities from project assets or packages.config. public IEnumerable GetInstalledPackages(string projectPath, bool includeTransitive, string? targetFramework = null, bool excludePublishFalse = false) { - IProject project = _msBuild.GetProject(projectPath); + IProject project = msBuild.GetProject(projectPath); if (TryGetInstalledPackagesFromAssetsFile(includeTransitive, project, targetFramework, excludePublishFalse, out IEnumerable? dependencies)) { @@ -56,17 +42,17 @@ public IEnumerable GetInstalledPackages(string projectPath, boo if (project.HasPackagesConfigFile()) { - return _packagesConfigReader.GetPackages(project); + return packagesConfigReader.GetPackages(project); } - return Array.Empty(); + return []; } private bool TryGetInstalledPackagesFromAssetsFile(bool includeTransitive, - IProject project, - string? targetFramework, - bool excludePublishFalse, - [NotNullWhen(true)] out IEnumerable? installedPackages) + IProject project, + string? targetFramework, + bool excludePublishFalse, + [NotNullWhen(true)] out IEnumerable? installedPackages) { installedPackages = null; if (!TryLoadAssetsFile(project, out ILockFile? assetsFile)) @@ -77,8 +63,8 @@ private bool TryGetInstalledPackagesFromAssetsFile(bool includeTransitive, string? normalizedRequestedTargetFramework = NormalizeTargetFrameworkOrNull(targetFramework); List selectedTargets = GetSelectedTargets(assetsFile, normalizedRequestedTargetFramework, targetFramework); - HashSet referencedLibraries = new HashSet(); - PublishExclusionContext publishExclusionContext = new PublishExclusionContext(normalizedRequestedTargetFramework); + HashSet referencedLibraries = []; + PublishExclusionContext publishExclusionContext = new(normalizedRequestedTargetFramework); foreach (ILockFileTarget target in selectedTargets) { @@ -86,12 +72,11 @@ private bool TryGetInstalledPackagesFromAssetsFile(bool includeTransitive, if (excludePublishFalse) { - HashSet excludedPackages = GetExcludedPackagesForTarget( - project, - assetsFile, - target, - includeTransitive, - publishExclusionContext); + HashSet excludedPackages = GetExcludedPackagesForTarget(project, + assetsFile, + target, + includeTransitive, + publishExclusionContext); targetReferencedLibraries.RemoveWhere(library => excludedPackages.Contains(library.Name)); } @@ -113,7 +98,7 @@ private List GetSelectedTargets(ILockFile assetsFile, } List selectedTargets = assetsFile.Targets - .Where(t => _nuGetFrameworkUtility.IsEquivalent(normalizedRequestedTargetFramework, t.TargetFramework)) + .Where(t => nuGetFrameworkUtility.IsEquivalent(normalizedRequestedTargetFramework, t.TargetFramework)) .ToList(); if (!selectedTargets.Any()) { @@ -124,12 +109,12 @@ private List GetSelectedTargets(ILockFile assetsFile, } private HashSet GetExcludedPackagesForTarget(IProject project, - ILockFile assetsFile, - ILockFileTarget target, - bool includeTransitive, - PublishExclusionContext context) + ILockFile assetsFile, + ILockFileTarget target, + bool includeTransitive, + PublishExclusionContext context) { - string targetFrameworkForPublishMetadata = context.NormalizedRequestedTargetFramework ?? _nuGetFrameworkUtility.Normalize(target.TargetFramework); + string targetFrameworkForPublishMetadata = context.NormalizedRequestedTargetFramework ?? nuGetFrameworkUtility.Normalize(target.TargetFramework); string targetFrameworkCacheKey = targetFrameworkForPublishMetadata ?? string.Empty; // Remove packages with Publish=false metadata from the evaluated PackageReferences for this target only. @@ -139,7 +124,7 @@ private HashSet GetExcludedPackagesForTarget(IProject project, context.PublishFalsePackagesByFramework[targetFrameworkCacheKey] = cachedPublishFalsePackages; } - HashSet excludedPackages = new HashSet(cachedPublishFalsePackages, StringComparer.OrdinalIgnoreCase); + HashSet excludedPackages = new(cachedPublishFalsePackages, StringComparer.OrdinalIgnoreCase); if (!includeTransitive || !excludedPackages.Any()) { return excludedPackages; @@ -153,7 +138,7 @@ private HashSet GetExcludedPackagesForTarget(IProject project, if (!context.PackageDependenciesByFramework.TryGetValue(targetFrameworkCacheKey, out Dictionary>? packageDependencies)) { - packageDependencies = _assetsPackageDependencyReader.GetPackageDependenciesForTargetFramework( + packageDependencies = assetsPackageDependencyReader.GetPackageDependenciesForTargetFramework( assetsFile, targetFrameworkCacheKey); context.PackageDependenciesByFramework[targetFrameworkCacheKey] = packageDependencies; @@ -183,21 +168,21 @@ private HashSet GetExcludedPackagesForTarget(IProject project, } private static IEnumerable GetReferencedLibrariesForTarget(bool includeTransitive, - ILockFile assetsFile, - ILockFileTarget target) + ILockFile assetsFile, + ILockFileTarget target) { IEnumerable dependencies = target.Libraries.Where(l => l.Type != ProjectReferenceIdentifier); - if (!includeTransitive) + if (includeTransitive) { - ITargetFrameworkInformation targetFrameworkInformation = GetTargetFrameworkInformation(target, assetsFile); - IEnumerable directDependencies = targetFrameworkInformation.Dependencies; - return dependencies.Where(d => directDependencies.Any(direct => direct.Name == d.Name)); + return dependencies; } - return dependencies; + + ITargetFrameworkInformation targetFrameworkInformation = GetTargetFrameworkInformation(target, assetsFile); + IEnumerable directDependencies = targetFrameworkInformation.Dependencies; + return dependencies.Where(d => directDependencies.Any(direct => direct.Name == d.Name)); } - private static ITargetFrameworkInformation GetTargetFrameworkInformation(ILockFileTarget target, - ILockFile assetsFile) + private static ITargetFrameworkInformation GetTargetFrameworkInformation(ILockFileTarget target, ILockFile assetsFile) { try { @@ -213,9 +198,9 @@ private static ITargetFrameworkInformation GetTargetFrameworkInformation(ILockFi } private static HashSet GetDirectDependenciesForTargets(ILockFile assetsFile, - IEnumerable selectedTargets) + IEnumerable selectedTargets) { - HashSet directDependencies = new HashSet(StringComparer.OrdinalIgnoreCase); + HashSet directDependencies = new(StringComparer.OrdinalIgnoreCase); foreach (ILockFileTarget target in selectedTargets) { ITargetFrameworkInformation targetFrameworkInformation = GetTargetFrameworkInformation(target, assetsFile); @@ -228,18 +213,17 @@ private static HashSet GetDirectDependenciesForTargets(ILockFile assetsF return directDependencies; } - private static HashSet GetPackagesExcludedFromPublishDependencyPaths( - Dictionary> packageDependencies, - IEnumerable directDependencies, - ISet publishFalseDirectDependencies) + private static HashSet GetPackagesExcludedFromPublishDependencyPaths(Dictionary> packageDependencies, + IEnumerable directDependencies, + ISet publishFalseDirectDependencies) { - HashSet excludedPackages = new HashSet(publishFalseDirectDependencies, StringComparer.OrdinalIgnoreCase); + HashSet excludedPackages = new(publishFalseDirectDependencies, StringComparer.OrdinalIgnoreCase); if (packageDependencies.Count == 0) { return excludedPackages; } - HashSet publishableRoots = new HashSet( + HashSet publishableRoots = new( directDependencies.Where(package => !publishFalseDirectDependencies.Contains(package)), StringComparer.OrdinalIgnoreCase); @@ -257,19 +241,18 @@ private static HashSet GetPackagesExcludedFromPublishDependencyPaths( } private static string BuildExclusionCacheKey(string targetFramework, - IEnumerable directDependencies, - IEnumerable publishFalseDirectDependencies) + IEnumerable directDependencies, + IEnumerable publishFalseDirectDependencies) { string directDependenciesKey = string.Join(";", directDependencies.OrderBy(dependency => dependency, StringComparer.OrdinalIgnoreCase)); string publishFalseDependenciesKey = string.Join(";", publishFalseDirectDependencies.OrderBy(dependency => dependency, StringComparer.OrdinalIgnoreCase)); return $"{targetFramework}|{directDependenciesKey}|{publishFalseDependenciesKey}"; } - private static HashSet GetReachablePackages(Dictionary> packageDependencies, - IEnumerable roots) + private static HashSet GetReachablePackages(Dictionary> packageDependencies, IEnumerable roots) { - HashSet visited = new HashSet(StringComparer.OrdinalIgnoreCase); - Stack stack = new Stack(roots); + HashSet visited = new(StringComparer.OrdinalIgnoreCase); + Stack stack = new(roots); while (stack.Count > 0) { @@ -305,7 +288,7 @@ private static HashSet GetReachablePackages(Dictionary GetPackagesExcludedFromPublish(IProject project, ? project.GetPackageReferences() : project.GetPackageReferencesForTarget(targetFramework); - HashSet excludedPackages = new HashSet(StringComparer.OrdinalIgnoreCase); - foreach (PackageReferenceMetadata packageReference in packageReferences ?? Array.Empty()) + HashSet excludedPackages = new(StringComparer.OrdinalIgnoreCase); + foreach (PackageReferenceMetadata packageReference in packageReferences ?? []) { if (packageReference.Metadata.TryGetValue("Publish", out string? value) && string.Equals(value, "false", StringComparison.OrdinalIgnoreCase)) @@ -355,13 +338,13 @@ private static HashSet GetPackagesExcludedFromPublish(IProject project, private sealed record PublishExclusionContext(string? NormalizedRequestedTargetFramework) { - public Dictionary> PublishFalsePackagesByFramework { get; } = new Dictionary>(StringComparer.OrdinalIgnoreCase); + public Dictionary> PublishFalsePackagesByFramework { get; } = new(StringComparer.OrdinalIgnoreCase); - public Dictionary> DirectDependenciesByFramework { get; } = new Dictionary>(StringComparer.OrdinalIgnoreCase); + public Dictionary> DirectDependenciesByFramework { get; } = new(StringComparer.OrdinalIgnoreCase); - public Dictionary>> PackageDependenciesByFramework { get; } = new Dictionary>>(StringComparer.OrdinalIgnoreCase); + public Dictionary>> PackageDependenciesByFramework { get; } = new(StringComparer.OrdinalIgnoreCase); - public Dictionary> RecursiveExclusionsByInput { get; } = new Dictionary>(StringComparer.Ordinal); + public Dictionary> RecursiveExclusionsByInput { get; } = new(StringComparer.Ordinal); } } } diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/DownloadFailedException.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/DownloadFailedException.cs index 73f8eccb..691a35d9 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/DownloadFailedException.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/DownloadFailedException.cs @@ -3,10 +3,5 @@ namespace NuGetUtility.Wrapper.HttpClientWrapper { - public class DownloadFailedException : Exception - { - public DownloadFailedException(Uri url) : base($"Download failed for URL: {url}") - { - } - } + public class DownloadFailedException(Uri url) : Exception($"Download failed for URL: {url}"); } diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs index f96d6343..f8b63c6f 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs @@ -6,21 +6,13 @@ namespace NuGetUtility.Wrapper.HttpClientWrapper { - public class FileDownloader : IFileDownloader + public class FileDownloader(HttpClient client, string downloadDirectory) : IFileDownloader { private readonly SemaphoreSlim _parallelDownloadLimiter = new(10, 10); - private readonly HttpClient _client; - private readonly string _downloadDirectory; private readonly ConcurrentDictionary> _downloadedLicenses = new(); private const int EXPONENTIAL_BACKOFF_WAIT_TIME_MILLISECONDS = 200; private const int MAX_RETRIES = 5; - public FileDownloader(HttpClient client, string downloadDirectory) - { - _client = client; - _downloadDirectory = downloadDirectory; - } - public async Task DownloadFile(Uri url, string fileNameStem, CancellationToken token) { string initialDownloadName = await _downloadedLicenses.GetOrAdd(url, u => DownloadFileActuallyAsync(u, fileNameStem, token)); @@ -28,7 +20,7 @@ public async Task DownloadFile(Uri url, string fileNameStem, CancellationToken t if (!initialDownloadName.StartsWith(fileNameStem)) { string destinationFile = $"{fileNameStem}{Path.GetExtension(initialDownloadName)}"; - File.Copy(Path.Combine(_downloadDirectory, initialDownloadName), Path.Combine(_downloadDirectory, destinationFile), true); + File.Copy(Path.Combine(downloadDirectory, initialDownloadName), Path.Combine(downloadDirectory, destinationFile), true); } } @@ -60,12 +52,11 @@ private async Task DownloadFileActuallyAsync(Uri url, string fileNameSte { var request = new HttpRequestMessage(HttpMethod.Get, url); + HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); #if NETFRAMEWORK - HttpResponseMessage response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); // System.Net.HttpStatusCode.TooManyRequests does not exist in .net472 if (response.StatusCode == (System.Net.HttpStatusCode)429) #else - HttpResponseMessage response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests) #endif { @@ -80,9 +71,9 @@ private async Task DownloadFileActuallyAsync(Uri url, string fileNameSte } string fileName = $"{fileNameStem}.{extension}"; #if NETFRAMEWORK - using FileStream file = File.OpenWrite(Path.Combine(_downloadDirectory, fileName)); + using FileStream file = File.OpenWrite(Path.Combine(downloadDirectory, fileName)); #else - await using FileStream file = File.OpenWrite(Path.Combine(_downloadDirectory, fileName)); + await using FileStream file = File.OpenWrite(Path.Combine(downloadDirectory, fileName)); #endif using Stream downloadStream = await response.Content.ReadAsStreamAsync(); @@ -98,10 +89,10 @@ public Task StoreFileAsync(string licenseText, string fileNameStem, Cancellation { string fileName = $"{fileNameStem}.txt"; #if NETFRAMEWORK - File.WriteAllText(Path.Combine(_downloadDirectory, fileName), licenseText); + File.WriteAllText(Path.Combine(downloadDirectory, fileName), licenseText); return Task.CompletedTask; #else - return File.WriteAllTextAsync(Path.Combine(_downloadDirectory, fileName), licenseText, token); + return File.WriteAllTextAsync(Path.Combine(downloadDirectory, fileName), licenseText, token); #endif } } diff --git a/src/NuGetUtility/Wrapper/MsBuildWrapper/ProjectWrapper.cs b/src/NuGetUtility/Wrapper/MsBuildWrapper/ProjectWrapper.cs index 0c894b57..6e525a6b 100644 --- a/src/NuGetUtility/Wrapper/MsBuildWrapper/ProjectWrapper.cs +++ b/src/NuGetUtility/Wrapper/MsBuildWrapper/ProjectWrapper.cs @@ -6,22 +6,15 @@ namespace NuGetUtility.Wrapper.MsBuildWrapper { - internal class ProjectWrapper : IProject + internal class ProjectWrapper(Project project) : IProject { private const string ProjectAssetsFile = "ProjectAssetsFile"; private const string PackageReferenceItemType = "PackageReference"; private const string TargetFrameworkProperty = "TargetFramework"; - private readonly Project _project; - - public ProjectWrapper(Project project) - { - _project = project; - } - public bool TryGetAssetsPath([NotNullWhen(true)] out string assetsFile) { - assetsFile = _project.GetPropertyValue(ProjectAssetsFile); + assetsFile = project.GetPropertyValue(ProjectAssetsFile); if (string.IsNullOrEmpty(assetsFile)) { return false; @@ -30,7 +23,7 @@ public bool TryGetAssetsPath([NotNullWhen(true)] out string assetsFile) if (!File.Exists(assetsFile)) { throw new MsBuildAbstractionException( - $"Failed to get the project assets file for project {_project.FullPath} ({assetsFile})"); + $"Failed to get the project assets file for project {project.FullPath} ({assetsFile})"); } return true; @@ -38,26 +31,26 @@ public bool TryGetAssetsPath([NotNullWhen(true)] out string assetsFile) public IEnumerable GetEvaluatedIncludes() { - return _project.AllEvaluatedItems.Select(projectItem => projectItem.EvaluatedInclude); + return project.AllEvaluatedItems.Select(projectItem => projectItem.EvaluatedInclude); } public IEnumerable GetPackageReferences() { // Read evaluated PackageReference items from the current project context. - return _project.GetItems(PackageReferenceItemType) + return project.GetItems(PackageReferenceItemType) .Select(item => new PackageReferenceMetadata(item.EvaluatedInclude, CreateMetadata(item))); } public IEnumerable GetPackageReferencesForTarget(string targetFramework) { // Re-evaluate the project for a specific target framework to read conditional references. - Dictionary properties = new Dictionary(_project.GlobalProperties, StringComparer.OrdinalIgnoreCase) + Dictionary properties = new(project.GlobalProperties, StringComparer.OrdinalIgnoreCase) { [TargetFrameworkProperty] = targetFramework }; - using ProjectCollection projectCollection = new ProjectCollection(); - Project targetProject = new Project(_project.FullPath, properties, _project.ToolsVersion, projectCollection); + using ProjectCollection projectCollection = new(); + Project targetProject = new(project.FullPath, properties, project.ToolsVersion, projectCollection); try { return targetProject.GetItems(PackageReferenceItemType) @@ -70,12 +63,12 @@ public IEnumerable GetPackageReferencesForTarget(strin } } - public string FullPath => _project.FullPath; + public string FullPath => project.FullPath; private static IReadOnlyDictionary CreateMetadata(ProjectItem item) { // Normalize metadata names for case-insensitive lookups (e.g., Publish). - Dictionary metadata = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary metadata = new(StringComparer.OrdinalIgnoreCase); foreach (ProjectMetadata projectMetadata in item.Metadata) { metadata[projectMetadata.Name] = projectMetadata.EvaluatedValue; diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Frameworks/WrappedNuGetFramework.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Frameworks/WrappedNuGetFramework.cs index 4e857266..ecc2ad7f 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Frameworks/WrappedNuGetFramework.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Frameworks/WrappedNuGetFramework.cs @@ -5,14 +5,9 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Frameworks { - internal class WrappedNuGetFramework : INuGetFramework + internal class WrappedNuGetFramework(NuGetFramework framework) : INuGetFramework { - private readonly NuGetFramework _framework; - - public WrappedNuGetFramework(NuGetFramework framework) - { - _framework = framework; - } + private readonly NuGetFramework _framework = framework; public override bool Equals(object? obj) { diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/NugetWrapperException.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/NugetWrapperException.cs index 936a9b7b..8fc7c7eb 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/NugetWrapperException.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/NugetWrapperException.cs @@ -3,9 +3,5 @@ namespace NuGetUtility.Wrapper.NuGetWrapper { - public class NugetWrapperException : Exception - { - public NugetWrapperException(string message) - : base(message) { } - } + public class NugetWrapperException(string message) : Exception(message); } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/PackagesConfigReaderException.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/PackagesConfigReaderException.cs index 97ffaedb..e0c99597 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/PackagesConfigReaderException.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/PackagesConfigReaderException.cs @@ -3,8 +3,5 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Packaging.Core { - public class PackagesConfigReaderException : Exception - { - public PackagesConfigReaderException(string? message) : base(message) { } - } + public class PackagesConfigReaderException(string? message) : Exception(message); } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/WrappedPackageDependency.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/WrappedPackageDependency.cs index 5cf43076..7427e118 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/WrappedPackageDependency.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Packaging/Core/WrappedPackageDependency.cs @@ -5,13 +5,9 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Packaging.Core { - internal class WrappedPackageDependency : IPackageDependency + internal class WrappedPackageDependency(PackageDependency dependency) : IPackageDependency { - public WrappedPackageDependency(PackageDependency dependency) - { - Id = dependency.Id; - } - public string Id { get; } + public string Id { get; } = dependency.Id; } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/AssetsPackageDependencyReader.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/AssetsPackageDependencyReader.cs index ac752ea6..3e1fe9e0 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/AssetsPackageDependencyReader.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/AssetsPackageDependencyReader.cs @@ -66,7 +66,7 @@ public Dictionary> GetPackageDependenciesForTargetFramew private Dictionary> BuildDependencyMapFromAssetsFile(ILockFile lockFile, string requestedTargetFramework) { - Dictionary> packageDependencies = new Dictionary>(StringComparer.OrdinalIgnoreCase); + Dictionary> packageDependencies = new(StringComparer.OrdinalIgnoreCase); foreach (ILockFileTarget target in lockFile.Targets) { diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLibraryDependency.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLibraryDependency.cs index 2cd2253f..212c06b7 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLibraryDependency.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLibraryDependency.cs @@ -5,14 +5,8 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel { - internal class WrappedLibraryDependency : ILibraryDependency + internal class WrappedLibraryDependency(LibraryDependency dependency) : ILibraryDependency { - private readonly LibraryDependency _dependency; - - public WrappedLibraryDependency(LibraryDependency dependency) - { - _dependency = dependency; - } - public string Name => _dependency.Name; + public string Name => dependency.Name; } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFile.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFile.cs index 9ef104a1..bc135d3e 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFile.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFile.cs @@ -5,24 +5,15 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel { - internal class WrappedLockFile : ILockFile + internal class WrappedLockFile(LockFile file) : ILockFile { - private readonly LockFile _file; - - public WrappedLockFile(LockFile file) - { - _file = file; - } - - public IEnumerable Libraries => _file.Libraries.Select(l => new WrappedLockFileLibrary(l)); - - public IPackageSpec PackageSpec => new WrappedPackageSpec(_file.PackageSpec); - public IEnumerable Targets => _file.Targets.Select(t => new WrappedLockFileTarget(t)); - public string Path => _file.Path; + public IPackageSpec PackageSpec => new WrappedPackageSpec(file.PackageSpec); + public IEnumerable Targets => file.Targets.Select(t => new WrappedLockFileTarget(t)); + public string Path => file.Path; public bool TryGetErrors(out string[] errors) { - IAssetsLogMessage[] fileErrors = _file.LogMessages.Where(l => l.Level == NuGet.Common.LogLevel.Error).ToArray(); + IAssetsLogMessage[] fileErrors = file.LogMessages.Where(l => l.Level == NuGet.Common.LogLevel.Error).ToArray(); errors = fileErrors.Select(e => $"[{e.Code}] {e.Message}").ToArray(); return errors.Length > 0; } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileLibrary.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileLibrary.cs index 7cd0e3d8..44e187f7 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileLibrary.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileLibrary.cs @@ -6,19 +6,12 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel { - internal class WrappedLockFileLibrary : ILockFileLibrary + internal class WrappedLockFileLibrary(LockFileLibrary library) : ILockFileLibrary { - private readonly LockFileLibrary _library; + public string Type => library.Type; - public WrappedLockFileLibrary(LockFileLibrary library) - { - _library = library; - } + public string Name => library.Name; - public string Type => _library.Type; - - public string Name => _library.Name; - - public INuGetVersion Version => new WrappedNuGetVersion(_library.Version); + public INuGetVersion Version => new WrappedNuGetVersion(library.Version); } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileTarget.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileTarget.cs index 2ffecad3..81aab863 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileTarget.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedLockFileTarget.cs @@ -6,17 +6,10 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel { - internal class WrappedLockFileTarget : ILockFileTarget + internal class WrappedLockFileTarget(LockFileTarget target) : ILockFileTarget { - private readonly LockFileTarget _target; + public INuGetFramework TargetFramework => new WrappedNuGetFramework(target.TargetFramework); - public WrappedLockFileTarget(LockFileTarget target) - { - _target = target; - } - - public INuGetFramework TargetFramework => new WrappedNuGetFramework(_target.TargetFramework); - - public IEnumerable Libraries => _target.Libraries.Select(l => new WrappedLockFileTargetLibrary(l)); + public IEnumerable Libraries => target.Libraries.Select(l => new WrappedLockFileTargetLibrary(l)); } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedPackageSpec.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedPackageSpec.cs index b7591aae..170e8754 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedPackageSpec.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedPackageSpec.cs @@ -5,22 +5,15 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel { - internal class WrappedPackageSpec : IPackageSpec + internal class WrappedPackageSpec(PackageSpec? spec) : IPackageSpec { - private readonly PackageSpec? _spec; - - public WrappedPackageSpec(PackageSpec? spec) - { - _spec = spec; - } - public bool IsValid() { - return _spec != null; + return spec != null; } public IEnumerable TargetFrameworks => - _spec?.TargetFrameworks.Select(t => new WrappedTargetFrameworkInformation(t)) ?? + spec?.TargetFrameworks.Select(t => new WrappedTargetFrameworkInformation(t)) ?? Enumerable.Empty(); } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedTargetFrameworkInformation.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedTargetFrameworkInformation.cs index 31a33823..af93807d 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedTargetFrameworkInformation.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/ProjectModel/WrappedTargetFrameworkInformation.cs @@ -6,22 +6,15 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel { - internal class WrappedTargetFrameworkInformation : ITargetFrameworkInformation + internal class WrappedTargetFrameworkInformation(TargetFrameworkInformation info) : ITargetFrameworkInformation { - private readonly TargetFrameworkInformation _info; + public INuGetFramework FrameworkName => new WrappedNuGetFramework(info.FrameworkName); - public WrappedTargetFrameworkInformation(TargetFrameworkInformation info) - { - _info = info; - } - - public INuGetFramework FrameworkName => new WrappedNuGetFramework(_info.FrameworkName); - - public IEnumerable Dependencies => _info.Dependencies.Select(library => new WrappedLibraryDependency(library)); + public IEnumerable Dependencies => info.Dependencies.Select(library => new WrappedLibraryDependency(library)); public override string ToString() { - return _info.ToString(); + return info.ToString(); } } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingDisposableSourceRepository.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingDisposableSourceRepository.cs index 47a4c307..38279f84 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingDisposableSourceRepository.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingDisposableSourceRepository.cs @@ -5,18 +5,12 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Protocol.Core.Types { - internal sealed class CachingDisposableSourceRepository : IDisposableSourceRepository + internal sealed class CachingDisposableSourceRepository(SourceRepository sourceRepository) : IDisposableSourceRepository { private readonly SourceCacheContext _cacheContext = new(); - private readonly SourceRepository _sourceRepository; private IPackageMetadataResource? _packageMetadataResource; private IFindPackageByIdResource? _findPackageByIdResource; - public CachingDisposableSourceRepository(SourceRepository repo) - { - _sourceRepository = repo; - } - public void Dispose() { _packageMetadataResource = null; @@ -30,9 +24,8 @@ public void Dispose() return _packageMetadataResource; } - _packageMetadataResource = new CachingPackageMetadataResource( - await _sourceRepository.GetResourceAsync(token), - _cacheContext); + _packageMetadataResource = new CachingPackageMetadataResource(await sourceRepository.GetResourceAsync(token), + _cacheContext); return _packageMetadataResource; } @@ -43,9 +36,8 @@ await _sourceRepository.GetResourceAsync(token), return _findPackageByIdResource; } - _findPackageByIdResource = new CachingFindPackageByIdResource( - await _sourceRepository.GetResourceAsync(token), - _cacheContext); + _findPackageByIdResource = new CachingFindPackageByIdResource(await sourceRepository.GetResourceAsync(token), + _cacheContext); return _findPackageByIdResource; } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingPackageMetadataResource.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingPackageMetadataResource.cs index 8fab3a7a..d67021a0 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingPackageMetadataResource.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/Core/Types/CachingPackageMetadataResource.cs @@ -10,26 +10,18 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Protocol.Core.Types { - internal class CachingPackageMetadataResource : IPackageMetadataResource + internal class CachingPackageMetadataResource(PackageMetadataResource metadataResource, SourceCacheContext cacheContext) + : IPackageMetadataResource { - private readonly SourceCacheContext _cacheContext; - private readonly PackageMetadataResource _metadataResource; - - public CachingPackageMetadataResource(PackageMetadataResource metadataResource, SourceCacheContext cacheContext) - { - _metadataResource = metadataResource; - _cacheContext = cacheContext; - } - public async Task TryGetMetadataAsync(PackageIdentity identity, CancellationToken cancellationToken) { try { - IPackageSearchMetadata result = await _metadataResource.GetMetadataAsync(new NuGet.Packaging.Core.PackageIdentity(identity.Id, new NuGetVersion(identity.Version.ToString()!)), - _cacheContext, - NullLogger.Instance, - cancellationToken); + IPackageSearchMetadata result = await metadataResource.GetMetadataAsync(new NuGet.Packaging.Core.PackageIdentity(identity.Id, new NuGetVersion(identity.Version.ToString()!)), + cacheContext, + NullLogger.Instance, + cancellationToken); return new WrappedPackageSearchMetadata(result); } catch (Exception) @@ -38,34 +30,25 @@ public CachingPackageMetadataResource(PackageMetadataResource metadataResource, } } - private sealed class WrappedPackageSearchMetadata : IPackageMetadata + private sealed class WrappedPackageSearchMetadata(IPackageSearchMetadata searchMetadata) : IPackageMetadata { - private readonly IPackageSearchMetadata _searchMetadata; - - public WrappedPackageSearchMetadata(IPackageSearchMetadata searchMetadata) - { - Identity = new PackageIdentity(searchMetadata.Identity.Id, new WrappedNuGetVersion(searchMetadata.Identity.Version)); - LicenseMetadata = searchMetadata.LicenseMetadata; - _searchMetadata = searchMetadata; - } - - public PackageIdentity Identity { get; } + public PackageIdentity Identity { get; } = new(searchMetadata.Identity.Id, new WrappedNuGetVersion(searchMetadata.Identity.Version)); - public string? Title => _searchMetadata.Title; + public string? Title => searchMetadata.Title; - public Uri? LicenseUrl => _searchMetadata.LicenseUrl; + public Uri? LicenseUrl => searchMetadata.LicenseUrl; - public string? ProjectUrl => _searchMetadata.ProjectUrl?.ToString(); + public string? ProjectUrl => searchMetadata.ProjectUrl?.ToString(); - public string? Description => _searchMetadata.Description; + public string? Description => searchMetadata.Description; - public string? Summary => _searchMetadata.Summary; + public string? Summary => searchMetadata.Summary; public string? Copyright => null; - public string? Authors => _searchMetadata.Authors; + public string? Authors => searchMetadata.Authors; - public LicenseMetadata? LicenseMetadata { get; } + public LicenseMetadata? LicenseMetadata { get; } = searchMetadata.LicenseMetadata; } } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs index 04f6e64a..23e908bd 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/GlobalPackagesFolderUtility.cs @@ -13,14 +13,9 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Protocol { - public class GlobalPackagesFolderUtility : IGlobalPackagesFolderUtility + public class GlobalPackagesFolderUtility(ISettings settings) : IGlobalPackagesFolderUtility { - private readonly string _globalPackagesFolder; - - public GlobalPackagesFolderUtility(ISettings settings) - { - _globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(settings); - } + private readonly string _globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(settings); public IWrappedPackageMetadata? GetPackage(PackageIdentity identity) { diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/LicenseAugmentedPackageMetadata.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/LicenseAugmentedPackageMetadata.cs index e21dd1cd..e3bc4619 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/LicenseAugmentedPackageMetadata.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/LicenseAugmentedPackageMetadata.cs @@ -30,6 +30,6 @@ public LicenseAugmentedPackageMetadata(IWrappedPackageMetadata metadata, string public string? Summary => _metadata.Summary; public string? Copyright => _metadata.Copyright; public string? Authors => _metadata.Authors; - public Packaging.LicenseMetadata? LicenseMetadata => new Packaging.LicenseMetadata(Packaging.LicenseType.File, _licenseText); + public Packaging.LicenseMetadata? LicenseMetadata => new(Packaging.LicenseType.File, _licenseText); } } diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs index 33a04832..c0dbda1a 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs @@ -4,38 +4,30 @@ using NuGet.Packaging; using NuGetUtility.Wrapper.NuGetWrapper.Packaging.Core; using NuGetUtility.Wrapper.NuGetWrapper.Versioning; -using IWrappedPackageMetadata = NuGetUtility.Wrapper.NuGetWrapper.Packaging.IPackageMetadata; namespace NuGetUtility.Wrapper.NuGetWrapper.Protocol { - internal class WrappedPackageMetadata : IWrappedPackageMetadata - { - private readonly ManifestMetadata _metadata; - - public WrappedPackageMetadata(ManifestMetadata metadata) - { - Identity = new PackageIdentity(metadata.Id ?? throw new ArgumentNullException(nameof(metadata.Id)), - new WrappedNuGetVersion(metadata.Version ?? throw new ArgumentNullException(nameof(metadata.Version)))); - LicenseMetadata = metadata.LicenseMetadata; - _metadata = metadata; - } + using IWrappedPackageMetadata = NuGetUtility.Wrapper.NuGetWrapper.Packaging.IPackageMetadata; - public PackageIdentity Identity { get; } + internal class WrappedPackageMetadata(ManifestMetadata metadata) : IWrappedPackageMetadata + { + public PackageIdentity Identity { get; } = new(metadata.Id ?? throw new ArgumentNullException(nameof(metadata.Id)), + new WrappedNuGetVersion(metadata.Version ?? throw new ArgumentNullException(nameof(metadata.Version)))); - public string? Title => _metadata.Title; + public string? Title => metadata.Title; - public Uri? LicenseUrl => _metadata.LicenseUrl; + public Uri? LicenseUrl => metadata.LicenseUrl; - public string? ProjectUrl => _metadata.ProjectUrl?.ToString(); + public string? ProjectUrl => metadata.ProjectUrl?.ToString(); - public string? Description => _metadata.Description; + public string? Description => metadata.Description; - public string? Summary => _metadata.Summary; + public string? Summary => metadata.Summary; - public string? Copyright => _metadata.Copyright; + public string? Copyright => metadata.Copyright; - public string? Authors => string.Join(",", _metadata.Authors); // https://learn.microsoft.com/en-us/nuget/reference/nuspec#authors + public string? Authors => string.Join(",", metadata.Authors); // https://learn.microsoft.com/en-us/nuget/reference/nuspec#authors - public Packaging.LicenseMetadata? LicenseMetadata { get; } + public Packaging.LicenseMetadata? LicenseMetadata { get; } = metadata.LicenseMetadata; } } diff --git a/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/ISolutionPersistanceWrapper.cs b/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/ISolutionPersistenceWrapper.cs similarity index 85% rename from src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/ISolutionPersistanceWrapper.cs rename to src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/ISolutionPersistenceWrapper.cs index 26c88fb8..3eff8ef2 100644 --- a/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/ISolutionPersistanceWrapper.cs +++ b/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/ISolutionPersistenceWrapper.cs @@ -3,7 +3,7 @@ namespace NuGetUtility.Wrapper.SolutionPersistenceWrapper { - public interface ISolutionPersistanceWrapper + public interface ISolutionPersistenceWrapper { Task> GetProjectsFromSolutionAsync(string inputPath); } diff --git a/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/SolutionPersistanceWrapper.cs b/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/SolutionPersistenceWrapper.cs similarity index 93% rename from src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/SolutionPersistanceWrapper.cs rename to src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/SolutionPersistenceWrapper.cs index b9483060..ceb41133 100644 --- a/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/SolutionPersistanceWrapper.cs +++ b/src/NuGetUtility/Wrapper/SolutionPersistenceWrapper/SolutionPersistenceWrapper.cs @@ -6,7 +6,7 @@ namespace NuGetUtility.Wrapper.SolutionPersistenceWrapper { - public class SolutionPersistanceWrapper : ISolutionPersistanceWrapper + public class SolutionPersistenceWrapper : ISolutionPersistenceWrapper { public async Task> GetProjectsFromSolutionAsync(string inputPath) { diff --git a/tests/FileLicenseMatcher.Test/Combine/LicenseMatcherTest.cs b/tests/FileLicenseMatcher.Test/Combine/LicenseMatcherTest.cs index 90d1d2ad..0b91b986 100644 --- a/tests/FileLicenseMatcher.Test/Combine/LicenseMatcherTest.cs +++ b/tests/FileLicenseMatcher.Test/Combine/LicenseMatcherTest.cs @@ -8,14 +8,8 @@ namespace FileLicenseMatcher.Test.Combine { public class LicenseMatcherTest { - private readonly IFileLicenseMatcher _first; - private readonly IFileLicenseMatcher _second; - - public LicenseMatcherTest() - { - _first = Substitute.For(); - _second = Substitute.For(); - } + private readonly IFileLicenseMatcher _first = Substitute.For(); + private readonly IFileLicenseMatcher _second = Substitute.For(); [Test] public async Task Match_Should_Return_Empty_If_No_Matchers() diff --git a/tests/FileLicenseMatcher.Test/SPDX/LicenseMatcherTest.cs b/tests/FileLicenseMatcher.Test/SPDX/LicenseMatcherTest.cs index 840decff..2da1a6ff 100644 --- a/tests/FileLicenseMatcher.Test/SPDX/LicenseMatcherTest.cs +++ b/tests/FileLicenseMatcher.Test/SPDX/LicenseMatcherTest.cs @@ -11,7 +11,7 @@ public record Case(string Identifier, string Content); public class AllSpdxLicensesFastLicenseMatcher : IFileLicenseMatcher { - private readonly FastLicenseMatcher _fastLicenseMatcher = new FastLicenseMatcher(Spdx.Licenses.SpdxLicenseStore.Licenses); + private readonly FastLicenseMatcher _fastLicenseMatcher = new(Spdx.Licenses.SpdxLicenseStore.Licenses); public string Match(string licenseText) => _fastLicenseMatcher.Match(licenseText); } @@ -31,8 +31,11 @@ public static IEnumerable> GetCases() foreach (string name in executingAssembly.GetManifestResourceNames().Where(n => n.StartsWith(PREFIX)).Where(n => n.EndsWith("txt"))) { string expectedIdentifier = name.Substring(s_prefixLength, name.Length - s_postfixLength - s_prefixLength); - using var reader = new StreamReader(executingAssembly.GetManifestResourceStream(name)!); - yield return () => new Case(expectedIdentifier, reader.ReadToEnd()); + yield return () => + { + using var reader = new StreamReader(executingAssembly.GetManifestResourceStream(name)!); + return new Case(expectedIdentifier, reader.ReadToEnd()); + }; } } } @@ -47,8 +50,11 @@ public static IEnumerable> GetCases() var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly(); foreach (string name in executingAssembly.GetManifestResourceNames().Where(n => n.StartsWith(PREFIX)).Where(n => n.EndsWith("txt"))) { - using var reader = new StreamReader(executingAssembly.GetManifestResourceStream(name)!); - yield return () => reader.ReadToEnd(); + yield return () => + { + using var reader = new StreamReader(executingAssembly.GetManifestResourceStream(name)!); + return reader.ReadToEnd(); + }; } } } @@ -64,8 +70,11 @@ public static IEnumerable> GetCases() { string fileName = name.Substring(s_prefixLength); string expectedIdentifier = fileName.Split("__")[0]; - using var reader = new StreamReader(executingAssembly.GetManifestResourceStream(name)!); - yield return () => new Case(expectedIdentifier, reader.ReadToEnd()); + yield return () => + { + using var reader = new StreamReader(executingAssembly.GetManifestResourceStream(name)!); + return new Case(expectedIdentifier, reader.ReadToEnd()); + }; } } } @@ -86,7 +95,7 @@ public async Task Fast_License_Matcher_Should_Not_Pick_A_License(string licenseT [Test] [MethodDataSource(typeof(RealWorldLicenses), nameof(RealWorldLicenses.GetCases))] - public async Task Fast_License_Matcher_Should_Mattch_Real_World_Licenses(Case @case) + public async Task Fast_License_Matcher_Should_Match_Real_World_Licenses(Case @case) { _ = await Assert.That(FastlicenseMatcher.Match(@case.Content)).Contains(@case.Identifier); } diff --git a/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs b/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs index ada0d97d..66745f17 100644 --- a/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs +++ b/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs @@ -6,7 +6,6 @@ using NSubstitute; using NuGetLicense.LicenseValidator; using NuGetUtility; -using NuGetUtility.PackageInformationReader; using NuGetUtility.Wrapper.HttpClientWrapper; using NuGetUtility.Wrapper.MsBuildWrapper; using NuGetUtility.Wrapper.NuGetWrapper.Packaging.Core; @@ -18,7 +17,7 @@ namespace NuGetLicense.Test public class LicenseValidationOrchestratorTest { private readonly MockFileSystem _fileSystem; - private readonly ISolutionPersistanceWrapper _solutionPersistance; + private readonly ISolutionPersistenceWrapper _solutionPersistence; private readonly ICommandLineOptionsParser _optionsParser; private readonly MemoryStream _outputStream; private readonly MemoryStream _errorStream; @@ -28,7 +27,7 @@ public class LicenseValidationOrchestratorTest public LicenseValidationOrchestratorTest() { _fileSystem = new MockFileSystem(); - _solutionPersistance = Substitute.For(); + _solutionPersistence = Substitute.For(); IMsBuildAbstraction msBuild = Substitute.For(); IPackagesConfigReader packagesConfigReader = Substitute.For(); _optionsParser = Substitute.For(); @@ -40,7 +39,7 @@ public LicenseValidationOrchestratorTest() _orchestrator = new LicenseValidationOrchestrator( _fileSystem, - _solutionPersistance, + _solutionPersistence, msBuild, packagesConfigReader, _optionsParser, @@ -69,12 +68,12 @@ public async Task ValidateAsync_CallsOptionsParserWithCorrectArguments() _optionsParser.GetIgnoredPackages(_options.IgnoredPackages).Returns(["TestPkg"]); _optionsParser.GetExcludedProjects(_options.ExcludedProjects).Returns(["*Test*"]); _optionsParser.GetLicenseMappings(null).Returns(ImmutableDictionary.Empty); - _optionsParser.GetOverridePackageInformation(null).Returns(Array.Empty()); + _optionsParser.GetOverridePackageInformation(null).Returns([]); _optionsParser.GetFileDownloader(null).Returns(new NopFileDownloader()); _optionsParser.GetOutputFormatter(OutputType.Table, false, false).Returns(new LicenseOutput.Table.TableOutputFormatter(false, false)); _optionsParser.GetLicenseMatcher(null).Returns(new FileLicenseMatcher.SPDX.FastLicenseMatcher(Spdx.Licenses.SpdxLicenseStore.Licenses)); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); // Act await _orchestrator.ValidateAsync(_options); @@ -93,7 +92,7 @@ public async Task ValidateAsync_WithNoProjects_ReturnsZero() _options.InputFile.Returns("/test/project.csproj"); SetupDefaultMocks(); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); // Act int result = await _orchestrator.ValidateAsync(_options); @@ -112,7 +111,7 @@ public async Task ValidateAsync_WithDestinationFile_WritesToFile() _options.DestinationFile.Returns(destinationFile); SetupDefaultMocks(); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); // Act int result = await _orchestrator.ValidateAsync(_options); @@ -131,7 +130,7 @@ public async Task ValidateAsync_WithDestinationFileInNonExistentDirectory_Create _options.DestinationFile.Returns(destinationFile); SetupDefaultMocks(); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); // Act int result = await _orchestrator.ValidateAsync(_options); @@ -149,7 +148,7 @@ public async Task ValidateAsync_WithoutDestinationFile_WritesToOutputStream() _options.InputFile.Returns("/test/project.csproj"); SetupDefaultMocks(); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); // Act int result = await _orchestrator.ValidateAsync(_options); @@ -166,7 +165,7 @@ public async Task ValidateAsync_WithExceptionInOutputFormatter_ReturnsMinusOne() _options.InputFile.Returns("/test/project.csproj"); SetupDefaultMocks(); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); LicenseOutput.IOutputFormatter throwingFormatter = Substitute.For(); throwingFormatter.Write(Arg.Any(), Arg.Any>()) @@ -188,7 +187,7 @@ public async Task ValidateAsync_WithCancellationToken_CanBeCancelled() _options.InputFile.Returns("/test/project.csproj"); SetupDefaultMocks(); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); using var cancellationTokenSource = new CancellationTokenSource(); #if NETFRAMEWORK @@ -217,7 +216,7 @@ public async Task ValidateAsync_UsesAllConfiguredOptions() _options.InputJsonFile.Returns(default(string?)); SetupDefaultMocks(); - _solutionPersistance.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(Array.Empty())); + _solutionPersistence.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>([])); // Act await _orchestrator.ValidateAsync(_options); @@ -233,11 +232,11 @@ public async Task ValidateAsync_UsesAllConfiguredOptions() private void SetupDefaultMocks() { _optionsParser.GetInputFiles(Arg.Any(), Arg.Any()).Returns(["/test/project.csproj"]); - _optionsParser.GetAllowedLicenses(Arg.Any()).Returns(Array.Empty()); - _optionsParser.GetIgnoredPackages(Arg.Any()).Returns(Array.Empty()); - _optionsParser.GetExcludedProjects(Arg.Any()).Returns(Array.Empty()); + _optionsParser.GetAllowedLicenses(Arg.Any()).Returns([]); + _optionsParser.GetIgnoredPackages(Arg.Any()).Returns([]); + _optionsParser.GetExcludedProjects(Arg.Any()).Returns([]); _optionsParser.GetLicenseMappings(Arg.Any()).Returns(ImmutableDictionary.Empty); - _optionsParser.GetOverridePackageInformation(Arg.Any()).Returns(Array.Empty()); + _optionsParser.GetOverridePackageInformation(Arg.Any()).Returns([]); _optionsParser.GetFileDownloader(Arg.Any()).Returns(new NopFileDownloader()); _optionsParser.GetOutputFormatter(Arg.Any(), Arg.Any(), Arg.Any()).Returns(new LicenseOutput.Table.TableOutputFormatter(false, false)); _optionsParser.GetLicenseMatcher(Arg.Any()).Returns(new FileLicenseMatcher.SPDX.FastLicenseMatcher(Spdx.Licenses.SpdxLicenseStore.Licenses)); diff --git a/tests/NuGetLicense.Test/Output/Csv/CsvOutputFormatterTests.cs b/tests/NuGetLicense.Test/Output/Csv/CsvOutputFormatterTests.cs index 01002e8d..1098c37a 100644 --- a/tests/NuGetLicense.Test/Output/Csv/CsvOutputFormatterTests.cs +++ b/tests/NuGetLicense.Test/Output/Csv/CsvOutputFormatterTests.cs @@ -39,18 +39,16 @@ namespace NuGetLicense.Test.Output.Csv [Arguments(false, false, false, true, false)] [Arguments(false, false, false, false, true)] [Arguments(false, false, false, false, false)] - public class CsvOutputFormatterTests : TestBase + public class CsvOutputFormatterTests(bool omitValidLicensesOnError, + bool skipIgnoredPackages, + bool includeCopyright, + bool includeAuthors, + bool includeLicenseUrl) + : TestBase(includeCopyright, includeAuthors, includeLicenseUrl) { - private readonly bool _omitValidLicensesOnError; - private readonly bool _skipIgnoredPackages; - public CsvOutputFormatterTests(bool omitValidLicensesOnError, bool skipIgnoredPackages, bool includeCopyright, bool includeAuthors, bool includeLicenseUrl) : base(includeCopyright, includeAuthors, includeLicenseUrl) - { - _omitValidLicensesOnError = omitValidLicensesOnError; - _skipIgnoredPackages = skipIgnoredPackages; - } protected override IOutputFormatter CreateUut() { - return new CsvOutputFormatter(_omitValidLicensesOnError, _skipIgnoredPackages); + return new CsvOutputFormatter(omitValidLicensesOnError, skipIgnoredPackages); } } } diff --git a/tests/NuGetLicense.Test/Output/Helper/NuGetVersion.cs b/tests/NuGetLicense.Test/Output/Helper/NuGetVersion.cs index e32a4e4c..88f47f93 100644 --- a/tests/NuGetLicense.Test/Output/Helper/NuGetVersion.cs +++ b/tests/NuGetLicense.Test/Output/Helper/NuGetVersion.cs @@ -5,20 +5,13 @@ namespace NuGetLicense.Test.Output.Helper { - public class NuGetVersion : INuGetVersion + public class NuGetVersion(string version) : INuGetVersion { - private readonly string _version; - - public NuGetVersion(string version) - { - _version = version; - } - public int CompareTo(INuGetVersion? other) => throw new NotImplementedException(); public override string ToString() { - return _version; + return version; } } } diff --git a/tests/NuGetLicense.Test/Output/Json/JsonOutputFormatterTest.cs b/tests/NuGetLicense.Test/Output/Json/JsonOutputFormatterTest.cs index 35228175..e8500a4e 100644 --- a/tests/NuGetLicense.Test/Output/Json/JsonOutputFormatterTest.cs +++ b/tests/NuGetLicense.Test/Output/Json/JsonOutputFormatterTest.cs @@ -71,21 +71,17 @@ namespace NuGetLicense.Test.Output.Json [Arguments(false, false, false, false, true, false)] [Arguments(false, false, false, false, false, true)] [Arguments(false, false, false, false, false, false)] - public class JsonOutputFormatterTest : TestBase + public class JsonOutputFormatterTest(bool prettyPrint, + bool omitValidLicensesOnError, + bool skipIgnoredPackages, + bool includeCopyright, + bool includeAuthors, + bool includeLicenseUrl) + : TestBase(includeCopyright, includeAuthors, includeLicenseUrl) { - private readonly bool _prettyPrint; - private readonly bool _omitValidLicensesOnError; - private readonly bool _skipIgnoredPackages; - - public JsonOutputFormatterTest(bool prettyPrint, bool omitValidLicensesOnError, bool skipIgnoredPackages, bool includeCopyright, bool includeAuthors, bool includeLicenseUrl) : base(includeCopyright, includeAuthors, includeLicenseUrl) - { - _prettyPrint = prettyPrint; - _omitValidLicensesOnError = omitValidLicensesOnError; - _skipIgnoredPackages = skipIgnoredPackages; - } protected override IOutputFormatter CreateUut() { - return new JsonOutputFormatter(_prettyPrint, _omitValidLicensesOnError, _skipIgnoredPackages); + return new JsonOutputFormatter(prettyPrint, omitValidLicensesOnError, skipIgnoredPackages); } } } diff --git a/tests/NuGetLicense.Test/Output/Table/MarkdownTableOutputFormatterTest.cs b/tests/NuGetLicense.Test/Output/Table/MarkdownTableOutputFormatterTest.cs index af894cf4..96b27d30 100644 --- a/tests/NuGetLicense.Test/Output/Table/MarkdownTableOutputFormatterTest.cs +++ b/tests/NuGetLicense.Test/Output/Table/MarkdownTableOutputFormatterTest.cs @@ -39,19 +39,16 @@ namespace NuGetLicense.Test.Output.Table [Arguments(false, false, false, true, false)] [Arguments(false, false, false, false, true)] [Arguments(false, false, false, false, false)] - public class MarkdownTableOutputFormatterTest : TestBase + public class MarkdownTableOutputFormatterTest(bool omitValidLicensesOnError, + bool skipIgnoredPackages, + bool includeCopyright, + bool includeAuthors, + bool includeLicenseUrl) + : TestBase(includeCopyright, includeAuthors, includeLicenseUrl) { - private readonly bool _omitValidLicensesOnError; - private readonly bool _skipIgnoredPackages; - - public MarkdownTableOutputFormatterTest(bool omitValidLicensesOnError, bool skipIgnoredPackages, bool includeCopyright, bool includeAuthors, bool includeLicenseUrl) : base(includeCopyright, includeAuthors, includeLicenseUrl) - { - _omitValidLicensesOnError = omitValidLicensesOnError; - _skipIgnoredPackages = skipIgnoredPackages; - } protected override IOutputFormatter CreateUut() { - return new TableOutputFormatter(_omitValidLicensesOnError, _skipIgnoredPackages, true); + return new TableOutputFormatter(omitValidLicensesOnError, skipIgnoredPackages, true); } } } diff --git a/tests/NuGetLicense.Test/Output/Table/TableOutputFormatterTest.cs b/tests/NuGetLicense.Test/Output/Table/TableOutputFormatterTest.cs index b58025d8..e8c94c0f 100644 --- a/tests/NuGetLicense.Test/Output/Table/TableOutputFormatterTest.cs +++ b/tests/NuGetLicense.Test/Output/Table/TableOutputFormatterTest.cs @@ -39,19 +39,16 @@ namespace NuGetLicense.Test.Output.Table [Arguments(false, false, false, true, false)] [Arguments(false, false, false, false, true)] [Arguments(false, false, false, false, false)] - public class TableOutputFormatterTest : TestBase + public class TableOutputFormatterTest(bool omitValidLicensesOnError, + bool skipIgnoredPackages, + bool includeCopyright, + bool includeAuthors, + bool includeLicenseUrl) + : TestBase(includeCopyright, includeAuthors, includeLicenseUrl) { - private readonly bool _omitValidLicensesOnError; - private readonly bool _skipIgnoredPackages; - - public TableOutputFormatterTest(bool omitValidLicensesOnError, bool skipIgnoredPackages, bool includeCopyright, bool includeAuthors, bool includeLicenseUrl) : base(includeCopyright, includeAuthors, includeLicenseUrl) - { - _omitValidLicensesOnError = omitValidLicensesOnError; - _skipIgnoredPackages = skipIgnoredPackages; - } protected override IOutputFormatter CreateUut() { - return new TableOutputFormatter(_omitValidLicensesOnError, _skipIgnoredPackages); + return new TableOutputFormatter(omitValidLicensesOnError, skipIgnoredPackages); } } } diff --git a/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerable.cs b/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerable.cs index 3bda0596..c8ab8397 100644 --- a/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerable.cs +++ b/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerable.cs @@ -3,18 +3,11 @@ namespace NuGetUtility.Test.Extensions.Helper.AsyncEnumerableExtension { - internal class AsyncEnumerable : IAsyncEnumerable + internal class AsyncEnumerable(IEnumerable synchronous) : IAsyncEnumerable { - private readonly IEnumerable _synchronous; - - public AsyncEnumerable(IEnumerable synchronous) - { - _synchronous = synchronous; - } - - public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new()) { - return new AsyncEnumerator(_synchronous.GetEnumerator()); + return new AsyncEnumerator(synchronous.GetEnumerator()); } } } diff --git a/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerator.cs b/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerator.cs index 923ae36a..88f6efb0 100644 --- a/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerator.cs +++ b/tests/NuGetUtility.Test.Extensions/Helper/AsyncEnumerableExtension/AsyncEnumerator.cs @@ -3,18 +3,11 @@ namespace NuGetUtility.Test.Extensions.Helper.AsyncEnumerableExtension { - internal class AsyncEnumerator : IAsyncEnumerator + internal class AsyncEnumerator(IEnumerator sync) : IAsyncEnumerator { - private readonly IEnumerator _sync; - - public AsyncEnumerator(IEnumerator sync) - { - _sync = sync; - } - public ValueTask DisposeAsync() { - _sync.Dispose(); + sync.Dispose(); #if NETFRAMEWORK return new ValueTask(Task.CompletedTask); #else @@ -24,7 +17,7 @@ public ValueTask DisposeAsync() public ValueTask MoveNextAsync() { - bool result = _sync.MoveNext(); + bool result = sync.MoveNext(); #if NETFRAMEWORK return new ValueTask(Task.FromResult(result)); #else @@ -32,6 +25,6 @@ public ValueTask MoveNextAsync() #endif } - public T Current => _sync.Current; + public T Current => sync.Current; } } diff --git a/tests/NuGetUtility.Test.Extensions/Helper/AutoFixture/NuGet/Versioning/NuGetVersionBuilder.cs b/tests/NuGetUtility.Test.Extensions/Helper/AutoFixture/NuGet/Versioning/NuGetVersionBuilder.cs index ecd59bbe..bf0267dc 100644 --- a/tests/NuGetUtility.Test.Extensions/Helper/AutoFixture/NuGet/Versioning/NuGetVersionBuilder.cs +++ b/tests/NuGetUtility.Test.Extensions/Helper/AutoFixture/NuGet/Versioning/NuGetVersionBuilder.cs @@ -8,7 +8,7 @@ namespace NuGetUtility.Test.Extensions.Helper.AutoFixture.NuGet.Versioning { public class NuGetVersionBuilder : ISpecimenBuilder { - private readonly Random _rnd = new Random(); + private readonly Random _rnd = new(); public object Create(object request, ISpecimenContext context) { @@ -35,20 +35,13 @@ private bool RandomBool() return _rnd.Next() % 2 == 0; } - private class NuGetVersion : INuGetVersion + private class NuGetVersion(string version) : INuGetVersion { - private readonly string _version; - - public NuGetVersion(string version) - { - _version = version; - } - public int CompareTo(INuGetVersion? other) => throw new NotImplementedException(); public override string ToString() { - return _version; + return version; } } } diff --git a/tests/NuGetUtility.Test/Architecture/ArchitectureTest.cs b/tests/NuGetUtility.Test/Architecture/ArchitectureTest.cs index 79ef5222..32b9478e 100644 --- a/tests/NuGetUtility.Test/Architecture/ArchitectureTest.cs +++ b/tests/NuGetUtility.Test/Architecture/ArchitectureTest.cs @@ -1,19 +1,13 @@ // Licensed to the project contributors. // The license conditions are provided in the LICENSE file located in the project root -using System.Reflection; using NetArchTest.Rules; namespace NuGetUtility.Test.Architecture { public abstract class ArchitectureTest { - protected Types Types { get; } - - protected ArchitectureTest() - { - Types = Types.InAssemblies([global::System.Reflection.Assembly.Load(AssemblyNames.NuGetUtility)]); - } + protected Types Types { get; } = Types.InAssemblies([System.Reflection.Assembly.Load(AssemblyNames.NuGetUtility)]); internal static class AssemblyNames { diff --git a/tests/NuGetUtility.Test/Architecture/ConditionsExtensions.cs b/tests/NuGetUtility.Test/Architecture/ConditionsExtensions.cs index 042bd0cd..03242716 100644 --- a/tests/NuGetUtility.Test/Architecture/ConditionsExtensions.cs +++ b/tests/NuGetUtility.Test/Architecture/ConditionsExtensions.cs @@ -15,7 +15,7 @@ public static Task Assert(this ConditionList conditions, string message = "Archi return Task.CompletedTask; } - string failingTypeNames = string.Join(Environment.NewLine, ruleResult.FailingTypeNames ?? Array.Empty()); + string failingTypeNames = string.Join(Environment.NewLine, ruleResult.FailingTypeNames ?? []); throw new Exception($"{message}{Environment.NewLine}Offending types:{Environment.NewLine}{failingTypeNames}"); } } diff --git a/tests/NuGetUtility.Test/Extensions/HashSetExtensionsTest.cs b/tests/NuGetUtility.Test/Extensions/HashSetExtensionsTest.cs index 73bebac0..fb5352e7 100644 --- a/tests/NuGetUtility.Test/Extensions/HashSetExtensionsTest.cs +++ b/tests/NuGetUtility.Test/Extensions/HashSetExtensionsTest.cs @@ -9,17 +9,12 @@ namespace NuGetUtility.Test.Extensions { public abstract class HashSetExtensionsTestBase { - private readonly Fixture _fixture; - - protected HashSetExtensionsTestBase() - { - _fixture = new Fixture(); - } + private readonly Fixture _fixture = new(); [Test] public async Task AddMany_Should_AddNewElementsToHashSet() { - HashSet uut = new HashSet(_fixture.CreateMany()); + HashSet uut = new(_fixture.CreateMany()); T[] newElements = _fixture.CreateMany().ToArray(); ImmutableList initialElements = [.. uut]; @@ -31,7 +26,7 @@ public async Task AddMany_Should_AddNewElementsToHashSet() [Test] public async Task AddMany_Should_OnlyAddNewItems() { - HashSet uut = new HashSet(_fixture.CreateMany()); + HashSet uut = new(_fixture.CreateMany()); T[] newElements = _fixture.CreateMany().ToArray(); ImmutableList initialElements = [.. uut]; @@ -43,7 +38,7 @@ public async Task AddMany_Should_OnlyAddNewItems() [Test] public async Task AddMany_Should_KeepSameHashSetIfOnlyAddingSameElements() { - HashSet uut = new HashSet(_fixture.CreateMany()); + HashSet uut = new(_fixture.CreateMany()); ImmutableList initialElements = [.. uut]; uut.AddRange(initialElements); diff --git a/tests/NuGetUtility.Test/Extensions/ProjectExtensionsTest.cs b/tests/NuGetUtility.Test/Extensions/ProjectExtensionsTest.cs index 7359aebe..b478bfe8 100644 --- a/tests/NuGetUtility.Test/Extensions/ProjectExtensionsTest.cs +++ b/tests/NuGetUtility.Test/Extensions/ProjectExtensionsTest.cs @@ -9,12 +9,7 @@ namespace NuGetUtility.Test.Extensions { public class ProjectExtensionsTest { - private readonly IProject _project; - - public ProjectExtensionsTest() - { - _project = Substitute.For(); - } + private readonly IProject _project = Substitute.For(); [Test] public async Task GetPackagesConfigPath_Should_Return_CorrectPath() @@ -30,13 +25,13 @@ public async Task GetPackagesConfigPath_Should_Return_CorrectPath() [Test] [Arguments(new string?[] { }, false)] [Arguments(new string?[] { null }, false)] - [Arguments(new string?[] { null, "not-packages.config" }, false)] - [Arguments(new string?[] { "not-packages.config" }, false)] - [Arguments(new string?[] { "packages.config" }, true)] - [Arguments(new string?[] { null, "packages.config" }, true)] - [Arguments(new string?[] { "not-packages.config", "packages.config" }, true)] - [Arguments(new string?[] { null, "not-packages.config", "packages.config" }, true)] - public async Task HasPackagesConfigFile_Should_Return_Correct_Result(IEnumerable evaluatedIncludes, bool expectation) + [Arguments(new[] { null, "not-packages.config" }, false)] + [Arguments(new[] { "not-packages.config" }, false)] + [Arguments(new[] { "packages.config" }, true)] + [Arguments(new[] { null, "packages.config" }, true)] + [Arguments(new[] { "not-packages.config", "packages.config" }, true)] + [Arguments(new[] { null, "not-packages.config", "packages.config" }, true)] + public async Task HasPackagesConfigFile_Should_Return_Correct_Result(IEnumerable evaluatedIncludes, bool expectation) { _project.GetEvaluatedIncludes().Returns(evaluatedIncludes); diff --git a/tests/NuGetUtility.Test/PackageInformationReader/PackageInformationReaderTest.cs b/tests/NuGetUtility.Test/PackageInformationReader/PackageInformationReaderTest.cs index 569ba7c2..54b98e9a 100644 --- a/tests/NuGetUtility.Test/PackageInformationReader/PackageInformationReaderTest.cs +++ b/tests/NuGetUtility.Test/PackageInformationReader/PackageInformationReaderTest.cs @@ -24,7 +24,7 @@ public PackageInformationReaderTest() _fixture = new Fixture().Customize(new AutoNSubstituteCustomization()); _fixture.Customizations.Add(new NuGetVersionBuilder()); _fixture.Customizations.Add(new CustomPackageInformationBuilderWithOptionalFileds()); - _repositories = Array.Empty(); + _repositories = []; _globalPackagesFolderUtility = Substitute.For(); _globalPackagesFolderUtility.GetPackage(Arg.Any()).Returns(default(IPackageMetadata?)); diff --git a/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs b/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs index d3cb5d95..52c19a3f 100644 --- a/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs +++ b/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs @@ -7,38 +7,26 @@ namespace NuGetUtility.Test.ProjectFiltering { class ProjectFiltererTest { - private readonly ProjectFilter _filterer; - - public ProjectFiltererTest() - { - _filterer = new ProjectFilter(); - } - - [Test] - public async Task FilterProjects_ExcludesSharedProjects_WhenIncludeSharedProjectsIsFalse() - { - string[] projects = ["one.csproj", "two.shproj", "three.csproj", "four.SHPROJ"]; - - string[] result = _filterer.FilterProjects(projects, false).ToArray(); - - await Assert.That(result.Count).IsEqualTo(2); - await Assert.That(result.Contains("one.csproj")).IsTrue(); - await Assert.That(result.Contains("three.csproj")).IsTrue(); - await Assert.That(result.Contains("two.shproj")).IsFalse(); - await Assert.That(result.Contains("four.SHPROJ")).IsFalse(); - } + private readonly ProjectFilter _filterer = new(); [Test] - public async Task FilterProjects_IncludesAllProjects_WhenIncludeSharedProjectsIsTrue() + [Arguments("one.csproj", false, false)] + [Arguments("two.shproj", true, false)] + [Arguments("three.csproj", false, false)] + [Arguments("four.SHPROJ", true, false)] + [Arguments("one.csproj", true, true)] + [Arguments("two.shproj", true, true)] + [Arguments("three.csproj", true, true)] + [Arguments("four.SHPROJ", true, true)] + public async Task FilterProjects_ExcludesSharedProjects_WhenIncludeSharedProjectsIsFalse(string project, bool isFiltered, bool includeSharedProjects) { - string[] projects = ["one.csproj", "two.shproj", "three.csproj", "four.SHPROJ"]; - - string[] result = _filterer.FilterProjects(projects, true).ToArray(); + string[] result = _filterer.FilterProjects([project], includeSharedProjects).ToArray(); - await Assert.That(result.Count).IsEqualTo(4); - await Assert.That(result.Contains("one.csproj")).IsTrue(); - await Assert.That(result.Contains("two.shproj")).IsTrue(); - await Assert.That(result.Contains("three.csproj")).IsTrue(); + await Assert.That(result).Count().IsEqualTo(isFiltered ? 0 : 1); + if (!isFiltered) + { + await Assert.That(result).Contains(project); + } } } } diff --git a/tests/NuGetUtility.Test/ReferencedPackagesReader/ProjectsCollectorTest.cs b/tests/NuGetUtility.Test/ReferencedPackagesReader/ProjectsCollectorTest.cs index d0a5b6a2..824a9d0e 100644 --- a/tests/NuGetUtility.Test/ReferencedPackagesReader/ProjectsCollectorTest.cs +++ b/tests/NuGetUtility.Test/ReferencedPackagesReader/ProjectsCollectorTest.cs @@ -18,12 +18,12 @@ public ProjectsCollectorTest() _osPlatformSpecificVerifySettings = new(); _osPlatformSpecificVerifySettings.UniqueForOSPlatform(); _fixture = new Fixture(); - _solutionPersistanceWrapper = Substitute.For(); + _solutionPersistenceWrapper = Substitute.For(); _fileSystem = new MockFileSystem(); - _uut = new ProjectsCollector(_solutionPersistanceWrapper, _fileSystem); + _uut = new ProjectsCollector(_solutionPersistenceWrapper, _fileSystem); } - private readonly ISolutionPersistanceWrapper _solutionPersistanceWrapper; + private readonly ISolutionPersistenceWrapper _solutionPersistenceWrapper; private readonly IFileSystem _fileSystem; private readonly ProjectsCollector _uut; private readonly Fixture _fixture; @@ -38,7 +38,7 @@ public async Task GetProjects_Should_ReturnProjectsAsListDirectly(string project { IEnumerable result = await _uut.GetProjectsAsync(projectFile); await Assert.That(result).IsEquivalentTo([_fileSystem.Path.GetFullPath(projectFile)]); - await _solutionPersistanceWrapper.DidNotReceive().GetProjectsFromSolutionAsync(Arg.Any()); + await _solutionPersistenceWrapper.DidNotReceive().GetProjectsFromSolutionAsync(Arg.Any()); } [Test] @@ -50,7 +50,7 @@ public async Task GetProjects_Should_QueryMsBuildToGetProjectsForSolutionFiles(s { _ = await _uut.GetProjectsAsync(solutionFile); - await _solutionPersistanceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); + await _solutionPersistenceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); } [Test] @@ -60,12 +60,12 @@ public async Task GetProjects_Should_QueryMsBuildToGetProjectsForSolutionFiles(s [Arguments("C.slnx")] public async Task GetProjects_Should_ReturnEmptyArray_If_SolutionContainsNoProjects(string solutionFile) { - _solutionPersistanceWrapper.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult(Enumerable.Empty())); + _solutionPersistenceWrapper.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult(Enumerable.Empty())); IEnumerable result = await _uut.GetProjectsAsync(solutionFile); await Assert.That(result).IsEmpty(); - await _solutionPersistanceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); + await _solutionPersistenceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); } [Test] @@ -76,12 +76,12 @@ public async Task GetProjects_Should_ReturnEmptyArray_If_SolutionContainsNoProje public async Task GetProjects_Should_ReturnEmptyArray_If_SolutionContainsProjectsThatDontExist(string solutionFile) { IEnumerable projects = _fixture.CreateMany(); - _solutionPersistanceWrapper.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult(projects)); + _solutionPersistenceWrapper.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult(projects)); IEnumerable result = await _uut.GetProjectsAsync(solutionFile); await Assert.That(result).IsEmpty(); - await _solutionPersistanceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); + await _solutionPersistenceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); } [Test] @@ -93,12 +93,12 @@ public async Task GetProjects_Should_ReturnArrayOfProjects_If_SolutionContainsPr { string[] projects = _fixture.CreateMany().ToArray(); CreateFiles(projects); - _solutionPersistanceWrapper.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(projects)); + _solutionPersistenceWrapper.GetProjectsFromSolutionAsync(Arg.Any()).Returns(Task.FromResult>(projects)); IEnumerable result = await _uut.GetProjectsAsync(solutionFile); await Assert.That(result).IsEquivalentTo(projects.Select(_fileSystem.Path.GetFullPath)); - await _solutionPersistanceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); + await _solutionPersistenceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); } [Test] @@ -113,19 +113,19 @@ public async Task GetProjects_Should_ReturnOnlyExistingProjectsInSolutionFile(st CreateFiles(existingProjects); - _solutionPersistanceWrapper.GetProjectsFromSolutionAsync(Arg.Any()) + _solutionPersistenceWrapper.GetProjectsFromSolutionAsync(Arg.Any()) .Returns(existingProjects.Concat(missingProjects).Shuffle(54321)); IEnumerable result = await _uut.GetProjectsAsync(solutionFile); await Assert.That(result).IsEquivalentTo(existingProjects.Select(_fileSystem.Path.GetFullPath)); - await _solutionPersistanceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); + await _solutionPersistenceWrapper.Received(1).GetProjectsFromSolutionAsync(_fileSystem.Path.GetFullPath(solutionFile)); } [Test] public async Task GetProjectsFromSolution_Should_ReturnProjectsInActualSolutionFileRelativePath() { - var solutionPersistance = new SolutionPersistanceWrapper(); + var solutionPersistance = new SolutionPersistenceWrapper(); string solutionFolder = Path.GetFullPath("../../../../targets"); string solutionFileName = "Projects.sln"; IEnumerable result = await solutionPersistance.GetProjectsFromSolutionAsync(_fileSystem.Path.Combine(solutionFolder, solutionFileName)); @@ -138,7 +138,7 @@ public async Task GetProjectsFromSolution_Should_ReturnProjectsInActualSolutionF [Test] public async Task GetProjectsFromXmlSolution_Should_ReturnProjectsInActualSolutionFileRelativePath() { - var solutionPersistance = new SolutionPersistanceWrapper(); + var solutionPersistance = new SolutionPersistenceWrapper(); string solutionFolder = Path.GetFullPath("../../../../targets/slnx"); string solutionFileName = "slnx.slnx"; IEnumerable result = await solutionPersistance.GetProjectsFromSolutionAsync(_fileSystem.Path.Combine(solutionFolder, solutionFileName)); @@ -152,7 +152,7 @@ private void CreateFiles(IEnumerable files) { foreach (string file in files) { - _fileSystem.File.WriteAllBytes(file, Array.Empty()); + _fileSystem.File.WriteAllBytes(file, []); } } @@ -163,8 +163,8 @@ private string GetPathRelativeTo(string relativeTo, string path) relativeTo = relativeTo.TrimEnd(_fileSystem.Path.DirectorySeparatorChar, _fileSystem.Path.AltDirectorySeparatorChar); relativeTo += _fileSystem.Path.DirectorySeparatorChar; - Uri baseUri = new Uri(relativeTo); - Uri fullUri = new Uri(path); + Uri baseUri = new(relativeTo); + Uri fullUri = new(path); Uri relativeUri = baseUri.MakeRelativeUri(fullUri); diff --git a/tests/NuGetUtility.Test/ReferencedPackagesReader/ReferencedPackageReaderTest.cs b/tests/NuGetUtility.Test/ReferencedPackagesReader/ReferencedPackageReaderTest.cs index c434ac01..91600ada 100644 --- a/tests/NuGetUtility.Test/ReferencedPackagesReader/ReferencedPackageReaderTest.cs +++ b/tests/NuGetUtility.Test/ReferencedPackagesReader/ReferencedPackageReaderTest.cs @@ -52,8 +52,8 @@ public ReferencedPackageReaderTest() return true; }); _projectMock.FullPath.Returns(_projectPath); - _projectMock.GetPackageReferences().Returns(Array.Empty()); - _projectMock.GetPackageReferencesForTarget(Arg.Any()).Returns(Array.Empty()); + _projectMock.GetPackageReferences().Returns([]); + _projectMock.GetPackageReferencesForTarget(Arg.Any()).Returns([]); _lockFileFactory.GetFromFile(_assetsFilePath).Returns(_lockFileMock); _lockFileMock.PackageSpec.Returns(_packageSpecMock); _packageSpecMock.IsValid().Returns(true); @@ -172,7 +172,7 @@ await Assert.That(() => _uut.GetInstalledPackages(_projectPath, includeTransitiv [Arguments(false)] public async Task GetInstalledPackages_Should_ThrowReferencedPackageReaderException_If_TargetsArrayDoesNotContainAnyElement(bool includeTransitive) { - _lockFileMock.Targets.Returns(Enumerable.Empty()); + _lockFileMock.Targets.Returns([]); await Assert.That(() => _uut.GetInstalledPackages(_projectPath, includeTransitive)) .Throws() @@ -183,7 +183,7 @@ await Assert.That(() => _uut.GetInstalledPackages(_projectPath, includeTransitiv public async Task GetInstalledPackages_Should_ThrowReferencedPackageReaderException_If_NotIncludingTransitive_And_PackageSpecFrameworkInformationGetFails() { _packageSpecMock.TargetFrameworks - .Returns(Enumerable.Empty()); + .Returns([]); ReferencedPackageReaderException exception = (await Assert.That(() => _uut.GetInstalledPackages(_projectPath, false)) .Throws())!; @@ -202,13 +202,13 @@ public async Task GetInstalledPackages_Should_ThrowReferencedPackageReaderExcept INuGetFramework frameworkNet80 = Substitute.For(); frameworkNet80.ToString().Returns("net8.0"); targetNet80.TargetFramework.Returns(frameworkNet80); - targetNet80.Libraries.Returns(Array.Empty()); + targetNet80.Libraries.Returns([]); ILockFileTarget targetNet90 = Substitute.For(); INuGetFramework frameworkNet90 = Substitute.For(); frameworkNet90.ToString().Returns("net9.0"); targetNet90.TargetFramework.Returns(frameworkNet90); - targetNet90.Libraries.Returns(Array.Empty()); + targetNet90.Libraries.Returns([]); @@ -222,7 +222,7 @@ await Assert.That(() => _uut.GetInstalledPackages(_projectPath, false, targetFra [Test] public async Task GetInstalledPackages_Should_ReturnCorrectValues_If_TargetFrameworks_Returns_Empty_And_Requested_Transitive_Packages() { - _packageSpecMock.TargetFrameworks.Returns(Enumerable.Empty()); + _packageSpecMock.TargetFrameworks.Returns([]); IEnumerable result = _uut.GetInstalledPackages(_projectPath, true); await Assert.That(result).IsEquivalentTo(_referencedPackagesForFramework.SelectMany(kvp => kvp.Value).Distinct()); } @@ -362,7 +362,7 @@ public async Task GetInstalledPackages_Should_ReturnCorrectValues_If_NotIncludin public async Task GetInstalledPackages_Should_ReturnEmptyCollection_If_Cannot_Get_Asset_File_Path_And_Has_No_Packages_Config() { _projectMock.TryGetAssetsPath(out Arg.Any()).Returns(false); - _projectMock.GetEvaluatedIncludes().Returns(Enumerable.Empty()); + _projectMock.GetEvaluatedIncludes().Returns([]); IEnumerable result = _uut.GetInstalledPackages(_projectPath, false); await Assert.That(result).Count().IsEqualTo(0); @@ -502,7 +502,7 @@ public async Task GetInstalledPackages_Should_Apply_PublishFalse_PerTarget_When_ }) ]); - _projectMock.GetPackageReferencesForTarget("net9.0").Returns(Array.Empty()); + _projectMock.GetPackageReferencesForTarget("net9.0").Returns([]); IEnumerable result = _uut.GetInstalledPackages(_projectPath, true, null, true); From 7b0dea1722f556de7eaa51d03b557e7202b9afd1 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 21:04:40 +0200 Subject: [PATCH 5/8] avpod coderabbit to suggest xml comments --- .coderabbit.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 8dc8ebd9..f5fe857e 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -3,3 +3,6 @@ reviews: path_filters: # Exclude all Verify snapshot testing files - "!**/*.verified.txt" + # Provide custom prompt instructions to CodeRabbit + instructions: | + Do not suggest adding XML documentation comments or summary tags to public methods, classes, or properties unless specifically requested. From e35a83cb1ccf2e8a10ec999354747cb81f81b2fd Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 21:11:35 +0200 Subject: [PATCH 6/8] fix compilation --- src/NuGetLicense/LicenseValidationOrchestrator.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/NuGetLicense/LicenseValidationOrchestrator.cs b/src/NuGetLicense/LicenseValidationOrchestrator.cs index d0351a32..263abecf 100644 --- a/src/NuGetLicense/LicenseValidationOrchestrator.cs +++ b/src/NuGetLicense/LicenseValidationOrchestrator.cs @@ -89,7 +89,11 @@ public async Task ValidateAsync(ICommandLineOptions options, CancellationTo { if (shouldDisposeStream) { +#if NETFRAMEWORK + os.Dispose(); +#else await os.DisposeAsync(); +#endif } } } From 198a307a6892dfbcb12960fb2777fdb1a011e386 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 21:18:38 +0200 Subject: [PATCH 7/8] Fix tests --- .../ProjectFiltering/ProjectFiltererTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs b/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs index 52c19a3f..a3a68927 100644 --- a/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs +++ b/tests/NuGetUtility.Test/ProjectFiltering/ProjectFiltererTest.cs @@ -14,10 +14,10 @@ class ProjectFiltererTest [Arguments("two.shproj", true, false)] [Arguments("three.csproj", false, false)] [Arguments("four.SHPROJ", true, false)] - [Arguments("one.csproj", true, true)] - [Arguments("two.shproj", true, true)] - [Arguments("three.csproj", true, true)] - [Arguments("four.SHPROJ", true, true)] + [Arguments("one.csproj", false, true)] + [Arguments("two.shproj", false, true)] + [Arguments("three.csproj", false, true)] + [Arguments("four.SHPROJ", false, true)] public async Task FilterProjects_ExcludesSharedProjects_WhenIncludeSharedProjectsIsFalse(string project, bool isFiltered, bool includeSharedProjects) { string[] result = _filterer.FilterProjects([project], includeSharedProjects).ToArray(); From 88c18aef9671cb5b6173069be3a09713a66cf3d0 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Sun, 17 May 2026 21:29:24 +0200 Subject: [PATCH 8/8] Fix more rabbit complaints --- src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs | 4 ++-- .../Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs index f8b63c6f..f9babb54 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs @@ -50,9 +50,9 @@ private async Task DownloadFileActuallyAsync(Uri url, string fileNameSte private async Task TryDownload(string fileNameStem, Uri url, CancellationToken token) #pragma warning restore S1172 // Unused parameter { - var request = new HttpRequestMessage(HttpMethod.Get, url); + using var request = new HttpRequestMessage(HttpMethod.Get, url); - HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); + using HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); #if NETFRAMEWORK // System.Net.HttpStatusCode.TooManyRequests does not exist in .net472 if (response.StatusCode == (System.Net.HttpStatusCode)429) diff --git a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs index c0dbda1a..115975bf 100644 --- a/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs +++ b/src/NuGetUtility/Wrapper/NuGetWrapper/Protocol/WrappedPackageMetadata.cs @@ -11,8 +11,8 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Protocol internal class WrappedPackageMetadata(ManifestMetadata metadata) : IWrappedPackageMetadata { - public PackageIdentity Identity { get; } = new(metadata.Id ?? throw new ArgumentNullException(nameof(metadata.Id)), - new WrappedNuGetVersion(metadata.Version ?? throw new ArgumentNullException(nameof(metadata.Version)))); + public PackageIdentity Identity { get; } = new(metadata.Id ?? throw new ArgumentException("Id must not be null", nameof(metadata)), + new WrappedNuGetVersion(metadata.Version ?? throw new ArgumentException("Version must not be null", nameof(metadata)))); public string? Title => metadata.Title;