Skip to content

Commit 2669e37

Browse files
authored
NuGetAuditSuppress for LegacyPackageReferenceProject in VS (#5714)
1 parent 252bbee commit 2669e37

8 files changed

Lines changed: 106 additions & 22 deletions

File tree

build/Shared/vs-threading.MembersRequiringMainThread.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
[NuGet.PackageManagement.VisualStudio.EnvDTEProjectUtility]::TryGetFolder
1212
[NuGet.PackageManagement.VisualStudio.EnvDTEProjectUtility]::TryGetNestedFile
1313
[NuGet.ProjectManagement.IProjectBuildProperties]::GetPropertyValue
14-
[NuGet.VisualStudio.IVsProjectBuildProperties]::GetPropertyValue
14+
[NuGet.VisualStudio.IVsProjectAdapter]::GetBuildItemInformation
1515
[NuGet.VisualStudio.IVsProjectAdapter]::IsCapabilityMatch
16+
[NuGet.VisualStudio.IVsProjectBuildProperties]::GetPropertyValue

src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProject.cs

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,12 @@ protected override async Task<string> GetAssetsFilePathAsync(bool shouldThrow)
128128
return (new[] { packageSpec }, null);
129129
}
130130

131-
private async Task<Dictionary<string, CentralPackageVersion>> GetCentralPackageVersionsAsync()
131+
private Dictionary<string, CentralPackageVersion> GetCentralPackageVersions()
132132
{
133+
ThreadHelper.ThrowIfNotOnUIThread();
134+
133135
IEnumerable<(string PackageId, string Version)> packageVersions =
134-
(await _vsProjectAdapter.GetBuildItemInformationAsync(ProjectBuildProperties.PackageVersion, ProjectBuildProperties.Version))
136+
_vsProjectAdapter.GetBuildItemInformation(ProjectBuildProperties.PackageVersion, ProjectBuildProperties.Version)
135137
.Select(item => (PackageId: item.ItemId, Version: item.ItemMetadata.FirstOrDefault()));
136138

137139
return packageVersions
@@ -156,6 +158,57 @@ private CentralPackageVersion ToCentralPackageVersion(string packageId, string v
156158
return new CentralPackageVersion(packageId, VersionRange.Parse(version));
157159
}
158160

161+
private RestoreAuditProperties GetRestoreAuditProperties()
162+
{
163+
ThreadHelper.ThrowIfNotOnUIThread();
164+
165+
string enableAudit = _vsProjectAdapter.BuildProperties.GetPropertyValue(ProjectBuildProperties.NuGetAudit);
166+
string auditLevel = _vsProjectAdapter.BuildProperties.GetPropertyValue(ProjectBuildProperties.NuGetAuditLevel);
167+
string auditMode = _vsProjectAdapter.BuildProperties.GetPropertyValue(ProjectBuildProperties.NuGetAuditMode);
168+
HashSet<string> suppressedAdvisories = GetSuppressedAdvisories();
169+
170+
return new RestoreAuditProperties()
171+
{
172+
EnableAudit = enableAudit,
173+
AuditLevel = auditLevel,
174+
AuditMode = auditMode,
175+
SuppressedAdvisories = suppressedAdvisories,
176+
};
177+
}
178+
179+
private HashSet<string> GetSuppressedAdvisories()
180+
{
181+
ThreadHelper.ThrowIfNotOnUIThread();
182+
183+
IEnumerable<(string ItemId, string[] ItemMetadata)> buildItems = _vsProjectAdapter.GetBuildItemInformation(ProjectBuildProperties.NuGetAuditSuppress);
184+
if (buildItems is null)
185+
{
186+
return null;
187+
}
188+
else if (buildItems is ICollection<(string, string[])> collection)
189+
{
190+
if (collection.Count == 0) return null;
191+
192+
var suppressedAdvisories = new HashSet<string>(collection.Count, StringComparer.OrdinalIgnoreCase);
193+
foreach ((string itemId, _) in buildItems.NoAllocEnumerate())
194+
{
195+
suppressedAdvisories.Add(itemId);
196+
}
197+
198+
return suppressedAdvisories;
199+
}
200+
else
201+
{
202+
var suppressedAdvisories = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
203+
foreach ((string itemId, _) in buildItems.NoAllocEnumerate())
204+
{
205+
suppressedAdvisories.Add(itemId);
206+
}
207+
208+
return suppressedAdvisories.Count == 0 ? null : suppressedAdvisories;
209+
}
210+
}
211+
159212
#endregion
160213

161214
#region NuGetProject
@@ -396,7 +449,7 @@ private async Task<PackageSpec> GetPackageSpecAsync(ISettings settings)
396449
if (isCpvmEnabled)
397450
{
398451
// Add the central version information and merge the information to the package reference dependencies
399-
projectTfi.CentralPackageVersions.AddRange(await GetCentralPackageVersionsAsync());
452+
projectTfi.CentralPackageVersions.AddRange(GetCentralPackageVersions());
400453
LibraryDependency.ApplyCentralVersionInformation(projectTfi.Dependencies, projectTfi.CentralPackageVersions);
401454
}
402455

@@ -441,17 +494,7 @@ private async Task<PackageSpec> GetPackageSpecAsync(ISettings settings)
441494
}
442495
}
443496

