Skip to content

Commit 4437119

Browse files
committed
Add support for labels. Packages can be included and excluded. Update nugets
1 parent b1fc40d commit 4437119

File tree

16 files changed

+187
-139
lines changed

16 files changed

+187
-139
lines changed

SDV.App/MainWindow.xaml

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,29 @@
2020
Margin="10,10,0,0" />
2121
</WrapPanel>
2222

23-
<WrapPanel HorizontalAlignment="Left" Margin="0,10,0,10">
24-
<Label Content="Filter mode" />
25-
<ComboBox x:Name="Mode" Width="200"></ComboBox>
23+
<WrapPanel HorizontalAlignment="Left" Margin="0,10,0,0">
24+
<Label Content="Included packages" />
25+
<TextBox x:Name="PackageFiltersInclude" Width="450" />
2626
</WrapPanel>
27-
27+
<WrapPanel HorizontalAlignment="Center" Margin="0,0,0,10">
28+
<TextBlock Text="Comma separated values" FontSize="10" />
29+
</WrapPanel>
30+
2831
<WrapPanel HorizontalAlignment="Left" Margin="0,10,0,0">
29-
<Label Content="Filtered packages" />
30-
<TextBox x:Name="PackagePrefixes" Width="465" />
32+
<Label Content="Excluded packages" />
33+
<TextBox x:Name="PackageFiltersExclude" Width="450" />
3134
</WrapPanel>
3235
<WrapPanel HorizontalAlignment="Center" Margin="0,0,0,10">
3336
<TextBlock Text="Comma separated values" FontSize="10" />
3437
</WrapPanel>
38+
39+
<WrapPanel HorizontalAlignment="Left" Margin="0,10,0,0">
40+
<Label Content="Labels" />
41+
<TextBox x:Name="Labels" Width="450" />
42+
</WrapPanel>
43+
<WrapPanel HorizontalAlignment="Center" Margin="0,0,0,10">
44+
<TextBlock Text="Comma separated values. Like: Microsoft.*=⭐ (Emoji as labels recommended)" FontSize="10" />
45+
</WrapPanel>
3546

3647
<WrapPanel HorizontalAlignment="Left" Margin="0,10,0,0">
3748
<CheckBox x:Name="IncludeDependentProjects" Content="Include dependencies between projects" />

SDV.App/MainWindow.xaml.cs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using Microsoft.Win32;
1212
using SDV.App.Logging;
1313
using Serilog.Events;
14-
using SDV.DependenciesAnalyzer.Interfaces;
1514
using SDV.GraphGenerator.Interfaces;
1615

1716
namespace SDV.App
@@ -36,10 +35,10 @@ public MainWindow(ILogger<MainWindow> logger, WindowLogSink logSink, IGraphBuild
3635
{
3736
Filter = "solution files (*.sln)|*.sln"
3837
};
39-
PackagePrefixes.Text = "Microsoft.*, System.*";
38+
PackageFiltersExclude.Text = "Microsoft.*, System.*";
4039
IncludeDependentProjects.IsChecked = true;
4140
ClearSelectionButton.IsEnabled = false;
42-
SetupModeComboBox();
41+
Labels.Text = "IsNuget=\ud83d\udce6";
4342
logSink.OnLogEmitted = OnLogEmitted;
4443
}
4544

@@ -69,19 +68,25 @@ private async void btnBuild_Click(object sender, RoutedEventArgs e)
6968
_logger.LogError("Please, select sln file to proceed");
7069
return;
7170
}
72-
71+
7372
ToggleControlsAs(false);
7473

7574
try
7675
{
7776
var request = new GraphBuilderRequest(_slnFilePaths)
7877
{
79-
Mode = (PackageFilterMode)Mode.SelectedValue,
80-
PackageFilters = PackagePrefixes.Text.Split(",").Select(t => t.Trim()).Where(t => !string.IsNullOrEmpty(t)).ToArray(),
78+
FiltersInclude = GetCommaSeparatedValues(PackageFiltersInclude.Text).ToArray(),
79+
FiltersExclude = GetCommaSeparatedValues(PackageFiltersExclude.Text).ToArray(),
80+
Labels = GetCommaSeparatedValues(Labels.Text).Select(s => s.Split('=')).Where(a => a.Length == 2)
81+
.GroupBy(s => s[0].Trim())
82+
.ToDictionary(
83+
g => g.Key,
84+
g => g.SelectMany(v => v).Select(s => s.Trim())
85+
.Where(s => !string.IsNullOrEmpty(s) && s != g.Key).ToArray()),
8186
IncludeDependentProjects = IncludeDependentProjects.IsChecked ?? false,
8287
MergeProjects = MergeProjects.IsChecked ?? false
8388
};
84-
89+
8590
var path = await BuildGraphAndGetFilePathAsync(request);
8691

8792
OpenUrl(path);
@@ -97,12 +102,17 @@ private async void btnBuild_Click(object sender, RoutedEventArgs e)
97102
}
98103
}
99104

