Skip to content

Commit 26e2222

Browse files
authored
Fix type resolution for MSForms controls (#3324)
* Improved startup & shutdown logging and exception handling * Tweaked AnnotationPass to resolve MSForms controls as such; fixes #2982.
1 parent 7b5899b commit 26e2222

File tree

8 files changed

+103
-68
lines changed

8 files changed

+103
-68
lines changed

RetailCoder.VBE/Common/Hotkeys/HotkeyInfo.cs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,35 @@ public struct HotkeyInfo
99
{
1010
private const Keys Modifiers = Keys.Alt | Keys.Control | Keys.Shift;
1111

12-
private readonly IntPtr _hookId;
13-
private readonly Keys _keys;
14-
1512
public HotkeyInfo(IntPtr hookId, Keys keys)
1613
{
17-
_hookId = hookId;
18-
_keys = keys;
14+
HookId = hookId;
15+
Keys = keys;
1916
}
2017

21-
public IntPtr HookId { get { return _hookId; } }
22-
public Keys Keys { get { return _keys; } }
18+
public IntPtr HookId { get; }
19+
public Keys Keys { get; }
2320

2421
public override string ToString()
2522
{
2623
var builder = new StringBuilder();
27-
if (_keys.HasFlag(Keys.Alt))
24+
if (Keys.HasFlag(Keys.Alt))
2825
{
2926
builder.Append(RubberduckUI.GeneralSettings_HotkeyAlt);
3027
builder.Append('+');
3128
}
32-
if (_keys.HasFlag(Keys.Control))
29+
if (Keys.HasFlag(Keys.Control))
3330
{
3431
builder.Append(RubberduckUI.GeneralSettings_HotkeyCtrl);
3532
builder.Append('+');
3633
}
37-
if (_keys.HasFlag(Keys.Shift))
34+
if (Keys.HasFlag(Keys.Shift))
3835
{
3936
builder.Append(RubberduckUI.GeneralSettings_HotkeyShift);
4037
builder.Append('+');
4138
}
4239

43-
builder.Append(HotkeyDisplayConverter.Convert(_keys & ~Modifiers));
40+
builder.Append(HotkeyDisplayConverter.Convert(Keys & ~Modifiers));
4441
return builder.ToString();
4542
}
4643
}

RetailCoder.VBE/Extension.cs

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
using Rubberduck.Settings;
2020
using Rubberduck.SettingsProvider;
2121
using Rubberduck.VBEditor.Events;
22-
using Rubberduck.VBEditor.SafeComWrappers;
2322
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
2423
using Rubberduck.VBEditor.WindowsApi;
2524
using User32 = Rubberduck.Common.WinAPI.User32;
25+
using Windows = Rubberduck.VBEditor.SafeComWrappers.VBA.Windows;
2626

2727
namespace Rubberduck
2828
{
@@ -204,56 +204,83 @@ private void InitializeAddIn()
204204

205205
private void Startup()
206206
{
207-
var currentDomain = AppDomain.CurrentDomain;
208-
currentDomain.AssemblyResolve += LoadFromSameFolder;
207+
try
208+
{
209+
var currentDomain = AppDomain.CurrentDomain;
210+
currentDomain.UnhandledException += HandlAppDomainException;
211+
currentDomain.AssemblyResolve += LoadFromSameFolder;
212+
213+
_kernel = new StandardKernel(new NinjectSettings {LoadExtensions = true}, new FuncModule(), new DynamicProxyModule());
214+
_kernel.Load(new RubberduckModule(_ide, _addin));
209215

210-
_kernel = new StandardKernel(new NinjectSettings {LoadExtensions = true}, new FuncModule(), new DynamicProxyModule());
211-
_kernel.Load(new RubberduckModule(_ide, _addin));
216+
_app = _kernel.Get<App>();
217+
_app.Startup();
212218

213-
_app = _kernel.Get<App>();
214-
_app.Startup();
219+
_isInitialized = true;
220+
221+
}
222+
catch (Exception e)
223+
{
224+
_logger.Log(LogLevel.Fatal, e, "Startup sequence threw an unexpected exception.");
225+
//throw; // <<~ uncomment to crash the process
226+
}
227+
}
215228

216-
_isInitialized = true;
229+
private void HandlAppDomainException(object sender, UnhandledExceptionEventArgs e)
230+
{
231+
_logger.Log(LogLevel.Fatal, e);
217232
}
218233

219234
private void ShutdownAddIn()
220235
{
221-
Debug.WriteLine("Extension unhooking VBENativeServices events.");
222-
VBENativeServices.UnhookEvents();
223-
224236
var currentDomain = AppDomain.CurrentDomain;
225-
currentDomain.AssemblyResolve -= LoadFromSameFolder;
226-
Debug.WriteLine("Extension broadcasting shutdown.");
227-
User32.EnumChildWindows(_ide.MainWindow.Handle(), EnumCallback, new IntPtr(0));
228-
229-
Debug.WriteLine("Extension calling ReleaseDockableHosts.");
230-
VBEditor.SafeComWrappers.VBA.Windows.ReleaseDockableHosts();
231-
232-
if (_app != null)
233-
{
234-
Debug.WriteLine("Extension calling App.Shutdown.");
235-
_app.Shutdown();
236-
_app = null;
237-
}
238-
239-
if (_kernel != null)
237+
try
240238
{
241-
Debug.WriteLine("Extension calling Kernel.Dispose.");
242-
_kernel.Dispose();
243-
_kernel = null;
244-
}
245-
246-
Debug.WriteLine("Extension: Initiating garbage collection.");
239+
_logger.Log(LogLevel.Info, "Rubberduck is shutting down.");
240+
_logger.Log(LogLevel.Trace, "Unhooking VBENativeServices events...");
241+
VBENativeServices.UnhookEvents();
247242

248-
GC.Collect();
243+
_logger.Log(LogLevel.Trace, "Broadcasting shutdown...");
244+
User32.EnumChildWindows(_ide.MainWindow.Handle(), EnumCallback, new IntPtr(0));
249245

250-
Debug.WriteLine("Extension: Initiated garbage collection.");
246+
_logger.Log(LogLevel.Trace, "Releasing dockable hosts...");
247+
Windows.ReleaseDockableHosts();
251248

252-
GC.WaitForPendingFinalizers();
249+
if (_app != null)
250+
{
251+
_logger.Log(LogLevel.Trace, "Initiating App.Shutdown...");
252+
_app.Shutdown();
253+
_app = null;
254+
}
253255

254-
Debug.WriteLine("Extension: Finalizers have run.");
256+
if (_kernel != null)
257+
{
258+
_logger.Log(LogLevel.Trace, "Disposing IoC container...");
259+
_kernel.Dispose();
260+
_kernel = null;
261+
}
255262

256-
_isInitialized = false;
263+
_isInitialized = false;
264+
_logger.Log(LogLevel.Info, "No exceptions were thrown.");
265+
}
266+
catch (Exception e)
267+
{
268+
_logger.Error(e);
269+
_logger.Log(LogLevel.Warn, "Exception is swallowed.");
270+
//throw; // <<~ uncomment to crash the process
271+
}
272+
finally
273+
{
274+
_logger.Log(LogLevel.Trace, "Unregistering AppDomain handlers....");
275+
currentDomain.AssemblyResolve -= LoadFromSameFolder;
276+
currentDomain.UnhandledException -= HandlAppDomainException;
277+
_logger.Log(LogLevel.Trace, "Done. Initiating garbage collection...");
278+
GC.Collect();
279+
_logger.Log(LogLevel.Trace, "Done. Waiting for pending finalizers...");
280+
GC.WaitForPendingFinalizers();
281+
_logger.Log(LogLevel.Trace, "Done. Shutdown completed. Quack!");
282+
_isInitialized = false;
283+
}
257284
}
258285

259286
private static int EnumCallback(IntPtr hwnd, IntPtr lparam)

RetailCoder.VBE/UI/Command/IndentCurrentModuleCommand.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ public IndentCurrentModuleCommand(IVBE vbe, IIndenter indenter, RubberduckParser
2121
_state = state;
2222
}
2323

24-
public override RubberduckHotkey Hotkey
25-
{
26-
get { return RubberduckHotkey.IndentModule; }
27-
}
24+
public override RubberduckHotkey Hotkey => RubberduckHotkey.IndentModule;
2825

2926
protected override bool EvaluateCanExecute(object parameter)
3027
{
@@ -34,7 +31,10 @@ protected override bool EvaluateCanExecute(object parameter)
3431
protected override void OnExecute(object parameter)
3532
{
3633
_indenter.IndentCurrentModule();
37-
_state.OnParseRequested(this, _vbe.ActiveCodePane.CodeModule.Parent);
34+
if (_state.Status >= ParserState.Ready || _state.Status == ParserState.Pending)
35+
{
36+
_state.OnParseRequested(this, _vbe.ActiveCodePane.CodeModule.Parent);
37+
}
3838
}
3939
}
4040
}

