-
Notifications
You must be signed in to change notification settings - Fork 296
/
CodeMetricsViewModel.cs
152 lines (131 loc) · 4.57 KB
/
CodeMetricsViewModel.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.UI;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Rubberduck.Navigation.CodeExplorer;
using Rubberduck.Parsing.UIContext;
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
namespace Rubberduck.CodeAnalysis.CodeMetrics
{
public sealed class CodeMetricsViewModel : ViewModelBase, IDisposable
{
private readonly RubberduckParserState _state;
private readonly ICodeMetricsAnalyst _analyst;
private readonly IVBE _vbe;
private readonly IUiDispatcher _uiDispatcher;
public CodeMetricsViewModel(
RubberduckParserState state,
ICodeMetricsAnalyst analyst,
IVBE vbe,
IUiDispatcher uiDispatcher)
{
_state = state;
_state.StateChanged += OnStateChanged;
_analyst = analyst;
_vbe = vbe;
_uiDispatcher = uiDispatcher;
OnPropertyChanged(nameof(Projects));
}
private bool _unparsed = true;
public bool Unparsed
{
get => _unparsed;
set
{
if (_unparsed == value)
{
return;
}
_unparsed = value;
OnPropertyChanged();
}
}
private void OnStateChanged(object sender, ParserStateEventArgs e)
{
Unparsed = false;
IsBusy = _state.Status != ParserState.Pending && _state.Status <= ParserState.ResolvedDeclarations;
if (e.State != ParserState.ResolvedDeclarations)
{
return;
}
Synchronize(_state.DeclarationFinder.AllUserDeclarations.ToList());
}
private void Synchronize(List<Declaration> declarations)
{
var metricResults = _analyst.GetMetrics(_state);
_resultsByDeclaration = metricResults.GroupBy(r => r.Declaration).ToDictionary(g => g.Key, g => g.ToList());
_uiDispatcher.Invoke(() =>
{
var existing = Projects.OfType<CodeExplorerProjectViewModel>().ToList();
foreach (var project in existing)
{
project.Synchronize(declarations);
if (project.Declaration is null)
{
Projects.Remove(project);
}
}
var adding = declarations.OfType<ProjectDeclaration>().ToList();
foreach (var project in adding)
{
var model = new CodeExplorerProjectViewModel(project, declarations.Where(proj => proj.ProjectId.Equals(project.ProjectId)).ToList(), _state, _vbe, false);
Projects.Add(model);
model.IsExpanded = true;
}
});
}
private ICodeExplorerNode _selectedItem;
public ICodeExplorerNode SelectedItem
{
get => _selectedItem;
set
{
if (_selectedItem == value)
{
return;
}
_selectedItem = value;
OnPropertyChanged();
OnPropertyChanged(nameof(Metrics));
}
}
public ObservableCollection<ICodeExplorerNode> Projects { get; } = new ObservableCollection<ICodeExplorerNode>();
private Dictionary<Declaration, List<ICodeMetricResult>> _resultsByDeclaration;
public ObservableCollection<ICodeMetricResult> Metrics
{
get
{
var results = _resultsByDeclaration?.FirstOrDefault(f => ReferenceEquals(f.Key, SelectedItem.Declaration));
return results?.Value == null ? new ObservableCollection<ICodeMetricResult>() : new ObservableCollection<ICodeMetricResult>(results.Value.Value);
}
}
private bool _isBusy;
public bool IsBusy
{
get => _isBusy;
set
{
_isBusy = value;
OnPropertyChanged();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _isDisposed;
private void Dispose(bool disposing)
{
if (_isDisposed || !disposing)
{
return;
}
_isDisposed = true;
_state.StateChanged -= OnStateChanged;
}
}
}