100-
private Task<string> BuildGraphAndGetFilePathAsync(GraphBuilderRequest graphBuilderRequest) =>
105+
private static IEnumerable<string> GetCommaSeparatedValues(string str)
106+
{
107+
return str.Split(",").Select(t => t.Trim()).Where(t => !string.IsNullOrEmpty(t));
108+
}
109+
110+
private Task<string> BuildGraphAndGetFilePathAsync(GraphBuilderRequest graphBuilderRequest) =>
101111
Task.Run(() => _builder.BuildGraphAndGetFilePath(graphBuilderRequest));
102112

103113
private void btnClearSelection_Click(object sender, RoutedEventArgs e)
104114
{
105-
_slnFilePaths = new HashSet<string>();
115+
_slnFilePaths = [];
106116
Log.Text = string.Empty;
107117
_logger.LogInformation("Selection cleared");
108118
ClearSelectionButton.IsEnabled = false;
@@ -136,27 +146,17 @@ private static void OpenUrl(string url)
136146
}
137147
}
138148

139-
private void SetupModeComboBox()
140-
{
141-
var item = Tuple.Create("Disabled", PackageFilterMode.None);
142-
Mode.DisplayMemberPath = nameof(item.Item1);
143-
Mode.SelectedValuePath = nameof(item.Item2);
144-
Mode.SelectedValue = PackageFilterMode.Exclude;
145-
Mode.Items.Add(item);
146-
Mode.Items.Add(Tuple.Create("Include listed packages", PackageFilterMode.Include));
147-
Mode.Items.Add(Tuple.Create("Exclude listed packages", PackageFilterMode.Exclude));
148-
}
149-
150149
private void ToggleControlsAs(bool state)
151150
{
152151
SlnFileSelectorButton.IsEnabled = state;
153-
Mode.IsEnabled = state;
154-
PackagePrefixes.IsEnabled = state;
152+
PackageFiltersInclude.IsEnabled = state;
153+
PackageFiltersExclude.IsEnabled = state;
154+
Labels.IsEnabled = state;
155155
IncludeDependentProjects.IsEnabled = state;
156156
MergeProjects.IsEnabled = state;
157157
BuildGraphButton.IsEnabled = state;
158158
}
159-
159+
160160
private void OnLogEmitted(LogEventLevel level, string log)
161161
{
162162
Log.Dispatcher.Invoke(DispatcherPriority.Background, () =>
@@ -167,7 +167,7 @@ private void OnLogEmitted(LogEventLevel level, string log)
167167
});
168168
}
169169

