Skip to content

Commit

Permalink
Merge pull request #30 from tom-englert/feature/improvements
Browse files Browse the repository at this point in the history
Feature: Normalize package references, using attributes only.
  • Loading branch information
sboulema authored Nov 18, 2023
2 parents 932ca35 + 06f19b3 commit 090afac
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 9 deletions.
6 changes: 3 additions & 3 deletions src/NuGetMonitor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
<PackageReference Include="Microsoft.Build" Version="[17.4.0]" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="[17.4.0]" ExcludeAssets="runtime" />
<PackageReference Include="Community.VisualStudio.Toolkit.17" Version="17.0.507" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="17.7.2196" PrivateAssets="all" />
<PackageReference Include="NuGet.Protocol" Version="6.7.0" />
<PackageReference Include="NuGet.Protocol" Version="6.8.0" />
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets="all" />
<PackageReference Include="Throttle.Fody" Version="1.7.0" PrivateAssets="all" />
<PackageReference Include="TomsToolbox.Wpf.Styles" Version="2.9.1" />
<PackageReference Include="TomsToolbox.Wpf.Styles" Version="2.10.0" />
<PackageReference Include="VSIX-SdkProjectAdapter" Version="3.0.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
Expand Down
3 changes: 1 addition & 2 deletions src/Services/InfoBarService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.IO;
using System.Text;
using System.Text;
using System.Windows;
using Community.VisualStudio.Toolkit;
using Microsoft.VisualStudio.Imaging;
Expand Down
2 changes: 1 addition & 1 deletion src/Services/NuGetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static async Task<ICollection<TransitiveDependencies>> GetTransitivePacka
{
var results = new List<TransitiveDependencies>();

var projectItemsByTargetFramework = packageReferences.GroupBy(item => item.ProjectItemInTargetFramework.TargetFramework);
var projectItemsByTargetFramework = packageReferences.GroupBy(item => item.ProjectItemInTargetFramework.Project.TargetFramework);

foreach (var projectItemsInTargetFramework in projectItemsByTargetFramework)
{
Expand Down
70 changes: 68 additions & 2 deletions src/Services/ProjectService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ public ProjectItemInTargetFramework(ProjectItem projectItem, ProjectInTargetFram

public ProjectItem ProjectItem { get; init; }

public NuGetFramework TargetFramework => Project.TargetFramework;

public ProjectInTargetFramework Project { get; }
}

Expand Down Expand Up @@ -63,6 +61,8 @@ private static ReadOnlyDictionary<string, ProjectItem> GetCentralVersionMap(Proj

internal static class ProjectService
{
private static readonly string[] _allAssets = new[] { "runtime", "build", "native", "contentfiles", "analyzers", "buildtransitive" }.OrderBy(i => i).ToArray();

private static ProjectCollection _projectCollection = new();

static ProjectService()
Expand Down Expand Up @@ -97,6 +97,72 @@ public static async Task<IReadOnlyCollection<PackageReferenceEntry>> GetPackageR
});
}

public static int NormalizePackageReferences(IEnumerable<ProjectItem> projectItems)
{
using var projectCollection = new ProjectCollection();
var numberOfUpdatedItems = 0;

var projectFiles = projectItems
.Select(i => i.GetContainingProject().FullPath)
.Distinct(StringComparer.OrdinalIgnoreCase);

foreach (var projectFile in projectFiles)
{
var isDirty = false;

var project = ProjectRootElement.Open(projectFile, projectCollection, true);

var itemElements = project.Items
.Where(item => item.ItemType == "PackageReference");

foreach (var itemElement in itemElements)
{
var metadata = itemElement.Metadata;

var metadataElements = metadata.Where(meta => !meta.ExpressedAsAttribute).ToArray();
if (metadataElements.Length == 0)
continue;

foreach (var metadataElement in metadataElements)
{
metadataElement.ExpressedAsAttribute = true;
}

NormalizeIncludeAssets(metadata);

numberOfUpdatedItems += 1;
isDirty = true;
}

if (isDirty)
{
project.Save();
}
}

return numberOfUpdatedItems;
}

private static void NormalizeIncludeAssets(IEnumerable<ProjectMetadataElement> metadata)
{
var includeAssetsElement = metadata.FirstOrDefault(meta => meta.Name == "IncludeAssets");
if (includeAssetsElement is null)
return;

var includeAssets = includeAssetsElement.Value;
if (string.IsNullOrEmpty(includeAssets))
return;

var parts = includeAssets.Split(';')
.Select(s => s.Trim())
.OrderBy(s => s, StringComparer.OrdinalIgnoreCase);

if (!_allAssets.SequenceEqual(parts, StringComparer.OrdinalIgnoreCase))
return;

includeAssetsElement.Value = string.Empty;
}

public static ProjectInTargetFramework[] GetProjectsInTargetFramework(this Project project)
{
var frameworkNames = (project.GetProperty("TargetFrameworks") ?? project.GetProperty("TargetFramework"))
Expand Down
3 changes: 3 additions & 0 deletions src/View/Monitor/NuGetMonitorControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
<Button Command="{Binding ShowDependencyTreeCommand}" ToolTip="Show dependency tree">
<imaging:CrispImage Width="16" Height="16" Moniker="{x:Static imageCatalog:KnownMonikers.DecisionTree}" />
</Button>
<Button Command="{Binding NormalizePackageReferencesCommand}" ToolTip="Normalize package references">
<imaging:CrispImage Width="16" Height="16" Moniker="{x:Static imageCatalog:KnownMonikers.GraphRightToLeft}" />
</Button>
<Button Command="{Binding CopyIssueDetailsCommand}" ToolTip="Copy issue details">
<imaging:CrispImage Width="16" Height="16" Moniker="{x:Static imageCatalog:KnownMonikers.Copy}" />
</Button>
Expand Down
4 changes: 3 additions & 1 deletion src/View/Monitor/NuGetMonitorToolWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
namespace NuGetMonitor.View.Monitor;


[Guid("6ce47eec-3296-48f5-9dec-8883a276a7c8")]
[Guid(Guid)]
public sealed class NuGetMonitorToolWindow : ToolWindowPane
{
public const string Guid = "6ce47eec-3296-48f5-9dec-8883a276a7c8";

/// <summary>
/// Initializes a new instance of the <see cref="NuGetMonitorToolWindow"/> class.
/// </summary>
Expand Down
29 changes: 29 additions & 0 deletions src/View/Monitor/NugetMonitorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Microsoft.Build.Evaluation;
using Microsoft.VisualStudio.Shell;
using NuGetMonitor.Services;
using NuGetMonitor.View.Monitor;
using TomsToolbox.Essentials;
using TomsToolbox.Wpf;

Expand Down Expand Up @@ -43,6 +44,8 @@ public NuGetMonitorViewModel()

public ICommand CopyIssueDetailsCommand => new DelegateCommand(CanCopyIssueDetails, CopyIssueDetails);

public ICommand NormalizePackageReferencesCommand => new DelegateCommand(NormalizePackageReferences);

private void SolutionEvents_OnAfterOpenSolution(Solution? obj)
{
Load();
Expand Down Expand Up @@ -166,6 +169,32 @@ private static void Update(ICollection<PackageViewModel> packageViewModels)
ProjectService.ClearCache();
}

private void NormalizePackageReferences()
{
NormalizePackageReferencesAsync().FireAndForget();
}

private async Task NormalizePackageReferencesAsync()
{
var projectItems = Packages
.SelectMany(p => p.Items.Select(item => item.ProjectItemInTargetFramework.ProjectItem));

var numberOfUpdatedItems = ProjectService.NormalizePackageReferences(projectItems);

await ShowInfoBar($"{numberOfUpdatedItems} package references normalized");
}

private static async Task ShowInfoBar(string text)
{
var model = new InfoBarModel(text);
var infoBar = await VS.InfoBar.CreateAsync(NuGetMonitorToolWindow.Guid, model).ConfigureAwait(true) ?? throw new InvalidOperationException("Failed to create the info bar");
await infoBar.TryShowInfoBarUIAsync().ConfigureAwait(true);

await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(true);

infoBar.Close();
}

private bool CanCopyIssueDetails()
{
return Packages?.Any(p => p.PackageInfo?.HasIssues ?? false) == true;
Expand Down

0 comments on commit 090afac

Please sign in to comment.