444-
string enableAudit = _vsProjectAdapter.BuildProperties.GetPropertyValue(ProjectBuildProperties.NuGetAudit);
445-
string auditLevel = _vsProjectAdapter.BuildProperties.GetPropertyValue(ProjectBuildProperties.NuGetAuditLevel);
446-
string auditMode = _vsProjectAdapter.BuildProperties.GetPropertyValue(ProjectBuildProperties.NuGetAuditMode);
447-
RestoreAuditProperties auditProperties = !string.IsNullOrEmpty(enableAudit) || !string.IsNullOrEmpty(auditLevel)
448-
? new RestoreAuditProperties()
449-
{
450-
EnableAudit = enableAudit,
451-
AuditLevel = auditLevel,
452-
AuditMode = auditMode,
453-
}
454-
: null;
497+
RestoreAuditProperties auditProperties = GetRestoreAuditProperties();
455498

456499
var msbuildProjectExtensionsPath = await GetMSBuildProjectExtensionsPathAsync();
457500

src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,19 +212,19 @@ public NuGetFramework GetTargetFramework()
212212
return NuGetFramework.UnsupportedFramework;
213213
}
214214

215-
public async Task<IEnumerable<(string ItemId, string[] ItemMetadata)>> GetBuildItemInformationAsync(string itemName, params string[] metadataNames)
215+
public IEnumerable<(string ItemId, string[] ItemMetadata)> GetBuildItemInformation(string itemName, params string[] metadataNames)
216216
{
217+
ThreadHelper.ThrowIfNotOnUIThread();
218+
217219
if (itemName == null)
218220
{
219221
throw new ArgumentNullException(nameof(itemName));
220222
}
221223
if (metadataNames == null)
222224
{
223-
throw new ArgumentNullException(nameof(itemName));
225+
throw new ArgumentNullException(nameof(metadataNames));
224226
}
225227

226-
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
227-
228228
var itemStorage = VsHierarchy as IVsBuildItemStorage;
229229
if (itemStorage != null)
230230
{

src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public interface IVsProjectAdapter
7171
/// <param name="itemName">The item name.</param>
7272
/// <param name="metadataNames">The metadata names to read.</param>
7373
/// <returns>An <see cref="IEnumerable{(string ItemId, string[] ItemMetadata)}"/> containing the itemId and the metadata values.</returns>
74-
Task<IEnumerable<(string ItemId, string[] ItemMetadata)>> GetBuildItemInformationAsync(string itemName, params string[] metadataNames);
74+
IEnumerable<(string ItemId, string[] ItemMetadata)> GetBuildItemInformation(string itemName, params string[] metadataNames);
7575

7676
/// <summary>
7777
/// See <see cref="Microsoft.VisualStudio.Shell.PackageUtilities.IsCapabilityMatch(IVsHierarchy, string)"/>

src/NuGet.Core/NuGet.PackageManagement/Projects/ProjectBuildProperties.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static class ProjectBuildProperties
5959
public const string NuGetAudit = nameof(NuGetAudit);
6060
public const string NuGetAuditLevel = nameof(NuGetAuditLevel);
6161
public const string NuGetAuditMode = nameof(NuGetAuditMode);
62+
public const string NuGetAuditSuppress = nameof(NuGetAuditSuppress);
6263
public const string CentralPackageFloatingVersionsEnabled = nameof(CentralPackageFloatingVersionsEnabled);
6364
}
6465
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
#nullable enable
2+
~const NuGet.ProjectManagement.ProjectBuildProperties.NuGetAuditSuppress = "NuGetAuditSuppress" -> string

test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceProjectTests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,44 @@ public async Task GetPackageSpecs_WithWarningProperties()
15831583
projectBuildProperties.VerifyAll();
15841584
}
15851585

