Skip to content

Commit 01276fc

Browse files
authored
Migrate LegacyPackageReferenceProject to PackageSpecFactory (#7263)
1 parent 07e47f1 commit 01276fc

26 files changed

Lines changed: 1353 additions & 422 deletions

File tree

src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/GlobalSuppressions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task<IEnumerable<Project>> EnvDTESolutionUtility.GetAllEnvDTEProjectsAsync(DTE dte)', validate parameter 'dte' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.EnvDTESolutionUtility.GetAllEnvDTEProjectsAsync(EnvDTE.DTE)~System.Threading.Tasks.Task{System.Collections.Generic.IEnumerable{EnvDTE.Project}}")]
3030
[assembly: SuppressMessage("Build", "CA1031:Modify 'GetFrameworkAssemblies' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.FrameworkAssemblyResolver.GetFrameworkAssemblies(System.String)~System.Collections.Generic.List{NuGet.PackageManagement.VisualStudio.FrameworkAssembly}")]
3131
[assembly: SuppressMessage("Build", "CA1031:Modify 'RemoveReferenceAsync' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.FSharpProjectSystem.RemoveReferenceAsync(System.String)~System.Threading.Tasks.Task")]
32-
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'LegacyPackageReferenceProject.LegacyPackageReferenceProject(IVsProjectAdapter vsProjectAdapter, string projectId, INuGetProjectServices projectServices, IVsProjectThreadingService threadingService)', validate parameter 'vsProjectAdapter' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.#ctor(NuGet.VisualStudio.IVsProjectAdapter,System.String,NuGet.ProjectManagement.INuGetProjectServices,NuGet.PackageManagement.VisualStudio.IVsProjectThreadingService)")]
3332
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task LegacyPackageReferenceProject.AddFileToProjectAsync(string filePath)', validate parameter 'filePath' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.AddFileToProjectAsync(System.String)~System.Threading.Tasks.Task")]
3433
[assembly: SuppressMessage("Build", "CA1822:Member GetConfigFilePaths does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.GetConfigFilePaths(NuGet.Configuration.ISettings)~System.Collections.Generic.IList{System.String}")]
3534
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task<bool> LegacyPackageReferenceProject.UninstallPackageAsync(PackageIdentity packageIdentity, INuGetProjectContext _, CancellationToken token)', validate parameter 'packageIdentity' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.UninstallPackageAsync(NuGet.Packaging.Core.PackageIdentity,NuGet.ProjectManagement.INuGetProjectContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Boolean}")]

src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsManagedLanguagesProjectSystemServices.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using NuGet.Common;
1616
using NuGet.Frameworks;
1717
using NuGet.LibraryModel;
18+
using NuGet.PackageManagement.VisualStudio.Projects;
1819
using NuGet.ProjectManagement;
1920
using NuGet.ProjectModel;
2021
using NuGet.Versioning;
@@ -32,12 +33,14 @@ internal class VsManagedLanguagesProjectSystemServices :
3233
, IProjectSystemCapabilities
3334
, IProjectSystemReferencesReader
3435
, IProjectSystemReferencesService
36+
, ILegacyPackageReferenceProjectServices
3537
{
3638
private static readonly string[] ReferenceMetadata;
3739

3840
private readonly IVsProjectAdapter _vsProjectAdapter;
3941
private readonly IVsProjectThreadingService _threadingService;
40-
private readonly VSProject4 _vsProject4;
42+
43+
public VSProject4 Project4 { get; }
4144

4245
public bool SupportsPackageReferences => true;
4346

@@ -85,7 +88,7 @@ public VsManagedLanguagesProjectSystemServices(
8588

8689
_vsProjectAdapter = vsProjectAdapter;
8790
_threadingService = threadingService;
88-
_vsProject4 = vsProject4;
91+
Project4 = vsProject4;
8992

9093
ScriptService = new VsProjectScriptHostService(vsProjectAdapter, scriptExecutor);
9194

@@ -99,7 +102,7 @@ public async Task<IEnumerable<LibraryDependency>> GetPackageReferencesAsync(
99102

100103
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
101104

102-
var installedPackages = _vsProject4.PackageReferences?.InstalledPackages;
105+
var installedPackages = Project4.PackageReferences?.InstalledPackages;
103106

104107
if (installedPackages == null)
105108
{
@@ -113,7 +116,7 @@ public async Task<IEnumerable<LibraryDependency>> GetPackageReferencesAsync(
113116
.Where(r => !string.IsNullOrEmpty(r))
114117
.Select(installedPackage =>
115118
{
116-
if (_vsProject4.PackageReferences.TryGetReference(
119+
if (Project4.PackageReferences.TryGetReference(
117120
installedPackage,
118121
ReferenceMetadata,
119122
out var version,
@@ -141,13 +144,13 @@ public async Task<IEnumerable<ProjectRestoreReference>> GetProjectReferencesAsyn
141144
{
142145
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
143146

144-
if (_vsProject4.References == null)
147+
if (Project4.References == null)
145148
{
146149
return Array.Empty<ProjectRestoreReference>();
147150
}
148151

149152
var references = new List<ProjectRestoreReference>();
150-
foreach (Reference6 r in _vsProject4.References.Cast<Reference6>())
153+
foreach (Reference6 r in Project4.References.Cast<Reference6>())
151154
{
152155
if (r.SourceProject != null && await EnvDTEProjectUtility.IsSupportedAsync(r.SourceProject))
153156
{
@@ -317,7 +320,7 @@ private void AddOrUpdatePackageReference(string packageName, VersionRange packag
317320
// - specify a metadata element name with a value => add/replace that metadata item on the package reference
318321
// - specify a metadata element name with no value => remove that metadata item from the project reference
319322
// - don't specify a particular metadata name => if it exists on the package reference, don't change it (e.g. for user defined metadata)
320-
_vsProject4.PackageReferences.AddOrUpdate(
323+
Project4.PackageReferences.AddOrUpdate(
321324
packageName,
322325
packageVersion.OriginalString ?? packageVersion.ToShortString(),
323326
metadataElements,
@@ -330,7 +333,7 @@ public async Task RemovePackageReferenceAsync(string packageName)
330333

331334
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
332335

333-
_vsProject4.PackageReferences.Remove(packageName);
336+
Project4.PackageReferences.Remove(packageName);
334337
}
335338

336339
private bool IsCentralPackageManagementVersionsEnabled()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using NuGet.ProjectManagement;
5+
using VSLangProj150;
6+
7+
namespace NuGet.PackageManagement.VisualStudio.Projects;
8+
9+
public interface ILegacyPackageReferenceProjectServices : INuGetProjectServices
10+
{
11+
VSProject4 Project4 { get; }
12+
}

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

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
using Microsoft.VisualStudio.Shell;
1717
using Microsoft.VisualStudio.Threading;
1818
using NuGet.Commands;
19+
using NuGet.Commands.Restore;
20+
using NuGet.Commands.Restore.Utility;
1921
using NuGet.Common;
2022
using NuGet.Configuration;
2123
using NuGet.Frameworks;
2224
using NuGet.LibraryModel;
25+
using NuGet.PackageManagement.VisualStudio.Projects;
2326
using NuGet.PackageManagement.VisualStudio.Utility;
2427
using NuGet.Packaging;
2528
using NuGet.Packaging.Core;
@@ -41,14 +44,17 @@ public sealed class LegacyPackageReferenceProject : PackageReferenceProject<Dict
4144
{
4245
private readonly IVsProjectAdapter _vsProjectAdapter;
4346
private readonly IVsProjectThreadingService _threadingService;
47+
private readonly bool _usePackageSpecFactory;
48+
private readonly ILegacyPackageReferenceProjectServices _projectServices;
4449

4550
public NuGetFramework TargetFramework { get; }
4651

4752
public LegacyPackageReferenceProject(
4853
IVsProjectAdapter vsProjectAdapter,
4954
string projectId,
50-
INuGetProjectServices projectServices,
51-
IVsProjectThreadingService threadingService)
55+
ILegacyPackageReferenceProjectServices projectServices,
56+
IVsProjectThreadingService threadingService,
57+
bool usePackageSpecFactory)
5258
: base(vsProjectAdapter.ProjectName,
5359
vsProjectAdapter.UniqueName,
5460
vsProjectAdapter.FullProjectPath)
@@ -69,18 +75,23 @@ public LegacyPackageReferenceProject(
6975
InternalMetadata.Add(NuGetProjectMetadataKeys.ProjectId, projectId);
7076

7177
ProjectServices = projectServices;
78+
_projectServices = projectServices;
79+
80+
_usePackageSpecFactory = usePackageSpecFactory;
7281
}
7382

7483
public LegacyPackageReferenceProject(
7584
IVsProjectAdapter vsProjectAdapter,
7685
string projectId,
77-
INuGetProjectServices projectServices,
86+
ILegacyPackageReferenceProjectServices projectServices,
7887
IVsProjectThreadingService threadingService,
79-
NuGetFramework targetFramework)
88+
NuGetFramework targetFramework,
89+
bool usePackageSpecFactory)
8090
: this(vsProjectAdapter,
8191
projectId,
8292
projectServices,
83-
threadingService)
93+
threadingService,
94+
usePackageSpecFactory)
8495
{
8596
Assumes.NotNull(targetFramework);
8697
TargetFramework = targetFramework;
@@ -431,6 +442,18 @@ private IList<string> GetConfigFilePaths(ISettings settings)
431442
/// Emulates a JSON deserialization from project.json to PackageSpec in a post-project.json world
432443
/// </summary>
433444
private async Task<PackageSpec> GetPackageSpecAsync(ISettings settings)
445+
{
446+
if (_usePackageSpecFactory)
447+
{
448+
return await GetPackageSpecWithFactoryAsync(settings);
449+
}
450+
else
451+
{
452+
return await GetPackageSpecClassicAsync(settings);
453+
}
454+
}
455+
456+
private async Task<PackageSpec> GetPackageSpecClassicAsync(ISettings settings)
434457
{
435458
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
436459

@@ -595,6 +618,14 @@ private async Task<PackageSpec> GetPackageSpecAsync(ISettings settings)
595618
};
596619
}
597620

621+
private async Task<PackageSpec> GetPackageSpecWithFactoryAsync(ISettings settings)
622+
{
623+
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
624+
IProject project = new LegacyProjectAdapter(_vsProjectAdapter, _projectServices.Project4);
625+
PackageSpec packageSpec = PackageSpecFactory.GetPackageSpec(project, settings);
626+
return packageSpec;
627+
}
628+
598629
internal static ImmutableArray<LibraryDependency> ApplyCentralVersionInformation(ImmutableArray<LibraryDependency> packageReferences, IReadOnlyDictionary<string, CentralPackageVersion> centralPackageVersions)
599630
{
600631
if (packageReferences.IsDefault)

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using Microsoft;
99
using Microsoft.VisualStudio.Shell;
1010
using Microsoft.VisualStudio.Utilities;
11+
using NuGet.Commands.Restore.Utility;
12+
using NuGet.Common;
1113
using NuGet.Frameworks;
1214
using NuGet.ProjectManagement;
1315
using NuGet.ProjectModel;
@@ -27,6 +29,7 @@ public sealed class LegacyPackageReferenceProjectProvider : INuGetProjectProvide
2729

2830
private readonly IVsProjectThreadingService _threadingService;
2931
private readonly Lazy<IScriptExecutor> _scriptExecutor;
32+
private readonly bool _usePackageSpecFactory;
3033

3134
public RuntimeTypeHandle ProjectType => typeof(LegacyPackageReferenceProject).TypeHandle;
3235

@@ -36,20 +39,24 @@ public LegacyPackageReferenceProjectProvider(
3639
Lazy<IScriptExecutor> scriptExecutor)
3740
: this(AsyncServiceProvider.GlobalProvider,
3841
threadingService,
39-
scriptExecutor)
42+
scriptExecutor,
43+
EnvironmentVariableWrapper.Instance)
4044
{ }
4145

4246
public LegacyPackageReferenceProjectProvider(
4347
IAsyncServiceProvider vsServiceProvider,
4448
IVsProjectThreadingService threadingService,
45-
Lazy<IScriptExecutor> scriptExecutor)
49+
Lazy<IScriptExecutor> scriptExecutor,
50+
IEnvironmentVariableReader environmentVariableReader)
4651
{
4752
Assumes.Present(vsServiceProvider);
4853
Assumes.Present(threadingService);
4954
Assumes.Present(scriptExecutor);
55+
Assumes.Present(environmentVariableReader);
5056

5157
_threadingService = threadingService;
5258
_scriptExecutor = scriptExecutor;
59+
_usePackageSpecFactory = !bool.FalseString.Equals(PackageSpecFactory.EnvironmentVariableName, StringComparison.OrdinalIgnoreCase);
5360
}
5461

5562
public NuGetProject TryCreateNuGetProject(
@@ -75,13 +82,14 @@ public NuGetProject TryCreateNuGetProject(
7582
vsProjectAdapter.ProjectId,
7683
projectServices,
7784
_threadingService,
78-
targetFramework);
85+
targetFramework,
86+
_usePackageSpecFactory);
7987
}
8088

8189
/// <summary>
8290
/// Is this project a non-CPS package reference based csproj?
8391
/// </summary>
84-
private INuGetProjectServices TryCreateProjectServices(
92+
private VsManagedLanguagesProjectSystemServices TryCreateProjectServices(
8593
IVsProjectAdapter vsProjectAdapter, bool forceCreate)
8694
{
8795
ThreadHelper.ThrowIfNotOnUIThread();

0 commit comments

Comments
 (0)