RetailCoder.VBE/UI/Command/IndentCurrentProcedureCommand.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ public IndentCurrentProcedureCommand(IVBE vbe, IIndenter indenter, RubberduckPar
2222
_state = state;
2323
}
2424

25-
public override RubberduckHotkey Hotkey
26-
{
27-
get { return RubberduckHotkey.IndentProcedure; }
28-
}
25+
public override RubberduckHotkey Hotkey => RubberduckHotkey.IndentProcedure;
2926

3027
protected override bool EvaluateCanExecute(object parameter)
3128
{
@@ -35,7 +32,10 @@ protected override bool EvaluateCanExecute(object parameter)
3532
protected override void OnExecute(object parameter)
3633
{
3734
_indenter.IndentCurrentProcedure();
38-
_state.OnParseRequested(this, _vbe.ActiveCodePane.CodeModule.Parent);
35+
if (_state.Status >= ParserState.Ready || _state.Status == ParserState.Pending)
36+
{
37+
_state.OnParseRequested(this, _vbe.ActiveCodePane.CodeModule.Parent);
38+
}
3939
}
4040
}
4141
}

RetailCoder.VBE/UI/Command/IndentCurrentProjectCommand.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Runtime.InteropServices;
5-
using System.Text;
6-
using System.Threading.Tasks;
1+
using System.Runtime.InteropServices;
72
using NLog;
83
using Rubberduck.Parsing.VBA;
9-
using Rubberduck.Settings;
104
using Rubberduck.SmartIndenter;
115
using Rubberduck.VBEditor.SafeComWrappers;
126
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
@@ -35,7 +29,10 @@ protected override bool EvaluateCanExecute(object parameter)
3529
protected override void OnExecute(object parameter)
3630
{
3731
_indenter.IndentCurrentProject();
38-
_state.OnParseRequested(this);
32+
if (_state.Status >= ParserState.Ready || _state.Status == ParserState.Pending)
33+
{
34+
_state.OnParseRequested(this);
35+
}
3936
}
4037
}
4138
}

