Skip to content

Commit 84299ac

Browse files
committed
Merge branch 'next' of https://github.com/rubberduck-vba/Rubberduck into next
2 parents 2ac65de + 3a25a65 commit 84299ac

File tree

119 files changed

+12381
-5004
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+12381
-5004
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
name: Bug report
3+
about: Rubberduck does not work as expected
4+
title: ''
5+
labels: bug
6+
assignees: ''
7+
8+
---
9+
**Rubberduck version information**
10+
The info below can be copy-paste-completed from the first lines of Rubberduck's Log or the About box:
11+
12+
Rubberduck version [...]
13+
Operating System: [...]
14+
Host Product: [...]
15+
Host Version: [...]
16+
Host Executable: [...]
17+
18+
19+
**Description**
20+
A clear and concise description of what the bug is.
21+
22+
**To Reproduce**
23+
Steps to reproduce the behavior:
24+
1. Go to '...'
25+
2. Click on '....'
26+
3. Scroll down to '....'
27+
4. See error
28+
29+
**Expected behavior**
30+
A clear and concise description of what you expected to happen.
31+
32+
**Screenshots**
33+
If applicable, add screenshots to help explain your problem.
34+
35+
**Logfile**
36+
Rubberduck generates extensive logging in TRACE-Level. If no log was created at `%APP_DATA%\Rubberduck\Logs`, check your settings. Include this Log for bugreports about the behavior of Rubbberduck
37+
38+
**Additional context**
39+
Add any other context about the problem here.

Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
5151
private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference)
5252
{
5353
var argExpression = reference.Context.GetAncestor<VBAParser.ArgumentExpressionContext>();
54-
var parameter = State.DeclarationFinder.FindParameterFromArgument(argExpression, enclosingProcedure);
54+
var parameter = State.DeclarationFinder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure);
5555

5656
// note: not recursive, by design.
5757
return parameter != null

Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs

Lines changed: 167 additions & 91 deletions
Large diffs are not rendered by default.

Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
5454
private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference)
5555
{
5656
var argExpression = reference.Context.GetAncestor<VBAParser.ArgumentExpressionContext>();
57-
var parameter = State.DeclarationFinder.FindParameterFromArgument(argExpression, enclosingProcedure);
57+
var parameter = State.DeclarationFinder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure);
5858

5959
// note: not recursive, by design.
6060
return parameter != null

Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
3737
private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference)
3838
{
3939
var argExpression = reference.Context.GetAncestor<VBAParser.ArgumentExpressionContext>();
40-
var parameter = State.DeclarationFinder.FindParameterFromArgument(argExpression, enclosingProcedure);
40+
var parameter = State.DeclarationFinder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure);
4141

4242
// note: not recursive, by design.
4343
return parameter != null

Rubberduck.Core/AddRemoveReferences/ReferenceModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public bool Matches(ReferenceInfo info)
183183
FullPath.Equals(info.FullPath, StringComparison.OrdinalIgnoreCase) ||
184184
FullPath32.Equals(info.FullPath, StringComparison.OrdinalIgnoreCase) ||
185185
FullPath64.Equals(info.FullPath, StringComparison.OrdinalIgnoreCase) ||
186-
Guid.Equals(info.Guid);
186+
!Guid.Equals(Guid.Empty) && Guid.Equals(info.Guid);
187187
}
188188

189189
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")

Rubberduck.Core/CodeAnalysis/CodeMetrics/CodeMetricsViewModel.cs

Lines changed: 67 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -6,136 +6,91 @@
66
using System.Collections.Generic;
77
using System.Collections.ObjectModel;
88
using Rubberduck.Navigation.CodeExplorer;
9-
using System.Windows;
10-
using Rubberduck.Navigation.Folders;
9+
using Rubberduck.Parsing.UIContext;
1110
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
1211

