Skip to content

Commit 3da8162

Browse files
authored
Merge pull request #3402 from mansellan/3260
Introduces "Find all References" command in UserForm designer context menu, to locate in-code references to UserForm controls.
2 parents f405462 + e3daa3b commit 3da8162

File tree

8 files changed

+362
-24
lines changed

8 files changed

+362
-24
lines changed

RetailCoder.VBE/Root/RubberduckModule.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,8 @@ private IEnumerable<IMenuItem> GetFormDesignerContextMenuItems()
613613
{
614614
return new IMenuItem[]
615615
{
616-
KernelInstance.Get<FormDesignerRefactorRenameCommandMenuItem>()
616+
KernelInstance.Get<FormDesignerRefactorRenameCommandMenuItem>(),
617+
KernelInstance.Get<FormDesignerFindAllReferencesCommandMenuItem>()
617618
};
618619
}
619620

RetailCoder.VBE/Rubberduck.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,10 @@
423423
<Compile Include="UI\CodeExplorer\Commands\AddStdModuleCommand.cs" />
424424
<Compile Include="UI\CodeExplorer\Commands\AddTestModuleCommand.cs" />
425425
<Compile Include="UI\CodeExplorer\Commands\AddComponentCommand.cs" />
426+
<Compile Include="UI\Command\FormDesignerFindAllReferencesCommand.cs" />
426427
<Compile Include="UI\Command\IndentCurrentProjectCommand.cs" />
427428
<Compile Include="UI\Command\MenuItems\CommandBars\ContextDescriptionLabelMenuItem.cs" />
429+
<Compile Include="UI\Command\MenuItems\FormDesignerFindAllReferencesCommandMenuItem.cs" />
428430
<Compile Include="UI\Command\MenuItems\IndentCurrentProjectCommandMenuItem.cs" />
429431
<Compile Include="UI\Command\MenuItems\ExportAllCommandMenuItem.cs" />
430432
<Compile Include="UI\Controls\EmptyUIRefresh.xaml.cs">

RetailCoder.VBE/UI/Command/FindAllReferencesCommand.cs

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Rubberduck.Parsing.VBA;
88
using Rubberduck.UI.Command.MenuItems;
99
using Rubberduck.UI.Controls;
10+
using Rubberduck.VBEditor;
1011
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
1112

1213
namespace Rubberduck.UI.Command
@@ -41,12 +42,12 @@ public FindAllReferencesCommand(INavigateCommand navigateCommand, IMessageBox me
4142

4243
private Declaration FindNewDeclaration(Declaration declaration)
4344
{
44-
return _state.AllUserDeclarations.SingleOrDefault(item =>
45-
item.ProjectId == declaration.ProjectId &&
46-
item.ComponentName == declaration.ComponentName &&
47-
item.ParentScope == declaration.ParentScope &&
48-
item.IdentifierName == declaration.IdentifierName &&
49-
item.DeclarationType == declaration.DeclarationType);
45+
return _state.DeclarationFinder
46+
.MatchName(declaration.IdentifierName)
47+
.SingleOrDefault(d => d.ProjectId == declaration.ProjectId
48+
&& d.ComponentName == declaration.ComponentName
49+
&& d.ParentScope == declaration.ParentScope
50+
&& d.DeclarationType == declaration.DeclarationType);
5051
}
5152

5253
private void _state_StateChanged(object sender, ParserStateEventArgs e)
@@ -87,7 +88,8 @@ private void UpdateTab()
8788

8889
protected override bool EvaluateCanExecute(object parameter)
8990
{
90-
if (_vbe.ActiveCodePane == null || _state.Status != ParserState.Ready)
91+
if (_state.Status != ParserState.Ready ||
92+
(_vbe.ActiveCodePane == null && !(_vbe.SelectedVBComponent?.HasDesigner ?? false)))
9193
{
9294
return false;
9395
}
@@ -134,7 +136,7 @@ protected override void OnExecute(object parameter)
134136
}
135137
catch (Exception e)
136138
{
137-
Console.WriteLine(e);
139+
Logger.Error(e);
138140
}
139141
}
140142

@@ -154,15 +156,56 @@ private SearchResultsViewModel CreateViewModel(Declaration declaration)
154156

155157
private Declaration FindTarget(object parameter)
156158
{
157-
var declaration = parameter as Declaration;
158-
if (declaration != null)
159+
if (parameter is Declaration declaration)
159160
{
160161
return declaration;
161162
}
162163

164+
return _vbe.ActiveCodePane != null && (_vbe.SelectedVBComponent?.HasDesigner ?? false)
165+
? FindFormDesignerTarget()
166+
: FindCodePaneTarget();
167+
}
168+
169+
private Declaration FindCodePaneTarget()
170+
{
163171
return _state.FindSelectedDeclaration(_vbe.ActiveCodePane);
164172
}
165173

