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