1312
namespace Rubberduck.CodeAnalysis.CodeMetrics
1413
{
15-
public class CodeMetricsViewModel : ViewModelBase, IDisposable
14+
public sealed class CodeMetricsViewModel : ViewModelBase, IDisposable
1615
{
1716
private readonly RubberduckParserState _state;
1817
private readonly ICodeMetricsAnalyst _analyst;
19-
private readonly FolderHelper _folderHelper;
2018
private readonly IVBE _vbe;
19+
private readonly IUiDispatcher _uiDispatcher;
2120

22-
public CodeMetricsViewModel(RubberduckParserState state, ICodeMetricsAnalyst analyst, FolderHelper folderHelper, IVBE vbe)
21+
public CodeMetricsViewModel(
22+
RubberduckParserState state,
23+
ICodeMetricsAnalyst analyst,
24+
IVBE vbe,
25+
IUiDispatcher uiDispatcher)
2326
{
2427
_state = state;
25-
_analyst = analyst;
26-
_folderHelper = folderHelper;
2728
_state.StateChanged += OnStateChanged;
29+
30+
_analyst = analyst;
2831
_vbe = vbe;
29-
}
30-
31-
private void OnStateChanged(object sender, ParserStateEventArgs e)
32-
{
33-
if (e.State != ParserState.Ready && e.State != ParserState.Error && e.State != ParserState.ResolverError && e.State != ParserState.UnexpectedError)
34-
{
35-
IsBusy = true;
36-
}
32+
_uiDispatcher = uiDispatcher;
3733

38-
if (e.State == ParserState.Ready)
39-
{
40-
UpdateData();
41-
IsBusy = false;
42-
}
34+
OnPropertyChanged(nameof(Projects));
35+
}
4336

44-
if (e.State == ParserState.Error || e.State == ParserState.ResolverError || e.State == ParserState.UnexpectedError)
37+
private bool _unparsed = true;
38+
public bool Unparsed
39+
{
40+
get => _unparsed;
41+
set
4542
{
46-
IsBusy = false;
43+
if (_unparsed == value)
44+
{
45+
return;
46+
}
47+
_unparsed = value;
48+
OnPropertyChanged();
4749
}
4850
}
4951

50-
private void UpdateData()
52+
private void OnStateChanged(object sender, ParserStateEventArgs e)
5153
{
52-
IsBusy = true;
53-
54-
var metricResults = _analyst.GetMetrics(_state);
55-
resultsByDeclaration = metricResults.GroupBy(r => r.Declaration).ToDictionary(g => g.Key, g => g.ToList());
54+
Unparsed = false;
55+
IsBusy = _state.Status != ParserState.Pending && _state.Status <= ParserState.ResolvedDeclarations;
5656

57-
if (Projects == null)
57+
if (e.State == ParserState.ResolvedDeclarations)
5858
{
59-
Projects = new ObservableCollection<CodeExplorerItemViewModel>();
59+
Synchronize(_state.DeclarationFinder.AllUserDeclarations);
6060
}
61-
62-
IsBusy = _state.Status != ParserState.Pending && _state.Status <= ParserState.ResolvedDeclarations;
63-
64-
var userDeclarations = _state.DeclarationFinder.AllUserDeclarations
65-
.GroupBy(declaration => declaration.ProjectId)
66-
.ToList();
67-
68-
var newProjects = userDeclarations
69-
.Where(grouping => grouping.Any(declaration => declaration.DeclarationType == DeclarationType.Project))
70-
.Select(grouping =>
71-
new CodeExplorerProjectViewModel(_folderHelper,
72-
grouping.SingleOrDefault(declaration => declaration.DeclarationType == DeclarationType.Project),
73-
grouping,
74-
_vbe)).ToList();
75-
76-
UpdateNodes(Projects, newProjects);
77-
78-
Projects = new ObservableCollection<CodeExplorerItemViewModel>(newProjects);
79-
80-
IsBusy = false;
8161
}
8262

83-
private void UpdateNodes(IEnumerable<CodeExplorerItemViewModel> oldList, IEnumerable<CodeExplorerItemViewModel> newList)
63+
private void Synchronize(IEnumerable<Declaration> declarations)
8464
{
85-
foreach (var item in newList)
86-
{
87-
CodeExplorerItemViewModel oldItem;
65+
var metricResults = _analyst.GetMetrics(_state);
66+
_resultsByDeclaration = metricResults.GroupBy(r => r.Declaration).ToDictionary(g => g.Key, g => g.ToList());
8867

89-
if (item is CodeExplorerCustomFolderViewModel)
90-
{
91-
oldItem = oldList.FirstOrDefault(i => i.Name == item.Name);
92-
}
93-
else
94-
{
95-
oldItem = oldList.FirstOrDefault(i =>
96-
item.QualifiedSelection != null && i.QualifiedSelection != null &&
97-
i.QualifiedSelection.Value.QualifiedName.ProjectId ==
98-
item.QualifiedSelection.Value.QualifiedName.ProjectId &&
99-
i.QualifiedSelection.Value.QualifiedName.ComponentName ==
100-
item.QualifiedSelection.Value.QualifiedName.ComponentName &&
101-
i.QualifiedSelection.Value.Selection == item.QualifiedSelection.Value.Selection);
102-
}
68+
_uiDispatcher.Invoke(() =>
69+
{
70+
var updates = declarations.ToList();
71+
var existing = Projects.OfType<CodeExplorerProjectViewModel>().ToList();
10372

104-
if (oldItem != null)
73+
foreach (var project in existing)
10574
{
106-
item.IsExpanded = oldItem.IsExpanded;
107-
item.IsSelected = oldItem.IsSelected;
108-
109-
if (oldItem.Items.Any() && item.Items.Any())
75+
project.Synchronize(ref updates);
76+
if (project.Declaration is null)
11077
{
111-
UpdateNodes(oldItem.Items, item.Items);
78+
Projects.Remove(project);
11279
}
11380
}
114-
}
115-
}
116-
117-
public void Dispose()
118-
{
119-
Dispose(true);
120-
GC.SuppressFinalize(this);
121-
}
12281

123-
private bool _isDisposed;
124-
protected virtual void Dispose(bool disposing)
125-
{
126-
if (_isDisposed || !disposing)
127-
{
128-
return;
129-
}
130-
_isDisposed = true;
82+
var adding = updates.OfType<ProjectDeclaration>().ToList();
13183

132-
_state.StateChanged -= OnStateChanged;
84+
foreach (var project in adding)
85+
{
86+
var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe, false);
87+
Projects.Add(model);
88+
}
89+
});
13390
}
13491

135-
private Dictionary<Declaration, List<ICodeMetricResult>> resultsByDeclaration;
136-
137-
private CodeExplorerItemViewModel _selectedItem;
138-
public CodeExplorerItemViewModel SelectedItem
92+
private ICodeExplorerNode _selectedItem;
93+
public ICodeExplorerNode SelectedItem
13994
{
14095
get => _selectedItem;
14196
set
@@ -150,27 +105,15 @@ public CodeExplorerItemViewModel SelectedItem
150105
}
151106
}
152107