1586+
[Fact]
1587+
public async Task GetPackageSpec_WithNuGetAuditSuppress()
1588+
{
1589+
await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
1590+
1591+
// Arrange
1592+
using var testDirectory = TestDirectory.Create();
1593+
1594+
var projectBuildProperties = new Mock<IVsProjectBuildProperties>();
1595+
var projectAdapter = CreateProjectAdapter(testDirectory, projectBuildProperties);
1596+
1597+
Mock<IVsProjectAdapter> projectAdapterMock = Mock.Get(projectAdapter);
1598+
projectAdapterMock.Setup(m => m.GetBuildItemInformation(ProjectBuildProperties.NuGetAuditSuppress, It.IsAny<string[]>()))
1599+
.Returns([("https://cve.test/1", Array.Empty<string>())]);
1600+
1601+
var projectServices = new TestProjectSystemServices();
1602+
var testProject = new LegacyPackageReferenceProject(
1603+
projectAdapter,
1604+
Guid.NewGuid().ToString(),
1605+
projectServices,
1606+
_threadingService);
1607+
1608+
var settings = NullSettings.Instance;
1609+
var testDependencyGraphCacheContext = new DependencyGraphCacheContext(NullLogger.Instance, settings);
1610+
1611+
// Act
1612+
var packageSpecs = await testProject.GetPackageSpecsAsync(testDependencyGraphCacheContext);
1613+
1614+
// Assert
1615+
Assert.NotNull(packageSpecs);
1616+
var actualRestoreSpec = packageSpecs.Single();
1617+
SpecValidationUtility.ValidateProjectSpec(actualRestoreSpec);
1618+
1619+
var auditProperties = actualRestoreSpec.RestoreMetadata.RestoreAuditProperties;
1620+
auditProperties.SuppressedAdvisories.Should().NotBeNull();
1621+
auditProperties.SuppressedAdvisories.Should().BeEquivalentTo(["https://cve.test/1"]);
1622+
}
1623+
15861624
private LegacyPackageReferenceProject CreateLegacyPackageReferenceProject(TestDirectory testDirectory, string range)
15871625
{
15881626
return ProjectFactories.CreateLegacyPackageReferenceProject(testDirectory, Guid.NewGuid().ToString(), range, _threadingService);

test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ public NuGetFramework GetTargetFramework()
158158
return Task.FromResult(_projectPackageVersions);
159159
}
160160

161-
public async Task<IEnumerable<(string ItemId, string[] ItemMetadata)>> GetBuildItemInformationAsync(string itemName, params string[] metadataNames)
161+
public IEnumerable<(string ItemId, string[] ItemMetadata)> GetBuildItemInformation(string itemName, params string[] metadataNames)
162162
{
163163
if (itemName == "PackageVersion")
164164
{
165-
return await Task.FromResult(_projectPackageVersions.Select(x => (ItemId: x.PackageId, ItemMetadata: new string[] { x.Version })));
165+
return _projectPackageVersions.Select(x => (ItemId: x.PackageId, ItemMetadata: new string[] { x.Version }));
166166
}
167167

168168
return Enumerable.Empty<(string ItemId, string[] ItemMetadata)>();

0 commit comments

Comments
 (0)