Skip to content

Commit 29d3890

Browse files
committed
Merge remote-tracking branch 'upstream/next' into rkapka-master
2 parents 89212c4 + b817344 commit 29d3890

38 files changed

+742
-290
lines changed

RetailCoder.VBE/AppMenu.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Threading;
5+
using NLog;
46
using Rubberduck.Parsing;
57
using Rubberduck.Parsing.VBA;
68
using Rubberduck.UI;
@@ -17,6 +19,8 @@ public class AppMenu : IAppMenu, IDisposable
1719
private readonly ISelectionChangeService _selectionService;
1820
private readonly RubberduckCommandBar _stateBar;
1921

22+
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
23+
2024
public AppMenu(IEnumerable<IParentMenuItem> menus, IParseCoordinator parser, ISelectionChangeService selectionService, RubberduckCommandBar stateBar)
2125
{
2226
_menus = menus.ToList();
@@ -77,7 +81,13 @@ private void RemoveMenus()
7781
{
7882
foreach (var menu in _menus.Where(menu => menu.Item != null))
7983
{
84+
_logger.Debug($"Starting removal of top-level menu {menu.GetType()}.");
8085
menu.RemoveMenu();
86+
//We do this here and not in the menu items because we only want to dispose of/release the parents of the top level parent menus.
87+
//The parents further down get disposed of/released as part of the remove chain.
88+
_logger.Trace($"Removing parent menu of top-level menu {menu.GetType()}.");
89+
menu.Parent.Dispose();
90+
menu.Parent = null;
8191
}
8292
}
8393
}

RetailCoder.VBE/Common/RubberduckHooks.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ public override int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr
147147
break;
148148
case WM.CLOSE:
149149
case WM.DESTROY:
150-
case WM.RUBBERDUCK_SINKING:
151150
Detach();
152151
break;
153152
}
@@ -172,5 +171,14 @@ private bool HandleHotkeyMessage(IntPtr wParam)
172171
}
173172
return processed;
174173
}
174+
175+
protected override void Dispose(bool disposing)
176+
{
177+
if (disposing)
178+
{
179+
Detach();
180+
}
181+
base.Dispose(disposing);
182+
}
175183
}
176184
}

RetailCoder.VBE/Extension.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
using Rubberduck.SettingsProvider;
1919
using Rubberduck.VBEditor.Events;
2020
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
21-
using Rubberduck.VBEditor.WindowsApi;
22-
using User32 = Rubberduck.Common.WinAPI.User32;
2321
using Windows = Rubberduck.VBEditor.SafeComWrappers.VBA.Windows;
2422

2523
namespace Rubberduck
@@ -75,6 +73,7 @@ public void OnConnection(object Application, ext_ConnectMode ConnectMode, object
7573
// normal execution path - don't initialize just yet, wait for OnStartupComplete to be called by the host.
7674
break;
7775
case ext_ConnectMode.ext_cm_AfterStartup:
76+
_isBeginShutdownExecuted = false; //When we reconnect after having been unloaded, the variable might no longer have its initial value.
7877
InitializeAddIn();
7978
break;
8079
}
@@ -245,9 +244,6 @@ private void ShutdownAddIn()
245244
_logger.Log(LogLevel.Trace, "Unhooking VBENativeServices events...");
246245
VBENativeServices.UnhookEvents();
247246

248-
_logger.Log(LogLevel.Trace, "Broadcasting shutdown...");
249-
User32.EnumChildWindows(_ide.MainWindow.Handle(), EnumCallback, new IntPtr(0));
250-
251247
_logger.Log(LogLevel.Trace, "Releasing dockable hosts...");
252248
Windows.ReleaseDockableHosts();
253249

@@ -265,6 +261,20 @@ private void ShutdownAddIn()
265261
_container = null;
266262
}
267263

264+
if (_addin != null)
265+
{
266+
_logger.Log(LogLevel.Trace, "Disposing AddIn wrapper...");
267+
_addin.Dispose();
268+
_addin = null;
269+
}
270+
271+
if (_ide != null)
272+
{
273+
_logger.Log(LogLevel.Trace, "Disposing VBE wrapper...");
274+
_ide.Dispose();
275+
_ide = null;
276+
}
277+
268278
_isInitialized = false;
269279
_logger.Log(LogLevel.Info, "No exceptions were thrown.");
270280
}
@@ -287,11 +297,5 @@ private void ShutdownAddIn()
287297
_isInitialized = false;
288298
}
289299
}
290-
291-
private static int EnumCallback(IntPtr hwnd, IntPtr lparam)
292-
{
293-
User32.SendMessage(hwnd, WM.RUBBERDUCK_SINKING, IntPtr.Zero, IntPtr.Zero);
294-
return 1;
295-
}
296300
}
297301
}