153-
private ObservableCollection<CodeExplorerItemViewModel> _projects;
154-
public ObservableCollection<CodeExplorerItemViewModel> Projects
155-
{
156-
get => _projects;
157-
set
158-
{
159-
_projects = new ObservableCollection<CodeExplorerItemViewModel>(value.OrderBy(o => o.NameWithSignature));
108+
public ObservableCollection<ICodeExplorerNode> Projects { get; } = new ObservableCollection<ICodeExplorerNode>();
160109

161-
OnPropertyChanged();
162-
OnPropertyChanged(nameof(TreeViewVisibility));
163-
}
164-
}
165-
166-
public Visibility TreeViewVisibility => Projects == null || Projects.Count == 0 ? Visibility.Collapsed : Visibility.Visible;
167-
110+
private Dictionary<Declaration, List<ICodeMetricResult>> _resultsByDeclaration;
168111
public ObservableCollection<ICodeMetricResult> Metrics
169112
{
170113
get
171114
{
172-
var results = resultsByDeclaration?.FirstOrDefault(f => f.Key == SelectedItem.GetSelectedDeclaration());
173-
return !results.HasValue || results.Value.Value == null ? new ObservableCollection<ICodeMetricResult>() : new ObservableCollection<ICodeMetricResult>(results.Value.Value);
115+
var results = _resultsByDeclaration?.FirstOrDefault(f => ReferenceEquals(f.Key, SelectedItem.Declaration));
116+
return results?.Value == null ? new ObservableCollection<ICodeMetricResult>() : new ObservableCollection<ICodeMetricResult>(results.Value.Value);
174117
}
175118
}
176119

@@ -181,23 +124,27 @@ public bool IsBusy
181124
set
182125
{
183126
_isBusy = value;
184-
EmptyUIRefreshMessageVisibility = false;
185127
OnPropertyChanged();
186128
}
187129
}
188130

189-
private bool _emptyUIRefreshMessageVisibility = true;
190-
public bool EmptyUIRefreshMessageVisibility
131+
public void Dispose()
191132
{
192-
get => _emptyUIRefreshMessageVisibility;
193-
set
133+
Dispose(true);
134+
GC.SuppressFinalize(this);
135+
}
136+
137+
private bool _isDisposed;
138+
139+
private void Dispose(bool disposing)
140+
{
141+
if (_isDisposed || !disposing)
194142
{
195-
if (_emptyUIRefreshMessageVisibility != value)
196-
{
197-
_emptyUIRefreshMessageVisibility = value;
198-
OnPropertyChanged();
199-
}
143+
return;
200144
}
145+
_isDisposed = true;
146+
147+
_state.StateChanged -= OnStateChanged;
201148
}
202149
}
203150
}

0 commit comments

Comments
 (0)