Rubberduck.Parsing/Symbols/Declaration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ public string AsTypeNameWithoutArrayDesignator
445445
private Declaration _asTypeDeclaration;
446446
public Declaration AsTypeDeclaration
447447
{
448-
get { return _asTypeDeclaration; }
448+
get => _asTypeDeclaration;
449449
internal set
450450
{
451451
_asTypeDeclaration = value;

Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace Rubberduck.Parsing.Symbols
1515
{
1616
public class DeclarationSymbolsListener : VBAParserBaseListener
1717
{
18+
private readonly RubberduckParserState _state;
1819
private readonly QualifiedModuleName _qualifiedModuleName;
1920
private readonly Declaration _moduleDeclaration;
2021

@@ -26,7 +27,7 @@ public class DeclarationSymbolsListener : VBAParserBaseListener
2627
private readonly IDictionary<Tuple<string, DeclarationType>, Attributes> _attributes;
2728

2829
private readonly List<Declaration> _createdDeclarations = new List<Declaration>();
29-
public IReadOnlyList<Declaration> CreatedDeclarations { get { return _createdDeclarations; } }
30+
public IReadOnlyList<Declaration> CreatedDeclarations => _createdDeclarations;
3031

3132
public DeclarationSymbolsListener(
3233
RubberduckParserState state,
@@ -36,6 +37,7 @@ public DeclarationSymbolsListener(
3637
Attributes> attributes,
3738
Declaration projectDeclaration)
3839
{
40+
_state = state;
3941
_qualifiedModuleName = qualifiedModuleName;
4042
_annotations = annotations;
4143
_attributes = attributes;
@@ -131,6 +133,7 @@ private IEnumerable<IAnnotation> FindAnnotations(int line)
131133
private void DeclareControlsAsMembers(IVBComponent form)
132134
{
133135
if (form.Controls == null) { return; }
136+
var msFormsLib = _state.DeclarationFinder.FindProject("MSForms");
134137

135138
foreach (var control in form.Controls)
136139
{
@@ -151,6 +154,12 @@ private void DeclareControlsAsMembers(IVBComponent form)
151154
false,
152155
null,
153156
true);
157+
158+
if (msFormsLib != null)
159+
{
160+
declaration.AsTypeDeclaration = _state.DeclarationFinder.FindClassModule(typeName, msFormsLib, true);
161+
}
162+
154163
AddDeclaration(declaration);
155164
}
156165
}

Rubberduck.Parsing/Symbols/TypeAnnotationPass.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public void Execute(IReadOnlyCollection<QualifiedModuleName> modules)
4545

4646
private void AnnotateType(Declaration declaration)
4747
{
48+
if (declaration.AsTypeDeclaration != null)
49+
{
50+
return;
51+
}
52+
4853
if (declaration.DeclarationType == DeclarationType.ClassModule ||
4954
declaration.DeclarationType == DeclarationType.UserDefinedType ||
5055
declaration.DeclarationType == DeclarationType.ComAlias)

0 commit comments

Comments
 (0)