174+
private Declaration FindFormDesignerTarget(QualifiedModuleName? qualifiedModuleName = null)
175+
{
176+
(var projectId, var component) = qualifiedModuleName.HasValue
177+
? (qualifiedModuleName.Value.ProjectId, qualifiedModuleName.Value.Component)
178+
: (_vbe.ActiveVBProject.ProjectId, _vbe.SelectedVBComponent);
179+
180+
if (component?.HasDesigner ?? false)
181+
{
182+
if (qualifiedModuleName.HasValue)
183+
{
184+
return _state.DeclarationFinder
185+
.MatchName(qualifiedModuleName.Value.Name)
186+
.SingleOrDefault(m => m.ProjectId == projectId
187+
&& m.DeclarationType.HasFlag(qualifiedModuleName.Value.ComponentType)
188+
&& m.ComponentName == component.Name);
189+
}
190+
191+
var selectedCount = component.SelectedControls.Count;
192+
if (selectedCount > 1) { return null; }
193+
194+
// Cannot use DeclarationType.UserForm, parser only assigns UserForms the ClassModule flag
195+
(var selectedType, var selectedName) = selectedCount == 0
196+
? (DeclarationType.ClassModule, component.Name)
197+
: (DeclarationType.Control, component.SelectedControls[0].Name);
198+
199+
return _state.DeclarationFinder
200+
.MatchName(selectedName)
201+
.SingleOrDefault(m => m.ProjectId == projectId
202+
&& m.DeclarationType.HasFlag(selectedType)
203+
&& m.ComponentName == component.Name);
204+
}
205+
return null;
206+
}
207+
208+
166209
public void Dispose()
167210
{
168211
if (_state != null)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Runtime.InteropServices;
2+
using NLog;
3+
using Rubberduck.Parsing.VBA;
4+
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
5+
6+
namespace Rubberduck.UI.Command
7+
{
8+
/// <summary>
9+
/// A command that locates all references to the active form designer component.
10+
/// </summary>
11+
[ComVisible(false)]
12+
public class FormDesignerFindAllReferencesCommand : CommandBase
13+
{
14+
private readonly FindAllReferencesCommand _findAllReferences;
15+
16+
public FormDesignerFindAllReferencesCommand(FindAllReferencesCommand findAllReferences)
17+
: base(LogManager.GetCurrentClassLogger())
18+
{
19+
_findAllReferences = findAllReferences;
20+
}
21+
22+
protected override bool EvaluateCanExecute(object parameter)
23+
{
24+
return _findAllReferences.CanExecute(parameter);
25+
}
26+
27+
protected override void OnExecute(object parameter)
28+
{
29+
_findAllReferences.Execute(parameter);
30+
}
31+
}
32+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Rubberduck.Parsing.VBA;
2+
using Rubberduck.UI.Command.MenuItems.ParentMenus;
3+
4+
namespace Rubberduck.UI.Command.MenuItems
5+
{
6+
public class FormDesignerFindAllReferencesCommandMenuItem : CommandMenuItemBase
7+
{
8+
public FormDesignerFindAllReferencesCommandMenuItem(CommandBase command)
9+
: base(command)
10+
{
11+
}
12+
13+
public override bool BeginGroup { get { return true; } }
14+
public override string Key { get { return "ContextMenu_FindAllReferences"; } }
15+
public override int DisplayOrder { get { return (int)NavigationMenuItemDisplayOrder.FindAllReferences; } }
16+
17+
public override bool EvaluateCanExecute(RubberduckParserState state)
18+
{
19+
return state != null && Command.CanExecute(null);
20+
}
21+
}
22+
}

RetailCoder.VBE/UI/SelectionChangeService.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,25 @@ private void DispatchSelectedDesignerDeclaration(IVBComponent component)
109109
return;
110110
}
111111

112-
var selected = component.SelectedControls.Count;
113-
if (selected == 1)
112+
var selectedCount = component.SelectedControls.Count;
113+
if (selectedCount == 1)
114114
{
115-
var name = component.SelectedControls.First().Name;
115+
var name = component.SelectedControls.Single().Name;
116116
var control =
117-
_parser.State.DeclarationFinder.UserDeclarations(DeclarationType.Control).SingleOrDefault(decl =>
118-
decl.IdentifierName.Equals(name) &&
119-
decl.ParentDeclaration.IdentifierName.Equals(component.Name) &&
120-
decl.ProjectId.Equals(component.ParentProject.ProjectId));
117+
_parser.State.DeclarationFinder.MatchName(name)
118+
.SingleOrDefault(d => d.DeclarationType == DeclarationType.Control
119+
&& d.ProjectId == component.ParentProject.ProjectId
120+
&& d.ParentDeclaration.IdentifierName == component.Name);
121121

122122
DispatchSelectedDeclaration(new DeclarationChangedEventArgs(null, control, component));
123123
return;
124124
}
125125
var form =
126-
_parser.State.DeclarationFinder.UserDeclarations(DeclarationType.UserForm).SingleOrDefault(decl =>
127-
decl.IdentifierName.Equals(component.Name) &&
128-
decl.ProjectId.Equals(component.ParentProject.ProjectId));
126+
_parser.State.DeclarationFinder.MatchName(component.Name)
127+
.SingleOrDefault(d => d.DeclarationType.HasFlag(DeclarationType.ClassModule)
128+
&& d.ProjectId == component.ParentProject.ProjectId);
129129

130-
DispatchSelectedDeclaration(new DeclarationChangedEventArgs(null, form, component, selected > 1));
130+
DispatchSelectedDeclaration(new DeclarationChangedEventArgs(null, form, component, selectedCount > 1));
131131
}
132132

133133
private void DispatchSelectedProjectNodeDeclaration(IVBComponent component)
@@ -166,7 +166,7 @@ private void DispatchSelectedProjectNodeDeclaration(IVBComponent component)
166166
private bool DeclarationChanged(Declaration current)
167167
{
168168
if ((_lastSelectedDeclaration == null && current == null) ||
169-
((_lastSelectedDeclaration != null && current != null) && !_lastSelectedDeclaration.Equals(current)))
169+
((_lastSelectedDeclaration != null && current != null) && _lastSelectedDeclaration.Equals(current)))
170170
{
171171
return false;
172172
}

0 commit comments

Comments
 (0)