diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs index 1e2bfd1f191..2cc21104bec 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs @@ -13,13 +13,11 @@ [assembly: SuppressMessage("Build", "CA1308:In method 'LogInternal', replace the call to 'ToLowerInvariant' with 'ToUpperInvariant'.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.CommandOutputLogger.LogInternal(NuGet.Common.LogLevel,System.String)")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void CommandOutputLogger.LogInternal(LogLevel logLevel, string message)', validate parameter 'message' 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 = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.CommandOutputLogger.LogInternal(NuGet.Common.LogLevel,System.String)")] [assembly: SuppressMessage("Build", "CA1307:The behavior of 'string.IndexOf(char)' could vary based on the current user's locale settings. Replace this call in 'NuGet.CommandLine.XPlat.CommandOutputLogger.LogInternal(NuGet.Common.LogLevel, string)' with a call to 'string.IndexOf(char, System.StringComparison)'.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.CommandOutputLogger.LogInternal(NuGet.Common.LogLevel,System.String)")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void ListPackageCommand.Register(CommandLineApplication app, Func getLogger, Func getCommandRunner)', validate parameter 'app' 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 = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommand.Register(Microsoft.Extensions.CommandLineUtils.CommandLineApplication,System.Func{NuGet.Common.ILogger},System.Func{NuGet.CommandLine.XPlat.IListPackageCommandRunner})")] [assembly: SuppressMessage("Build", "CA1822:Member AddPackagesToDict does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.AddPackagesToDict(System.Collections.Generic.IEnumerable{NuGet.CommandLine.XPlat.FrameworkPackages},System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.IList{NuGet.Protocol.Core.Types.IPackageSearchMetadata}})")] [assembly: SuppressMessage("Build", "CA1307:The behavior of 'string.Equals(string)' could vary based on the current user's locale settings. Replace this call in 'NuGet.CommandLine.XPlat.ListPackageCommandRunner.ExecuteCommandAsync(NuGet.CommandLine.XPlat.ListPackageArgs)' with a call to 'string.Equals(string, System.StringComparison)'.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.ExecuteCommandAsync(NuGet.CommandLine.XPlat.ListPackageArgs)~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1305:The behavior of 'string.Format(string, object)' could vary based on the current user's locale settings. Replace this call in 'ListPackageCommandRunner.ExecuteCommandAsync(ListPackageArgs)' with a call to 'string.Format(IFormatProvider, string, params object[])'.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.ExecuteCommandAsync(NuGet.CommandLine.XPlat.ListPackageArgs)~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task ListPackageCommandRunner.ExecuteCommandAsync(ListPackageArgs listPackageArgs)', validate parameter 'listPackageArgs' 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 = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.ExecuteCommandAsync(NuGet.CommandLine.XPlat.ListPackageArgs)~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1822:Member GetLatestVersionPerSourceAsync does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.GetLatestVersionPerSourceAsync(NuGet.Configuration.PackageSource,NuGet.CommandLine.XPlat.ListPackageArgs,System.String,System.Collections.Generic.IEnumerable{System.Lazy{NuGet.Protocol.Core.Types.INuGetResourceProvider}},System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.IList{NuGet.Protocol.Core.Types.IPackageSearchMetadata}})~System.Threading.Tasks.Task")] -[assembly: SuppressMessage("Build", "CA1822:Member GetPackageMetadataFromSourceAsync does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.GetPackageMetadataFromSourceAsync(NuGet.Configuration.PackageSource,NuGet.CommandLine.XPlat.ListPackageArgs,System.String,NuGet.Versioning.NuGetVersion,System.Collections.Generic.IEnumerable{System.Lazy{NuGet.Protocol.Core.Types.INuGetResourceProvider}},System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.IList{NuGet.Protocol.Core.Types.IPackageSearchMetadata}})~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1822:Member GetUpdateLevel does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.GetUpdateLevel(NuGet.Versioning.NuGetVersion,NuGet.Versioning.NuGetVersion)~NuGet.CommandLine.XPlat.UpdateLevel")] [assembly: SuppressMessage("Build", "CA1822:Member MeetsConstraints does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.ListPackageCommandRunner.MeetsConstraints(NuGet.Versioning.NuGetVersion,NuGet.CommandLine.XPlat.InstalledPackageReference,NuGet.CommandLine.XPlat.ListPackageArgs)~System.Boolean")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void MSBuildAPIUtility.AddPackageReferencePerTFM(string projectPath, LibraryDependency libraryDependency, IEnumerable frameworks)', validate parameter 'libraryDependency' 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 = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.MSBuildAPIUtility.AddPackageReferencePerTFM(System.String,NuGet.LibraryModel.LibraryDependency,System.Collections.Generic.IEnumerable{System.String})")] @@ -32,9 +30,5 @@ [assembly: SuppressMessage("Build", "CA1303:Method 'int Program.MainInternal(string[] args, CommandOutputLogger log)' passes a literal string as parameter 'value' of a call to 'void Console.WriteLine(string value)'. Retrieve the following string(s) from a resource table instead: \"Waiting for debugger to attach.\".", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.Program.MainInternal(System.String[],NuGet.CommandLine.XPlat.CommandOutputLogger)~System.Int32")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void RemovePackageReferenceCommand.Register(CommandLineApplication app, Func getLogger, Func getCommandRunner)', validate parameter 'app' 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 = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.RemovePackageReferenceCommand.Register(Microsoft.Extensions.CommandLineUtils.CommandLineApplication,System.Func{NuGet.Common.ILogger},System.Func{NuGet.CommandLine.XPlat.IPackageReferenceCommandRunner})")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task RemovePackageReferenceCommandRunner.ExecuteCommand(PackageReferenceArgs packageReferenceArgs, MSBuildAPIUtility msBuild)', validate parameter 'msBuild' 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 = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.RemovePackageReferenceCommandRunner.ExecuteCommand(NuGet.CommandLine.XPlat.PackageReferenceArgs,NuGet.CommandLine.XPlat.MSBuildAPIUtility)~System.Threading.Tasks.Task{System.Int32}")] -[assembly: SuppressMessage("Build", "CA1305:The behavior of 'string.Format(string, object)' could vary based on the current user's locale settings. Replace this call in 'ProjectPackagesPrintUtility.PrintPackagesAsync(IEnumerable, string, bool, bool, bool)' with a call to 'string.Format(IFormatProvider, string, params object[])'.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.Utility.ProjectPackagesPrintUtility.PrintPackagesAsync(System.Collections.Generic.IEnumerable{NuGet.CommandLine.XPlat.FrameworkPackages},System.String,System.Boolean,System.Boolean,System.Boolean)~System.Threading.Tasks.Task{NuGet.CommandLine.XPlat.Utility.PrintPackagesResult}")] -[assembly: SuppressMessage("Build", "CA1814:arrValues is a multidimensional array. Replace it with a jagged array if possible.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.Utility.TableParser.GetMaxColumnsWidth(System.String[,])~System.Int32[]")] -[assembly: SuppressMessage("Build", "CA1814:arrValues is a multidimensional array. Replace it with a jagged array if possible.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.Utility.TableParser.ToStringTable``1(``0[],System.String[,])~System.Collections.Generic.IEnumerable{System.String}")] -[assembly: SuppressMessage("Build", "CA1814:ToStringTableAsync uses a multidimensional array of string[*,*]. Replace it with a jagged array if possible.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.Utility.TableParser.ToStringTableAsync``1(``0[],System.String[],System.Func{``0,System.Threading.Tasks.Task{System.Object}}[])~System.Threading.Tasks.Task{System.Collections.Generic.IEnumerable{System.String}}")] [assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:NuGet.CommandLine.XPlat.PackageReferenceArgs.Frameworks")] [assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:NuGet.CommandLine.XPlat.PackageReferenceArgs.Sources")] diff --git a/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs index c3296db5619..a91b2917cad 100644 --- a/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs @@ -166,7 +166,6 @@ [assembly: SuppressMessage("Build", "CA1822:Member ExecuteCommandAsync does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.Commands.SignCommandRunner.ExecuteCommandAsync(System.Collections.Generic.IEnumerable{System.String},NuGet.Packaging.Signing.SignPackageRequest,System.String,NuGet.Common.ILogger,System.String,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Int32}")] [assembly: SuppressMessage("Build", "CA1031:Modify 'ExecuteCommandAsync' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.Commands.SignCommandRunner.ExecuteCommandAsync(System.Collections.Generic.IEnumerable{System.String},NuGet.Packaging.Signing.SignPackageRequest,System.String,NuGet.Common.ILogger,System.String,System.Boolean,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Int32}")] [assembly: SuppressMessage("Build", "CA1305:The behavior of 'string.Format(string, object)' could vary based on the current user's locale settings. Replace this call in 'SignCommandRunner.GetCertificateAsync(SignArgs)' with a call to 'string.Format(IFormatProvider, string, params object[])'.", Justification = "", Scope = "member", Target = "~M:NuGet.Commands.SignCommandRunner.GetCertificateAsync(NuGet.Commands.SignArgs)~System.Threading.Tasks.Task{System.Security.Cryptography.X509Certificates.X509Certificate2}")] -[assembly: SuppressMessage("Build", "CA1822:Member GetDependencies does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.Commands.SourceRepositoryDependencyProvider.GetDependencies(NuGet.Protocol.Core.Types.FindPackageByIdDependencyInfo,NuGet.Frameworks.NuGetFramework)~System.Collections.Generic.IEnumerable{NuGet.LibraryModel.LibraryDependency}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void SpecValidationUtility.ValidateDependencySpec(DependencyGraphSpec spec, HashSet projectsToSkip)', validate parameter 'projectsToSkip' 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 = "", Scope = "member", Target = "~M:NuGet.Commands.SpecValidationUtility.ValidateDependencySpec(NuGet.ProjectModel.DependencyGraphSpec,System.Collections.Generic.HashSet{System.String})")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'PackageSpec ToolRestoreUtility.GetSpec(string projectFilePath, string id, VersionRange versionRange, NuGetFramework framework, string packagesPath, IList fallbackFolders, IList sources, WarningProperties projectWideWarningProperties)', validate parameter 'framework' 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 = "", Scope = "member", Target = "~M:NuGet.Commands.ToolRestoreUtility.GetSpec(System.String,System.String,NuGet.Versioning.VersionRange,NuGet.Frameworks.NuGetFramework,System.String,System.Collections.Generic.IList{System.String},System.Collections.Generic.IList{NuGet.Configuration.PackageSource},NuGet.ProjectModel.WarningProperties)~NuGet.ProjectModel.PackageSpec")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'IReadOnlyList ToolRestoreUtility.GetSubSetRequests(IEnumerable requestSummaries)', validate parameter 'requestSummaries' 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 = "", Scope = "member", Target = "~M:NuGet.Commands.ToolRestoreUtility.GetSubSetRequests(System.Collections.Generic.IEnumerable{NuGet.Commands.RestoreSummaryRequest})~System.Collections.Generic.IReadOnlyList{NuGet.Commands.RestoreSummaryRequest}")] diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/SourceRepositoryDependencyProvider.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/SourceRepositoryDependencyProvider.cs index d859f17fb94..73f9e4bf292 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/SourceRepositoryDependencyProvider.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/SourceRepositoryDependencyProvider.cs @@ -85,7 +85,6 @@ public SourceRepositoryDependencyProvider( /// Thrown if /// is null. /// Thrown if is null. - /// Thrown if is null. public SourceRepositoryDependencyProvider( SourceRepository sourceRepository, ILogger logger, @@ -95,24 +94,9 @@ public SourceRepositoryDependencyProvider( LocalPackageFileCache fileCache, bool isFallbackFolderSource) { - if (sourceRepository == null) - { - throw new ArgumentNullException(nameof(sourceRepository)); - } - - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - if (cacheContext == null) - { - throw new ArgumentNullException(nameof(cacheContext)); - } - - _sourceRepository = sourceRepository; - _logger = logger; - _cacheContext = cacheContext; + _sourceRepository = sourceRepository ?? throw new ArgumentNullException(nameof(sourceRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _cacheContext = cacheContext ?? throw new ArgumentNullException(nameof(cacheContext)); _ignoreFailedSources = ignoreFailedSources; _ignoreWarning = ignoreWarning; _packageFileCache = fileCache; @@ -362,9 +346,9 @@ private async Task GetDependenciesCoreAsync( packageInfo.PackageIdentity.Version, match.Type); - var dependencies = GetDependencies(packageInfo, targetFramework); + IEnumerable dependencyGroup = GetDependencies(packageInfo, targetFramework); - return LibraryDependencyInfo.Create(originalIdentity, targetFramework, dependencies); + return LibraryDependencyInfo.Create(originalIdentity, targetFramework, dependencies: dependencyGroup); } } @@ -452,7 +436,7 @@ public async Task GetPackageDownloaderAsync( return null; } - private IEnumerable GetDependencies( + private static IEnumerable GetDependencies( FindPackageByIdDependencyInfo packageInfo, NuGetFramework targetFramework) { @@ -470,6 +454,15 @@ private IEnumerable GetDependencies( dependencyGroup = NuGetFrameworkUtility.GetNearest(packageInfo.DependencyGroups, dualCompatibilityFramework.SecondaryFramework, item => item.TargetFramework); } + // FrameworkReducer.GetNearest does not consider ATF since it is used for more than just compat + if (dependencyGroup == null && + targetFramework is AssetTargetFallbackFramework assetTargetFallbackFramework) + { + dependencyGroup = NuGetFrameworkUtility.GetNearest(packageInfo.DependencyGroups, + assetTargetFallbackFramework.AsFallbackFramework(), + item => item.TargetFramework); + } + if (dependencyGroup != null) { return dependencyGroup.Packages.Select(PackagingUtility.GetLibraryDependencyFromNuspec).ToArray(); diff --git a/src/NuGet.Core/NuGet.ProjectModel/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.ProjectModel/GlobalSuppressions.cs index 999085795c0..3802abcdac4 100644 --- a/src/NuGet.Core/NuGet.ProjectModel/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.ProjectModel/GlobalSuppressions.cs @@ -22,8 +22,6 @@ [assembly: SuppressMessage("Build", "CA1305:The behavior of 'string.Format(string, object)' could vary based on the current user's locale settings. Replace this call in 'JsonPackageSpecReader.ReadScripts(JsonTextReader, PackageSpec)' with a call to 'string.Format(IFormatProvider, string, params object[])'.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectModel.JsonPackageSpecReader.ReadScripts(Newtonsoft.Json.JsonTextReader,NuGet.ProjectModel.PackageSpec)")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'bool LockFile.IsValidForPackageSpec(PackageSpec spec, int requestLockFileVersion)', validate parameter 'spec' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.LockFile.IsValidForPackageSpec(NuGet.ProjectModel.PackageSpec,System.Int32)~System.Boolean")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'int LockFileDependencyIdVersionComparer.GetHashCode(LockFileDependency obj)', validate parameter 'obj' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.LockFileDependencyIdVersionComparer.GetHashCode(NuGet.ProjectModel.LockFileDependency)~System.Int32")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'LockFileDependencyProvider.LockFileDependencyProvider(LockFile lockFile)', validate parameter 'lockFile' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.LockFileDependencyProvider.#ctor(NuGet.ProjectModel.LockFile)")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Library LockFileDependencyProvider.GetLibrary(LibraryRange libraryRange, NuGetFramework targetFramework)', validate parameter 'libraryRange' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.LockFileDependencyProvider.GetLibrary(NuGet.LibraryModel.LibraryRange,NuGet.Frameworks.NuGetFramework)~NuGet.LibraryModel.Library")] [assembly: SuppressMessage("Build", "CA1031:Modify 'Read' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectModel.LockFileFormat.Read(System.IO.TextReader,NuGet.Common.ILogger,System.String)~NuGet.ProjectModel.LockFile")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'LockFile LockFileFormat.Read(TextReader reader, ILogger log, string path)', validate parameter 'log' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.LockFileFormat.Read(System.IO.TextReader,NuGet.Common.ILogger,System.String)~NuGet.ProjectModel.LockFile")] [assembly: SuppressMessage("Build", "CA1822:Member Read does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectModel.LockFileFormat.Read(System.IO.TextReader,NuGet.Common.ILogger,System.String)~NuGet.ProjectModel.LockFile")] @@ -40,7 +38,6 @@ [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'bool PackagesLockFileUtilities.IsLockFileStillValid(DependencyGraphSpec dgSpec, PackagesLockFile nuGetLockFile)', validate parameter 'dgSpec' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.PackagesLockFileUtilities.IsLockFileStillValid(NuGet.ProjectModel.DependencyGraphSpec,NuGet.ProjectModel.PackagesLockFile)~System.Boolean")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'bool PackagesLockFileUtilities.IsNuGetLockFileEnabled(PackageSpec project)', validate parameter 'project' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.PackagesLockFileUtilities.IsNuGetLockFileEnabled(NuGet.ProjectModel.PackageSpec)~System.Boolean")] [assembly: SuppressMessage("Build", "CA1822:Member CloneScripts does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectModel.PackageSpec.CloneScripts(System.Collections.Generic.IDictionary{System.String,System.Collections.Generic.IEnumerable{System.String}})~System.Collections.Generic.IDictionary{System.String,System.Collections.Generic.IEnumerable{System.String}}")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'ProjectRestoreMetadataFrameworkInfo PackageSpecExtensions.GetRestoreMetadataFramework(PackageSpec project, NuGetFramework targetFramework)', validate parameter 'project' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.PackageSpecExtensions.GetRestoreMetadataFramework(NuGet.ProjectModel.PackageSpec,NuGet.Frameworks.NuGetFramework)~NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'TargetFrameworkInformation PackageSpecExtensions.GetTargetFramework(PackageSpec project, NuGetFramework targetFramework)', validate parameter 'project' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.PackageSpecExtensions.GetTargetFramework(NuGet.ProjectModel.PackageSpec,NuGet.Frameworks.NuGetFramework)~NuGet.ProjectModel.TargetFrameworkInformation")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void PackageSpecOperations.AddOrUpdateDependency(PackageSpec spec, PackageDependency dependency)', validate parameter 'spec' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.PackageSpecOperations.AddOrUpdateDependency(NuGet.ProjectModel.PackageSpec,NuGet.Packaging.Core.PackageDependency)")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void PackageSpecOperations.AddOrUpdateDependency(PackageSpec spec, PackageDependency dependency, IEnumerable frameworksToAdd)', validate parameter 'spec' 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 = "", Scope = "member", Target = "~M:NuGet.ProjectModel.PackageSpecOperations.AddOrUpdateDependency(NuGet.ProjectModel.PackageSpec,NuGet.Packaging.Core.PackageDependency,System.Collections.Generic.IEnumerable{NuGet.Frameworks.NuGetFramework})")] diff --git a/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs b/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs index 52fcca1d041..5560582d432 100644 --- a/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs +++ b/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs @@ -212,9 +212,6 @@ private static void AddLibraryProperties(Library library, PackageSpec packageSpe } } - /// - /// .NETCore projects - /// private List GetDependenciesFromSpecRestoreMetadata(PackageSpec packageSpec, NuGetFramework targetFramework) { var dependencies = GetSpecDependencies(packageSpec, targetFramework); @@ -222,8 +219,14 @@ private List GetDependenciesFromSpecRestoreMetadata(PackageSp // Get the nearest framework var referencesForFramework = packageSpec.GetRestoreMetadataFramework(targetFramework); + if (referencesForFramework.FrameworkName == null && + targetFramework is AssetTargetFallbackFramework assetTargetFallbackFramework) + { + referencesForFramework = packageSpec.GetRestoreMetadataFramework(assetTargetFallbackFramework.AsFallbackFramework()); + } + // Ensure that this project is compatible - if (referencesForFramework.FrameworkName?.IsSpecificFramework == true) + if (referencesForFramework?.FrameworkName?.IsSpecificFramework == true) { foreach (var reference in referencesForFramework.ProjectReferences) { @@ -328,6 +331,12 @@ internal static List GetSpecDependencies( // Add framework specific dependencies var targetFrameworkInfo = packageSpec.GetTargetFramework(targetFramework); + + if (targetFrameworkInfo.FrameworkName == null && targetFramework is AssetTargetFallbackFramework atfFramework) + { + targetFrameworkInfo = packageSpec.GetTargetFramework(atfFramework.AsFallbackFramework()); + } + dependencies.AddRange(targetFrameworkInfo.Dependencies); #if enableCPVMTransitivePinning diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs index a25fc2168e1..6735abfd86b 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs @@ -3362,6 +3362,269 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( Assert.Equal(packageSource2, packageASource); } + // Project1(net5.0) -> A(net472) -> B(net472) + [Fact] + public async Task Restore_WhenPackageSelectedWithATF_ItsDependenciesAreIncluded_AndATFWarningsAreRaised() + { + // Arrange + using var pathContext = new SimpleTestPathContext(); + + var packageA = new SimpleTestPackageContext("a", "1.0.0"); + packageA.AddFile("lib/net472/a.dll"); + var packageB = new SimpleTestPackageContext("b", "1.0.0"); + packageB.AddFile("lib/net472/b.dll"); + packageA.PerFrameworkDependencies.Add(NuGetFramework.Parse("net472"), new List() { packageB }); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageA, + packageB); + + var spec = ProjectTestHelpers.GetPackageSpec("Project1", pathContext.SolutionRoot, framework: "net5.0", dependencyName: "a", useAssetTargetFallback: true, assetTargetFallbackFrameworks: "net472"); + var command = new RestoreCommand(ProjectTestHelpers.CreateRestoreRequest(spec, pathContext, new TestLogger())); + + // Act + var result = await command.ExecuteAsync(); + + // Assert + result.Success.Should().BeTrue(); + result.CompatibilityCheckResults.Sum(checkResult => checkResult.Issues.Count).Should().Be(0); + result.GetAllInstalled().Should().HaveCount(2); + result.LockFile.LogMessages.Should().HaveCount(2); + result.LockFile.LogMessages.Select(e => e.Code).Should().AllBeEquivalentTo(NuGetLogCode.NU1701); + result.LockFile.LogMessages.Single(e => e.LibraryId == "a"); + result.LockFile.LogMessages.Single(e => e.LibraryId == "b"); + } + + // Project1(net5.0) -> A(net472) -> B(net472, netstandard2.0) + [Fact] + public async Task Restore_WhenPackageSelectedWithATF_DependenciesAreIncludedAnd_AndWarningsAreRaisedForATFPackagesOnly() + { + // Arrange + using var pathContext = new SimpleTestPathContext(); + + var packageA = new SimpleTestPackageContext("a", "1.0.0"); + packageA.AddFile("lib/net472/a.dll"); + var packageB = new SimpleTestPackageContext("b", "1.0.0"); + packageB.AddFile("lib/net472/b.dll"); + packageB.AddFile("lib/netstandard2.0/b.dll"); + packageA.PerFrameworkDependencies.Add(NuGetFramework.Parse("net472"), new List() { packageB }); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageA, + packageB); + + var spec = ProjectTestHelpers.GetPackageSpec("Project1", pathContext.SolutionRoot, framework: "net5.0", dependencyName: "a", useAssetTargetFallback: true, assetTargetFallbackFrameworks: "net472"); + var command = new RestoreCommand(ProjectTestHelpers.CreateRestoreRequest(spec, pathContext, new TestLogger())); + + // Act + var result = await command.ExecuteAsync(); + + // Assert + result.Success.Should().BeTrue(); + result.CompatibilityCheckResults.Sum(checkResult => checkResult.Issues.Count).Should().Be(0); + result.GetAllInstalled().Should().HaveCount(2); + result.LockFile.LogMessages.Should().HaveCount(1); + result.LockFile.LogMessages.Select(e => e.Code).Should().AllBeEquivalentTo(NuGetLogCode.NU1701); + result.LockFile.LogMessages.Single(e => e.LibraryId == "a"); + } + + // Project1(net5.0) -> A(net472,netstandard2.0) -> B(net472,netstandard2.0) + [Fact] + public async Task Restore_WhenPackageDependenciesAreSelectedWithATF_AndPackageAssetsAreNot_DoesNotRaiseATFWarning() + { + // Arrange + using var pathContext = new SimpleTestPathContext(); + + var packageA = new SimpleTestPackageContext("a", "1.0.0"); + packageA.AddFile("lib/net472/a.dll"); + packageA.AddFile("lib/netstandard2.0/b.dll"); + var packageB = new SimpleTestPackageContext("b", "1.0.0"); + packageB.AddFile("lib/net472/b.dll"); + packageB.AddFile("lib/netstandard2.0/b.dll"); + packageA.PerFrameworkDependencies.Add(NuGetFramework.Parse("net472"), new List() { packageB }); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageA, + packageB); + + var spec = ProjectTestHelpers.GetPackageSpec("TestProject", pathContext.SolutionRoot, framework: "net5.0", dependencyName: "a", useAssetTargetFallback: true, assetTargetFallbackFrameworks: "net472"); + var command = new RestoreCommand(ProjectTestHelpers.CreateRestoreRequest(spec, pathContext, new TestLogger())); + + // Act + var result = await command.ExecuteAsync(); + + // Assert + result.Success.Should().BeTrue(); + result.CompatibilityCheckResults.Sum(checkResult => checkResult.Issues.Count).Should().Be(0); + result.GetAllInstalled().Should().HaveCount(2); + result.LockFile.LogMessages.Should().HaveCount(0); + } + + // Project1(net5.0) -> Project2(net472) -> A(net472) -> B(net472) + [Fact] + public async Task Restore_WithProjectReference_WhenTransitivePackagesAreSelectedWithPackagesWithATF_DependenciesAreIncluded_AndRaisesATFWarning() + { + // Arrange + using var pathContext = new SimpleTestPathContext(); + + var packageA = new SimpleTestPackageContext("a", "1.0.0"); + packageA.AddFile("lib/net472/a.dll"); + var packageB = new SimpleTestPackageContext("b", "1.0.0"); + packageB.AddFile("lib/net472/b.dll"); + packageA.PerFrameworkDependencies.Add(NuGetFramework.Parse("net472"), new List() { packageB }); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageA, + packageB); + + var project1spec = ProjectTestHelpers.GetPackageSpec("Project1", pathContext.SolutionRoot, framework: "net5.0", useAssetTargetFallback: true, assetTargetFallbackFrameworks: "net472"); + var project2spec = ProjectTestHelpers.GetPackageSpec("Project2", pathContext.SolutionRoot, framework: "net472", dependencyName: "a"); + project1spec = project1spec.WithTestProjectReference(project2spec); + CreateFakeProjectFile(project2spec); + + var command = new RestoreCommand(ProjectTestHelpers.CreateRestoreRequest(project1spec, new PackageSpec[] { project2spec }, pathContext, new TestLogger())); + + // Act + var result = await command.ExecuteAsync(); + + // Assert + result.Success.Should().BeTrue(); + result.CompatibilityCheckResults.Sum(checkResult => checkResult.Issues.Count).Should().Be(0); + result.GetAllInstalled().Should().HaveCount(2); + result.LockFile.Libraries.Should().HaveCount(3); + result.LockFile.LogMessages.Should().HaveCount(2); + result.LockFile.LogMessages.Select(e => e.Code).Should().AllBeEquivalentTo(NuGetLogCode.NU1701); + result.LockFile.LogMessages.Single(e => e.LibraryId == "a"); + result.LockFile.LogMessages.Single(e => e.LibraryId == "b"); + } + + + // Project1(net5.0) -> Project2(net472) -> Project3(net472) + [Fact] + public async Task Restore_WithProjectReference_WhenTransitiveProjectsAreSelectedWithATF_AllProjectsAreIncluded() + { + // Arrange + using var pathContext = new SimpleTestPathContext(); + + var project1spec = ProjectTestHelpers.GetPackageSpec("Project1", pathContext.SolutionRoot, framework: "net5.0", useAssetTargetFallback: true, assetTargetFallbackFrameworks: "net472"); + var project2spec = ProjectTestHelpers.GetPackageSpec("Project2", pathContext.SolutionRoot, framework: "net472"); + var project3spec = ProjectTestHelpers.GetPackageSpec("Project3", pathContext.SolutionRoot, framework: "net472"); + project2spec = project2spec.WithTestProjectReference(project3spec); + project1spec = project1spec.WithTestProjectReference(project2spec); + CreateFakeProjectFile(project2spec); + CreateFakeProjectFile(project3spec); + + var command = new RestoreCommand(ProjectTestHelpers.CreateRestoreRequest(project1spec, new PackageSpec[] { project2spec, project3spec }, pathContext, new TestLogger())); + + // Act + var result = await command.ExecuteAsync(); + + // Assert + result.Success.Should().BeTrue(); + result.CompatibilityCheckResults.Sum(checkResult => checkResult.Issues.Count).Should().Be(0); + result.GetAllInstalled().Should().HaveCount(0); + result.LockFile.Libraries.Should().HaveCount(2); + } + + // Project1(net5) -> Project2(net472) -> A (ATF) + // Project1(net5) -> Project2(net472) -> B (non-ATF) + [Fact] + public async Task Restore_WithProjectReference_WhenProjectIsSelectedWithATF_AllDependenciesAreIncluded_AndRaisesATFWarning() + { + // Arrange + using var pathContext = new SimpleTestPathContext(); + + var packageA = new SimpleTestPackageContext("a", "1.0.0"); + packageA.AddFile("lib/net472/a.dll"); + var packageB = new SimpleTestPackageContext("b", "1.0.0"); + packageB.AddFile("lib/net472/b.dll"); + packageB.AddFile("lib/netstandard2.0/b.dll"); + packageA.PerFrameworkDependencies.Add(NuGetFramework.Parse("net472"), new List() { packageB }); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageA, + packageB); + + var project1spec = ProjectTestHelpers.GetPackageSpec("Project1", pathContext.SolutionRoot, framework: "net5.0", useAssetTargetFallback: true, assetTargetFallbackFrameworks: "net472"); + var project2spec = ProjectTestHelpers.GetPackageSpec("Project2", pathContext.SolutionRoot, framework: "net472", dependencyName: "a"); + project1spec = project1spec.WithTestProjectReference(project2spec); + CreateFakeProjectFile(project2spec); + + var command = new RestoreCommand(ProjectTestHelpers.CreateRestoreRequest(project1spec, new PackageSpec[] { project2spec }, pathContext, new TestLogger())); + + // Act + var result = await command.ExecuteAsync(); + + // Assert + result.Success.Should().BeTrue(); + result.CompatibilityCheckResults.Sum(checkResult => checkResult.Issues.Count).Should().Be(0); + result.GetAllInstalled().Should().HaveCount(2); + result.LockFile.Libraries.Should().HaveCount(3); + result.LockFile.LogMessages.Should().HaveCount(1); + result.LockFile.LogMessages.Select(e => e.Code).Should().AllBeEquivalentTo(NuGetLogCode.NU1701); + result.LockFile.LogMessages.Single(e => e.LibraryId == "a"); + } + + // Project1(net5) -> Project2(net472) -> Project3(net472) -> A (ATF) + // Project1(net5) -> Project2(net472) -> Project3(net472) -> B (non-ATF) + [Fact] + public async Task Restore_WithTransitiveProjectReference_WhenTransitiveProjectReferenceIsSelectedWithATF_AllDependenciesAreIncluded_AndRaisesATFWarning() + { + // Arrange + using var pathContext = new SimpleTestPathContext(); + + var packageA = new SimpleTestPackageContext("a", "1.0.0"); + packageA.AddFile("lib/net472/a.dll"); + var packageB = new SimpleTestPackageContext("b", "1.0.0"); + packageB.AddFile("lib/net472/b.dll"); + packageB.AddFile("lib/netstandard2.0/b.dll"); + packageA.PerFrameworkDependencies.Add(NuGetFramework.Parse("net472"), new List() { packageB }); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageA, + packageB); + + var project1spec = ProjectTestHelpers.GetPackageSpec("Project1", pathContext.SolutionRoot, framework: "net5.0", useAssetTargetFallback: true, assetTargetFallbackFrameworks: "net472"); + var project2spec = ProjectTestHelpers.GetPackageSpec("Project2", pathContext.SolutionRoot, framework: "net472"); + var project3spec = ProjectTestHelpers.GetPackageSpec("Project3", pathContext.SolutionRoot, framework: "net472", dependencyName: "a"); + project2spec = project2spec.WithTestProjectReference(project3spec); + project1spec = project1spec.WithTestProjectReference(project2spec); + CreateFakeProjectFile(project2spec); + + var command = new RestoreCommand(ProjectTestHelpers.CreateRestoreRequest(project1spec, new PackageSpec[] { project2spec, project3spec }, pathContext, new TestLogger())); + + // Act + var result = await command.ExecuteAsync(); + + // Assert + result.Success.Should().BeTrue(); + result.CompatibilityCheckResults.Sum(checkResult => checkResult.Issues.Count).Should().Be(0); + result.GetAllInstalled().Should().HaveCount(2); + result.LockFile.Libraries.Should().HaveCount(4); + result.LockFile.LogMessages.Should().HaveCount(1); + result.LockFile.LogMessages.Select(e => e.Code).Should().AllBeEquivalentTo(NuGetLogCode.NU1701); + result.LockFile.LogMessages.Single(e => e.LibraryId == "a"); + } + + private static void CreateFakeProjectFile(PackageSpec project2spec) + { + Directory.CreateDirectory(Path.GetDirectoryName(project2spec.RestoreMetadata.ProjectUniqueName)); + File.WriteAllText(project2spec.RestoreMetadata.ProjectUniqueName, ""); + } + + private static byte[] GetTestUtilityResource(string name) { return ResourceTestUtility.GetResourceBytes( diff --git a/test/TestUtilities/Test.Utility/Commands/ProjectTestHelpers.cs b/test/TestUtilities/Test.Utility/Commands/ProjectTestHelpers.cs index 655902a0303..7d8cbc14ac7 100644 --- a/test/TestUtilities/Test.Utility/Commands/ProjectTestHelpers.cs +++ b/test/TestUtilities/Test.Utility/Commands/ProjectTestHelpers.cs @@ -235,7 +235,7 @@ public static TestRestoreRequest CreateRestoreRequest(PackageSpec projectToResto dgSpec.AddProject(spec); } - var externalClosure = DependencyGraphSpecRequestProvider.GetExternalClosure(dgSpec, projectToRestore.Name).ToList(); + var externalClosure = DependencyGraphSpecRequestProvider.GetExternalClosure(dgSpec, projectToRestore.RestoreMetadata.ProjectUniqueName).ToList(); return new TestRestoreRequest(projectToRestore, sources, pathContext.UserPackagesFolder, logger) { @@ -293,23 +293,26 @@ public static PackageSpec WithPackagesConfigRestoreMetadata(this PackageSpec spe /// Project name /// Root path, normally solution root. The project is gonna be "located" at rootPath/projectName/projectName.csproj /// framework + /// Whether to use ATF. Default is false. + /// ATF string. /// Returns a PackageReference spec with all details similar to what a spec from a nomination would contain. - public static PackageSpec GetPackageSpec(string projectName, string rootPath = @"C:\", string framework = "net5.0") + public static PackageSpec GetPackageSpec(string projectName, string rootPath = @"C:\", string framework = "net5.0", bool useAssetTargetFallback = false, string assetTargetFallbackFrameworks = "") { + var actualAssetTargetFallback = GetAssetTargetFallbackString(useAssetTargetFallback, assetTargetFallbackFrameworks); + const string referenceSpec = @" { ""frameworks"": { ""TARGET_FRAMEWORK"": { ""dependencies"": { } + ASSET_TARGET_FALLBACK } } }"; - var spec = referenceSpec.Replace("TARGET_FRAMEWORK", framework); - var packageSpec = JsonPackageSpecReader.GetPackageSpec(spec, projectName, Path.Combine(rootPath, projectName, projectName)).WithTestRestoreMetadata(); - packageSpec.RestoreSettings.HideWarningsAndErrors = true; // Pretend this is running in VS and this is a .NET Core project. - return packageSpec; + var spec = referenceSpec.Replace("TARGET_FRAMEWORK", framework).Replace("ASSET_TARGET_FALLBACK", actualAssetTargetFallback); + return GetPackageSpecWithProjectNameAndSpec(projectName, rootPath, spec); } /// @@ -334,8 +337,10 @@ public static PackageSpec GetPackageSpec(ISettings settings, string projectName, return packageSpec; } - public static PackageSpec GetPackageSpec(string projectName, string rootPath, string framework, string dependencyName) + public static PackageSpec GetPackageSpec(string projectName, string rootPath, string framework, string dependencyName, bool useAssetTargetFallback = false, string assetTargetFallbackFrameworks = "") { + var actualAssetTargetFallback = GetAssetTargetFallbackString(useAssetTargetFallback, assetTargetFallbackFrameworks); + const string referenceSpec = @" { ""frameworks"": { @@ -343,11 +348,31 @@ public static PackageSpec GetPackageSpec(string projectName, string rootPath, st ""dependencies"": { ""DEPENDENCY_NAME"" : ""1.0.0"" } + ASSET_TARGET_FALLBACK } } }"; - var spec = referenceSpec.Replace("TARGET_FRAMEWORK", framework).Replace("DEPENDENCY_NAME", dependencyName); + var spec = referenceSpec.Replace("TARGET_FRAMEWORK", framework).Replace("DEPENDENCY_NAME", dependencyName).Replace("ASSET_TARGET_FALLBACK", actualAssetTargetFallback); + return GetPackageSpecWithProjectNameAndSpec(projectName, rootPath, spec); + } + + + private static string GetAssetTargetFallbackString(bool useAssetTargetFallback, string assetTargetFallbackFrameworks) + { + const string assetTargetFallback = @", + ""assetTargetFallback"" : true, + ""imports"" : [ ""ASSET_TARGET_FALLBACK_FRAMEWORK_LIST"" ], + ""warn"" : true + "; + var actualAssetTargetFallback = useAssetTargetFallback ? + assetTargetFallback.Replace("ASSET_TARGET_FALLBACK_FRAMEWORK_LIST", assetTargetFallbackFrameworks) : + string.Empty; + return actualAssetTargetFallback; + } + + private static PackageSpec GetPackageSpecWithProjectNameAndSpec(string projectName, string rootPath, string spec) + { var packageSpec = JsonPackageSpecReader.GetPackageSpec(spec, projectName, Path.Combine(rootPath, projectName, projectName)).WithTestRestoreMetadata(); packageSpec.RestoreSettings.HideWarningsAndErrors = true; // Pretend this is running in VS and this is a .NET Core project. return packageSpec;