1
1
using System ;
2
+ using System . Collections . Concurrent ;
3
+ using System . Collections . Generic ;
2
4
using System . Globalization ;
5
+ using System . Linq ;
6
+ using System . Runtime . InteropServices ;
7
+ using System . Threading ;
8
+ using System . Threading . Tasks ;
3
9
using System . Windows . Forms ;
10
+ using Microsoft . Vbe . Interop ;
4
11
using NLog ;
12
+ using Rubberduck . Common ;
5
13
using Rubberduck . Inspections ;
6
14
using Rubberduck . Parsing ;
7
- using Rubberduck . Parsing . VBA ;
8
15
using Rubberduck . Settings ;
9
16
using Rubberduck . UI ;
10
17
using Rubberduck . UI . Command . MenuItems ;
11
18
using Rubberduck . UI . ParserErrors ;
19
+ using Rubberduck . VBEditor . Extensions ;
12
20
13
21
namespace Rubberduck
14
22
{
15
23
public class App : IDisposable
16
24
{
25
+ private readonly VBE _vbe ;
17
26
private readonly IMessageBox _messageBox ;
18
27
private readonly IParserErrorsPresenterFactory _parserErrorsPresenterFactory ;
19
- private readonly IRubberduckParserFactory _parserFactory ;
28
+ private readonly IRubberduckParser _parser ;
20
29
private readonly IInspectorFactory _inspectorFactory ;
21
30
private readonly IGeneralConfigService _configService ;
22
31
private readonly IAppMenu _appMenus ;
32
+ private readonly ParserStateCommandBar _stateBar ;
33
+ private readonly IKeyHook _hook ;
23
34
24
- private IParserErrorsPresenter _parserErrorsPresenter ;
25
35
private readonly Logger _logger ;
26
- private IRubberduckParser _parser ;
27
36
28
37
private Configuration _config ;
29
38
30
- public App ( IMessageBox messageBox ,
39
+ private readonly ConcurrentDictionary < VBComponent , CancellationTokenSource > _tokenSources =
40
+ new ConcurrentDictionary < VBComponent , CancellationTokenSource > ( ) ;
41
+
42
+ public App ( VBE vbe , IMessageBox messageBox ,
31
43
IParserErrorsPresenterFactory parserErrorsPresenterFactory ,
32
- IRubberduckParserFactory parserFactory ,
44
+ IRubberduckParser parser ,
33
45
IInspectorFactory inspectorFactory ,
34
46
IGeneralConfigService configService ,
35
- IAppMenu appMenus )
47
+ IAppMenu appMenus ,
48
+ ParserStateCommandBar stateBar ,
49
+ IKeyHook hook )
36
50
{
51
+ _vbe = vbe ;
37
52
_messageBox = messageBox ;
38
53
_parserErrorsPresenterFactory = parserErrorsPresenterFactory ;
39
- _parserFactory = parserFactory ;
54
+ _parser = parser ;
40
55
_inspectorFactory = inspectorFactory ;
41
56
_configService = configService ;
42
57
_appMenus = appMenus ;
58
+ _stateBar = stateBar ;
59
+ _hook = hook ;
43
60
_logger = LogManager . GetCurrentClassLogger ( ) ;
44
61
62
+ _hook . KeyPressed += _hook_KeyPressed ;
45
63
_configService . SettingsChanged += _configService_SettingsChanged ;
64
+ _parser . State . StateChanged += Parser_StateChanged ;
65
+ _stateBar . Refresh += _stateBar_Refresh ;
66
+ }
67
+
68
+ private void _stateBar_Refresh ( object sender , EventArgs e )
69
+ {
70
+ Task . Run ( ( ) => ParseAll ( ) ) ;
71
+ }
72
+
73
+ private void Parser_StateChanged ( object sender , EventArgs e )
74
+ {
75
+ _appMenus . EvaluateCanExecute ( _parser . State ) ;
76
+ }
77
+
78
+ private async void _hook_KeyPressed ( object sender , KeyHookEventArgs e )
79
+ {
80
+ await ParseComponentAsync ( e . Component ) ;
81
+ }
82
+
83
+ private async Task ParseComponentAsync ( VBComponent component , bool resolve = true )
84
+ {
85
+ var tokenSource = RenewTokenSource ( component ) ;
86
+
87
+ var token = tokenSource . Token ;
88
+ await _parser . ParseAsync ( component , token ) ;
89
+
90
+ if ( resolve && ! token . IsCancellationRequested )
91
+ {
92
+ using ( var source = new CancellationTokenSource ( ) )
93
+ {
94
+ _parser . Resolve ( source . Token ) ;
95
+ }
96
+ }
97
+ }
98
+
99
+ private CancellationTokenSource RenewTokenSource ( VBComponent component )
100
+ {
101
+ if ( _tokenSources . ContainsKey ( component ) )
102
+ {
103
+ CancellationTokenSource existingTokenSource ;
104
+ _tokenSources . TryRemove ( component , out existingTokenSource ) ;
105
+ existingTokenSource . Cancel ( ) ;
106
+ existingTokenSource . Dispose ( ) ;
107
+ }
108
+
109
+ var tokenSource = new CancellationTokenSource ( ) ;
110
+ _tokenSources [ component ] = tokenSource ;
111
+ return tokenSource ;
46
112
}
47
113
48
114
public void Startup ( )
@@ -51,12 +117,35 @@ public void Startup()
51
117
52
118
_appMenus . Initialize ( ) ;
53
119
_appMenus . Localize ( ) ;
120
+
121
+ Task . Delay ( 1000 ) . ContinueWith ( t =>
122
+ {
123
+ _parser . State . AddBuiltInDeclarations ( _vbe . HostApplication ( ) ) ;
124
+ ParseAll ( ) ;
125
+ } ) ;
126
+
127
+ _hook . Attach ( ) ;
128
+ }
129
+
130
+ private void ParseAll ( )
131
+ {
132
+ var components = _vbe . VBProjects . Cast < VBProject > ( )
133
+ . SelectMany ( project => project . VBComponents . Cast < VBComponent > ( ) ) ;
134
+
135
+ var result = Parallel . ForEach ( components , async component => { await ParseComponentAsync ( component , false ) ; } ) ;
136
+
137
+ if ( result . IsCompleted )
138
+ {
139
+ using ( var tokenSource = new CancellationTokenSource ( ) )
140
+ {
141
+ _parser . Resolve ( tokenSource . Token ) ;
142
+ }
143
+ }
54
144
}
55
145
56
146
private void CleanReloadConfig ( )
57
147
{
58
148
LoadConfig ( ) ;
59
- CleanUp ( ) ;
60
149
Setup ( ) ;
61
150
}
62
151
@@ -87,44 +176,23 @@ private void LoadConfig()
87
176
88
177
private void Setup ( )
89
178
{
90
- _parser = _parserFactory . Create ( ) ;
91
- _parser . ParseStarted += _parser_ParseStarted ;
92
- _parser . ParserError += _parser_ParserError ;
93
-
94
179
_inspectorFactory . Create ( ) ;
95
-
96
- _parserErrorsPresenter = _parserErrorsPresenterFactory . Create ( ) ;
97
- }
98
-
99
- private void _parser_ParseStarted ( object sender , ParseStartedEventArgs e )
100
- {
101
- _parserErrorsPresenter . Clear ( ) ;
102
- }
103
-
104
- private void _parser_ParserError ( object sender , ParseErrorEventArgs e )
105
- {
106
- _parserErrorsPresenter . AddError ( e ) ;
107
- _parserErrorsPresenter . Show ( ) ;
180
+ _parserErrorsPresenterFactory . Create ( ) ;
108
181
}
109
182
110
183
public void Dispose ( )
111
184
{
112
- Dispose ( true ) ;
113
- }
185
+ _hook . KeyPressed -= _hook_KeyPressed ;
186
+ _configService . SettingsChanged -= _configService_SettingsChanged ;
187
+ _parser . State . StateChanged -= Parser_StateChanged ;
114
188
115
- protected virtual void Dispose ( bool disposing )
116
- {
117
- if ( ! disposing ) { return ; }
118
-
119
- CleanUp ( ) ;
120
- }
121
-
122
- private void CleanUp ( )
123
- {
124
- if ( _parser != null )
189
+ if ( _tokenSources . Any ( ) )
125
190
{
126
- _parser . ParseStarted -= _parser_ParseStarted ;
127
- _parser . ParserError -= _parser_ParserError ;
191
+ foreach ( var tokenSource in _tokenSources )
192
+ {
193
+ tokenSource . Value . Cancel ( ) ;
194
+ tokenSource . Value . Dispose ( ) ;
195
+ }
128
196
}
129
197
}
130
198
}
0 commit comments