170-
private static Brush GetBrushForLevel(LogEventLevel level)
170+
private static SolidColorBrush GetBrushForLevel(LogEventLevel level)
171171
{
172172
return level switch
173173
{

SDV.App/SDV.App.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<TargetFramework>net8.0-windows</TargetFramework>
66
<Nullable>enable</Nullable>
77
<UseWPF>true</UseWPF>
8-
<Version>1.0.2</Version>
8+
<Version>1.0.4</Version>
99
<LangVersion>default</LangVersion>
1010
</PropertyGroup>
1111

SDV.DependenciesAnalyzer/Dependencies/DependenciesUtils.cs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,21 @@ public class DependenciesUtils
1212
public DependenciesUtils(ILogger log)
1313
{
1414
_log = log;
15-
_configuration = new TreeGeneratorConfiguration(string.Empty, []);
15+
_configuration = new TreeGeneratorConfiguration(string.Empty, [], []);
1616
}
1717

1818
public DependencyTree[] CreateDependencyTree(IExtractor extractor, TreeGeneratorConfiguration configuration)
1919
{
2020
_configuration = configuration;
2121
var rootTree = _configuration.IncludeDependentProjects
2222
? extractor.DependentProjects().Select(p => DependencyTree.AsProject(p.Id, p.Version)).ToList()
23-
: new List<DependencyTree>();
23+
: [];
2424
var rootDependencies = extractor.DirectDependencies();
2525
var allDependencies = extractor.AllDependencies();
2626
var childrenMap = extractor.ChildrenMap();
2727

28-
foreach (var rootId in rootDependencies)
28+
foreach (var rootId in rootDependencies.Where(_configuration.IsPackageEnabled))
2929
{
30-
if (!CanBeProcessed(rootId))
31-
{
32-
continue;
33-
}
34-
3530
if (allDependencies.TryGetValue(rootId, out var dependency))
3631
{
3732
var childrenDependencies = FindChildrenDependencies(rootId, allDependencies, childrenMap).ToList();
@@ -55,14 +50,9 @@ private IEnumerable<DependencyTree> FindChildrenDependencies(string id,
5550
{
5651
yield break;
5752
}
58-
59-
foreach (var childId in childArray)
53+
54+
foreach (var childId in childArray.Where(_configuration.IsPackageEnabled))
6055
{
61-
if (!CanBeProcessed(childId))
62-
{
63-
continue;
64-
}
65-
6656
if (allDependencies.TryGetValue(childId, out var dependency))
6757
{
6858
var childrenDependencies = FindChildrenDependencies(childId, allDependencies, childrenMap).ToList();
@@ -74,7 +64,4 @@ private IEnumerable<DependencyTree> FindChildrenDependencies(string id,
7464
}
7565
}
7666
}
77-
78-
79-
private bool CanBeProcessed(string name) => _configuration.IsPackageEnabled(name);
8067
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
namespace SDV.DependenciesAnalyzer.Helpers;
2+
3+
public static class FilterHelper
4+
{
5+
private const char Mask = '*';
6+
7+
public static Func<string, bool>? BuildFilter(string packagePrefix)
8+
{
9+
if (string.IsNullOrWhiteSpace(packagePrefix))
10+
return null;
11+
12+
packagePrefix = packagePrefix.Trim();
13+
var split = packagePrefix.Split(Mask);
14+
switch (split.Length)
15+
{
16+
// filter
17+
case 1:
18+
return s => split[0].Equals(s);
19+
case 2:
20+
{
21+
if(split.First() != string.Empty && split.Last() != string.Empty) // fil*ter
22+
{
23+
return s => s.StartsWith(split.First()) && packagePrefix.EndsWith(split.Last());
24+
25+
}
26+
if (split.First() == string.Empty && split.Last() == string.Empty) // *
27+
{
28+
throw new ArgumentException($"Unknown filter specified: {packagePrefix}");
29+
}
30+
if (split.First() == string.Empty) // *filter
31+
{
32+
return s => s.EndsWith(split.Last());
33+
}
34+
// filter*
35+
return s => s.StartsWith(split.First());
36+
37+
}
38+
case 3 when split.First() == string.Empty && split.Last() == string.Empty:
39+
return s => s.Contains(split[1]);
40+
default:
41+
throw new ArgumentException($"Unknown filter specified: {packagePrefix}");
42+
}
43+
}
44+
45+
}
Lines changed: 15 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using SDV.DependenciesAnalyzer.Models;
1+
using SDV.DependenciesAnalyzer.Helpers;
2+
using SDV.DependenciesAnalyzer.Models;
23

34
namespace SDV.DependenciesAnalyzer.Interfaces;
45

@@ -16,81 +17,32 @@ public interface INugetDependenciesGenerator
1617

1718
public class TreeGeneratorConfiguration
1819
{
19-
public string SlnFilePath { get; }
20-
public PackageFilterMode Mode { get; init; }
20+
public string SlnFilePath { get; set; }
2121
public bool IncludeDependentProjects { get; init; }
2222

23-
private readonly List<Func<string, bool>> _filters;
24-
private const char Mask = '*';
23+
private readonly Func<string, bool>[] _filtersInclude;
24+
private readonly Func<string, bool>[] _filtersExclude;
2525

26-
public TreeGeneratorConfiguration(string slnFilePath, string[] packageFilters)
26+
public TreeGeneratorConfiguration(string slnFilePath, string[] filtersInclude, string[] filtersExclude)
2727
{
28-
_filters = new List<Func<string, bool>>();
28+
_filtersInclude = filtersInclude.Select(FilterHelper.BuildFilter).Where(f => f != null).ToArray()!;
29+
_filtersExclude = filtersExclude.Select(FilterHelper.BuildFilter).Where(f => f != null).ToArray()!;
2930
SlnFilePath = slnFilePath;
30-
Mode = PackageFilterMode.None;
3131
IncludeDependentProjects = false;
32-
BuildFilters(packageFilters);
3332
}
3433

3534
public bool IsPackageEnabled(string packageName)
3635
{
37-
if (Mode == PackageFilterMode.None || _filters.Count == 0)
38-
return true;
39-
40-
var isMatched = _filters.Any(f => f(packageName));
41-
var shouldBeProcessed = Mode == PackageFilterMode.Include ? isMatched : !isMatched;
36+
return IsIncluded(packageName) && !IsExcluded(packageName);
37+
}
4238

43-
return shouldBeProcessed;
39+
private bool IsIncluded(string packageName)
40+
{
41+
return _filtersInclude.Length < 1 || _filtersInclude.Any(f => f(packageName));
4442
}
4543

46-
private void BuildFilters(string[] packagePrefixes)
44+
private bool IsExcluded(string packageName)
4745
{
48-
foreach (var filter in packagePrefixes.Where(p => !string.IsNullOrWhiteSpace(p)).Select(p => p.Trim()))
49-
{
50-
var split = filter.Split(Mask);
51-
if (split.Length == 1) // filter
52-
{
53-
_filters.Add(s => split[0].Equals(s));
54-
return;
55-
}
56-
57-
if (split.Length == 2)
58-
{
59-
if(split.First() != string.Empty && split.Last() != string.Empty) // fil*ter
60-
{
61-
_filters.Add(s => s.StartsWith(split.First()) && filter.EndsWith(split.Last()));
62-
63-
}
64-
else if (split.First() == string.Empty && split.Last() == string.Empty) // *
65-
{
66-
throw new ArgumentException($"Unknown filter specified: {filter}");
67-
}
68-
else if (split.First() == string.Empty) // *filter
69-
{
70-
_filters.Add(s => s.EndsWith(split.Last()));
71-
}
72-
else // filter*
73-
{
74-
_filters.Add(s => s.StartsWith(split.First()));
75-
}
76-
77-
return;
78-
}
79-
80-
if (split.Length == 3 && split.First() == string.Empty && split.Last() == string.Empty)
81-
{
82-
_filters.Add(s => s.Contains(split[1]));
83-
return;
84-
}
85-
86-
throw new ArgumentException($"Unknown filter specified: {filter}");
87-
}
46+
return _filtersExclude.Any(f => f(packageName));
8847
}
89-
}
90-
91-
public enum PackageFilterMode
92-
{
93-
None = 0,
94-
Include = 1,
95-
Exclude = 2
9648
}

SDV.DependenciesAnalyzer/Models/DependencyTree.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ private DependencyTree(string id, string version, List<DependencyTree> dependenc
1919

2020
public static DependencyTree AsProject(string id, string version)
2121
{
22-
return new DependencyTree(id, version, new List<DependencyTree>(0), DependencyType.Project);
22+
return new DependencyTree(id, version, [], DependencyType.Project);
2323
}
2424

2525
public static DependencyTree AsPackage(string id, string version, List<DependencyTree> dependencies)
@@ -28,6 +28,7 @@ public static DependencyTree AsPackage(string id, string version, List<Dependenc
2828
}
2929
}
3030

31+
[Flags]
3132
public enum DependencyType
3233
{
3334
Project = 1,

SDV.DependenciesAnalyzer/NugetDependenciesGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public NugetDependenciesGenerator(ILogger<NugetDependenciesGenerator> log)
2020

2121
public Tree Generate(string slnFilePath)
2222
{
23-
return Generate(new TreeGeneratorConfiguration(slnFilePath, []));
23+
return Generate(new TreeGeneratorConfiguration(slnFilePath, [], []));
2424
}
2525

2626
public Tree Generate(TreeGeneratorConfiguration configuration)

0 commit comments

Comments
 (0)