Skip to content

Commit 28f93ea

Browse files
committed
Allow partial loading of solutions if some projects fail
1 parent 85bb5a6 commit 28f93ea

File tree

6 files changed

+80
-14
lines changed

6 files changed

+80
-14
lines changed

CSharpCodeAnalyst/MainViewModel.cs

+14-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Globalization;
55
using System.IO;
66
using System.Reflection;
7-
using System.Runtime;
87
using System.Text.Json;
98
using System.Text.Json.Serialization;
109
using System.Windows;
@@ -36,6 +35,7 @@ namespace CSharpCodeAnalyst;
3635

3736
internal class MainViewModel : INotifyPropertyChanged
3837
{
38+
private readonly int _maxDegreeOfParallelism;
3939
private readonly MessageBus _messaging;
4040

4141
private readonly ProjectExclusionRegExCollection _projectExclusionFilters;
@@ -58,6 +58,8 @@ internal class MainViewModel : INotifyPropertyChanged
5858
private string _loadMessage;
5959
private ObservableCollection<IMetric> _metrics = [];
6060

61+
private LegendDialog? _openedLegendDialog;
62+
6163
private List<QuickInfo> _quickInfo = QuickInfoFactory.NoInfoProviderRegistered;
6264
private int _selectedTabIndex;
6365

@@ -319,16 +321,13 @@ GraphSession AddSession(string name)
319321
}
320322
}
321323

322-
LegendDialog? _openedLegendDialog;
323-
private readonly int _maxDegreeOfParallelism;
324-
325324
private void ShowLegend()
326325
{
327326
if (_openedLegendDialog == null)
328327
{
329328
_openedLegendDialog = new LegendDialog();
330329
_openedLegendDialog.Owner = Application.Current.MainWindow;
331-
_openedLegendDialog.Closed += (object? sender, EventArgs e) => _openedLegendDialog = null;
330+
_openedLegendDialog.Closed += (sender, e) => _openedLegendDialog = null;
332331
_openedLegendDialog.Show();
333332
}
334333
}
@@ -509,7 +508,14 @@ private async Task LoadAndAnalyzeSolution(string solutionPath)
509508
{
510509
IsLoading = true;
511510

512-
var codeGraph = await Task.Run(async () => await LoadAsync(solutionPath));
511+
var (codeGraph, diagnostics) = await Task.Run(async () => await LoadAsync(solutionPath));
512+
513+
var failures = diagnostics.FormatFailures();
514+
if (string.IsNullOrEmpty(failures) is false)
515+
{
516+
var failureText = Strings.Parser_FailureHeader + failures;
517+
MessageBox.Show(failureText, Strings.Error_Title, MessageBoxButton.OK, MessageBoxImage.Warning);
518+
}
513519

514520
LoadCodeGraph(codeGraph);
515521

@@ -529,15 +535,15 @@ private async Task LoadAndAnalyzeSolution(string solutionPath)
529535
}
530536
}
531537

532-
private async Task<CodeGraph> LoadAsync(string solutionPath)
538+
private async Task<(CodeGraph, IParserDiagnostics)> LoadAsync(string solutionPath)
533539
{
534540
LoadMessage = "Loading ...";
535541
var parser = new Parser(new ParserConfig(_projectExclusionFilters, _maxDegreeOfParallelism));
536542
parser.Progress.ParserProgress += OnProgress;
537543
var graph = await parser.ParseSolution(solutionPath).ConfigureAwait(true);
538544

539545
parser.Progress.ParserProgress -= OnProgress;
540-
return graph;
546+
return (graph, parser.Diagnostics);
541547
}
542548

543549
private void LoadCodeGraph(CodeGraph codeGraph)

CSharpCodeAnalyst/Resources/Strings.Designer.cs

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CSharpCodeAnalyst/Resources/Strings.resx

+5
Original file line numberDiff line numberDiff line change
@@ -414,4 +414,9 @@
414414
<data name="Legend_Tooltip" xml:space="preserve">
415415
<value>Show color legend</value>
416416
</data>
417+
<data name="Parser_FailureHeader" xml:space="preserve">
418+
<value>There are failures when loading the solution. The code graph may not complete:
419+
420+
</value>
421+
</data>
417422
</root>

CodeParser/Parser/Parser.cs

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System.Diagnostics;
22
using CodeParser.Parser.Config;
3+
using Contracts.Common;
34
using Contracts.Graph;
5+
using Microsoft.CodeAnalysis;
46
using Microsoft.CodeAnalysis.MSBuild;
57

68
namespace CodeParser.Parser;
@@ -15,16 +17,22 @@ public class Parser(ParserConfig config)
1517
{
1618
public Progress Progress { get; set; } = new();
1719

20+
private readonly ParserDiagnostics _diagnostics = new ParserDiagnostics();
21+
22+
public IParserDiagnostics Diagnostics => _diagnostics;
23+
1824
public async Task<CodeGraph> ParseSolution(string solutionPath)
1925
{
26+
_diagnostics.Clear();
27+
2028
var sw = Stopwatch.StartNew();
2129

2230
Progress.SendProgress("Compiling ...");
2331

2432
var workspace = MSBuildWorkspace.Create();
2533
workspace.WorkspaceFailed += Workspace_WorkspaceFailed;
2634
var solution = await workspace.OpenSolutionAsync(solutionPath);
27-
35+
2836

2937
sw.Stop();
3038
Trace.WriteLine("Compiling: " + sw.Elapsed);
@@ -56,12 +64,10 @@ public async Task<CodeGraph> ParseSolution(string solutionPath)
5664
return codeGraph;
5765
}
5866

59-
private void Workspace_WorkspaceFailed(object? sender, Microsoft.CodeAnalysis.WorkspaceDiagnosticEventArgs e)
67+
private void Workspace_WorkspaceFailed(object? sender, WorkspaceDiagnosticEventArgs e)
6068
{
61-
if (e.Diagnostic.Kind == Microsoft.CodeAnalysis.WorkspaceDiagnosticKind.Failure)
62-
{
63-
throw new InvalidOperationException(e.Diagnostic.Message);
64-
}
69+
_diagnostics.Add(e.Diagnostic);
70+
Trace.WriteLine(e.Diagnostic.Message);
6571
}
6672

6773
private bool IsDistinct<T>(List<T> collection)
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using Contracts.Common;
2+
using Microsoft.CodeAnalysis;
3+
4+
namespace CodeParser.Parser;
5+
6+
internal class ParserDiagnostics : IParserDiagnostics
7+
{
8+
public List<WorkspaceDiagnostic> Diagnostics { get; } = new();
9+
10+
public string FormatFailures()
11+
{
12+
var failures = Diagnostics.Where(d => d.Kind == WorkspaceDiagnosticKind.Failure).Select(d => d.Message);
13+
return string.Join(Environment.NewLine, failures);
14+
}
15+
16+
public string FormatWarnings()
17+
{
18+
var failures = Diagnostics.Where(d => d.Kind == WorkspaceDiagnosticKind.Warning).Select(d => d.Message);
19+
return string.Join(Environment.NewLine, failures);
20+
}
21+
22+
public void Add(WorkspaceDiagnostic diagnostic)
23+
{
24+
Diagnostics.Add(diagnostic);
25+
}
26+
27+
public void Clear()
28+
{
29+
Diagnostics.Clear();
30+
}
31+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Contracts.Common;
2+
3+
public interface IParserDiagnostics
4+
{
5+
string FormatFailures();
6+
string FormatWarnings();
7+
}

0 commit comments

Comments
 (0)