From c65e15fb7a961f403de2fce586b327454bed2e25 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:28:30 +1100 Subject: [PATCH 01/32] Remove unused property setters --- .../PreprocessPackageDependenciesDesignTime.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index aa602d74fff6..e713d1893b01 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -54,19 +54,19 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase [Output] public ITaskItem[] DependenciesDesignTime { get; set; } - private Dictionary Targets { get; set; } + private Dictionary Targets { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary Packages { get; set; } + private Dictionary Packages { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary Assemblies { get; set; } + private Dictionary Assemblies { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary DiagnosticsMap { get; set; } + private Dictionary DiagnosticsMap { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary DependenciesWorld { get; set; } + private Dictionary DependenciesWorld { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); private HashSet ImplicitPackageReferences { get; set; } From 4148ba57174aed95b028f3389ecc4f72765248ee Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:28:41 +1100 Subject: [PATCH 02/32] Update documentation --- .../PreprocessPackageDependenciesDesignTime.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index e713d1893b01..7f67aa3545f1 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -15,8 +15,8 @@ namespace Microsoft.NET.Build.Tasks /// Task combines data returned from ResolvePackageDependencies into single items collection /// that can be consumed by DesignTime build and contains all info needed to expand packages /// dependency graph. - /// If any changes are made here, make sure corresponding changes are made to NuGetDependenciesSubTreeProvider - /// in roslyn-project-system repo and corresponding tests. + /// If any changes are made here, make sure corresponding changes are made to PackageRuleHandler + /// in the dotnet/project-system repo and corresponding tests. /// public class PreprocessPackageDependenciesDesignTime : TaskBase { From ce14bf983ada3134c5cd3659262d76a82a19c2bb Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:31:39 +1100 Subject: [PATCH 03/32] Simplify lazy initialization --- ...PreprocessPackageDependenciesDesignTime.cs | 2 +- .../ResolvePackageDependencies.cs | 26 ++----------------- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 7f67aa3545f1..240c26af31bf 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -84,7 +84,7 @@ protected override void ExecuteCore() PopulateAssemblies(); PopulateExistingReferenceItems(); - InputDiagnosticMessages = InputDiagnosticMessages ?? Array.Empty(); + InputDiagnosticMessages ??= Array.Empty(); PopulateDiagnosticsMap(); AddDependenciesToTheWorld(Packages, PackageDependencies); diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs index cd885abb656d..03400840f776 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs @@ -123,31 +123,9 @@ internal ResolvePackageDependencies(LockFile lockFile, IPackageResolver packageR #endregion - private IPackageResolver PackageResolver - { - get - { - if (_packageResolver == null) - { - _packageResolver = NuGetPackageResolver.CreateResolver(LockFile); - } - - return _packageResolver; - } - } + private IPackageResolver PackageResolver => _packageResolver ??= NuGetPackageResolver.CreateResolver(LockFile); - private LockFile LockFile - { - get - { - if (_lockFile == null) - { - _lockFile = new LockFileCache(this).GetLockFile(ProjectAssetsFile); - } - - return _lockFile; - } - } + private LockFile LockFile => _lockFile ??= new LockFileCache(this).GetLockFile(ProjectAssetsFile); /// /// Raise Nuget LockFile representation to MSBuild items From 1e77c0af0c030d07c30574fce4962e417f43d17f Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:34:47 +1100 Subject: [PATCH 04/32] Make methods static --- .../PreprocessPackageDependenciesDesignTime.cs | 2 +- .../Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 240c26af31bf..0efa03374355 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -267,7 +267,7 @@ private void PopulateDiagnosticsMap() } } - private DependencyType GetDependencyType(string dependencyTypeString) + private static DependencyType GetDependencyType(string dependencyTypeString) { var dependencyType = DependencyType.Unknown; if (!string.IsNullOrEmpty(dependencyTypeString)) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs index 03400840f776..0769d9f99247 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs @@ -379,7 +379,7 @@ private string ResolvePackagePath(LockFileLibrary package) } } - private string ResolveFilePath(string relativePath, string resolvedPackagePath) + private static string ResolveFilePath(string relativePath, string resolvedPackagePath) { if (NuGetUtils.IsPlaceholderFile(relativePath)) { From e71eec1629179448f3945b97f4664869cd708b37 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:37:32 +1100 Subject: [PATCH 05/32] Reduce string allocations String.Replace(char, char) allocates a new string even if no replacement is made. --- .../ResolvePackageDependencies.cs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs index 0769d9f99247..a3985ecb9a9f 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs @@ -385,12 +385,23 @@ private static string ResolveFilePath(string relativePath, string resolvedPackag { return null; } + + if (resolvedPackagePath == null) + { + return string.Empty; + } + + if (Path.DirectorySeparatorChar != '/') + { + relativePath = relativePath.Replace('/', Path.DirectorySeparatorChar); + } + + if (Path.DirectorySeparatorChar != '\\') + { + relativePath = relativePath.Replace('\\', Path.DirectorySeparatorChar); + } - relativePath = relativePath.Replace('/', Path.DirectorySeparatorChar); - relativePath = relativePath.Replace('\\', Path.DirectorySeparatorChar); - return resolvedPackagePath != null - ? Path.Combine(resolvedPackagePath, relativePath) - : string.Empty; + return Path.Combine(resolvedPackagePath, relativePath); } private string GetAbsolutePathFromProjectRelativePath(string path) From 6a5458579290668b50fb3b544b364399b8767c3a Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:38:05 +1100 Subject: [PATCH 06/32] Avoid array covariance --- .../PreprocessPackageDependenciesDesignTime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 0efa03374355..449ff2321c7e 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -118,7 +118,7 @@ protected override void ExecuteCore() } return newTaskItem; - }).ToArray(); + }).ToArray(); } /// From 69d73a12b890d3d3828064590d11d4410bad62a2 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:38:29 +1100 Subject: [PATCH 07/32] Remove redundant assignments --- .../PreprocessPackageDependenciesDesignTime.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 449ff2321c7e..f3c6fe96564f 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -93,7 +93,7 @@ protected override void ExecuteCore() { // We keep analyzers and assemblies with CompileTimeAssembly metadata; skip everything else. - ItemMetadata itemMetadata = null; + ItemMetadata itemMetadata; if (Assemblies.TryGetValue(item.ItemSpec, out itemMetadata) && itemMetadata.Type == DependencyType.AnalyzerAssembly) { @@ -269,12 +269,7 @@ private void PopulateDiagnosticsMap() private static DependencyType GetDependencyType(string dependencyTypeString) { - var dependencyType = DependencyType.Unknown; - if (!string.IsNullOrEmpty(dependencyTypeString)) - { - Enum.TryParse(dependencyTypeString, /* ignoreCase */ true, out dependencyType); - } - + Enum.TryParse(dependencyTypeString, ignoreCase: true, out DependencyType dependencyType); return dependencyType; } @@ -317,7 +312,7 @@ private void AddDependenciesToTheWorld(Dictionary items, // update parent var parentDependencyId = $"{parentTargetId}/{parentPackageId}".Trim('/'); - ItemMetadata parentDependency = null; + ItemMetadata parentDependency; if (DependenciesWorld.TryGetValue(parentDependencyId, out parentDependency)) { parentDependency.Dependencies.Add(currentItemId); From 046b8e92966a3d7886672b61db191221405a728d Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:39:08 +1100 Subject: [PATCH 08/32] Array cannot be null or have negative item length --- .../PreprocessPackageDependenciesDesignTime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index f3c6fe96564f..058db4ed1a70 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -704,7 +704,7 @@ internal static HashSet GetImplicitPackageReferences(string defaultImpli } var packageNames = defaultImplicitPackages.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - if (packageNames == null || packageNames.Length <= 0) + if (packageNames.Length == 0) { return implicitPackageReferences; } From 4b9f98029187fb9765e673de27d4c6bf6e05bfa9 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:43:35 +1100 Subject: [PATCH 09/32] Inline out var declarations --- .../PreprocessPackageDependenciesDesignTime.cs | 6 ++---- .../ResolvePackageDependencies.cs | 9 +++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 058db4ed1a70..e52c79f75610 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -93,8 +93,7 @@ protected override void ExecuteCore() { // We keep analyzers and assemblies with CompileTimeAssembly metadata; skip everything else. - ItemMetadata itemMetadata; - if (Assemblies.TryGetValue(item.ItemSpec, out itemMetadata) && + if (Assemblies.TryGetValue(item.ItemSpec, out ItemMetadata itemMetadata) && itemMetadata.Type == DependencyType.AnalyzerAssembly) { return false; @@ -312,8 +311,7 @@ private void AddDependenciesToTheWorld(Dictionary items, // update parent var parentDependencyId = $"{parentTargetId}/{parentPackageId}".Trim('/'); - ItemMetadata parentDependency; - if (DependenciesWorld.TryGetValue(parentDependencyId, out parentDependency)) + if (DependenciesWorld.TryGetValue(parentDependencyId, out ItemMetadata parentDependency)) { parentDependency.Dependencies.Add(currentItemId); if (parentDependency.Type == DependencyType.Target) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs index a3985ecb9a9f..86e75d5dd351 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs @@ -200,8 +200,7 @@ private void GetPackageAndFileDefinitions() else { // get a type for the file if one is available - string fileType; - if (!_fileTypes.TryGetValue(fileKey, out fileType)) + if (!_fileTypes.TryGetValue(fileKey, out string fileType)) { fileType = "unknown"; } @@ -276,8 +275,7 @@ private void GetPackageDependencies( TaskItem item; foreach (var deps in package.Dependencies) { - string version; - if (!resolvedPackageVersions.TryGetValue(deps.Id, out version)) + if (!resolvedPackageVersions.TryGetValue(deps.Id, out string version)) { continue; } @@ -348,8 +346,7 @@ private void SaveFileKeyType(string fileKey, FileGroup fileGroup) string fileType = fileGroup.GetTypeMetadata(); if (fileType != null) { - string currentFileType; - if (!_fileTypes.TryGetValue(fileKey, out currentFileType)) + if (!_fileTypes.TryGetValue(fileKey, out string currentFileType)) { _fileTypes.Add(fileKey, fileType); } From 2c9da2bcae75048a402255cef26cacc7b2952b3f Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:51:28 +1100 Subject: [PATCH 10/32] Reduce constructor visibilities --- .../PreprocessPackageDependenciesDesignTime.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index e52c79f75610..458cc57e9442 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -345,7 +345,7 @@ private ItemMetadata GetItem(Dictionary items, string id) private abstract class ItemMetadata { - public ItemMetadata(DependencyType type, IList dependencies = null, bool isTopLevelDependency = false) + protected ItemMetadata(DependencyType type, IList dependencies = null, bool isTopLevelDependency = false) { Type = type; Dependencies = dependencies == null ? new List() : new List(dependencies); @@ -444,7 +444,7 @@ public PackageMetadata(ITaskItem item) : item.GetMetadata(MetadataKeys.Path)) ?? string.Empty; } - protected PackageMetadata( + private PackageMetadata( DependencyType type, IList dependencies, bool isTopLevelDependency, From b556fabe3f6adae3004c2512d76837f605b3e323 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:56:48 +1100 Subject: [PATCH 11/32] Use local function --- .../PreprocessPackageDependenciesDesignTime.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 458cc57e9442..02420f7785cd 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -336,11 +336,13 @@ private void AddDependenciesToTheWorld(Dictionary items, DependenciesWorld[parentDependencyId] = parentDependency; } } - } - private ItemMetadata GetItem(Dictionary items, string id) - { - return Targets.Count > 1 ? items[id].Clone() : items[id]; + return; + + ItemMetadata GetItem(Dictionary items, string id) + { + return Targets.Count > 1 ? items[id].Clone() : items[id]; + } } private abstract class ItemMetadata From 4f69a00c6f93d481048dc14d93e140a86376c95e Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Mar 2020 20:56:55 +1100 Subject: [PATCH 12/32] Formatting --- .../PreprocessPackageDependenciesDesignTime.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 02420f7785cd..72481478cc2a 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -89,7 +89,7 @@ protected override void ExecuteCore() AddDependenciesToTheWorld(Packages, PackageDependencies); - AddDependenciesToTheWorld(Assemblies, FileDependencies, (item) => + AddDependenciesToTheWorld(Assemblies, FileDependencies, item => { // We keep analyzers and assemblies with CompileTimeAssembly metadata; skip everything else. @@ -111,7 +111,7 @@ protected override void ExecuteCore() DependenciesDesignTime = DependenciesWorld.Select(itemKvp => { var newTaskItem = new TaskItem(itemKvp.Key); - foreach(var metadataKvp in itemKvp.Value.ToDictionary()) + foreach (var metadataKvp in itemKvp.Value.ToDictionary()) { newTaskItem.SetMetadata(metadataKvp.Key, metadataKvp.Value); } @@ -378,7 +378,7 @@ protected ItemMetadata(DependencyType type, IList dependencies = null, b private class TargetMetadata : ItemMetadata { public TargetMetadata(ITaskItem item) - :base(DependencyType.Target) + : base(DependencyType.Target) { RuntimeIdentifier = item.GetMetadata(MetadataKeys.RuntimeIdentifier) ?? string.Empty; TargetFrameworkMoniker = item.GetMetadata(MetadataKeys.TargetFrameworkMoniker) ?? string.Empty; From 23256d32756f3ffb482cf8f3ad308c031eb223e8 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Thu, 19 Mar 2020 23:23:53 +1100 Subject: [PATCH 13/32] Remove diagnostics from PreprocessPackageDependenciesDesignTime These are no longer being consumed by the Dependencies node, which now sources them directly from the assets file. --- ...PreprocessPackageDependenciesDesignTime.cs | 102 ------------------ ...rosoft.PackageDependencyResolution.targets | 1 - 2 files changed, 103 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 72481478cc2a..96a0e60bae32 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -49,8 +49,6 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase [Required] public string TargetFrameworkMoniker { get; set; } - public ITaskItem[] InputDiagnosticMessages { get; set; } - [Output] public ITaskItem[] DependenciesDesignTime { get; set; } @@ -63,9 +61,6 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase private Dictionary Assemblies { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary DiagnosticsMap { get; } - = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary DependenciesWorld { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -84,9 +79,6 @@ protected override void ExecuteCore() PopulateAssemblies(); PopulateExistingReferenceItems(); - InputDiagnosticMessages ??= Array.Empty(); - PopulateDiagnosticsMap(); - AddDependenciesToTheWorld(Packages, PackageDependencies); AddDependenciesToTheWorld(Assemblies, FileDependencies, item => @@ -105,8 +97,6 @@ protected override void ExecuteCore() AddDependenciesToTheWorld(Assemblies, ExistingReferenceItemDependencies); - AddDependenciesToTheWorld(DiagnosticsMap, InputDiagnosticMessages); - // prepare output collection: add corresponding metadata to ITaskItem based in item type DependenciesDesignTime = DependenciesWorld.Select(itemKvp => { @@ -257,15 +247,6 @@ private void PopulateExistingReferenceItems() ExistingReferenceItemDependencies = existingReferenceItemDependencies.ToArray(); } - private void PopulateDiagnosticsMap() - { - foreach (var diagnostic in InputDiagnosticMessages) - { - var metadata = new DiagnosticMetadata(diagnostic); - DiagnosticsMap[diagnostic.ItemSpec] = metadata; - } - } - private static DependencyType GetDependencyType(string dependencyTypeString) { Enum.TryParse(dependencyTypeString, ignoreCase: true, out DependencyType dependencyType); @@ -556,89 +537,6 @@ public override ItemMetadata Clone() } } - private sealed class DiagnosticMetadata : ItemMetadata - { - public DiagnosticMetadata(ITaskItem item) - : base(DependencyType.Diagnostic) - { - DiagnosticCode = item.GetMetadata(MetadataKeys.DiagnosticCode) ?? string.Empty; - Message = item.GetMetadata(MetadataKeys.Message) ?? string.Empty; - FilePath = item.GetMetadata(MetadataKeys.FilePath) ?? string.Empty; - Severity = item.GetMetadata(MetadataKeys.Severity) ?? string.Empty; - StartLine = item.GetMetadata(MetadataKeys.StartLine) ?? string.Empty; - StartColumn = item.GetMetadata(MetadataKeys.StartColumn) ?? string.Empty; - EndLine = item.GetMetadata(MetadataKeys.EndLine) ?? string.Empty; - EndColumn = item.GetMetadata(MetadataKeys.EndColumn) ?? string.Empty; - } - - private DiagnosticMetadata( - DependencyType type, - IList dependencies, - bool isTopLevelDependency, - string diagnosticCode, - string message, - string filePath, - string severity, - string startLine, - string startColumn, - string endLine, - string endColumn) - : base(type, dependencies, isTopLevelDependency) - { - DiagnosticCode = diagnosticCode; - Message = message; - FilePath = filePath; - Severity = severity; - StartLine = startLine; - StartColumn = startColumn; - EndLine = endLine; - EndColumn = endColumn; - } - - public string DiagnosticCode { get; } - public string Message { get; } - public string FilePath { get; } - public string Severity { get; } - public string StartLine { get; } - public string StartColumn { get; } - public string EndLine { get; } - public string EndColumn { get; } - - public override IDictionary ToDictionary() - { - return new Dictionary - { - { MetadataKeys.Name, Message }, - { MetadataKeys.DiagnosticCode, DiagnosticCode }, - { MetadataKeys.Message, Message }, - { MetadataKeys.FilePath, FilePath }, - { MetadataKeys.Severity, Severity }, - { MetadataKeys.StartLine, StartLine }, - { MetadataKeys.StartColumn, StartColumn }, - { MetadataKeys.EndLine, EndLine }, - { MetadataKeys.EndColumn, EndColumn }, - { MetadataKeys.Type, Type.ToString() }, - { DependenciesMetadata, string.Join(";", Dependencies) } - }; - } - - public override ItemMetadata Clone() - { - return new DiagnosticMetadata( - Type, - Dependencies, - IsTopLevelDependency, - DiagnosticCode, - Message, - FilePath, - Severity, - StartLine, - StartColumn, - EndLine, - EndColumn); - } - } - /// /// Represents the FileDependency metadata for a Reference item that we want to pretend was /// resolved as a standard NuGet package assembly. diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets index 083d70564ad7..fbc82731fac5 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets @@ -310,7 +310,6 @@ Copyright (c) .NET Foundation. All rights reserved. FileDependencies="@(FileDependencies)" References="@(Reference)" DefaultImplicitPackages="$(DefaultImplicitPackages)" - InputDiagnosticMessages="@(DiagnosticMessages)" TargetFrameworkMoniker="$(NuGetTargetMoniker)"> From 4535ef63a3bf170a8c7fb620ba9b423d1eb72e16 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Thu, 2 Apr 2020 10:31:10 +1100 Subject: [PATCH 14/32] Documentation --- .../PreprocessPackageDependenciesDesignTime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 96a0e60bae32..bb4ca22cfa00 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -12,7 +12,7 @@ namespace Microsoft.NET.Build.Tasks { /// - /// Task combines data returned from ResolvePackageDependencies into single items collection + /// Task combines data returned from into single items collection /// that can be consumed by DesignTime build and contains all info needed to expand packages /// dependency graph. /// If any changes are made here, make sure corresponding changes are made to PackageRuleHandler From dfcbaf3b5cf9c7cf57078d111417a10682d2c704 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Thu, 2 Apr 2020 10:31:39 +1100 Subject: [PATCH 15/32] Make local functions static --- src/Tasks/Microsoft.NET.Build.Tasks/LockFileExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/LockFileExtensions.cs b/src/Tasks/Microsoft.NET.Build.Tasks/LockFileExtensions.cs index f70be8866d63..a95beba36800 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/LockFileExtensions.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/LockFileExtensions.cs @@ -113,7 +113,7 @@ public static Dictionary GetProjectFileDependencies(this LockFil public static HashSet GetProjectFileDependencySet(this LockFile lockFile) { // Get package name from e.g. Microsoft.VSSDK.BuildTools >= 15.0.25604-Preview4 - string GetPackageNameFromDependency(string dependency) + static string GetPackageNameFromDependency(string dependency) { int indexOfWhiteSpace = IndexOfWhiteSpace(dependency); if (indexOfWhiteSpace < 0) @@ -124,7 +124,7 @@ string GetPackageNameFromDependency(string dependency) return dependency.Substring(0, indexOfWhiteSpace); } - int IndexOfWhiteSpace(string s) + static int IndexOfWhiteSpace(string s) { for (int i = 0; i < s.Length; i++) { From a3971a1d947c9f5b4a4959c45e332e066c7ef15f Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Thu, 2 Apr 2020 10:44:21 +1100 Subject: [PATCH 16/32] Convert property to local variable --- .../PreprocessPackageDependenciesDesignTime.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index bb4ca22cfa00..c37d756cd27f 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -64,14 +64,10 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase private Dictionary DependenciesWorld { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private HashSet ImplicitPackageReferences { get; set; } - private ITaskItem[] ExistingReferenceItemDependencies { get; set; } protected override void ExecuteCore() { - ImplicitPackageReferences = GetImplicitPackageReferences(DefaultImplicitPackages); - PopulateTargets(); PopulatePackages(); @@ -144,6 +140,8 @@ private void PopulateTargets() /// private void PopulatePackages() { + var implicitPackageReferences = GetImplicitPackageReferences(DefaultImplicitPackages); + foreach (var packageDef in PackageDefinitions) { var dependencyType = GetDependencyType(packageDef.GetMetadata(MetadataKeys.Type)); @@ -157,7 +155,7 @@ private void PopulatePackages() } var dependency = new PackageMetadata(packageDef); - dependency.IsImplicitlyDefined = ImplicitPackageReferences.Contains(dependency.Name); + dependency.IsImplicitlyDefined = implicitPackageReferences.Contains(dependency.Name); Packages[packageDef.ItemSpec] = dependency; } From 0343967bc9b6295a7b0057fb4ca1be55c7cce5a4 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Thu, 2 Apr 2020 10:54:28 +1100 Subject: [PATCH 17/32] Replace O(N) with O(1) lookup --- .../PreprocessPackageDependenciesDesignTime.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index c37d756cd27f..e9f9d7400dc4 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -258,7 +258,7 @@ private void AddDependenciesToTheWorld(Dictionary items, foreach (var dependency in itemDependencies) { var currentItemId = dependency.ItemSpec; - if (!items.Keys.Contains(currentItemId)) + if (!items.ContainsKey(currentItemId)) { // if this package definition does not even exist - skip it continue; @@ -270,14 +270,14 @@ private void AddDependenciesToTheWorld(Dictionary items, } var parentTargetId = dependency.GetMetadata(MetadataKeys.ParentTarget) ?? string.Empty; - if (parentTargetId.Contains("/") || !Targets.Keys.Contains(parentTargetId)) + if (parentTargetId.Contains("/") || !Targets.ContainsKey(parentTargetId)) { // skip "target/rid"s and only consume actual targets and ignore non-existent parent targets continue; } var parentPackageId = dependency.GetMetadata(MetadataKeys.ParentPackage) ?? string.Empty; - if (!string.IsNullOrEmpty(parentPackageId) && !Packages.Keys.Contains(parentPackageId)) + if (!string.IsNullOrEmpty(parentPackageId) && !Packages.ContainsKey(parentPackageId)) { // ignore non-existent parent packages continue; From 10fce0cc3e650fd7f3b343e9baddaacaad4a51ea Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Thu, 2 Apr 2020 11:21:44 +1100 Subject: [PATCH 18/32] Reduce allocation when applying item metadata --- ...PreprocessPackageDependenciesDesignTime.cs | 70 ++++++++----------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index e9f9d7400dc4..eb2b57c8ab01 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -97,11 +97,7 @@ protected override void ExecuteCore() DependenciesDesignTime = DependenciesWorld.Select(itemKvp => { var newTaskItem = new TaskItem(itemKvp.Key); - foreach (var metadataKvp in itemKvp.Value.ToDictionary()) - { - newTaskItem.SetMetadata(metadataKvp.Key, metadataKvp.Value); - } - + itemKvp.Value.SetMetadataOnTaskItem(newTaskItem); return newTaskItem; }).ToArray(); } @@ -343,10 +339,9 @@ protected ItemMetadata(DependencyType type, IList dependencies = null, b public List Dependencies { get; } /// - /// Returns name/value pairs for metadata specific to given item type's implementation. + /// Populates metadata on . /// - /// - public abstract IDictionary ToDictionary(); + public abstract void SetMetadataOnTaskItem(TaskItem taskItem); /// /// Creates a copy of the item @@ -386,17 +381,14 @@ private TargetMetadata( public string FrameworkName { get; } public string FrameworkVersion { get; } - public override IDictionary ToDictionary() + public override void SetMetadataOnTaskItem(TaskItem taskItem) { - return new Dictionary - { - { MetadataKeys.RuntimeIdentifier, RuntimeIdentifier }, - { MetadataKeys.TargetFrameworkMoniker, TargetFrameworkMoniker }, - { MetadataKeys.FrameworkName, FrameworkName }, - { MetadataKeys.FrameworkVersion, FrameworkVersion }, - { MetadataKeys.Type, Type.ToString() }, - { DependenciesMetadata, string.Join(";", Dependencies) } - }; + taskItem.SetMetadata(MetadataKeys.RuntimeIdentifier, RuntimeIdentifier); + taskItem.SetMetadata(MetadataKeys.TargetFrameworkMoniker, TargetFrameworkMoniker); + taskItem.SetMetadata(MetadataKeys.FrameworkName, FrameworkName); + taskItem.SetMetadata(MetadataKeys.FrameworkVersion, FrameworkVersion); + taskItem.SetMetadata(MetadataKeys.Type, Type.ToString()); + taskItem.SetMetadata(DependenciesMetadata, string.Join(";", Dependencies)); } public override ItemMetadata Clone() @@ -449,19 +441,16 @@ private PackageMetadata( public bool Resolved { get; } public bool IsImplicitlyDefined { get; set; } - public override IDictionary ToDictionary() + public override void SetMetadataOnTaskItem(TaskItem taskItem) { - return new Dictionary - { - { MetadataKeys.Name, Name }, - { MetadataKeys.Version, Version }, - { MetadataKeys.Path, Path }, - { MetadataKeys.Type, Type.ToString() }, - { MetadataKeys.IsImplicitlyDefined, IsImplicitlyDefined.ToString() }, - { MetadataKeys.IsTopLevelDependency, IsTopLevelDependency.ToString() }, - { ResolvedMetadata, Resolved.ToString() }, - { DependenciesMetadata, string.Join(";", Dependencies) } - }; + taskItem.SetMetadata(MetadataKeys.Name, Name); + taskItem.SetMetadata(MetadataKeys.Version, Version); + taskItem.SetMetadata(MetadataKeys.Path, Path); + taskItem.SetMetadata(MetadataKeys.Type, Type.ToString()); + taskItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, IsImplicitlyDefined.ToString()); + taskItem.SetMetadata(MetadataKeys.IsTopLevelDependency, IsTopLevelDependency.ToString()); + taskItem.SetMetadata(ResolvedMetadata, Resolved.ToString()); + taskItem.SetMetadata(DependenciesMetadata, string.Join(";", Dependencies)); } public override ItemMetadata Clone() @@ -511,19 +500,16 @@ public ExistingReferenceItemMetadata(string name, string path, bool visible) public string Path { get; } public bool Visible { get; } - public override IDictionary ToDictionary() + public override void SetMetadataOnTaskItem(TaskItem taskItem) { - return new Dictionary - { - { MetadataKeys.Name, Name }, - { MetadataKeys.Path, Path }, - { MetadataKeys.Type, Type.ToString() }, - { MetadataKeys.IsImplicitlyDefined, "false" }, - { MetadataKeys.IsTopLevelDependency, "false" }, - { ResolvedMetadata, "true" }, - { VisibleMetadata, Visible.ToString() }, - { DependenciesMetadata, string.Empty } - }; + taskItem.SetMetadata(MetadataKeys.Name, Name); + taskItem.SetMetadata(MetadataKeys.Path, Path); + taskItem.SetMetadata(MetadataKeys.Type, Type.ToString()); + taskItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, "false"); + taskItem.SetMetadata(MetadataKeys.IsTopLevelDependency, "false"); + taskItem.SetMetadata(ResolvedMetadata, "true"); + taskItem.SetMetadata(VisibleMetadata, Visible.ToString()); + taskItem.SetMetadata(DependenciesMetadata, string.Empty); } public override ItemMetadata Clone() From 78088a7e9f164fed94cc387c0753e1b80e4eaea8 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Thu, 2 Apr 2020 12:18:28 +1100 Subject: [PATCH 19/32] Remove assemblies from PreprocessPackageDependenciesDesignTime From now on, this task will only return top-level items, so we do not need to output assemblies, nor do we need to accept FileDefinitions. --- ...PreprocessPackageDependenciesDesignTime.cs | 228 +----------------- ...rosoft.PackageDependencyResolution.targets | 1 - 2 files changed, 2 insertions(+), 227 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index eb2b57c8ab01..a982611d134e 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -2,9 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -21,7 +19,6 @@ namespace Microsoft.NET.Build.Tasks public class PreprocessPackageDependenciesDesignTime : TaskBase { public const string DependenciesMetadata = "Dependencies"; - public const string CompileTimeAssemblyMetadata = "CompileTimeAssembly"; public const string ResolvedMetadata = "Resolved"; public const string VisibleMetadata = "Visible"; @@ -31,9 +28,6 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase [Required] public ITaskItem[] PackageDefinitions { get; set; } - [Required] - public ITaskItem[] FileDefinitions { get; set; } - [Required] public ITaskItem[] PackageDependencies { get; set; } @@ -58,41 +52,17 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase private Dictionary Packages { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary Assemblies { get; } - = new Dictionary(StringComparer.OrdinalIgnoreCase); - private Dictionary DependenciesWorld { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - private ITaskItem[] ExistingReferenceItemDependencies { get; set; } - protected override void ExecuteCore() { PopulateTargets(); PopulatePackages(); - PopulateAssemblies(); - PopulateExistingReferenceItems(); - AddDependenciesToTheWorld(Packages, PackageDependencies); - AddDependenciesToTheWorld(Assemblies, FileDependencies, item => - { - // We keep analyzers and assemblies with CompileTimeAssembly metadata; skip everything else. - - if (Assemblies.TryGetValue(item.ItemSpec, out ItemMetadata itemMetadata) && - itemMetadata.Type == DependencyType.AnalyzerAssembly) - { - return false; - } - - var fileGroup = item.GetMetadata(MetadataKeys.FileGroup); - return string.IsNullOrEmpty(fileGroup) || !fileGroup.Equals(CompileTimeAssemblyMetadata); - }); - - AddDependenciesToTheWorld(Assemblies, ExistingReferenceItemDependencies); - // prepare output collection: add corresponding metadata to ITaskItem based in item type DependenciesDesignTime = DependenciesWorld.Select(itemKvp => { @@ -157,90 +127,6 @@ private void PopulatePackages() } } - /// - /// Adds assemblies, analyzers and framework assemblies from FileDefinitions to dependencies world dictionary. - /// - private void PopulateAssemblies() - { - foreach (var fileDef in FileDefinitions) - { - var dependencyType = GetDependencyType(fileDef.GetMetadata(MetadataKeys.Type)); - if (dependencyType != DependencyType.Assembly && - dependencyType != DependencyType.FrameworkAssembly && - dependencyType != DependencyType.AnalyzerAssembly) - { - continue; - } - - var name = Path.GetFileName(fileDef.ItemSpec); - var assembly = new AssemblyMetadata(dependencyType, fileDef, name); - Assemblies[fileDef.ItemSpec] = assembly; - } - } - - /// - /// Update FileDefinitions and FileDependencies to pretend that certain Reference items - /// explicitly added by a .targets file in the NETStandard.Library are actually normal - /// package items. This allows them to show up properly under the "SDK" node in Solution - /// Explorer, rather than just under the "Assemblies" node. - /// - /// This is not meant to be a general mechanism for injecting files that can't be handled - /// through the normal NuGet package mechanisms. - /// - private void PopulateExistingReferenceItems() - { - var existingReferenceItemDependencies = new List(); - foreach (var reference in References) - { - var packageName = reference.GetMetadata(MetadataKeys.NuGetPackageId); - var packageVersion = reference.GetMetadata(MetadataKeys.NuGetPackageVersion); - - // This is not a "pre-resolved" assembly; skip it. - if (packageName == null || packageVersion == null) - { - continue; - } - - // If we don't know about the specified package, skip it. - var packageId = $"{packageName}/{packageVersion}"; - if (!Packages.TryGetValue(packageId, out ItemMetadata packageItemMetadata)) - { - continue; - } - - // If the file isn't actually a part of the package, skip it. - var packageMetadata = (PackageMetadata)packageItemMetadata; - if (!reference.ItemSpec.StartsWith(packageMetadata.Path, StringComparison.OrdinalIgnoreCase)) - { - continue; - } - - var referenceRelativePath = reference.ItemSpec.Substring(packageMetadata.Path.Length).Trim('\\'); - var referenceKey = $"{packageId}/{referenceRelativePath.Replace('\\', '/')}"; - - // If we already know about the assembly file, skip it. - if (Assemblies.TryGetValue(referenceKey, out ItemMetadata assemblyItemMetadata)) - { - continue; - } - - // Create the appropriate metadata. - var name = Path.GetFileName(referenceKey); - var facadeMetadata = reference.GetBooleanMetadata("Facade"); - var visible = facadeMetadata.HasValue ? !facadeMetadata.Value : true; - var assembly = new ExistingReferenceItemMetadata(name, reference.ItemSpec, visible); - Assemblies[referenceKey] = assembly; - - // Create the file dependency. - existingReferenceItemDependencies.Add(new ExistingReferenceItemDependency( - referenceKey, - TargetFrameworkMoniker, - packageId)); - } - - ExistingReferenceItemDependencies = existingReferenceItemDependencies.ToArray(); - } - private static DependencyType GetDependencyType(string dependencyTypeString) { Enum.TryParse(dependencyTypeString, ignoreCase: true, out DependencyType dependencyType); @@ -329,7 +215,7 @@ protected ItemMetadata(DependencyType type, IList dependencies = null, b IsTopLevelDependency = isTopLevelDependency; } - public DependencyType Type { get; protected set; } + public DependencyType Type { get; } public bool IsTopLevelDependency { get; set; } /// @@ -435,7 +321,7 @@ private PackageMetadata( IsImplicitlyDefined = isImplicitlyDefined; } - public string Name { get; protected set; } + public string Name { get; } public string Version { get; } public string Path { get; } public bool Resolved { get; } @@ -467,116 +353,6 @@ public override ItemMetadata Clone() } } - private class AssemblyMetadata : PackageMetadata - { - public AssemblyMetadata(DependencyType type, - ITaskItem item, - string name) - : base(item) - { - Name = name ?? string.Empty; - Type = type; - } - } - - /// - /// Represents metadata for a Reference item that we want to pretend was resolved as a - /// standard NuGet package assembly. - /// - private class ExistingReferenceItemMetadata : ItemMetadata - { - public ExistingReferenceItemMetadata(string name, string path, bool visible) - : base( - type: DependencyType.Assembly, - dependencies: null, - isTopLevelDependency: false) - { - Name = name; - Path = path; - Visible = visible; - } - - public string Name { get; } - public string Path { get; } - public bool Visible { get; } - - public override void SetMetadataOnTaskItem(TaskItem taskItem) - { - taskItem.SetMetadata(MetadataKeys.Name, Name); - taskItem.SetMetadata(MetadataKeys.Path, Path); - taskItem.SetMetadata(MetadataKeys.Type, Type.ToString()); - taskItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, "false"); - taskItem.SetMetadata(MetadataKeys.IsTopLevelDependency, "false"); - taskItem.SetMetadata(ResolvedMetadata, "true"); - taskItem.SetMetadata(VisibleMetadata, Visible.ToString()); - taskItem.SetMetadata(DependenciesMetadata, string.Empty); - } - - public override ItemMetadata Clone() - { - return new ExistingReferenceItemMetadata( - Name, - Path, - Visible); - } - } - - /// - /// Represents the FileDependency metadata for a Reference item that we want to pretend was - /// resolved as a standard NuGet package assembly. - /// - private sealed class ExistingReferenceItemDependency : ITaskItem - { - private readonly Dictionary _metadata = new Dictionary(capacity: 3, comparer: StringComparer.OrdinalIgnoreCase); - - public ExistingReferenceItemDependency(string itemSpec, string parentTarget, string parentPackage) - { - ItemSpec = itemSpec; - _metadata[MetadataKeys.FileGroup] = CompileTimeAssemblyMetadata; - _metadata[MetadataKeys.ParentTarget] = parentTarget; - _metadata[MetadataKeys.ParentPackage] = parentPackage; - } - - public string ItemSpec { get; set; } - - public ICollection MetadataNames => _metadata.Keys; - - public int MetadataCount => _metadata.Count; - - public IDictionary CloneCustomMetadata() - { - return new Dictionary(_metadata, _metadata.Comparer); - } - - public void CopyMetadataTo(ITaskItem destinationItem) - { - foreach (var pair in _metadata) - { - destinationItem.SetMetadata(pair.Key, pair.Value); - } - } - - public string GetMetadata(string metadataName) - { - if (_metadata.TryGetValue(metadataName, out string metadataValue)) - { - return metadataValue; - } - - return null; - } - - public void RemoveMetadata(string metadataName) - { - _metadata.Remove(metadataName); - } - - public void SetMetadata(string metadataName, string metadataValue) - { - _metadata[metadataName] = metadataValue; - } - } - internal static HashSet GetImplicitPackageReferences(string defaultImplicitPackages) { var implicitPackageReferences = new HashSet(StringComparer.OrdinalIgnoreCase); diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets index fbc82731fac5..cf75a0ae2974 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets @@ -305,7 +305,6 @@ Copyright (c) .NET Foundation. All rights reserved. Date: Thu, 2 Apr 2020 20:24:42 +1100 Subject: [PATCH 20/32] Remove non-top-level packages from PreprocessPackageDependenciesDesignTime Performance work on the Dependencies node in dotnet/project-system mean that only top-level package data is needed from the design-time build. This commit removes items and metadata related to transitive dependencies and hierarchy. - Remove metadata Dependencies, which used to list child IDs - Remove metadata IsTopLevelDependency, which is now implicitly true - Remove 'target' items - Remove object cloning, now that instances are immutable --- ...PreprocessPackageDependenciesDesignTime.cs | 357 +++++------------- ...rosoft.PackageDependencyResolution.targets | 5 +- 2 files changed, 91 insertions(+), 271 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index a982611d134e..7d97cba55022 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -3,354 +3,171 @@ using System; using System.Collections.Generic; -using System.Linq; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace Microsoft.NET.Build.Tasks { /// - /// Task combines data returned from into single items collection - /// that can be consumed by DesignTime build and contains all info needed to expand packages - /// dependency graph. - /// If any changes are made here, make sure corresponding changes are made to PackageRuleHandler - /// in the dotnet/project-system repo and corresponding tests. + /// Filters and projects items produced by for consumption by + /// the dependencies tree, via design-time builds. /// + /// + /// Only top-level package references are retained (i.e. those referenced directly by the project, not + /// those only brought in transitively). + /// + /// Changes to the implementation of this class must be coordinated with PackageRuleHandler + /// in the dotnet/project-system repo. + /// public class PreprocessPackageDependenciesDesignTime : TaskBase { - public const string DependenciesMetadata = "Dependencies"; public const string ResolvedMetadata = "Resolved"; - public const string VisibleMetadata = "Visible"; [Required] public ITaskItem[] TargetDefinitions { get; set; } + /// + /// Information about each package in the project, with metadata: + /// - Name = "MetadataExtractor" + /// - Path = "metadataextractor/1.0.0" + /// - ResolvedPath = "C:\Users\drnoakes\.nuget\packages\metadataextractor\1.0.0" + /// - Type = "package" + /// - Version = "2.3.0" + /// [Required] public ITaskItem[] PackageDefinitions { get; set; } + /// + /// Items with metadata "ParentTarget" and "ParentPackage", which allows determining the hierarchy of package references. + /// [Required] public ITaskItem[] PackageDependencies { get; set; } - [Required] - public ITaskItem[] FileDependencies { get; set; } - + /// + /// Eg: "Microsoft.NETCore.App;NETStandard.Library" + /// [Required] public string DefaultImplicitPackages { get; set; } - [Required] - public ITaskItem[] References { get; set; } - - [Required] - public string TargetFrameworkMoniker { get; set; } - [Output] - public ITaskItem[] DependenciesDesignTime { get; set; } - - private Dictionary Targets { get; } - = new Dictionary(StringComparer.OrdinalIgnoreCase); - - private Dictionary Packages { get; } - = new Dictionary(StringComparer.OrdinalIgnoreCase); - - private Dictionary DependenciesWorld { get; } - = new Dictionary(StringComparer.OrdinalIgnoreCase); + public ITaskItem[] DependenciesDesignTime { get; private set; } protected override void ExecuteCore() { - PopulateTargets(); - - PopulatePackages(); - - AddDependenciesToTheWorld(Packages, PackageDependencies); - - // prepare output collection: add corresponding metadata to ITaskItem based in item type - DependenciesDesignTime = DependenciesWorld.Select(itemKvp => - { - var newTaskItem = new TaskItem(itemKvp.Key); - itemKvp.Value.SetMetadataOnTaskItem(newTaskItem); - return newTaskItem; - }).ToArray(); - } - - /// - /// Adds targets from TargetDefinitions to dependencies world dictionary - /// - private void PopulateTargets() - { - foreach (var targetDef in TargetDefinitions) - { - if (string.IsNullOrEmpty(targetDef.ItemSpec) || targetDef.ItemSpec.Contains("/")) - { - // skip "target/rid"s and only consume actual targets - continue; - } - - var dependencyType = GetDependencyType(targetDef.GetMetadata(MetadataKeys.Type)); - if (dependencyType != DependencyType.Target) - { - // keep only targets here - continue; - } - - var target = new TargetMetadata(targetDef); - - Targets[targetDef.ItemSpec] = target; + var targets = GetTargets(TargetDefinitions); - // add target to the world now, since it does not have parents - DependenciesWorld[targetDef.ItemSpec] = target; - } - } - - /// - /// Adds packages from PackageDefinitions to the dependencies world dictionary. - /// - private void PopulatePackages() - { var implicitPackageReferences = GetImplicitPackageReferences(DefaultImplicitPackages); + var packageByItemSpec = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var packageDef in PackageDefinitions) { var dependencyType = GetDependencyType(packageDef.GetMetadata(MetadataKeys.Type)); - if (dependencyType != DependencyType.Package && - dependencyType != DependencyType.Unresolved) + + if (dependencyType == DependencyType.Package && + dependencyType == DependencyType.Unresolved) { - // we ignore all other dependency types since - // - assemblies we handle separately below - // - projects we don't care here, since they are sent to project system via other route - continue; + packageByItemSpec[packageDef.ItemSpec] = new PackageMetadata(packageDef, implicitPackageReferences); } - - var dependency = new PackageMetadata(packageDef); - dependency.IsImplicitlyDefined = implicitPackageReferences.Contains(dependency.Name); - - Packages[packageDef.ItemSpec] = dependency; } - } - private static DependencyType GetDependencyType(string dependencyTypeString) - { - Enum.TryParse(dependencyTypeString, ignoreCase: true, out DependencyType dependencyType); - return dependencyType; - } + var packageByUniqueId = new Dictionary(StringComparer.OrdinalIgnoreCase); - private void AddDependenciesToTheWorld(Dictionary items, - ITaskItem[] itemDependencies, - Func shouldSkipItemCheck = null) - { - foreach (var dependency in itemDependencies) + foreach (var dependency in PackageDependencies) { var currentItemId = dependency.ItemSpec; - if (!items.ContainsKey(currentItemId)) + + if (!packageByItemSpec.TryGetValue(currentItemId, out var package)) { // if this package definition does not even exist - skip it continue; } - if (shouldSkipItemCheck != null && shouldSkipItemCheck(dependency)) + if (dependency.HasMetadataValue(MetadataKeys.ParentPackage)) { + // ignore non-top-level packages (those with ParentPackage) continue; } var parentTargetId = dependency.GetMetadata(MetadataKeys.ParentTarget) ?? string.Empty; - if (parentTargetId.Contains("/") || !Targets.ContainsKey(parentTargetId)) + if (parentTargetId.IndexOf('/') != -1 || !targets.Contains(parentTargetId)) { // skip "target/rid"s and only consume actual targets and ignore non-existent parent targets continue; } - var parentPackageId = dependency.GetMetadata(MetadataKeys.ParentPackage) ?? string.Empty; - if (!string.IsNullOrEmpty(parentPackageId) && !Packages.ContainsKey(parentPackageId)) - { - // ignore non-existent parent packages - continue; - } - var currentPackageUniqueId = $"{parentTargetId}/{currentItemId}"; - // add current package to dependencies world - var currentItem = GetItem(items, currentItemId); - DependenciesWorld[currentPackageUniqueId] = currentItem; - - // update parent - var parentDependencyId = $"{parentTargetId}/{parentPackageId}".Trim('/'); - if (DependenciesWorld.TryGetValue(parentDependencyId, out ItemMetadata parentDependency)) - { - parentDependency.Dependencies.Add(currentItemId); - if (parentDependency.Type == DependencyType.Target) - { - currentItem.IsTopLevelDependency = true; - } - } - else - { - // Update parent's Dependencies count and make sure parent is in the dependencies world - if (!string.IsNullOrEmpty(parentPackageId)) - { - parentDependency = GetItem(Packages, parentPackageId); - } - else - { - parentDependency = GetItem(Targets, parentTargetId); - currentItem.IsTopLevelDependency = true; - } - - parentDependency.Dependencies.Add(currentItemId); - DependenciesWorld[parentDependencyId] = parentDependency; - } - } - - return; - - ItemMetadata GetItem(Dictionary items, string id) - { - return Targets.Count > 1 ? items[id].Clone() : items[id]; - } - } - - private abstract class ItemMetadata - { - protected ItemMetadata(DependencyType type, IList dependencies = null, bool isTopLevelDependency = false) - { - Type = type; - Dependencies = dependencies == null ? new List() : new List(dependencies); - IsTopLevelDependency = isTopLevelDependency; - } - - public DependencyType Type { get; } - public bool IsTopLevelDependency { get; set; } - - /// - /// A list of name/version strings to specify dependency identities. - /// Note: identity here is just a "name/version" and does not have TFM part in front. - /// - public List Dependencies { get; } - - /// - /// Populates metadata on . - /// - public abstract void SetMetadataOnTaskItem(TaskItem taskItem); - - /// - /// Creates a copy of the item - /// - public abstract ItemMetadata Clone(); - } - - private class TargetMetadata : ItemMetadata - { - public TargetMetadata(ITaskItem item) - : base(DependencyType.Target) - { - RuntimeIdentifier = item.GetMetadata(MetadataKeys.RuntimeIdentifier) ?? string.Empty; - TargetFrameworkMoniker = item.GetMetadata(MetadataKeys.TargetFrameworkMoniker) ?? string.Empty; - FrameworkName = item.GetMetadata(MetadataKeys.FrameworkName) ?? string.Empty; - FrameworkVersion = item.GetMetadata(MetadataKeys.FrameworkVersion) ?? string.Empty; - } - private TargetMetadata( - DependencyType type, - IList dependencies, - bool isTopLevelDependency, - string runtimeIdentifier, - string targetFrameworkMoniker, - string frameworkName, - string frameworkVersion) - : base(type, dependencies, isTopLevelDependency) - { - RuntimeIdentifier = runtimeIdentifier; - TargetFrameworkMoniker = targetFrameworkMoniker; - FrameworkName = frameworkName; - FrameworkVersion = frameworkVersion; + // add current package to dependencies world + packageByUniqueId[currentPackageUniqueId] = package; } - public string RuntimeIdentifier { get; } - public string TargetFrameworkMoniker { get; } - public string FrameworkName { get; } - public string FrameworkVersion { get; } + var outputItems = new List(packageByUniqueId.Count); - public override void SetMetadataOnTaskItem(TaskItem taskItem) + foreach (var pair in packageByUniqueId) { - taskItem.SetMetadata(MetadataKeys.RuntimeIdentifier, RuntimeIdentifier); - taskItem.SetMetadata(MetadataKeys.TargetFrameworkMoniker, TargetFrameworkMoniker); - taskItem.SetMetadata(MetadataKeys.FrameworkName, FrameworkName); - taskItem.SetMetadata(MetadataKeys.FrameworkVersion, FrameworkVersion); - taskItem.SetMetadata(MetadataKeys.Type, Type.ToString()); - taskItem.SetMetadata(DependenciesMetadata, string.Join(";", Dependencies)); + outputItems.Add(pair.Value.ToTaskItem(pair.Key)); } - public override ItemMetadata Clone() - { - return new TargetMetadata( - Type, - Dependencies, - IsTopLevelDependency, - RuntimeIdentifier, - TargetFrameworkMoniker, - FrameworkName, - FrameworkVersion); - } + DependenciesDesignTime = outputItems.ToArray(); } - private class PackageMetadata : ItemMetadata + private sealed class PackageMetadata { - public PackageMetadata(ITaskItem item) - : base(DependencyType.Package) + public PackageMetadata(ITaskItem item, HashSet implicitPackageReferences) { Name = item.GetMetadata(MetadataKeys.Name) ?? string.Empty; Version = item.GetMetadata(MetadataKeys.Version) ?? string.Empty; - Resolved = Type != DependencyType.Unknown && !string.IsNullOrEmpty(item.GetMetadata(MetadataKeys.ResolvedPath)); + Resolved = !string.IsNullOrEmpty(item.GetMetadata(MetadataKeys.ResolvedPath)); Path = (Resolved ? item.GetMetadata(MetadataKeys.ResolvedPath) : item.GetMetadata(MetadataKeys.Path)) ?? string.Empty; + IsImplicitlyDefined = implicitPackageReferences.Contains(Name); } - private PackageMetadata( - DependencyType type, - IList dependencies, - bool isTopLevelDependency, - string name, - string version, - string path, - bool resolved, - bool isImplicitlyDefined) - : base(type, dependencies, isTopLevelDependency) + private string Name { get; } + private string Version { get; } + private string Path { get; } + private bool Resolved { get; } + private bool IsImplicitlyDefined { get; } + + public ITaskItem ToTaskItem(string itemSpec) { - Name = name; - Version = version; - Path = path; - Resolved = resolved; - IsImplicitlyDefined = isImplicitlyDefined; + var outputItem = new TaskItem(itemSpec); + outputItem.SetMetadata(MetadataKeys.Name, Name); + outputItem.SetMetadata(MetadataKeys.Version, Version); + outputItem.SetMetadata(MetadataKeys.Path, Path); + outputItem.SetMetadata(MetadataKeys.Type, DependencyType.Package.ToString()); + outputItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, IsImplicitlyDefined.ToString()); + outputItem.SetMetadata(MetadataKeys.IsTopLevelDependency, bool.TrueString); + outputItem.SetMetadata(ResolvedMetadata, Resolved.ToString()); + return outputItem; } + } - public string Name { get; } - public string Version { get; } - public string Path { get; } - public bool Resolved { get; } - public bool IsImplicitlyDefined { get; set; } + private static HashSet GetTargets(ITaskItem[] targetDefinitions) + { + var targets = new HashSet(StringComparer.OrdinalIgnoreCase); - public override void SetMetadataOnTaskItem(TaskItem taskItem) + foreach (var targetDef in targetDefinitions) { - taskItem.SetMetadata(MetadataKeys.Name, Name); - taskItem.SetMetadata(MetadataKeys.Version, Version); - taskItem.SetMetadata(MetadataKeys.Path, Path); - taskItem.SetMetadata(MetadataKeys.Type, Type.ToString()); - taskItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, IsImplicitlyDefined.ToString()); - taskItem.SetMetadata(MetadataKeys.IsTopLevelDependency, IsTopLevelDependency.ToString()); - taskItem.SetMetadata(ResolvedMetadata, Resolved.ToString()); - taskItem.SetMetadata(DependenciesMetadata, string.Join(";", Dependencies)); - } + if (string.IsNullOrEmpty(targetDef.ItemSpec) || targetDef.ItemSpec.IndexOf('/') != -1) + { + // skip "target/rid"s and only consume actual targets + continue; + } - public override ItemMetadata Clone() - { - return new PackageMetadata( - Type, - Dependencies, - IsTopLevelDependency, - Name, - Version, - Path, - Resolved, - IsImplicitlyDefined); + var dependencyType = GetDependencyType(targetDef.GetMetadata(MetadataKeys.Type)); + if (dependencyType != DependencyType.Target) + { + // keep only targets here + continue; + } + + targets.Add(targetDef.ItemSpec); } + + return targets; } internal static HashSet GetImplicitPackageReferences(string defaultImplicitPackages) @@ -374,5 +191,11 @@ internal static HashSet GetImplicitPackageReferences(string defaultImpli return implicitPackageReferences; } + + private static DependencyType GetDependencyType(string dependencyTypeString) + { + Enum.TryParse(dependencyTypeString, ignoreCase: true, out DependencyType dependencyType); + return dependencyType; + } } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets index cf75a0ae2974..2a757e07cd6d 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets @@ -306,10 +306,7 @@ Copyright (c) .NET Foundation. All rights reserved. TargetDefinitions="@(TargetDefinitions)" PackageDefinitions="@(PackageDefinitions)" PackageDependencies="@(PackageDependencies)" - FileDependencies="@(FileDependencies)" - References="@(Reference)" - DefaultImplicitPackages="$(DefaultImplicitPackages)" - TargetFrameworkMoniker="$(NuGetTargetMoniker)"> + DefaultImplicitPackages="$(DefaultImplicitPackages)"> From 4632176dbacce90d023cae99a5c4cca562abd96a Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Fri, 3 Apr 2020 07:19:57 +1100 Subject: [PATCH 21/32] Filter DTB packages by TargetFrameworkMoniker Previously PreprocessPackageDependenciesDesignTime returned package dependencies for all targets, and PackageRuleHandler in the project system would filter based on TargetFrameworkMoniker. This change applies the filtering in this task instead. As part of this change we are now able to remove the target prefix from the item spec of output items. This reduces string allocation, improves the chance of pooling and reduces string manipulation by the consumer. --- ...PreprocessPackageDependenciesDesignTime.cs | 139 +++++++----------- ...rosoft.PackageDependencyResolution.targets | 8 +- 2 files changed, 54 insertions(+), 93 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 7d97cba55022..cb55086b2b88 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -15,6 +15,8 @@ namespace Microsoft.NET.Build.Tasks /// /// Only top-level package references are retained (i.e. those referenced directly by the project, not /// those only brought in transitively). + /// + /// Only package references applicable to are retained. /// /// Changes to the implementation of this class must be coordinated with PackageRuleHandler /// in the dotnet/project-system repo. @@ -23,9 +25,6 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase { public const string ResolvedMetadata = "Resolved"; - [Required] - public ITaskItem[] TargetDefinitions { get; set; } - /// /// Information about each package in the project, with metadata: /// - Name = "MetadataExtractor" @@ -49,125 +48,87 @@ public class PreprocessPackageDependenciesDesignTime : TaskBase [Required] public string DefaultImplicitPackages { get; set; } + /// + /// Eg: ".NETCoreApp,Version=v5.0". + /// Only packages targeting this framework will be returned. + /// + [Required] + public string TargetFrameworkMoniker { get; set; } + [Output] - public ITaskItem[] DependenciesDesignTime { get; private set; } + public ITaskItem[] PackageDependenciesDesignTime { get; private set; } protected override void ExecuteCore() { - var targets = GetTargets(TargetDefinitions); - var implicitPackageReferences = GetImplicitPackageReferences(DefaultImplicitPackages); - var packageByItemSpec = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (var packageDef in PackageDefinitions) - { - var dependencyType = GetDependencyType(packageDef.GetMetadata(MetadataKeys.Type)); - - if (dependencyType == DependencyType.Package && - dependencyType == DependencyType.Unresolved) - { - packageByItemSpec[packageDef.ItemSpec] = new PackageMetadata(packageDef, implicitPackageReferences); - } - } + // We have two types of data: + // + // 1) "PackageDependencies" which place a package in a given target/hierarchy + // 2) "PackageDefinitions" which provide general metadata about a package + // + // First, we scan PackageDependencies to build the set of packages in our target. - var packageByUniqueId = new Dictionary(StringComparer.OrdinalIgnoreCase); + var allowItemSpecs = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var dependency in PackageDependencies) { - var currentItemId = dependency.ItemSpec; - - if (!packageByItemSpec.TryGetValue(currentItemId, out var package)) - { - // if this package definition does not even exist - skip it - continue; - } - if (dependency.HasMetadataValue(MetadataKeys.ParentPackage)) { // ignore non-top-level packages (those with ParentPackage) continue; } - var parentTargetId = dependency.GetMetadata(MetadataKeys.ParentTarget) ?? string.Empty; - if (parentTargetId.IndexOf('/') != -1 || !targets.Contains(parentTargetId)) + var target = dependency.GetMetadata(MetadataKeys.ParentTarget); + + if (!StringComparer.OrdinalIgnoreCase.Equals(target, TargetFrameworkMoniker)) { - // skip "target/rid"s and only consume actual targets and ignore non-existent parent targets + // skip dependencies for other targets continue; } - var currentPackageUniqueId = $"{parentTargetId}/{currentItemId}"; - - // add current package to dependencies world - packageByUniqueId[currentPackageUniqueId] = package; - } - - var outputItems = new List(packageByUniqueId.Count); - - foreach (var pair in packageByUniqueId) - { - outputItems.Add(pair.Value.ToTaskItem(pair.Key)); - } - - DependenciesDesignTime = outputItems.ToArray(); - } - - private sealed class PackageMetadata - { - public PackageMetadata(ITaskItem item, HashSet implicitPackageReferences) - { - Name = item.GetMetadata(MetadataKeys.Name) ?? string.Empty; - Version = item.GetMetadata(MetadataKeys.Version) ?? string.Empty; - Resolved = !string.IsNullOrEmpty(item.GetMetadata(MetadataKeys.ResolvedPath)); - Path = (Resolved - ? item.GetMetadata(MetadataKeys.ResolvedPath) - : item.GetMetadata(MetadataKeys.Path)) ?? string.Empty; - IsImplicitlyDefined = implicitPackageReferences.Contains(Name); + allowItemSpecs.Add(dependency.ItemSpec); } - private string Name { get; } - private string Version { get; } - private string Path { get; } - private bool Resolved { get; } - private bool IsImplicitlyDefined { get; } + // Second, find PackageDefinitions that match our allowed item specs - public ITaskItem ToTaskItem(string itemSpec) - { - var outputItem = new TaskItem(itemSpec); - outputItem.SetMetadata(MetadataKeys.Name, Name); - outputItem.SetMetadata(MetadataKeys.Version, Version); - outputItem.SetMetadata(MetadataKeys.Path, Path); - outputItem.SetMetadata(MetadataKeys.Type, DependencyType.Package.ToString()); - outputItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, IsImplicitlyDefined.ToString()); - outputItem.SetMetadata(MetadataKeys.IsTopLevelDependency, bool.TrueString); - outputItem.SetMetadata(ResolvedMetadata, Resolved.ToString()); - return outputItem; - } - } + var outputItems = new List(allowItemSpecs.Count); - private static HashSet GetTargets(ITaskItem[] targetDefinitions) - { - var targets = new HashSet(StringComparer.OrdinalIgnoreCase); - - foreach (var targetDef in targetDefinitions) + foreach (var packageDef in PackageDefinitions) { - if (string.IsNullOrEmpty(targetDef.ItemSpec) || targetDef.ItemSpec.IndexOf('/') != -1) + if (!allowItemSpecs.Contains(packageDef.ItemSpec)) { - // skip "target/rid"s and only consume actual targets + // We are not interested in this definition (not top-level, or wrong target) continue; } - var dependencyType = GetDependencyType(targetDef.GetMetadata(MetadataKeys.Type)); - if (dependencyType != DependencyType.Target) + var dependencyType = GetDependencyType(packageDef.GetMetadata(MetadataKeys.Type)); + + if (dependencyType == DependencyType.Package || + dependencyType == DependencyType.Unresolved) { - // keep only targets here - continue; + var name = packageDef.GetMetadata(MetadataKeys.Name) ?? string.Empty; + var version = packageDef.GetMetadata(MetadataKeys.Version) ?? string.Empty; + var resolved = !string.IsNullOrEmpty(packageDef.GetMetadata(MetadataKeys.ResolvedPath)); + var path = (resolved + ? packageDef.GetMetadata(MetadataKeys.ResolvedPath) + : packageDef.GetMetadata(MetadataKeys.Path)) ?? string.Empty; + var isImplicitlyDefined = implicitPackageReferences.Contains(name); + + var outputItem = new TaskItem(packageDef.ItemSpec); + outputItem.SetMetadata(MetadataKeys.Name, name); + outputItem.SetMetadata(MetadataKeys.Version, version); + outputItem.SetMetadata(MetadataKeys.Path, path); + outputItem.SetMetadata(MetadataKeys.Type, DependencyType.Package.ToString()); + outputItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, isImplicitlyDefined.ToString()); + outputItem.SetMetadata(MetadataKeys.IsTopLevelDependency, bool.TrueString); + outputItem.SetMetadata(ResolvedMetadata, resolved.ToString()); + + outputItems.Add(outputItem); } - - targets.Add(targetDef.ItemSpec); } - return targets; + PackageDependenciesDesignTime = outputItems.ToArray(); } internal static HashSet GetImplicitPackageReferences(string defaultImplicitPackages) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets index 2a757e07cd6d..f5d1fd8b2145 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets @@ -299,16 +299,16 @@ Copyright (c) .NET Foundation. All rights reserved. AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" /> + DefaultImplicitPackages="$(DefaultImplicitPackages)" + TargetFrameworkMoniker="$(NuGetTargetMoniker)"> - + From aa3947ce29f3047c82dd818bdfa2e6d1becd53cb Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Fri, 3 Apr 2020 07:21:02 +1100 Subject: [PATCH 22/32] Don't set IsTopLevelDependency metadata This metadata always has 'true' as its value. We can infer this in the project system. --- .../PreprocessPackageDependenciesDesignTime.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index cb55086b2b88..384545c7f8a2 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -121,7 +121,6 @@ protected override void ExecuteCore() outputItem.SetMetadata(MetadataKeys.Path, path); outputItem.SetMetadata(MetadataKeys.Type, DependencyType.Package.ToString()); outputItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, isImplicitlyDefined.ToString()); - outputItem.SetMetadata(MetadataKeys.IsTopLevelDependency, bool.TrueString); outputItem.SetMetadata(ResolvedMetadata, resolved.ToString()); outputItems.Add(outputItem); From 455892ad67ab543a9d04027e38cd0f6d1c2e8c95 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Fri, 3 Apr 2020 07:47:43 +1100 Subject: [PATCH 23/32] Don't set Type metadata This metadata always has 'Package' as its value. We can infer this in the project system. --- .../PreprocessPackageDependenciesDesignTime.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 384545c7f8a2..285616c172ba 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -119,7 +119,6 @@ protected override void ExecuteCore() outputItem.SetMetadata(MetadataKeys.Name, name); outputItem.SetMetadata(MetadataKeys.Version, version); outputItem.SetMetadata(MetadataKeys.Path, path); - outputItem.SetMetadata(MetadataKeys.Type, DependencyType.Package.ToString()); outputItem.SetMetadata(MetadataKeys.IsImplicitlyDefined, isImplicitlyDefined.ToString()); outputItem.SetMetadata(ResolvedMetadata, resolved.ToString()); From b286e4b972e401a94a31503b0141a5125b44d035 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Fri, 3 Apr 2020 07:58:34 +1100 Subject: [PATCH 24/32] Require Name for DTB resolved package reference items --- .../PreprocessPackageDependenciesDesignTime.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 285616c172ba..282ac3488b1b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -107,7 +107,14 @@ protected override void ExecuteCore() if (dependencyType == DependencyType.Package || dependencyType == DependencyType.Unresolved) { - var name = packageDef.GetMetadata(MetadataKeys.Name) ?? string.Empty; + var name = packageDef.GetMetadata(MetadataKeys.Name); + + if (string.IsNullOrEmpty(name)) + { + // Name is required + continue; + } + var version = packageDef.GetMetadata(MetadataKeys.Version) ?? string.Empty; var resolved = !string.IsNullOrEmpty(packageDef.GetMetadata(MetadataKeys.ResolvedPath)); var path = (resolved From 24672f7e1c6786580a94ed5903b699d7844f256e Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Fri, 3 Apr 2020 07:58:55 +1100 Subject: [PATCH 25/32] Extract var for common subexpression --- .../PreprocessPackageDependenciesDesignTime.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs index 282ac3488b1b..5e9fe997a33b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PreprocessPackageDependenciesDesignTime.cs @@ -116,9 +116,10 @@ protected override void ExecuteCore() } var version = packageDef.GetMetadata(MetadataKeys.Version) ?? string.Empty; - var resolved = !string.IsNullOrEmpty(packageDef.GetMetadata(MetadataKeys.ResolvedPath)); + var resolvedPath = packageDef.GetMetadata(MetadataKeys.ResolvedPath); + var resolved = !string.IsNullOrEmpty(resolvedPath); var path = (resolved - ? packageDef.GetMetadata(MetadataKeys.ResolvedPath) + ? resolvedPath : packageDef.GetMetadata(MetadataKeys.Path)) ?? string.Empty; var isImplicitlyDefined = implicitPackageReferences.Contains(name); From a515ab913cdaa4ca126df76d7447c06e8ebec084 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Fri, 3 Apr 2020 20:53:43 +1100 Subject: [PATCH 26/32] Update unit tests for PreprocessPackageDependenciesDesignTime --- ...WantToGetDependenciesViaDesignTimeBuild.cs | 1587 ++++------------- 1 file changed, 339 insertions(+), 1248 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeWantToGetDependenciesViaDesignTimeBuild.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeWantToGetDependenciesViaDesignTimeBuild.cs index 8d94925b5ec6..a3140e0531fc 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeWantToGetDependenciesViaDesignTimeBuild.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeWantToGetDependenciesViaDesignTimeBuild.cs @@ -2,8 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; -using System.Linq; -using FluentAssertions; using Microsoft.Build.Framework; using Xunit; @@ -11,1296 +9,389 @@ namespace Microsoft.NET.Build.Tasks.UnitTests { public class GivenThatWeWantToGetDependenciesViaDesignTimeBuild { - [Fact] - public void ItShouldReturnOnlyValidTargetsWithoutRIDs() - { - // Arrange - // target definitions - var mockTargetWithType = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "target" } // lower case just in case - }); - - var mockTargetWithRidToBeSkipped = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5/win7x86", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "" }, - { MetadataKeys.TargetFrameworkMoniker, "" }, - { MetadataKeys.FrameworkName, "" }, - { MetadataKeys.FrameworkVersion, "" }, - { MetadataKeys.Type, ""} - }); - - var mockTargetWithoutType = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.6", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net46" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.6" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.6" }, - }); - - var mockTargetWithEmptyItemSpecToBeSkipped = new MockTaskItem( - itemSpec: "", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "" }, - { MetadataKeys.TargetFrameworkMoniker, "" }, - { MetadataKeys.FrameworkName, "" }, - { MetadataKeys.FrameworkVersion, "" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { - mockTargetWithType, - mockTargetWithRidToBeSkipped, - mockTargetWithoutType, - mockTargetWithEmptyItemSpecToBeSkipped - }; - task.PackageDefinitions = new ITaskItem[] { }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = string.Empty; - - // Act - var result = task.Execute(); - - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(1); - - var resultTargetsWithType = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargetsWithType.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Target, mockTargetWithType, resultTargetsWithType[0]); - } - [Fact] public void ItShouldNotReturnPackagesWithUnknownTypes() { - // Arrange - // target definitions - var mockTarget = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var mockPackageNoType = new MockTaskItem( - itemSpec: "mockPackageNoType/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageNoType" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some path" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageUnknown = new MockTaskItem( - itemSpec: "mockPackageUnknown/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageUnknown" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "qqqq" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - // package dependencies - var mockPackageDepNoType = new MockTaskItem( - itemSpec: "mockPackageNoType/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageDepUnknown = new MockTaskItem( - itemSpec: "mockPackageUnknown/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { mockTarget }; - task.PackageDefinitions = new ITaskItem[] { mockPackageNoType, mockPackageUnknown }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { mockPackageDepNoType, mockPackageDepUnknown }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = string.Empty; - - // Act - var result = task.Execute(); + var task = new PreprocessPackageDependenciesDesignTime + { + TargetFrameworkMoniker = ".Net Framework,Version=v4.5", + DefaultImplicitPackages = string.Empty, + PackageDefinitions = new ITaskItem[] + { + new MockTaskItem( + itemSpec: "mockPackageNoType/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageNoType" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some path" } + }), + new MockTaskItem( + itemSpec: "mockPackageUnknown/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageUnknown" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "qqqq" } + }) + }, + PackageDependencies = new ITaskItem[] + { + new MockTaskItem( + itemSpec: "mockPackageNoType/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageUnknown/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }) + } + }; - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(1); + Assert.True(task.Execute()); - var resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargets.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Target, mockTarget, resultTargets[0]); + Assert.Empty(task.PackageDependenciesDesignTime); } [Fact] public void ItShouldReturnUnresolvedPackageDependenciesWithTypePackage() { - // Arrange - // target definitions - var mockTarget = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var mockPackageUnresolved = new MockTaskItem( - itemSpec: "mockPackageUnresolved/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageUnresolved" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "" }, - { MetadataKeys.Type, "Unresolved" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - // package dependencies - var mockPackageDepUnresolved = new MockTaskItem( - itemSpec: "mockPackageUnresolved/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { mockTarget }; - task.PackageDefinitions = new ITaskItem[] { mockPackageUnresolved }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { mockPackageDepUnresolved }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = string.Empty; - - // Act - var result = task.Execute(); - - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(2); - - var resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargets.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Target, mockTarget, resultTargets[0]); - - var resultPackageUnresolved = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/mockPackageUnresolved/1.0.0")).ToArray(); - resultPackageUnresolved.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Package, mockPackageUnresolved, resultPackageUnresolved[0]); - } - - [Fact] - public void ItShouldIgnoreAllDependenciesWithTypeNotEqualToPackageOrUnresolved() - { - // Arrange - // target definitions - var mockTarget = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var mockPackageExternalProject = new MockTaskItem( - itemSpec: "mockPackageExternalProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageExternalProject" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some path" }, - { MetadataKeys.Type, "ExternalProject" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageProject = new MockTaskItem( - itemSpec: "mockPackageProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageProject" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Project" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageContent = new MockTaskItem( - itemSpec: "mockPackageContent/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageContent" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Content" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageAssembly = new MockTaskItem( - itemSpec: "mockPackageAssembly/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageAssembly" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Assembly" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageFrameworkAssembly = new MockTaskItem( - itemSpec: "mockPackageFrameworkAssembly/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageFrameworkAssembly" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "FrameworkAssembly" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageDiagnostic = new MockTaskItem( - itemSpec: "mockPackageDiagnostic/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageDiagnostic" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Diagnostic" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageWinmd = new MockTaskItem( - itemSpec: "mockPackageWinmd/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageWinmd" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Winmd" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackageReference = new MockTaskItem( - itemSpec: "mockPackageReference/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockPackageReference" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Reference" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - // package dependencies - var mockPackageExternalProjectDep = new MockTaskItem( - itemSpec: "mockPackageExternalProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageProjectDep = new MockTaskItem( - itemSpec: "mockPackageProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageContentDep = new MockTaskItem( - itemSpec: "mockPackageContent/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageAssemblyDep = new MockTaskItem( - itemSpec: "mockPackageAssembly/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageFrameworkAssemblyDep = new MockTaskItem( - itemSpec: "mockPackageFrameworkAssembly/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageDiagnosticDep = new MockTaskItem( - itemSpec: "mockPackageDiagnostic/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageWinmdDep = new MockTaskItem( - itemSpec: "mockPackageWinmd/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageReferenceDep = new MockTaskItem( - itemSpec: "mockPackageReference/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { mockTarget }; - task.PackageDefinitions = new ITaskItem[] { - mockPackageExternalProject, - mockPackageProject, - mockPackageContent, - mockPackageAssembly, - mockPackageFrameworkAssembly, - mockPackageWinmd, - mockPackageReference - }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { - mockPackageExternalProjectDep, - mockPackageProjectDep, - mockPackageContentDep, - mockPackageAssemblyDep, - mockPackageFrameworkAssemblyDep, - mockPackageWinmdDep, - mockPackageReferenceDep + var task = new PreprocessPackageDependenciesDesignTime + { + TargetFrameworkMoniker = ".Net Framework,Version=v4.5", + DefaultImplicitPackages = string.Empty, + PackageDefinitions = new ITaskItem[] + { + new MockTaskItem( + itemSpec: "mockPackageUnresolved/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageUnresolved" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "" }, + { MetadataKeys.Type, "Unresolved" } + }) + }, + PackageDependencies = new ITaskItem[] + { + new MockTaskItem( + itemSpec: "mockPackageUnresolved/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }) + } }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = string.Empty; - // Act - var result = task.Execute(); + Assert.True(task.Execute()); - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(1); + var item = Assert.Single(task.PackageDependenciesDesignTime); - // Target with type - var resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargets.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Target, mockTarget, resultTargets[0]); + Assert.Equal("mockPackageUnresolved/1.0.0", item.ItemSpec); + Assert.Equal("mockPackageUnresolved", item.GetMetadata(MetadataKeys.Name)); + Assert.Equal("1.0.0", item.GetMetadata(MetadataKeys.Version)); + Assert.Equal("some path", item.GetMetadata(MetadataKeys.Path)); + Assert.Equal("", item.GetMetadata(MetadataKeys.ResolvedPath)); + Assert.False(item.GetBooleanMetadata(MetadataKeys.IsImplicitlyDefined)); + Assert.False(item.GetBooleanMetadata(PreprocessPackageDependenciesDesignTime.ResolvedMetadata)); } [Fact] - public void ItReturnsCorrectHierarchyOfDependenciesThatHaveChildren() + public void ItShouldIdentifyDefaultImplicitPackages() { - // Arrange - // target definitions - var mockTarget = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var mockPackage = new MockTaskItem( - itemSpec: "Package3/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "Package3" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" }, - { PreprocessPackageDependenciesDesignTime.DependenciesMetadata, "ChildPackage1/1.0.0;ChildPackage2/2.0.0" }, - { MetadataKeys.IsTopLevelDependency, "True" } - }); - - var mockChildPackage1 = new MockTaskItem( - itemSpec: "ChildPackage1/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "ChildPackage1" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" }, - { PreprocessPackageDependenciesDesignTime.DependenciesMetadata, "ChildPackage11/1.0.0" }, - { MetadataKeys.IsTopLevelDependency, "False" } - }); - - var mockChildPackage11 = new MockTaskItem( - itemSpec: "ChildPackage11/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "ChildPackage11" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" }, - { MetadataKeys.IsTopLevelDependency, "False" } - }); - - var mockChildPackage2 = new MockTaskItem( - itemSpec: "ChildPackage2/2.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "ChildPackage2" }, - { MetadataKeys.Version, "2.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" }, - { MetadataKeys.IsTopLevelDependency, "False" } - }); - - // package dependencies - var mockPackageDep = new MockTaskItem( - itemSpec: "Package3/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockChildPackageDep1 = new MockTaskItem( - itemSpec: "ChildPackage1/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "Package3/1.0.0" } - }); - - var mockChildPackageDep11 = new MockTaskItem( - itemSpec: "ChildPackage11/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "ChildPackage1/1.0.0" } - }); - - var mockChildPackageDep2 = new MockTaskItem( - itemSpec: "ChildPackage2/2.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "Package3/1.0.0" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { mockTarget }; - task.PackageDefinitions = new ITaskItem[] { - mockPackage, - mockChildPackage1, - mockChildPackage11, - mockChildPackage2 - }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { - mockPackageDep, - mockChildPackageDep1, - mockChildPackageDep11, - mockChildPackageDep2 + var task = new PreprocessPackageDependenciesDesignTime + { + TargetFrameworkMoniker = ".Net Framework,Version=v4.5", + DefaultImplicitPackages = "DefaultImplicit", + PackageDefinitions = new ITaskItem[] + { + new MockTaskItem( + itemSpec: "DefaultImplicit/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "DefaultImplicit" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "" }, + { MetadataKeys.Type, "Package" } + }) + }, + PackageDependencies = new ITaskItem[] + { + new MockTaskItem( + itemSpec: "DefaultImplicit/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }) + } }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = string.Empty; - - // Act - var result = task.Execute(); - - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(5); - - var resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargets.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Target, mockTarget, resultTargets[0]); - mockPackage.SetMetadata(MetadataKeys.Path, mockPackage.GetMetadata(MetadataKeys.ResolvedPath)); - var resultPackage = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/Package3/1.0.0")).ToArray(); - resultPackage.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Package, mockPackage, resultPackage[0]); + Assert.True(task.Execute()); - mockChildPackage1.SetMetadata(MetadataKeys.Path, mockChildPackage1.GetMetadata(MetadataKeys.ResolvedPath)); - var resultChildPackage1 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/ChildPackage1/1.0.0")).ToArray(); - resultChildPackage1.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Package, mockChildPackage1, resultChildPackage1[0]); + var item = Assert.Single(task.PackageDependenciesDesignTime); - mockChildPackage11.SetMetadata(MetadataKeys.Path, mockChildPackage11.GetMetadata(MetadataKeys.ResolvedPath)); - var resultChildPackage11 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/ChildPackage11/1.0.0")).ToArray(); - resultChildPackage11.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Package, mockChildPackage11, resultChildPackage11[0]); - - mockChildPackage2.SetMetadata(MetadataKeys.Path, mockChildPackage2.GetMetadata(MetadataKeys.ResolvedPath)); - var resultChildPackage2 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/ChildPackage2/2.0.0")).ToArray(); - resultChildPackage2.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Package, mockChildPackage2, resultChildPackage2[0]); + Assert.Equal("DefaultImplicit/1.0.0", item.ItemSpec); + Assert.True(item.GetBooleanMetadata(MetadataKeys.IsImplicitlyDefined)); } [Fact] - public void ItShouldIgnoreFileDependenciesThatAre_NotAssemblies_And_DontBelongToCompileTimeAssemblyGroup() + public void ItShouldIgnoreAllDependenciesWithTypeNotEqualToPackageOrUnresolved() { - // Arrange - // target definitions - var mockTarget = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var mockExternalProject = new MockTaskItem( - itemSpec: "mockExternalProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockExternalProject" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some path" }, - { MetadataKeys.Type, "ExternalProject" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockProject = new MockTaskItem( - itemSpec: "mockProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockProject" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Project" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockContent = new MockTaskItem( - itemSpec: "mockContent/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockContent" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Content" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockPackage = new MockTaskItem( - itemSpec: "mockPackage/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockAssembly" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Assembly" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockDiagnostic = new MockTaskItem( - itemSpec: "mockDiagnostic/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockDiagnostic" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Diagnostic" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockWinmd = new MockTaskItem( - itemSpec: "mockWinmd/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockWinmd" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Winmd" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - var mockReference = new MockTaskItem( - itemSpec: "mockReference/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockReference" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Reference" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "False" } - }); - - // package dependencies - var mockExternalProjectDep = new MockTaskItem( - itemSpec: "mockExternalProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockProjectDep = new MockTaskItem( - itemSpec: "mockProject/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockContentDep = new MockTaskItem( - itemSpec: "mockContent/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageDep = new MockTaskItem( - itemSpec: "mockPackage/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockDiagnosticDep = new MockTaskItem( - itemSpec: "mockDiagnostic/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockWinmdDep = new MockTaskItem( - itemSpec: "mockWinmd/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockReferenceDep = new MockTaskItem( - itemSpec: "mockReference/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { mockTarget }; - task.PackageDefinitions = new ITaskItem[] { }; - task.FileDefinitions = new ITaskItem[] { - mockExternalProject, - mockProject, - mockContent, - mockPackage, - mockWinmd, - mockReference - }; - task.PackageDependencies = new ITaskItem[] { }; - task.FileDependencies = new ITaskItem[] { - mockExternalProjectDep, - mockProjectDep, - mockContentDep, - mockPackageDep, - mockWinmdDep, - mockReferenceDep + var task = new PreprocessPackageDependenciesDesignTime + { + TargetFrameworkMoniker = ".Net Framework,Version=v4.5", + DefaultImplicitPackages = string.Empty, + PackageDefinitions = new ITaskItem[] { + new MockTaskItem( + itemSpec: "mockPackageExternalProject/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageExternalProject" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some path" }, + { MetadataKeys.Type, "ExternalProject" } + }), + new MockTaskItem( + itemSpec: "mockPackageProject/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageProject" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "Project" } + }), + new MockTaskItem( + itemSpec: "mockPackageContent/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageContent" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "Content" } + }), + new MockTaskItem( + itemSpec: "mockPackageAssembly/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageAssembly" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "Assembly" } + }), + new MockTaskItem( + itemSpec: "mockPackageFrameworkAssembly/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageFrameworkAssembly" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "FrameworkAssembly" } + }), + new MockTaskItem( + itemSpec: "mockPackageDiagnostic/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageDiagnostic" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "Diagnostic" } + }), + new MockTaskItem( + itemSpec: "mockPackageWinmd/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageWinmd" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "Winmd" } + }), + new MockTaskItem( + itemSpec: "mockPackageReference/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "mockPackageReference" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "Reference" } + }) + }, + PackageDependencies = new ITaskItem[] { + new MockTaskItem( + itemSpec: "mockPackageExternalProject/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageProject/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageContent/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageAssembly/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageFrameworkAssembly/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageDiagnostic/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageWinmd/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "mockPackageReference/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }) + } }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = string.Empty; - // Act - var result = task.Execute(); + Assert.True(task.Execute()); - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(1); - - // Target with type - var resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargets.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Target, mockTarget, resultTargets[0]); + Assert.Empty(task.PackageDependenciesDesignTime); } [Fact] - public void ItShouldReturnCorrectHierarchyWhenPackageHasChildAssemblyOrAnalyzerDependencies() + public void ItShouldOnlyReturnPackagesInTheSpecifiedTarget() { - // Arrange - // target definitions - var mockTarget = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var mockPackage = new MockTaskItem( - itemSpec: "Package3/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "Package3" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" }, - { PreprocessPackageDependenciesDesignTime.DependenciesMetadata, - @"mockChildAssembly1;somepath/mockChildAssembly2;somepath/mockChildAnalyzerAssembly" }, - { MetadataKeys.IsImplicitlyDefined, "True" } - }); - - var mockPackage4 = new MockTaskItem( - itemSpec: "Package4/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "Package4" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" }, - { MetadataKeys.IsImplicitlyDefined, "True" } - }); - - var mockChildAssembly1 = new MockTaskItem( - itemSpec: @"mockChildAssembly1", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockChildAssembly1" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Assembly" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" } - }); - - var mockChildAssembly2 = new MockTaskItem( - itemSpec: @"somepath/mockChildAssembly2", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockChildAssembly2" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "FrameworkAssembly" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" } - }); - - var mockChildAssemblyNoCompileMetadata = new MockTaskItem( - itemSpec: @"somepath/mockChildAssemblyNoCompileMetadata", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockChildAssemblyNoCompileMetadata" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Assembly" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" } - }); - - var mockChildAnalyzerAssembly = new MockTaskItem( - itemSpec: @"somepath/mockChildAnalyzerAssembly", - metadata: new Dictionary - { - { MetadataKeys.Name, "mockChildAnalyzerAssembly" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "AnalyzerAssembly" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" } - }); - - // package dependencies - var mockPackageDep = new MockTaskItem( - itemSpec: "Package3/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockPackageDep4 = new MockTaskItem( - itemSpec: "Package4/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockChildAssemblyDep1 = new MockTaskItem( - itemSpec: "mockChildAssembly1", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "Package3/1.0.0" }, - { MetadataKeys.FileGroup, PreprocessPackageDependenciesDesignTime.CompileTimeAssemblyMetadata } - }); - - var mockChildAssemblyDep2 = new MockTaskItem( - itemSpec: @"somepath/mockChildAssembly2", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "Package3/1.0.0" }, - { MetadataKeys.FileGroup, PreprocessPackageDependenciesDesignTime.CompileTimeAssemblyMetadata } - }); - - var mockChildAssemblyNoCompileMetadataDep = new MockTaskItem( - itemSpec: "somepath/mockChildAssemblyNoCompileMetadata", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "Package3/1.0.0" } - }); - - var mockChildAnalyzerAssemblyDep = new MockTaskItem( - itemSpec: "somepath/mockChildAnalyzerAssembly", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "Package3/1.0.0" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { mockTarget }; - task.PackageDefinitions = new ITaskItem[] { - mockPackage, - mockPackage4 - }; - task.FileDefinitions = new ITaskItem[] { - mockChildAssembly1, - mockChildAssembly2, - mockChildAssemblyNoCompileMetadata, - mockChildAnalyzerAssembly - }; - task.PackageDependencies = new ITaskItem[] { - mockPackageDep, - mockPackageDep4 - }; - task.FileDependencies = new ITaskItem[] { - mockChildAssemblyDep1, - mockChildAssemblyDep2, - mockChildAssemblyNoCompileMetadataDep, - mockChildAnalyzerAssemblyDep + var task = new PreprocessPackageDependenciesDesignTime + { + TargetFrameworkMoniker = ".Net Framework,Version=v4.5", + DefaultImplicitPackages = string.Empty, + PackageDefinitions = new ITaskItem[] { + new MockTaskItem( + itemSpec: "Package1/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "Package1" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "" }, + { MetadataKeys.Type, "Package" } + }), + new MockTaskItem( + itemSpec: "Package2/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "Package2" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "" }, + { MetadataKeys.Type, "Package" } + }) + }, + PackageDependencies = new ITaskItem[] { + new MockTaskItem( + itemSpec: "Package1/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "Package2/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.6" } + }) + } }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = "Package3;Package4"; - task.TargetFrameworkMoniker = string.Empty; - - // Act - var result = task.Execute(); - - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(6); - - var resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargets.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Target, mockTarget, resultTargets[0]); - - mockPackage.SetMetadata(MetadataKeys.Path, mockPackage.GetMetadata(MetadataKeys.ResolvedPath)); - var resultPackage = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/Package3/1.0.0")).ToArray(); - resultPackage.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Package, mockPackage, resultPackage[0]); - - mockPackage4.SetMetadata(MetadataKeys.Path, mockPackage4.GetMetadata(MetadataKeys.ResolvedPath)); - var resultPackage4 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/Package4/1.0.0")).ToArray(); - resultPackage4.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Package, mockPackage4, resultPackage4[0]); - - mockChildAssembly1.SetMetadata(MetadataKeys.Path, mockChildAssembly1.GetMetadata(MetadataKeys.ResolvedPath)); - var resultChildAssembly1 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/mockChildAssembly1")).ToArray(); - resultChildAssembly1.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.Assembly, mockChildAssembly1, resultChildAssembly1[0]); - - mockChildAssembly2.SetMetadata(MetadataKeys.Path, mockChildAssembly2.GetMetadata(MetadataKeys.ResolvedPath)); - var resultChildAssembly2 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/somepath/mockChildAssembly2")).ToArray(); - resultChildAssembly2.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.FrameworkAssembly, mockChildAssembly2, resultChildAssembly2[0]); - - mockChildAnalyzerAssembly.SetMetadata(MetadataKeys.Path, mockChildAnalyzerAssembly.GetMetadata(MetadataKeys.ResolvedPath)); - var resultChildAnalyzerAssembly = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/somepath/mockChildAnalyzerAssembly")).ToArray(); - resultChildAnalyzerAssembly.Length.Should().Be(1); - VerifyTargetTaskItem(DependencyType.AnalyzerAssembly, mockChildAnalyzerAssembly, resultChildAnalyzerAssembly[0]); - } - - [Fact] - public void ItShouldReturnCorrectPackagesForCorrespondingTarget() - { - // Arrange - // target definitions - var mockTarget = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.5", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net45" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.5" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.5" }, - { MetadataKeys.Type, "Target" } - }); - - var mockTarget2 = new MockTaskItem( - itemSpec: ".Net Framework,Version=v4.6", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "net46" }, - { MetadataKeys.TargetFrameworkMoniker, ".Net Framework,Version=v4.6" }, - { MetadataKeys.FrameworkName, ".Net Framework" }, - { MetadataKeys.FrameworkVersion, "4.6" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var mockPackage1 = new MockTaskItem( - itemSpec: "Package1/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "Package1" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" } - }); - - var mockChildPackage1 = new MockTaskItem( - itemSpec: "ChildPackage1/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "ChildPackage1" }, - { MetadataKeys.Version, "1.0.0" }, - { MetadataKeys.Path, "some path" }, - { MetadataKeys.ResolvedPath, "some resolved path" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" }, - { MetadataKeys.IsTopLevelDependency, "False" } - }); - - // package dependencies - var mockPackageDep1 = new MockTaskItem( - itemSpec: "Package1/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } - }); - - var mockChildPackageDep1 = new MockTaskItem( - itemSpec: "ChildPackage1/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, - { MetadataKeys.ParentPackage, "Package1/1.0.0" } - }); - - var mockPackageDep2 = new MockTaskItem( - itemSpec: "Package1/1.0.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.6" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { mockTarget, mockTarget2 }; - task.PackageDefinitions = new ITaskItem[] { mockPackage1, mockChildPackage1 }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { mockPackageDep1, mockPackageDep2, mockChildPackageDep1 }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = string.Empty; + Assert.True(task.Execute()); - // Act - var result = task.Execute(); + var item = Assert.Single(task.PackageDependenciesDesignTime); - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(5); - - var resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5")).ToArray(); - resultTargets.Length.Should().Be(1); - - resultTargets = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.6")).ToArray(); - resultTargets.Length.Should().Be(1); - - var resultPackage1 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.5/Package1/1.0.0")).ToArray(); - resultPackage1.Length.Should().Be(1); - resultPackage1[0].GetMetadata(PreprocessPackageDependenciesDesignTime.DependenciesMetadata) - .Should().Be("ChildPackage1/1.0.0"); - - resultPackage1 = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".Net Framework,Version=v4.6/Package1/1.0.0")).ToArray(); - resultPackage1.Length.Should().Be(1); - resultPackage1[0].GetMetadata(PreprocessPackageDependenciesDesignTime.DependenciesMetadata) - .Should().Be(""); + Assert.Equal("Package1/1.0.0", item.ItemSpec); } [Fact] - public void ItShouldCreateDependenciesForReferencesWithNuGetMetadata() + public void ItShouldOnlyReturnTopLevelPackages() { - // Arrange - // target definitions - var netStandard20Target = new MockTaskItem( - itemSpec: ".NETStandard,Version=v2.0", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "netstandard2.0" }, - { MetadataKeys.TargetFrameworkMoniker, ".NETStandard,Version=v2.0" }, - { MetadataKeys.FrameworkName, ".NETStandard" }, - { MetadataKeys.FrameworkVersion, "2.0" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var myPackage = new MockTaskItem( - itemSpec: "MyPackage/1.5.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "MyPackage" }, - { MetadataKeys.Version, "1.5.0" }, - { MetadataKeys.Path, "Packages\\MyPackage\\1.5.0" }, - { MetadataKeys.ResolvedPath, "" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" } - }); - - // package dependencies - var myPackageDependency = new MockTaskItem( - itemSpec: "MyPackage/1.5.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".NETStandard,Version=v2.0" } - }); - - // references - var referenceWithMetadata = new MockTaskItem( - itemSpec: "Packages\\MyPackage\\1.5.0\\AnAssembly.dll", - metadata: new Dictionary - { - { "NuGetPackageId", "MyPackage" }, - { "NuGetPackageVersion", "1.5.0" } - }); - - var referenceWithoutMetadata = new MockTaskItem( - itemSpec: "Packages\\MyPackage\\1.5.0\\AnotherAssembly.dll", - metadata: new Dictionary()); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { netStandard20Target }; - task.PackageDefinitions = new ITaskItem[] { myPackage }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { myPackageDependency }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { referenceWithMetadata, referenceWithoutMetadata }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = ".NETStandard,Version=v2.0"; - - // Act - var result = task.Execute(); - - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(3); - - var resultPackage = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".NETStandard,Version=v2.0/MyPackage/1.5.0")).ToArray(); - resultPackage.Length.Should().Be(1); - resultPackage[0].GetMetadata(PreprocessPackageDependenciesDesignTime.DependenciesMetadata) - .Should().Be("MyPackage/1.5.0/AnAssembly.dll"); - } - - [Fact] - public void ItShouldMakeFacadeReferencesInvisible() - { - // Arrange - // target definitions - var netStandard20Target = new MockTaskItem( - itemSpec: ".NETStandard,Version=v2.0", - metadata: new Dictionary - { - { MetadataKeys.RuntimeIdentifier, "netstandard2.0" }, - { MetadataKeys.TargetFrameworkMoniker, ".NETStandard,Version=v2.0" }, - { MetadataKeys.FrameworkName, ".NETStandard" }, - { MetadataKeys.FrameworkVersion, "2.0" }, - { MetadataKeys.Type, "Target" } - }); - - // package definitions - var myPackage = new MockTaskItem( - itemSpec: "MyPackage/1.5.0", - metadata: new Dictionary - { - { MetadataKeys.Name, "MyPackage" }, - { MetadataKeys.Version, "1.5.0" }, - { MetadataKeys.Path, "Packages\\MyPackage\\1.5.0" }, - { MetadataKeys.ResolvedPath, "" }, - { MetadataKeys.Type, "Package" }, - { PreprocessPackageDependenciesDesignTime.ResolvedMetadata, "True" } - }); - - // package dependencies - var myPackageDependency = new MockTaskItem( - itemSpec: "MyPackage/1.5.0", - metadata: new Dictionary - { - { MetadataKeys.ParentTarget, ".NETStandard,Version=v2.0" } - }); - - // references - var alphaReference = new MockTaskItem( - itemSpec: "Packages\\MyPackage\\1.5.0\\AlphaAssembly.dll", - metadata: new Dictionary - { - { "NuGetPackageId", "MyPackage" }, - { "NuGetPackageVersion", "1.5.0" } - }); - - var betaReference = new MockTaskItem( - itemSpec: "Packages\\MyPackage\\1.5.0\\BetaAssembly.dll", - metadata: new Dictionary - { - { "NuGetPackageId", "MyPackage" }, - { "NuGetPackageVersion", "1.5.0" }, - { "Facade", "false" } - }); - - var gammaReference = new MockTaskItem( - itemSpec: "Packages\\MyPackage\\1.5.0\\GammaAssembly.dll", - metadata: new Dictionary - { - { "NuGetPackageId", "MyPackage" }, - { "NuGetPackageVersion", "1.5.0" }, - { "Facade", "true" } - }); - - var task = new PreprocessPackageDependenciesDesignTime(); - task.TargetDefinitions = new[] { netStandard20Target }; - task.PackageDefinitions = new ITaskItem[] { myPackage }; - task.FileDefinitions = new ITaskItem[] { }; - task.PackageDependencies = new ITaskItem[] { myPackageDependency }; - task.FileDependencies = new ITaskItem[] { }; - task.References = new ITaskItem[] { alphaReference, betaReference, gammaReference }; - task.DefaultImplicitPackages = string.Empty; - task.TargetFrameworkMoniker = ".NETStandard,Version=v2.0"; - - // Act - var result = task.Execute(); - - // Assert - result.Should().BeTrue(); - task.DependenciesDesignTime.Count().Should().Be(5); - - var alphaDependency = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".NETStandard,Version=v2.0/MyPackage/1.5.0/AlphaAssembly.dll")) - .Single(); - alphaDependency.GetBooleanMetadata(PreprocessPackageDependenciesDesignTime.VisibleMetadata) - .Should().BeTrue(); - - var betaDependency = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".NETStandard,Version=v2.0/MyPackage/1.5.0/BetaAssembly.dll")) - .Single(); - betaDependency.GetBooleanMetadata(PreprocessPackageDependenciesDesignTime.VisibleMetadata) - .Should().BeTrue(); - - var gammaDependency = task.DependenciesDesignTime - .Where(x => x.ItemSpec.Equals(".NETStandard,Version=v2.0/MyPackage/1.5.0/GammaAssembly.dll")) - .Single(); - gammaDependency.GetBooleanMetadata(PreprocessPackageDependenciesDesignTime.VisibleMetadata) - .Should().BeFalse(); - } - - private void VerifyTargetTaskItem(DependencyType type, ITaskItem input, ITaskItem output) - { - type.ToString().Should().Be(output.GetMetadata(MetadataKeys.Type)); + var task = new PreprocessPackageDependenciesDesignTime + { + TargetFrameworkMoniker = ".Net Framework,Version=v4.5", + DefaultImplicitPackages = string.Empty, + PackageDefinitions = new ITaskItem[] { + new MockTaskItem( + itemSpec: "Package1/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "Package1" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "" }, + { MetadataKeys.Type, "Package" } + }), + new MockTaskItem( + itemSpec: "ChildPackage1/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.Name, "ChildPackage1" }, + { MetadataKeys.Version, "1.0.0" }, + { MetadataKeys.Path, "some path" }, + { MetadataKeys.ResolvedPath, "some resolved path" }, + { MetadataKeys.Type, "Package" } + }) + }, + PackageDependencies = new ITaskItem[] { + new MockTaskItem( + itemSpec: "Package1/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" } + }), + new MockTaskItem( + itemSpec: "ChildPackage1/1.0.0", + metadata: new Dictionary + { + { MetadataKeys.ParentTarget, ".Net Framework,Version=v4.5" }, + { MetadataKeys.ParentPackage, "Package1/1.0.0" } + }) + } + }; - // remove unnecessary metadata to keep only ones that would be in result task items - var removeMetadata = new[] { MetadataKeys.Type, MetadataKeys.ResolvedPath }; + Assert.True(task.Execute()); - foreach (var rm in removeMetadata) - { - output.RemoveMetadata(rm); - input.RemoveMetadata(rm); - } + var item = Assert.Single(task.PackageDependenciesDesignTime); - foreach (var metadata in input.MetadataNames) - { - input.GetMetadata(metadata.ToString()).Should().Be(output.GetMetadata(metadata.ToString())); - } + Assert.Equal("Package1/1.0.0", item.ItemSpec); } } } From f86860682c3a185e51f0697a518bf29841108fa5 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Mon, 11 May 2020 12:14:45 +1000 Subject: [PATCH 27/32] Remove ReportAssetsLogMessages task Since VS 16.7, design-time builds no longer consume assets file diagnostics as items. This commit removes their generation and supporting code. --- src/Tasks/Common/DiagnosticMessageSeverity.cs | 15 -- src/Tasks/Common/DiagnosticsHelper.cs | 58 ----- .../GivenThatWeReportAssetsLogMessages.cs | 207 ------------------ .../LoadAssetsFile.cs | 22 -- .../ReportAssetsLogMessages.cs | 118 ---------- ...rosoft.PackageDependencyResolution.targets | 38 +--- 6 files changed, 1 insertion(+), 457 deletions(-) delete mode 100644 src/Tasks/Common/DiagnosticMessageSeverity.cs delete mode 100644 src/Tasks/Common/DiagnosticsHelper.cs delete mode 100644 src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeReportAssetsLogMessages.cs delete mode 100644 src/Tasks/Microsoft.NET.Build.Tasks/LoadAssetsFile.cs delete mode 100644 src/Tasks/Microsoft.NET.Build.Tasks/ReportAssetsLogMessages.cs diff --git a/src/Tasks/Common/DiagnosticMessageSeverity.cs b/src/Tasks/Common/DiagnosticMessageSeverity.cs deleted file mode 100644 index b127b4c9d591..000000000000 --- a/src/Tasks/Common/DiagnosticMessageSeverity.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.NET.Build.Tasks -{ - /// - /// Specifies the severity of Diagnostic Messages - /// - internal enum DiagnosticMessageSeverity - { - Info, - Warning, - Error, - } -} diff --git a/src/Tasks/Common/DiagnosticsHelper.cs b/src/Tasks/Common/DiagnosticsHelper.cs deleted file mode 100644 index 58518655beeb..000000000000 --- a/src/Tasks/Common/DiagnosticsHelper.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using System.Collections.Generic; - -namespace Microsoft.NET.Build.Tasks -{ - /// - /// Writes diagnostic messages to the task log and creates diagnostic task items - /// that can be returned from a task - /// - internal sealed class DiagnosticsHelper - { - private readonly List _diagnosticMessages = new List(); - - public ITaskItem[] GetDiagnosticMessages() => _diagnosticMessages.ToArray(); - - public ITaskItem Add( - string diagnosticCode, - string message, - string filePath, - DiagnosticMessageSeverity severity, - int startLine, - int startColumn, - int endLine, - int endColumn, - string targetFrameworkMoniker, - string packageId) - { - string itemspec = - (string.IsNullOrEmpty(targetFrameworkMoniker) ? string.Empty : $"{targetFrameworkMoniker}/") + - (string.IsNullOrEmpty(packageId) ? string.Empty : $"{packageId}/") + - diagnosticCode; - - var diagnostic = new TaskItem(itemspec, new Dictionary - { - { MetadataKeys.DiagnosticCode, diagnosticCode }, - { MetadataKeys.Message, message }, - { MetadataKeys.FilePath, filePath ?? string.Empty }, - { MetadataKeys.Severity, severity.ToString() }, - - { MetadataKeys.StartLine, startLine.ToString() }, - { MetadataKeys.StartColumn, startColumn.ToString() }, - { MetadataKeys.EndLine, endLine.ToString() }, - { MetadataKeys.EndColumn, endColumn.ToString() }, - - { MetadataKeys.ParentTarget, targetFrameworkMoniker ?? string.Empty }, - { MetadataKeys.ParentPackage, packageId ?? string.Empty }, - }); - - _diagnosticMessages.Add(diagnostic); - - return diagnostic; - } - } -} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeReportAssetsLogMessages.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeReportAssetsLogMessages.cs deleted file mode 100644 index 377703da8b24..000000000000 --- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenThatWeReportAssetsLogMessages.cs +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using FluentAssertions; -using NuGet.Common; -using NuGet.ProjectModel; -using System; -using System.Linq; -using Xunit; -using static Microsoft.NET.Build.Tasks.UnitTests.LockFileSnippets; - -namespace Microsoft.NET.Build.Tasks.UnitTests -{ - public class GivenThatWeReportAssetsLogMessages - { - [Fact] - public void ItReportsDiagnosticsWithMinimumData() - { - string lockFileContent = CreateDefaultLockFileSnippet( - logs: new string[] { - CreateLog(NuGetLogCode.NU1000, LogLevel.Warning, "Sample warning") - } - ); - - var task = GetExecutedTaskFromContents(lockFileContent); - - task.DiagnosticMessages.Should().HaveCount(1); - } - - [Theory] - [InlineData(null)] - [InlineData(new object[] { new string[0] })] - public void ItReportsZeroDiagnosticsWithNoLogs(string [] logsJson) - { - string lockFileContent = CreateDefaultLockFileSnippet(logsJson); - - var task = GetExecutedTaskFromContents(lockFileContent); - - task.DiagnosticMessages.Should().BeEmpty(); - } - - [Fact] - public void ItReportsDiagnosticsMetadataWithLogs() - { - string lockFileContent = CreateDefaultLockFileSnippet( - logs: new string[] { - CreateLog(NuGetLogCode.NU1000, LogLevel.Error, "Sample error", - filePath: "path/to/project.csproj", - libraryId: "LibA", - targetGraphs: new string[]{ ".NETCoreApp,Version=v1.0" }), - CreateLog(NuGetLogCode.NU1001, LogLevel.Warning, "Sample warning", - libraryId: "LibB", - targetGraphs: new string[]{ ".NETCoreApp,Version=v1.0" }) - } - ); - - var task = GetExecutedTaskFromContents(lockFileContent); - - task.DiagnosticMessages.Should().HaveCount(2); - - Action checkMetadata = (key, val1, val2) => { - task.DiagnosticMessages - .Select(item => item.GetMetadata(key)) - .Should().Contain(new string[] { val1, val2 }); - }; - - checkMetadata(MetadataKeys.DiagnosticCode, "NU1000", "NU1001"); - checkMetadata(MetadataKeys.Severity, "Error", "Warning"); - checkMetadata(MetadataKeys.Message, "Sample error", "Sample warning"); - checkMetadata(MetadataKeys.FilePath, "", "path/to/project.csproj"); - checkMetadata(MetadataKeys.ParentTarget, ".NETCoreApp,Version=v1.0", ".NETCoreApp,Version=v1.0"); - checkMetadata(MetadataKeys.ParentPackage, "LibA/1.2.3", "LibB/1.2.3"); - } - - [Theory] - [InlineData(null, null, ".NETCoreApp,Version=v1.0", "")] - [InlineData(new string[] { ".NETCoreApp,Version=v1.0" }, null, ".NETCoreApp,Version=v1.0", "")] - [InlineData(null, "LibA", ".NETCoreApp,Version=v1.0", "LibA/1.2.3")] - [InlineData(new string[] { ".NETCoreApp,Version=v1.0" }, "LibA", ".NETCoreApp,Version=v1.0", "LibA/1.2.3")] - public void ItReportsDiagnosticsWithAllTargetLibraryCases(string[] targetGraphs, string libraryId, string expectedTarget, string expectedPackage) - { - string lockFileContent = CreateDefaultLockFileSnippet( - logs: new string[] { - CreateLog(NuGetLogCode.NU1000, LogLevel.Warning, "Sample warning", - filePath: "path/to/project.csproj", - libraryId: libraryId, - targetGraphs: targetGraphs) - } - ); - - var task = GetExecutedTaskFromContents(lockFileContent); - - task.DiagnosticMessages.Should().HaveCount(1); - var item = task.DiagnosticMessages.First(); - - item.GetMetadata(MetadataKeys.ParentTarget).Should().Be(expectedTarget); - item.GetMetadata(MetadataKeys.ParentPackage).Should().Be(expectedPackage); - } - - [Fact] - public void ItHandlesInfoLogLevels() - { - string lockFileContent = CreateDefaultLockFileSnippet( - logs: new string[] { - CreateLog(NuGetLogCode.NU1000, LogLevel.Information, "Sample message"), - CreateLog(NuGetLogCode.NU1000, LogLevel.Minimal, "Sample message"), - CreateLog(NuGetLogCode.NU1000, LogLevel.Verbose, "Sample message"), - CreateLog(NuGetLogCode.NU1000, LogLevel.Debug, "Sample message"), - } - ); - - var task = GetExecutedTaskFromContents(lockFileContent); - - task.DiagnosticMessages.Should().HaveCount(4); - - task.DiagnosticMessages - .Select(item => item.GetMetadata(MetadataKeys.Severity)) - .Should().OnlyContain(s => s == "Info"); - } - - [Theory] - [InlineData(new string[] { ".NETCoreApp,Version=v1.0", ".NETFramework,Version=v4.6.1" }, "LibA")] - [InlineData(new string[] { ".NETCoreApp,Version=v1.0" }, "LibA")] - public void ItHandlesMultiTFMScenarios(string[] targetGraphs, string libraryId) - { - string lockFileContent = CreateLockFileSnippet( - targets: new string[] { - CreateTarget(".NETCoreApp,Version=v1.0", TargetLibA, TargetLibB, TargetLibC), - CreateTarget(".NETFramework,Version=v4.6.1", TargetLibA, TargetLibB, TargetLibC), - }, - libraries: new string[] { LibADefn, LibBDefn, LibCDefn }, - projectFileDependencyGroups: new string[] { - ProjectGroup, NETCoreGroup, NET461Group - }, - logs: new string[] { - CreateLog(NuGetLogCode.NU1000, LogLevel.Warning, "Sample warning", - filePath: "path/to/project.csproj", - libraryId: libraryId, - targetGraphs: targetGraphs) - } - ); - - var task = GetExecutedTaskFromContents(lockFileContent); - - // a diagnostic for each target graph... - task.DiagnosticMessages.Should().HaveCount(targetGraphs.Length); - - task.DiagnosticMessages - .Select(item => item.GetMetadata(MetadataKeys.ParentTarget)) - .Should().Contain(targetGraphs); - - task.DiagnosticMessages - .Select(item => item.GetMetadata(MetadataKeys.ParentPackage)) - .Should().OnlyContain(v => v.StartsWith(libraryId)); - } - - [Fact] - public void ItSkipsInvalidEntries() - { - string lockFileContent = CreateDefaultLockFileSnippet( - logs: new string[] { - CreateLog(NuGetLogCode.NU1000, LogLevel.Error, "Sample error that will be invalid"), - CreateLog(NuGetLogCode.NU1001, LogLevel.Warning, "Sample warning"), - } - ); - lockFileContent = lockFileContent.Replace("NU1000", "CA1000"); - - var task = GetExecutedTaskFromContents(lockFileContent); - - task.DiagnosticMessages.Should().HaveCount(1); - - task.DiagnosticMessages - .Select(item => item.GetMetadata(MetadataKeys.DiagnosticCode)) - .Should().OnlyContain(v => v == "NU1001"); - } - - private static string CreateDefaultLockFileSnippet(string[] logs = null) => - CreateLockFileSnippet( - targets: new string[] { - CreateTarget(".NETCoreApp,Version=v1.0", TargetLibA, TargetLibB, TargetLibC), - }, - libraries: new string[] { LibADefn, LibBDefn, LibCDefn }, - projectFileDependencyGroups: new string[] { - ProjectGroup, NETCoreGroup - }, - logs: logs - ); - - private ReportAssetsLogMessages GetExecutedTaskFromContents(string lockFileContents) - { - var lockFile = TestLockFiles.CreateLockFile(lockFileContents); - return GetExecutedTask(lockFile); - } - - private ReportAssetsLogMessages GetExecutedTask(LockFile lockFile) - { - var task = new ReportAssetsLogMessages(lockFile) - { - ProjectAssetsFile = lockFile.Path, - }; - - task.Execute().Should().BeTrue(); - - return task; - } - } -} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/LoadAssetsFile.cs b/src/Tasks/Microsoft.NET.Build.Tasks/LoadAssetsFile.cs deleted file mode 100644 index d0c22c83f777..000000000000 --- a/src/Tasks/Microsoft.NET.Build.Tasks/LoadAssetsFile.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Microsoft.NET.Build.Tasks -{ - public sealed class LoadAssetsFile : TaskBase - { - /// - /// The assets file to process - /// - public string ProjectAssetsFile - { - get; set; - } - - protected override void ExecuteCore() - { - var lockFile = new LockFileCache(this).GetLockFile(ProjectAssetsFile); - } - } -} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ReportAssetsLogMessages.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ReportAssetsLogMessages.cs deleted file mode 100644 index 180ad7634eb7..000000000000 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ReportAssetsLogMessages.cs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using Microsoft.Build.Framework; -using NuGet.Common; -using NuGet.ProjectModel; -using System.Linq; - -namespace Microsoft.NET.Build.Tasks -{ - /// - /// Raise log messages in the assets file as DiagnosticMessage items - /// that can be consumed downstream (e.g. by the dependency node in - /// the solution explorer) - /// - public sealed class ReportAssetsLogMessages : TaskBase - { - private LockFile _lockFile; - private DiagnosticsHelper _diagnostics; - - #region Outputs - - [Output] - public ITaskItem[] DiagnosticMessages => _diagnostics.GetDiagnosticMessages(); - - #endregion - - #region Inputs - - /// - /// The assets file to process - /// - public string ProjectAssetsFile - { - get; set; - } - - #endregion - - public ReportAssetsLogMessages() - { - _diagnostics = new DiagnosticsHelper(); - } - - #region Test Support - - internal ReportAssetsLogMessages(LockFile lockFile) : this() - { - _lockFile = lockFile; - } - - #endregion - - private LockFile LockFile - { - get - { - if (_lockFile == null) - { - _lockFile = new LockFileCache(this).GetLockFile(ProjectAssetsFile); - } - - return _lockFile; - } - } - - protected override void ExecuteCore() - { - foreach (var message in LockFile.LogMessages) - { - AddMessage(message); - } - } - - private void AddMessage(IAssetsLogMessage message) - { - var targetGraphs = message.GetTargetGraphs(LockFile); - - targetGraphs = targetGraphs.Any() ? targetGraphs : new LockFileTarget[] { null }; - - foreach (var target in targetGraphs) - { - var targetLib = message.LibraryId == null ? null : target?.GetTargetLibrary(message.LibraryId); - - _diagnostics.Add( - message.Code.ToString(), - message.Message, - message.FilePath, - FromLogLevel(message.Level), - message.StartLineNumber, - message.StartColumnNumber, - message.EndLineNumber, - message.EndColumnNumber, - target?.Name, - targetLib == null ? null : $"{targetLib.Name}/{targetLib.Version.ToNormalizedString()}"); - } - } - - private static DiagnosticMessageSeverity FromLogLevel(LogLevel level) - { - switch (level) - { - case LogLevel.Error: - return DiagnosticMessageSeverity.Error; - - case LogLevel.Warning: - return DiagnosticMessageSeverity.Warning; - - case LogLevel.Debug: - case LogLevel.Verbose: - case LogLevel.Information: - case LogLevel.Minimal: - default: - return DiagnosticMessageSeverity.Info; - } - } - } -} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets index f5d1fd8b2145..b065bbe50575 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets @@ -168,8 +168,7 @@ Copyright (c) .NET Foundation. All rights reserved. the Visual Studio error list when a project is created before NuGet restore has run and created the assets file. --> + Condition=" '$(DesignTimeBuild)' != 'true' Or Exists('$(ProjectAssetsFile)')"> - - - - - - - - - - - - - - - - - + false @@ -183,12 +187,15 @@ Copyright (c) .NET Foundation. All rights reserved. ProjectPath="$(MSBuildProjectFullPath)" ProjectAssetsFile="$(ProjectAssetsFile)" ProjectLanguage="$(Language)" + EmitLegacyAssetsFileItems="$(EmitLegacyAssetsFileItems)" ContinueOnError="ErrorAndContinue"> - - + + + + diff --git a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs index 1d1f90d7da87..0a80bfac1dbb 100644 --- a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs +++ b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs @@ -247,6 +247,7 @@ public void It_restores_only_ridless_tfm() "netcoreapp2.1", "TargetDefinitions", GetValuesCommand.ValueType.Item) { DependsOnTargets = "RunResolvePackageDependencies", + Properties = { { "EmitLegacyAssetsFileItems", "true" } } }; getValuesCommand diff --git a/src/Tests/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs b/src/Tests/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs index 6c0a9293ca99..33c36daa8030 100644 --- a/src/Tests/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs +++ b/src/Tests/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs @@ -30,6 +30,7 @@ public enum ValueType public string Configuration { get; set; } public List MetadataNames { get; set; } = new List(); + public Dictionary Properties { get; } = new Dictionary(); public GetValuesCommand(ITestOutputHelper log, string projectPath, string targetFramework, string valueName, ValueType valueType = ValueType.Property) @@ -69,8 +70,20 @@ protected override SdkCommandSpec CreateCommand(IEnumerable args) } } + string propertiesElement = ""; + if (Properties.Count != 0) + { + propertiesElement += "\n"; + foreach ((string key, string value) in Properties) + { + propertiesElement += $" <{key}>{value}\n"; + } + propertiesElement += " "; + } + string injectTargetContents = $@" + {propertiesElement} From e5e26b740017d50bd9dede73368f9b14ba46311b Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Wed, 13 May 2020 11:21:12 +1000 Subject: [PATCH 32/32] Document property value Co-authored-by: Daniel Plaisted --- .../targets/Microsoft.PackageDependencyResolution.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets index 296941795b43..98e5ed94f261 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets @@ -49,7 +49,7 @@ Copyright (c) .NET Foundation. All rights reserved. true - false