RetailCoder.VBE/Navigation/RegexSearchReplace/RegexSearchReplace.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,27 @@ private List<RegexSearchResult> SearchCurrentProject(string searchPattern)
167167
private List<RegexSearchResult> SearchOpenProjects(string searchPattern)
168168
{
169169
var results = new List<RegexSearchResult>();
170-
var projects = _vbe.VBProjects;
170+
using (var projects = _vbe.VBProjects)
171171
{
172-
var modules = projects
173-
.Where(project => project.Protection == ProjectProtection.Unprotected)
174-
.SelectMany(project => project.VBComponents)
175-
.Select(component => component.CodeModule);
176-
177-
foreach (var module in modules)
172+
foreach (var project in projects)
178173
{
179-
results.AddRange(GetResultsFromModule(module, searchPattern));
174+
if (project.Protection == ProjectProtection.Locked)
175+
{
176+
project.Dispose();
177+
continue;
178+
}
179+
using (var components = project.VBComponents)
180+
{
181+
foreach (var component in components)
182+
{
183+
using (var codeModule = component.CodeModule)
184+
{
185+
results.AddRange(GetResultsFromModule(codeModule, searchPattern));
186+
}
187+
component.Dispose();
188+
}
189+
}
190+
project.Dispose();
180191
}
181192

182193
return results;

RetailCoder.VBE/Refactorings/Rename/RenameRefactoring.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,15 +451,31 @@ private void RenameModule()
451451
private void RenameProject()
452452
{
453453
RequestParseAfterRename = false;
454-
var projects = _model.VBE.VBProjects;
455-
var project = projects.SingleOrDefault(p => p.ProjectId == _model.Target.ProjectId);
454+
var project = ProjectById(_vbe, _model.Target.ProjectId);
456455

457456
if (project != null)
458457
{
459458
project.Name = _model.NewName;
459+
project.Dispose();
460460
}
461461
}
462462

463+
private IVBProject ProjectById(IVBE vbe, string projectId)
464+
{
465+
using (var projects = vbe.VBProjects)
466+
{
467+
foreach (var project in projects)
468+
{
469+
if (project.ProjectId == projectId)
470+
{
471+
return project;
472+
}
473+
project.Dispose();
474+
}
475+
}
476+
return null;
477+
}
478+
463479
private void RenameDefinedFormatMembers(IEnumerable<Declaration> members, string underscoreFormat)
464480
{
465481
if (!members.Any()) { return; }

RetailCoder.VBE/Root/RubberduckIoCInstaller.cs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,7 @@ private static void RegisterParseTreeInspections(IWindsorContainer container, As
260260
private void RegisterRubberduckMenu(IWindsorContainer container)
261261
{
262262
const int windowMenuId = 30009;
263-
var commandBars = _vbe.CommandBars;
264-
var menuBar = commandBars[MenuBar];
265-
var controls = menuBar.Controls;
263+
var controls = MainCommandBarControls(MenuBar);
266264
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, windowMenuId);
267265
var menuItemTypes = RubberduckMenuItems();
268266
RegisterMenu<RubberduckParentMenu>(container, controls, beforeIndex, menuItemTypes);
@@ -299,24 +297,36 @@ private static int FindRubberduckMenuInsertionIndex(ICommandBarControls controls
299297
{
300298
for (var i = 1; i <= controls.Count; i++)
301299
{
302-
var item = controls[i];
303-
if (item.IsBuiltIn && item.Id == beforeId)
300+
using (var item = controls[i])
304301
{
305-
return i;
302+
if (item.IsBuiltIn && item.Id == beforeId)
303+
{
304+
return i;
305+
}
306306
}
307307
}
308308

309309
return controls.Count;
310310
}
311311

312+
private ICommandBarControls MainCommandBarControls(int commandBarIndex)
313+
{
314+
ICommandBarControls controls;
315+
using (var commandBars = _vbe.CommandBars)
316+
{
317+
using (var menuBar = commandBars[commandBarIndex])
318+
{
319+
controls = menuBar.Controls;
320+
}
321+
}
322+
return controls;
323+
}
324+
312325
private void RegisterCodePaneContextMenu(IWindsorContainer container)
313326
{
314327
const int listMembersMenuId = 2529;
315-
var commandBars = _vbe.CommandBars;
316-
var menuBar = commandBars[CodeWindow];
317-
var controls = menuBar.Controls;
318-
var beforeControl = controls.FirstOrDefault(control => control.Id == listMembersMenuId);
319-
var beforeIndex = beforeControl == null ? 1 : beforeControl.Index;
328+
var controls = MainCommandBarControls(CodeWindow);
329+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, listMembersMenuId);
320330
var menuItemTypes = CodePaneContextMenuItems();
321331
RegisterMenu<CodePaneContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
322332
}
@@ -336,11 +346,8 @@ private static Type[] CodePaneContextMenuItems()
336346
private void RegisterFormDesignerContextMenu(IWindsorContainer container)
337347
{
338348
const int viewCodeMenuId = 2558;
339-
var commandBars = _vbe.CommandBars;
340-
var menuBar = commandBars[MsForms];
341-
var controls = menuBar.Controls;
342-
var beforeControl = controls.FirstOrDefault(control => control.Id == viewCodeMenuId);
343-
var beforeIndex = beforeControl?.Index ?? 1;
349+
var controls = MainCommandBarControls(MsForms);
350+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, viewCodeMenuId);
344351
var menuItemTypes = FormDesignerContextMenuItems();
345352
RegisterMenu<FormDesignerContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
346353
}
@@ -357,23 +364,17 @@ private static Type[] FormDesignerContextMenuItems()
357364
private void RegisterFormDesignerControlContextMenu(IWindsorContainer container)
358365
{
359366
const int viewCodeMenuId = 2558;
360-
var commandBars = _vbe.CommandBars;
361-
var menuBar = commandBars[MsFormsControl];
362-
var controls = menuBar.Controls;
363-
var beforeControl = controls.FirstOrDefault(control => control.Id == viewCodeMenuId);
364-
var beforeIndex = beforeControl?.Index ?? 1;
367+
var controls = MainCommandBarControls(MsFormsControl);
368+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, viewCodeMenuId);
365369
var menuItemTypes = FormDesignerContextMenuItems();
366370
RegisterMenu<FormDesignerControlContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
367371
}
368372

369373
private void RegisterProjectExplorerContextMenu(IWindsorContainer container)
370374
{
371375
const int projectPropertiesMenuId = 2578;
372-
var commandBars = _vbe.CommandBars;
373-
var menuBar = commandBars[ProjectWindow];
374-
var controls = menuBar.Controls;
375-
var beforeControl = controls.FirstOrDefault(control => control.Id == projectPropertiesMenuId);
376-
var beforeIndex = beforeControl?.Index ?? 1;
376+
var controls = MainCommandBarControls(ProjectWindow);
377+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, projectPropertiesMenuId);
377378
var menuItemTypes = ProjectWindowContextMenuItems();
378379
RegisterMenu<ProjectWindowContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
379380
}

RetailCoder.VBE/UI/CodeExplorer/Commands/AddComponentCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public bool CanAddComponent(CodeExplorerItemViewModel parameter)
2020
{
2121
try
2222
{
23-
return GetDeclaration(parameter) != null || _vbe.VBProjects.Count == 1;
23+
return GetDeclaration(parameter) != null || _vbe.ProjectsCount == 1;
2424
}
2525
catch (COMException)
2626
{

RetailCoder.VBE/UI/CodeExplorer/Commands/AddTestModuleCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ protected override bool EvaluateCanExecute(object parameter)
2323
{
2424
try
2525
{
26-
return GetDeclaration(parameter) != null || _vbe.VBProjects.Count == 1;
26+
return GetDeclaration(parameter) != null || _vbe.ProjectsCount == 1;
2727
}
2828
catch (COMException)
2929
{

RetailCoder.VBE/UI/CodeExplorer/Commands/ImportCommand.cs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,39 +31,70 @@ public ImportCommand(IVBE vbe, IOpenFileDialog openFileDialog) : base(LogManager
3131

3232
protected override bool EvaluateCanExecute(object parameter)
3333
{
34-
return parameter != null || _vbe.VBProjects.Count == 1 || _vbe.ActiveVBProject != null;
34+
return parameter != null || _vbe.ProjectsCount == 1 || ThereIsAValidActiveProject();
35+
}
36+
37+
private bool ThereIsAValidActiveProject()
38+
{
39+
using (var activeProject = _vbe.ActiveVBProject)
40+
{
41+
return activeProject != null;
42+
}
3543
}
3644

3745
protected override void OnExecute(object parameter)
3846
{
39-
var project = GetNodeProject(parameter as CodeExplorerItemViewModel) ?? _vbe.ActiveVBProject;
47+
var usingFreshProjectWrapper = false;
48+
49+
var project = GetNodeProject(parameter as CodeExplorerItemViewModel);
4050

4151
if (project == null)
4252
{
43-
if (_vbe.VBProjects.Count == 1)
53+
if (_vbe.ProjectsCount == 1)
4454
{
45-
project = _vbe.VBProjects[1];
55+
usingFreshProjectWrapper = true;
56+
using (var projects = _vbe.VBProjects)
57+
{
58+
project = projects[1];
59+
}
4660
}
47-
else if (_vbe.ActiveVBProject != null)
61+
else if (ThereIsAValidActiveProject())
4862
{
63+
usingFreshProjectWrapper = true;
4964
project = _vbe.ActiveVBProject;
5065
}
5166
}
5267

5368
if (project == null || _openFileDialog.ShowDialog() != DialogResult.OK)
5469
{
70+
if (usingFreshProjectWrapper)
71+
{
72+
project?.Dispose();
73+
}
5574
return;
5675
}
5776

5877
var fileExts = _openFileDialog.FileNames.Select(s => s.Split('.').Last());
5978
if (fileExts.Any(fileExt => !new[] {"bas", "cls", "frm"}.Contains(fileExt)))
6079
{
80+
if (usingFreshProjectWrapper)
81+
{
82+
project.Dispose();
83+
}
6184
return;
6285
}
6386

6487
foreach (var filename in _openFileDialog.FileNames)
6588
{
66-
project.VBComponents.Import(filename);
89+
using (var components = project.VBComponents)
90+
{
91+
components.Import(filename);
92+
}
93+
}
94+
95+
if (usingFreshProjectWrapper)
96+
{
97+
project.Dispose();
6798
}
6899
}
69100

0 commit comments

Comments
 (0)