@@ -28,6 +28,7 @@ public class ParseCoordinator : IParseCoordinator
28
28
public RubberduckParserState State { get { return _state ; } }
29
29
30
30
private const int _maxDegreeOfParserParallelism = - 1 ;
31
+ private const int _maxDegreeOfModuleStateChangeParallelism = - 1 ;
31
32
32
33
private readonly IDictionary < IVBComponent , IDictionary < Tuple < string , DeclarationType > , Attributes > > _componentAttributes
33
34
= new Dictionary < IVBComponent , IDictionary < Tuple < string , DeclarationType > , Attributes > > ( ) ;
@@ -79,7 +80,8 @@ private void ReparseRequested(object sender, EventArgs e)
79
80
}
80
81
else
81
82
{
82
- Parse ( _cancellationTokens [ 0 ] ) ;
83
+ Cancel ( ) ;
84
+ ParseInternal ( _cancellationTokens [ 0 ] ) ;
83
85
}
84
86
}
85
87
@@ -100,7 +102,28 @@ private void Cancel(bool createNewTokenSource = true)
100
102
/// <summary>
101
103
/// For the use of tests only
102
104
/// </summary>
105
+ ///
103
106
public void Parse ( CancellationTokenSource token )
107
+ {
108
+ SetSavedCancellationTokenSource ( token ) ;
109
+ ParseInternal ( token ) ;
110
+ }
111
+
112
+ private void SetSavedCancellationTokenSource ( CancellationTokenSource token )
113
+ {
114
+ if ( _cancellationTokens . Any ( ) )
115
+ {
116
+ _cancellationTokens [ 0 ] . Cancel ( ) ;
117
+ _cancellationTokens [ 0 ] . Dispose ( ) ;
118
+ _cancellationTokens [ 0 ] = token ;
119
+ }
120
+ else
121
+ {
122
+ _cancellationTokens . Add ( token ) ;
123
+ }
124
+ }
125
+
126
+ private void ParseInternal ( CancellationTokenSource token )
104
127
{
105
128
State . RefreshProjects ( _vbe ) ;
106
129
@@ -163,10 +186,12 @@ private void RefreshDeclarationFinder()
163
186
164
187
private void SetModuleStates ( List < IVBComponent > components , ParserState parserState )
165
188
{
166
- foreach ( var component in components )
167
- {
168
- State . SetModuleState ( component , parserState ) ;
169
- }
189
+ var options = new ParallelOptions ( ) ;
190
+ options . MaxDegreeOfParallelism = _maxDegreeOfModuleStateChangeParallelism ;
191
+
192
+ Parallel . ForEach ( components , options , component => State . SetModuleState ( component , parserState , null , false ) ) ;
193
+
194
+ State . EvaluateParserState ( ) ;
170
195
}
171
196
172
197
private void CleanUpComponentAttributes ( List < IVBComponent > components )
@@ -190,20 +215,34 @@ private void ClearComponentStateCacheForTests()
190
215
191
216
private void ParseComponents ( List < IVBComponent > components , CancellationToken token )
192
217
{
218
+ SetModuleStates ( components , ParserState . Parsing ) ;
219
+
193
220
var options = new ParallelOptions ( ) ;
194
221
options . CancellationToken = token ;
195
222
options . MaxDegreeOfParallelism = _maxDegreeOfParserParallelism ;
196
223
197
- Parallel . ForEach ( components ,
198
- options ,
199
- component =>
224
+ try
225
+ {
226
+ Parallel . ForEach ( components ,
227
+ options ,
228
+ component =>
229
+ {
230
+ State . ClearStateCache ( component ) ;
231
+ var finishedParseTask = FinishedParseComponentTask ( component , token ) ;
232
+ ProcessComponentParseResults ( component , finishedParseTask ) ;
233
+ }
234
+ ) ;
235
+ }
236
+ catch ( AggregateException exception )
237
+ {
238
+ if ( exception . Flatten ( ) . InnerExceptions . All ( ex => ex is OperationCanceledException ) )
200
239
{
201
- State . SetModuleState ( component , ParserState . Parsing ) ;
202
- State . ClearStateCache ( component ) ;
203
- var finishedParseTask = FinishedParseComponentTask ( component , token ) ;
204
- ProcessComponentParseResults ( component , finishedParseTask ) ;
240
+ return ;
205
241
}
206
- ) ;
242
+ throw ;
243
+ }
244
+
245
+ State . EvaluateParserState ( ) ;
207
246
}
208
247
209
248
private Task < ComponentParseTask . ParseCompletionArgs > FinishedParseComponentTask ( IVBComponent component , CancellationToken token , TokenStreamRewriter rewriter = null )
@@ -239,6 +278,7 @@ private void ProcessComponentParseResults(IVBComponent component, Task<Component
239
278
{
240
279
if ( finishedParseTask . IsFaulted )
241
280
{
281
+ //In contrast to the situation in the success scenario, the overall parser state is reevaluated immediately.
242
282
State . SetModuleState ( component , ParserState . Error , finishedParseTask . Exception . InnerException as SyntaxErrorException ) ;
243
283
}
244
284
else if ( finishedParseTask . IsCompleted )
@@ -255,7 +295,9 @@ private void ProcessComponentParseResults(IVBComponent component, Task<Component
255
295
State . SetModuleAnnotations ( component , result . Annotations ) ;
256
296
257
297
// This really needs to go last
258
- State . SetModuleState ( component , ParserState . Parsed ) ;
298
+ //It does not reevaluate the overall parer state to avoid concurrent evaluation of all module states and for performance reasons.
299
+ //The evaluation has to be triggered manually in the calling procedure.
300
+ State . SetModuleState ( component , ParserState . Parsed , null , false ) ;
259
301
}
260
302
}
261
303
}
@@ -264,26 +306,48 @@ private void ProcessComponentParseResults(IVBComponent component, Task<Component
264
306
265
307
private void ResolveAllDeclarations ( List < IVBComponent > components , CancellationToken token )
266
308
{
309
+ SetModuleStates ( components , ParserState . ResolvingDeclarations ) ;
310
+
267
311
var options = new ParallelOptions ( ) ;
268
312
options . CancellationToken = token ;
269
313
options . MaxDegreeOfParallelism = _maxDegreeOfParserParallelism ;
270
-
271
- Parallel . ForEach ( components ,
272
- options ,
273
- component =>
314
+ try
315
+ {
316
+ Parallel . ForEach ( components ,
317
+ options ,
318
+ component =>
319
+ {
320
+ var qualifiedName = new QualifiedModuleName ( component ) ;
321
+ ResolveDeclarations ( qualifiedName . Component ,
322
+ State . ParseTrees . Find ( s => s . Key == qualifiedName ) . Value ) ;
323
+ }
324
+ ) ;
325
+ }
326
+ catch ( AggregateException exception )
327
+ {
328
+ if ( exception . Flatten ( ) . InnerExceptions . All ( ex => ex is OperationCanceledException ) )
274
329
{
275
- var qualifiedName = new QualifiedModuleName ( component ) ;
276
- State . SetModuleState ( component , ParserState . ResolvingDeclarations ) ;
277
- ResolveDeclarations ( qualifiedName . Component ,
278
- State . ParseTrees . Find ( s => s . Key == qualifiedName ) . Value ) ;
330
+ return ;
279
331
}
280
- ) ;
332
+ throw ;
333
+ }
281
334
}
282
335
283
336
284
337
private void ResolveReferences ( CancellationToken token )
285
338
{
286
- Task . WaitAll ( ResolveReferencesAsync ( token ) ) ;
339
+ try
340
+ {
341
+ Task . WaitAll ( ResolveReferencesAsync ( token ) ) ;
342
+ }
343
+ catch ( AggregateException exception )
344
+ {
345
+ if ( exception . Flatten ( ) . InnerExceptions . All ( ex => ex is OperationCanceledException ) )
346
+ {
347
+ return ;
348
+ }
349
+ throw ;
350
+ }
287
351
}
288
352
289
353
0 commit comments