@@ -78,12 +78,12 @@ private void ReparseRequested(object sender, EventArgs e)
78
78
if ( ! _isTestScope )
79
79
{
80
80
Cancel ( ) ;
81
- Task . Run ( ( ) => ParseAll ( sender , _cancellationTokens [ 0 ] ) ) ;
81
+ Task . Run ( ( ) => ParseAll ( sender , _cancellationTokens [ 0 ] . Token ) ) ;
82
82
}
83
83
else
84
84
{
85
85
Cancel ( ) ;
86
- ParseInternal ( _cancellationTokens [ 0 ] ) ;
86
+ ParseInternal ( _cancellationTokens [ 0 ] . Token ) ;
87
87
}
88
88
}
89
89
@@ -108,7 +108,7 @@ private void Cancel(bool createNewTokenSource = true)
108
108
public void Parse ( CancellationTokenSource token )
109
109
{
110
110
SetSavedCancellationTokenSource ( token ) ;
111
- ParseInternal ( token ) ;
111
+ ParseInternal ( token . Token ) ;
112
112
}
113
113
114
114
private void SetSavedCancellationTokenSource ( CancellationTokenSource token )
@@ -125,7 +125,7 @@ private void SetSavedCancellationTokenSource(CancellationTokenSource token)
125
125
}
126
126
}
127
127
128
- private void ParseInternal ( CancellationTokenSource token )
128
+ private void ParseInternal ( CancellationToken token )
129
129
{
130
130
State . RefreshProjects ( _vbe ) ;
131
131
@@ -160,9 +160,9 @@ private void CleanUpComponentAttributes(List<IVBComponent> components)
160
160
}
161
161
}
162
162
163
- private void ExecuteCommonParseActivities ( List < IVBComponent > toParse , CancellationTokenSource token )
163
+ private void ExecuteCommonParseActivities ( List < IVBComponent > toParse , CancellationToken token )
164
164
{
165
- SetModuleStates ( toParse , ParserState . Pending ) ;
165
+ SetModuleStates ( toParse , ParserState . Pending , token ) ;
166
166
167
167
SyncComReferences ( State . Projects ) ;
168
168
RefreshDeclarationFinder ( ) ;
@@ -178,14 +178,14 @@ private void ExecuteCommonParseActivities(List<IVBComponent> toParse, Cancellati
178
178
_projectDeclarations . Clear ( ) ;
179
179
State . ClearBuiltInReferences ( ) ;
180
180
181
- ParseComponents ( toParse , token . Token ) ;
181
+ ParseComponents ( toParse , token ) ;
182
182
183
183
if ( token . IsCancellationRequested || State . Status >= ParserState . Error )
184
184
{
185
185
return ;
186
186
}
187
187
188
- ResolveAllDeclarations ( toParse , token . Token ) ;
188
+ ResolveAllDeclarations ( toParse , token ) ;
189
189
RefreshDeclarationFinder ( ) ;
190
190
191
191
if ( token . IsCancellationRequested || State . Status >= ParserState . Error )
@@ -200,7 +200,7 @@ private void ExecuteCommonParseActivities(List<IVBComponent> toParse, Cancellati
200
200
return ;
201
201
}
202
202
203
- ResolveAllReferences ( token . Token ) ;
203
+ ResolveAllReferences ( token ) ;
204
204
205
205
if ( token . IsCancellationRequested || State . Status >= ParserState . Error )
206
206
{
@@ -215,19 +215,23 @@ private void RefreshDeclarationFinder()
215
215
State . RefreshFinder ( _hostApp ) ;
216
216
}
217
217
218
- private void SetModuleStates ( List < IVBComponent > components , ParserState parserState )
218
+ private void SetModuleStates ( List < IVBComponent > components , ParserState parserState , CancellationToken token )
219
219
{
220
220
var options = new ParallelOptions ( ) ;
221
+ options . CancellationToken = token ;
221
222
options . MaxDegreeOfParallelism = _maxDegreeOfModuleStateChangeParallelism ;
222
223
223
- Parallel . ForEach ( components , options , component => State . SetModuleState ( component , parserState , null , false ) ) ;
224
+ Parallel . ForEach ( components , options , component => State . SetModuleState ( component , parserState , token , null , false ) ) ;
224
225
225
- State . EvaluateParserState ( ) ;
226
+ if ( ! token . IsCancellationRequested )
227
+ {
228
+ State . EvaluateParserState ( ) ;
229
+ }
226
230
}
227
231
228
232
private void ParseComponents ( List < IVBComponent > components , CancellationToken token )
229
233
{
230
- SetModuleStates ( components , ParserState . Parsing ) ;
234
+ SetModuleStates ( components , ParserState . Parsing , token ) ;
231
235
232
236
var options = new ParallelOptions ( ) ;
233
237
options . CancellationToken = token ;
@@ -241,7 +245,7 @@ private void ParseComponents(List<IVBComponent> components, CancellationToken to
241
245
{
242
246
State . ClearStateCache ( component ) ;
243
247
var finishedParseTask = FinishedParseComponentTask ( component , token ) ;
244
- ProcessComponentParseResults ( component , finishedParseTask ) ;
248
+ ProcessComponentParseResults ( component , finishedParseTask , token ) ;
245
249
}
246
250
) ;
247
251
}
@@ -286,19 +290,19 @@ private void ParseComponents(List<IVBComponent> components, CancellationToken to
286
290
}
287
291
288
292
289
- private void ProcessComponentParseResults ( IVBComponent component , Task < ComponentParseTask . ParseCompletionArgs > finishedParseTask )
293
+ private void ProcessComponentParseResults ( IVBComponent component , Task < ComponentParseTask . ParseCompletionArgs > finishedParseTask , CancellationToken token )
290
294
{
291
295
if ( finishedParseTask . IsFaulted )
292
296
{
293
297
//In contrast to the situation in the success scenario, the overall parser state is reevaluated immediately.
294
- State . SetModuleState ( component , ParserState . Error , finishedParseTask . Exception . InnerException as SyntaxErrorException ) ;
298
+ State . SetModuleState ( component , ParserState . Error , token , finishedParseTask . Exception . InnerException as SyntaxErrorException ) ;
295
299
}
296
300
else if ( finishedParseTask . IsCompleted )
297
301
{
298
302
var result = finishedParseTask . Result ;
299
303
lock ( State )
300
304
{
301
- lock ( component )
305
+ lock ( component )
302
306
{
303
307
State . SetModuleAttributes ( component , result . Attributes ) ;
304
308
State . AddParseTree ( component , result . ParseTree ) ;
@@ -309,7 +313,7 @@ private void ProcessComponentParseResults(IVBComponent component, Task<Component
309
313
// This really needs to go last
310
314
//It does not reevaluate the overall parer state to avoid concurrent evaluation of all module states and for performance reasons.
311
315
//The evaluation has to be triggered manually in the calling procedure.
312
- State . SetModuleState ( component , ParserState . Parsed , null , false ) ;
316
+ State . SetModuleState ( component , ParserState . Parsed , token , null , false ) ; //Note that this is ok because locks allow re-entrancy.
313
317
}
314
318
}
315
319
}
@@ -318,7 +322,7 @@ private void ProcessComponentParseResults(IVBComponent component, Task<Component
318
322
319
323
private void ResolveAllDeclarations ( List < IVBComponent > components , CancellationToken token )
320
324
{
321
- SetModuleStates ( components , ParserState . ResolvingDeclarations ) ;
325
+ SetModuleStates ( components , ParserState . ResolvingDeclarations , token ) ;
322
326
323
327
var options = new ParallelOptions ( ) ;
324
328
options . CancellationToken = token ;
@@ -331,7 +335,8 @@ private void ResolveAllDeclarations(List<IVBComponent> components, CancellationT
331
335
{
332
336
var qualifiedName = new QualifiedModuleName ( component ) ;
333
337
ResolveDeclarations ( qualifiedName . Component ,
334
- State . ParseTrees . Find ( s => s . Key == qualifiedName ) . Value ) ;
338
+ State . ParseTrees . Find ( s => s . Key == qualifiedName ) . Value ,
339
+ token ) ;
335
340
}
336
341
) ;
337
342
}
@@ -346,7 +351,7 @@ private void ResolveAllDeclarations(List<IVBComponent> components, CancellationT
346
351
}
347
352
348
353
private readonly ConcurrentDictionary < string , Declaration > _projectDeclarations = new ConcurrentDictionary < string , Declaration > ( ) ;
349
- private void ResolveDeclarations ( IVBComponent component , IParseTree tree )
354
+ private void ResolveDeclarations ( IVBComponent component , IParseTree tree , CancellationToken token )
350
355
{
351
356
if ( component == null ) { return ; }
352
357
@@ -376,7 +381,7 @@ private void ResolveDeclarations(IVBComponent component, IParseTree tree)
376
381
catch ( Exception exception )
377
382
{
378
383
Logger . Error ( exception , "Exception thrown acquiring declarations for '{0}' (thread {1})." , component . Name , Thread . CurrentThread . ManagedThreadId ) ;
379
- State . SetModuleState ( component , ParserState . ResolverError ) ;
384
+ State . SetModuleState ( component , ParserState . ResolverError , token ) ;
380
385
}
381
386
stopwatch . Stop ( ) ;
382
387
Logger . Debug ( "{0}ms to resolve declarations for component {1}" , stopwatch . ElapsedMilliseconds , component . Name ) ;
@@ -409,18 +414,34 @@ private Declaration CreateProjectDeclaration(QualifiedModuleName projectQualifie
409
414
private void ResolveAllReferences ( CancellationToken token )
410
415
{
411
416
var components = State . ParseTrees . Select ( kvp => kvp . Key . Component ) . ToList ( ) ;
412
- SetModuleStates ( components , ParserState . ResolvingReferences ) ;
417
+
418
+ SetModuleStates ( components , ParserState . ResolvingReferences , token ) ;
419
+
420
+ if ( token . IsCancellationRequested )
421
+ {
422
+ return ;
423
+ }
413
424
414
425
ExecuteCompilationPasses ( ) ;
415
426
427
+ if ( token . IsCancellationRequested )
428
+ {
429
+ return ;
430
+ }
431
+
416
432
var options = new ParallelOptions ( ) ;
417
433
options . CancellationToken = token ;
418
434
options . MaxDegreeOfParallelism = _maxDegreeOfReferenceResolverParallelism ;
419
435
436
+ if ( token . IsCancellationRequested )
437
+ {
438
+ return ;
439
+ }
440
+
420
441
try
421
442
{
422
443
Parallel . For ( 0 , State . ParseTrees . Count , options ,
423
- ( index ) => ResolveReferences ( State . DeclarationFinder , State . ParseTrees [ index ] . Key . Component , State . ParseTrees [ index ] . Value )
444
+ ( index ) => ResolveReferences ( State . DeclarationFinder , State . ParseTrees [ index ] . Key , State . ParseTrees [ index ] . Value , token )
424
445
) ;
425
446
}
426
447
catch ( AggregateException exception )
@@ -432,8 +453,21 @@ private void ResolveAllReferences(CancellationToken token)
432
453
throw ;
433
454
}
434
455
456
+ if ( token . IsCancellationRequested )
457
+ {
458
+ return ;
459
+ }
460
+
435
461
AddUndeclaredVariablesToDeclarations ( ) ;
436
462
463
+ //This is here and not in the calling method because it has to happen before the ready state is reached.
464
+ //RefreshDeclarationFinder(); //Commented out because it breaks the unresolved and undeclared collections.
465
+
466
+ if ( token . IsCancellationRequested )
467
+ {
468
+ return ;
469
+ }
470
+
437
471
State . EvaluateParserState ( ) ;
438
472
}
439
473
@@ -449,11 +483,15 @@ private void ExecuteCompilationPasses()
449
483
passes . ForEach ( p => p . Execute ( ) ) ;
450
484
}
451
485
452
- private void ResolveReferences ( DeclarationFinder finder , IVBComponent component , IParseTree tree )
486
+ private void ResolveReferences ( DeclarationFinder finder , QualifiedModuleName qualifiedName , IParseTree tree , CancellationToken token )
453
487
{
454
- Debug . Assert ( State . GetModuleState ( component ) == ParserState . ResolvingReferences ) ;
488
+ Debug . Assert ( State . GetModuleState ( qualifiedName . Component ) == ParserState . ResolvingReferences || token . IsCancellationRequested ) ;
489
+
490
+ if ( token . IsCancellationRequested )
491
+ {
492
+ return ;
493
+ }
455
494
456
- var qualifiedName = new QualifiedModuleName ( component ) ;
457
495
Logger . Debug ( "Resolving identifier references in '{0}'... (thread {1})" , qualifiedName . Name , Thread . CurrentThread . ManagedThreadId ) ;
458
496
459
497
var resolver = new IdentifierReferenceResolver ( qualifiedName , finder ) ;
@@ -467,16 +505,20 @@ private void ResolveReferences(DeclarationFinder finder, IVBComponent component,
467
505
var watch = Stopwatch . StartNew ( ) ;
468
506
walker . Walk ( listener , tree ) ;
469
507
watch . Stop ( ) ;
470
- Logger . Debug ( "Binding resolution done for component '{0}' in {1}ms (thread {2})" , component . Name ,
508
+ Logger . Debug ( "Binding resolution done for component '{0}' in {1}ms (thread {2})" , qualifiedName . Name ,
471
509
watch . ElapsedMilliseconds , Thread . CurrentThread . ManagedThreadId ) ;
472
510
473
511
//Evaluation of the overall status has to be defered to allow processing of undeclared variables before setting the ready state.
474
- State . SetModuleState ( component , ParserState . Ready , null , false ) ;
512
+ State . SetModuleState ( qualifiedName . Component , ParserState . Ready , token , null , false ) ;
513
+ }
514
+ catch ( OperationCanceledException )
515
+ {
516
+ throw ; //We do not want to set an error state if the exception was just caused by some cancellation.
475
517
}
476
518
catch ( Exception exception )
477
519
{
478
- Logger . Error ( exception , "Exception thrown resolving '{0}' (thread {1})." , component . Name , Thread . CurrentThread . ManagedThreadId ) ;
479
- State . SetModuleState ( component , ParserState . ResolverError ) ;
520
+ Logger . Error ( exception , "Exception thrown resolving '{0}' (thread {1})." , qualifiedName . Name , Thread . CurrentThread . ManagedThreadId ) ;
521
+ State . SetModuleState ( qualifiedName . Component , ParserState . ResolverError , token ) ;
480
522
}
481
523
}
482
524
}
@@ -494,7 +536,7 @@ private void AddUndeclaredVariablesToDeclarations()
494
536
/// <summary>
495
537
/// Starts parsing all components of all unprotected VBProjects associated with the VBE-Instance passed to the constructor of this parser instance.
496
538
/// </summary>
497
- private void ParseAll ( object requestor , CancellationTokenSource token )
539
+ private void ParseAll ( object requestor , CancellationToken token )
498
540
{
499
541
State . RefreshProjects ( _vbe ) ;
500
542
0 commit comments