1
1
using System ;
2
2
using System . Collections . Concurrent ;
3
3
using System . Collections . Generic ;
4
- using System . Linq ;
5
4
using System . Threading ;
6
5
using System . Threading . Tasks ;
7
6
using Antlr4 . Runtime ;
16
15
using Rubberduck . VBEditor . Extensions ;
17
16
using System . IO ;
18
17
using NLog ;
18
+ // ReSharper disable LoopCanBeConvertedToQuery
19
19
20
20
namespace Rubberduck . Parsing . VBA
21
21
{
@@ -86,31 +86,46 @@ private void ReparseRequested(object sender, ParseRequestEventArgs e)
86
86
/// </summary>
87
87
public void Parse ( )
88
88
{
89
- if ( ! _state . Projects . Any ( ) )
89
+ if ( _state . Projects . Count == 0 )
90
90
{
91
91
foreach ( var project in _vbe . VBProjects . UnprotectedProjects ( ) )
92
92
{
93
93
_state . AddProject ( project ) ;
94
94
}
95
95
}
96
96
97
- var projects = _state . Projects . ToList ( ) ;
97
+ var components = new List < VBComponent > ( ) ;
98
+ foreach ( var project in _state . Projects )
99
+ {
100
+ foreach ( VBComponent component in project . VBComponents )
101
+ {
102
+ components . Add ( component ) ;
103
+ }
104
+ }
98
105
99
- var components = projects . SelectMany ( p => p . VBComponents . Cast < VBComponent > ( ) ) . ToList ( ) ;
100
- SyncComReferences ( projects ) ;
106
+ SyncComReferences ( _state . Projects ) ;
101
107
102
108
foreach ( var component in components )
103
109
{
104
110
_state . SetModuleState ( component , ParserState . Pending ) ;
105
111
}
106
112
107
113
// invalidation cleanup should go into ParseAsync?
108
- foreach ( var invalidated in _componentAttributes . Keys . Except ( components ) )
114
+ foreach ( var key in _componentAttributes . Keys )
115
+ {
116
+ if ( ! components . Contains ( key ) )
117
+ {
118
+ _componentAttributes . Remove ( key ) ;
119
+ }
120
+ }
121
+
122
+ var parseTasks = new Task [ components . Count ] ;
123
+ for ( var i = 0 ; i < components . Count ; i ++ )
109
124
{
110
- _componentAttributes . Remove ( invalidated ) ;
125
+ parseTasks [ i ] = ParseAsync ( components [ i ] , CancellationToken . None ) ;
126
+ parseTasks [ i ] . Start ( ) ;
111
127
}
112
128
113
- var parseTasks = components . Select ( vbComponent => ParseAsync ( vbComponent , CancellationToken . None ) ) . ToArray ( ) ;
114
129
Task . WaitAll ( parseTasks ) ;
115
130
116
131
if ( _state . Status != ParserState . Error )
@@ -125,24 +140,42 @@ public void Parse()
125
140
/// </summary>
126
141
private void ParseAll ( )
127
142
{
128
- if ( ! _state . Projects . Any ( ) )
143
+ if ( _state . Projects . Count == 0 )
129
144
{
130
145
foreach ( var project in _vbe . VBProjects . UnprotectedProjects ( ) )
131
146
{
132
147
_state . AddProject ( project ) ;
133
148
}
134
149
}
135
150
136
- var projects = _state . Projects . ToList ( ) ;
137
- var components = projects . SelectMany ( p => p . VBComponents . Cast < VBComponent > ( ) ) . ToList ( ) ;
151
+ var components = new List < VBComponent > ( ) ;
152
+ foreach ( var project in _state . Projects )
153
+ {
154
+ foreach ( VBComponent component in project . VBComponents )
155
+ {
156
+ components . Add ( component ) ;
157
+ }
158
+ }
138
159
139
- var toParse = components . Where ( c => _state . IsNewOrModified ( c ) ) . ToList ( ) ;
140
- var unchanged = components . Where ( c => ! _state . IsNewOrModified ( c ) ) . ToList ( ) ;
160
+ var toParse = new List < VBComponent > ( ) ;
161
+ var unchanged = new List < VBComponent > ( ) ;
141
162
142
- SyncComReferences ( projects ) ;
143
- AddBuiltInDeclarations ( projects ) ;
163
+ foreach ( var component in components )
164
+ {
165
+ if ( _state . IsNewOrModified ( component ) )
166
+ {
167
+ toParse . Add ( component ) ;
168
+ }
169
+ else
170
+ {
171
+ unchanged . Add ( component ) ;
172
+ }
173
+ }
174
+
175
+ SyncComReferences ( _state . Projects ) ;
176
+ AddBuiltInDeclarations ( _state . Projects ) ;
144
177
145
- if ( ! toParse . Any ( ) )
178
+ if ( toParse . Count == 0 )
146
179
{
147
180
State . SetStatusAndFireStateChanged ( _state . Status ) ;
148
181
return ;
@@ -161,17 +194,25 @@ private void ParseAll()
161
194
_state . SetModuleState ( component , ParserState . Ready ) ;
162
195
}
163
196
164
- Debug . Assert ( unchanged . All ( component => _state . GetModuleState ( component ) == ParserState . Ready ) ) ;
165
- Debug . Assert ( toParse . All ( component => _state . GetModuleState ( component ) == ParserState . Pending ) ) ;
197
+ // Debug.Assert(unchanged.All(component => _state.GetModuleState(component) == ParserState.Ready));
198
+ // Debug.Assert(toParse.All(component => _state.GetModuleState(component) == ParserState.Pending));
166
199
}
167
200
168
201
// invalidation cleanup should go into ParseAsync?
169
- foreach ( var invalidated in _componentAttributes . Keys . Except ( components ) )
202
+ foreach ( var key in _componentAttributes . Keys )
170
203
{
171
- _componentAttributes . Remove ( invalidated ) ;
204
+ if ( ! components . Contains ( key ) )
205
+ {
206
+ _componentAttributes . Remove ( key ) ;
207
+ }
208
+ }
209
+
210
+ var parseTasks = new Task [ components . Count ] ;
211
+ for ( var i = 0 ; i < components . Count ; i ++ )
212
+ {
213
+ parseTasks [ i ] = ParseAsync ( components [ i ] , CancellationToken . None ) ;
172
214
}
173
215
174
- var parseTasks = toParse . Select ( vbComponent => ParseAsync ( vbComponent , CancellationToken . None ) ) . ToArray ( ) ;
175
216
Task . WaitAll ( parseTasks ) ;
176
217
177
218
if ( _state . Status != ParserState . Error )
@@ -184,12 +225,16 @@ private void ParseAll()
184
225
private void AddBuiltInDeclarations ( IReadOnlyList < VBProject > projects )
185
226
{
186
227
var finder = new DeclarationFinder ( _state . AllDeclarations , new CommentNode [ ] { } , new IAnnotation [ ] { } ) ;
187
- if ( finder . MatchName ( Tokens . Err ) . Any ( item => item . IsBuiltIn
188
- && item . DeclarationType == DeclarationType . Variable
189
- && item . Accessibility == Accessibility . Global ) )
228
+
229
+ foreach ( var item in finder . MatchName ( Tokens . Err ) )
190
230
{
191
- return ;
231
+ if ( item . IsBuiltIn && item . DeclarationType == DeclarationType . Variable &&
232
+ item . Accessibility == Accessibility . Global )
233
+ {
234
+ return ;
235
+ }
192
236
}
237
+
193
238
var vba = finder . FindProject ( "VBA" ) ;
194
239
if ( vba == null )
195
240
{
@@ -213,21 +258,25 @@ private void AddBuiltInDeclarations(IReadOnlyList<VBProject> projects)
213
258
214
259
private string GetReferenceProjectId ( Reference reference , IReadOnlyList < VBProject > projects )
215
260
{
216
- var id = projects . FirstOrDefault ( project =>
261
+ VBProject project = null ;
262
+ foreach ( var item in projects )
217
263
{
218
264
try
219
265
{
220
- return project . FileName == reference . FullPath ;
266
+ if ( item . FileName == reference . FullPath )
267
+ {
268
+ project = item ;
269
+ }
221
270
}
222
271
catch ( IOException )
223
272
{
224
273
// Filename throws exception if unsaved.
225
- return false ;
226
274
}
227
- } ) ;
228
- if ( id != null )
275
+ }
276
+
277
+ if ( project != null )
229
278
{
230
- return QualifiedModuleName . GetProjectId ( id ) ;
279
+ return QualifiedModuleName . GetProjectId ( project ) ;
231
280
}
232
281
return QualifiedModuleName . GetProjectId ( reference ) ;
233
282
}
@@ -243,7 +292,16 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
243
292
{
244
293
var reference = vbProject . References . Item ( priority ) ;
245
294
var referencedProjectId = GetReferenceProjectId ( reference , projects ) ;
246
- var map = _projectReferences . SingleOrDefault ( r => r . ReferencedProjectId == referencedProjectId ) ;
295
+
296
+ ReferencePriorityMap map = null ;
297
+ foreach ( var item in _projectReferences )
298
+ {
299
+ if ( item . ReferencedProjectId == referencedProjectId )
300
+ {
301
+ map = map != null ? null : item ;
302
+ }
303
+ }
304
+
247
305
if ( map == null )
248
306
{
249
307
map = new ReferencePriorityMap ( referencedProjectId ) { { projectId , priority } } ;
@@ -267,9 +325,24 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
267
325
}
268
326
}
269
327
270
- var mappedIds = _projectReferences . Select ( map => map . ReferencedProjectId ) ;
271
- var unmapped = projects . SelectMany ( project => project . References . Cast < Reference > ( ) )
272
- . Where ( reference => ! mappedIds . Contains ( GetReferenceProjectId ( reference , projects ) ) ) ;
328
+ var mappedIds = new List < string > ( ) ;
329
+ foreach ( var item in _projectReferences )
330
+ {
331
+ mappedIds . Add ( item . ReferencedProjectId ) ;
332
+ }
333
+
334
+ var unmapped = new List < Reference > ( ) ;
335
+ foreach ( var project in projects )
336
+ {
337
+ foreach ( Reference item in project . References )
338
+ {
339
+ if ( ! mappedIds . Contains ( GetReferenceProjectId ( item , projects ) ) )
340
+ {
341
+ unmapped . Add ( item ) ;
342
+ }
343
+ }
344
+ }
345
+
273
346
foreach ( var reference in unmapped )
274
347
{
275
348
UnloadComReference ( reference , projects ) ;
@@ -279,15 +352,24 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
279
352
private void UnloadComReference ( Reference reference , IReadOnlyList < VBProject > projects )
280
353
{
281
354
var referencedProjectId = GetReferenceProjectId ( reference , projects ) ;
282
- var map = _projectReferences . SingleOrDefault ( r => r . ReferencedProjectId == referencedProjectId ) ;
355
+
356
+ ReferencePriorityMap map = null ;
357
+ foreach ( var item in _projectReferences )
358
+ {
359
+ if ( item . ReferencedProjectId == referencedProjectId )
360
+ {
361
+ map = map != null ? null : item ;
362
+ }
363
+ }
364
+
283
365
if ( map == null || ! map . IsLoaded )
284
366
{
285
367
// we're removing a reference we weren't tracking? ...this shouldn't happen.
286
368
Debug . Assert ( false ) ;
287
369
return ;
288
370
}
289
371
map . Remove ( referencedProjectId ) ;
290
- if ( ! map . Any ( ) )
372
+ if ( map . Count == 0 )
291
373
{
292
374
_projectReferences . Remove ( map ) ;
293
375
_state . RemoveBuiltInDeclarations ( reference ) ;
@@ -390,9 +472,20 @@ private void Resolve(CancellationToken token)
390
472
391
473
private void ResolveInternal ( CancellationToken token )
392
474
{
393
- var components = _state . Projects
394
- . Where ( project => project . Protection == vbext_ProjectProtection . vbext_pp_none )
395
- . SelectMany ( p => p . VBComponents . Cast < VBComponent > ( ) ) . ToList ( ) ;
475
+ var components = new List < VBComponent > ( ) ;
476
+ foreach ( var project in _state . Projects )
477
+ {
478
+ if ( project . Protection == vbext_ProjectProtection . vbext_pp_locked )
479
+ {
480
+ continue ;
481
+ }
482
+
483
+ foreach ( VBComponent component in project . VBComponents )
484
+ {
485
+ components . Add ( component ) ;
486
+ }
487
+ }
488
+
396
489
if ( ! _state . HasAllParseTrees ( components ) )
397
490
{
398
491
return ;
@@ -471,7 +564,16 @@ private Declaration CreateProjectDeclaration(QualifiedModuleName projectQualifie
471
564
var qualifiedName = projectQualifiedName . QualifyMemberName ( project . Name ) ;
472
565
var projectId = qualifiedName . QualifiedModuleName . ProjectId ;
473
566
var projectDeclaration = new ProjectDeclaration ( qualifiedName , project . Name , isBuiltIn : false ) ;
474
- var references = _projectReferences . Where ( projectContainingReference => projectContainingReference . ContainsKey ( projectId ) ) ;
567
+
568
+ var references = new List < ReferencePriorityMap > ( ) ;
569
+ foreach ( var item in _projectReferences )
570
+ {
571
+ if ( item . ContainsKey ( projectId ) )
572
+ {
573
+ references . Add ( item ) ;
574
+ }
575
+ }
576
+
475
577
foreach ( var reference in references )
476
578
{
477
579
int priority = reference [ projectId ] ;
0 commit comments