Skip to content

Commit 2b3f368

Browse files
committed
Pass a CancellationToken on (module)state changed events.
1 parent dc17662 commit 2b3f368

File tree

3 files changed

+66
-55
lines changed

3 files changed

+66
-55
lines changed
Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
using System;
2+
using System.Threading;
23
using Rubberduck.Parsing.VBA;
34
using Rubberduck.VBEditor;
45

56
namespace Rubberduck.Parsing
67
{
78
public class ParseProgressEventArgs : EventArgs
89
{
9-
private readonly QualifiedModuleName _module;
10-
private readonly ParserState _state;
11-
private readonly ParserState _oldState;
12-
13-
public ParseProgressEventArgs(QualifiedModuleName module, ParserState state, ParserState oldState)
10+
public ParseProgressEventArgs(QualifiedModuleName module, ParserState state, ParserState oldState, CancellationToken token)
1411
{
15-
_module = module;
16-
_state = state;
17-
_oldState = oldState;
12+
Module = module;
13+
State = state;
14+
OldState = oldState;
15+
Token = token;
1816
}
1917

20-
public QualifiedModuleName Module { get { return _module; } }
21-
public ParserState State { get { return _state; } }
22-
public ParserState OldState { get { return _oldState; } }
18+
public QualifiedModuleName Module { get; }
19+
public ParserState State { get; }
20+
public ParserState OldState { get; }
21+
public CancellationToken Token { get; }
2322
}
2423
}

Rubberduck.Parsing/VBA/ParserStateManagerBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public ParserState GetModuleState(QualifiedModuleName module)
3838

3939
public void EvaluateOverallParserState(CancellationToken token)
4040
{
41-
_state.EvaluateParserState();
41+
_state.EvaluateParserState(token);
4242
}
4343

4444
public void SetModuleState(QualifiedModuleName module, ParserState parserState, CancellationToken token, bool evaluateOverallParserState = true)
@@ -48,7 +48,7 @@ public void SetModuleState(QualifiedModuleName module, ParserState parserState,
4848

4949
public void SetStatusAndFireStateChanged(object requestor, ParserState status, CancellationToken token)
5050
{
51-
_state.SetStatusAndFireStateChanged(requestor, status);
51+
_state.SetStatusAndFireStateChanged(requestor, status, token);
5252
}
5353
}
5454
}

Rubberduck.Parsing/VBA/RubberduckParserState.cs

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ namespace Rubberduck.Parsing.VBA
2525
{
2626
public class ParserStateEventArgs : EventArgs
2727
{
28-
public ParserStateEventArgs(ParserState state)
28+
public ParserStateEventArgs(ParserState state, CancellationToken token)
2929
{
3030
State = state;
31+
Token = token;
3132
}
3233

3334
public ParserState State { get; }
35+
public CancellationToken Token { get; }
3436
}
3537

3638
public class RubberduckStatusMessageEventArgs : EventArgs
@@ -256,11 +258,11 @@ public void RefreshProjects()
256258
_projectRepository.Refresh();
257259
}
258260

259-
private void RefreshProject(string projectId, bool notifyStateChanged = false)
261+
private void RefreshProject(string projectId)
260262
{
261263
_projectRepository.Refresh(projectId);
262264

263-
ClearStateCache(projectId, notifyStateChanged);
265+
ClearStateCache(projectId);
264266
}
265267

266268
public List<IVBProject> Projects => _projectRepository.Projects().Select(tpl => tpl.Project).ToList();
@@ -289,37 +291,44 @@ public IReadOnlyList<Tuple<QualifiedModuleName, SyntaxErrorException>> ModuleExc
289291
public event EventHandler<ParserStateEventArgs> StateChanged;
290292

291293
private int _stateChangedInvocations;
292-
private void OnStateChanged(object requestor, ParserState state = ParserState.Pending)
294+
private void OnStateChanged(object requestor, CancellationToken token, ParserState state = ParserState.Pending)
293295
{
294296
Interlocked.Increment(ref _stateChangedInvocations);
295297

296298
Logger.Info($"{nameof(RubberduckParserState)} ({_stateChangedInvocations}) is invoking {nameof(StateChanged)} ({Status})");
297-
StateChanged?.Invoke(requestor, new ParserStateEventArgs(state));
299+
var handler = StateChanged;
300+
if (handler != null && !token.IsCancellationRequested)
301+
{
302+
var args = new ParserStateEventArgs(state, token);
303+
handler.Invoke(requestor, args);
304+
}
298305
}
299306

300307
public event EventHandler<ParseProgressEventArgs> ModuleStateChanged;
301308

302309
//Never spawn new threads changing module states in the handler! This will cause deadlocks.
303-
private void OnModuleStateChanged(QualifiedModuleName module, ParserState state, ParserState oldState)
310+
private void OnModuleStateChanged(QualifiedModuleName module, ParserState state, ParserState oldState, CancellationToken token)
304311
{
305312
var handler = ModuleStateChanged;
306-
if (handler != null)
313+
if (handler != null && !token.IsCancellationRequested)
307314
{
308-
var args = new ParseProgressEventArgs(module, state, oldState);
315+
var args = new ParseProgressEventArgs(module, state, oldState, token);
309316
handler.Invoke(this, args);
310317
}
311318
}
312319

320+
public void SetModuleState(QualifiedModuleName module, ParserState state, SyntaxErrorException parserError = null, bool evaluateOverallState = true)
321+
{
322+
SetModuleState(module, state, CancellationToken.None, parserError, evaluateOverallState);
323+
}
324+
313325
public void SetModuleState(QualifiedModuleName module, ParserState state, CancellationToken token, SyntaxErrorException parserError = null, bool evaluateOverallState = true)
314326
{
315-
if (!token.IsCancellationRequested)
327+
if (token.IsCancellationRequested)
316328
{
317-
SetModuleState(module, state, parserError, evaluateOverallState);
329+
return;
318330
}
319-
}
320331

321-
public void SetModuleState(QualifiedModuleName module, ParserState state, SyntaxErrorException parserError = null, bool evaluateOverallState = true)
322-
{
323332
if (AllUserDeclarations.Any())
324333
{
325334
var projectId = module.ProjectId;
@@ -339,21 +348,30 @@ public void SetModuleState(QualifiedModuleName module, ParserState state, Syntax
339348
_moduleStates.AddOrUpdate(module, new ModuleState(state), (c, e) => e.SetState(state));
340349
_moduleStates.AddOrUpdate(module, new ModuleState(parserError), (c, e) => e.SetModuleException(parserError));
341350
Logger.Debug("Module '{0}' state is changing to '{1}' (thread {2})", module.ComponentName, state, Thread.CurrentThread.ManagedThreadId);
342-
OnModuleStateChanged(module, state, oldState);
351+
OnModuleStateChanged(module, state, oldState, token);
343352
if (evaluateOverallState)
344353
{
345-
EvaluateParserState();
354+
EvaluateParserState(token);
346355
}
347356
}
348357

349358
private IVBProject GetProject(string projectId)
350359
{
351360
return _projectRepository.Project(projectId);
352-
}
361+
}
353362

354363
public void EvaluateParserState()
355364
{
356-
lock (_statusLockObject) Status = OverallParserStateFromModuleStates();
365+
EvaluateParserState(CancellationToken.None);
366+
}
367+
368+
public void EvaluateParserState(CancellationToken token)
369+
{
370+
lock (_statusLockObject)
371+
{
372+
var newState = OverallParserStateFromModuleStates();
373+
SetStatusWithCancellation(newState, token);
374+
}
357375
}
358376

359377
private ParserState OverallParserStateFromModuleStates()
@@ -489,26 +507,33 @@ public ParserState GetModuleState(QualifiedModuleName module)
489507
private ParserState _status;
490508
public ParserState Status
491509
{
492-
get { return _status; }
493-
private set
510+
get => _status;
511+
private set => SetStatusWithCancellation(value, CancellationToken.None);
512+
}
513+
514+
private void SetStatusWithCancellation(ParserState value, CancellationToken token)
515+
{
516+
if (_status != value)
494517
{
495-
if (_status != value)
496-
{
497-
_status = value;
498-
OnStateChanged(this, _status);
499-
}
518+
_status = value;
519+
OnStateChanged(this, token, _status);
500520
}
501521
}
502522

503523
public void SetStatusAndFireStateChanged(object requestor, ParserState status)
524+
{
525+
SetStatusAndFireStateChanged(requestor, status, CancellationToken.None);
526+
}
527+
528+
public void SetStatusAndFireStateChanged(object requestor, ParserState status, CancellationToken token)
504529
{
505530
if (Status == status)
506531
{
507-
OnStateChanged(requestor, status);
532+
OnStateChanged(requestor, token, status);
508533
}
509534
else
510535
{
511-
Status = status;
536+
SetStatusWithCancellation(status, token);
512537
}
513538
}
514539

@@ -654,8 +679,7 @@ public void AddUnresolvedMemberDeclaration(UnboundMemberDeclaration declaration)
654679

655680
if (declarations.ContainsKey(declaration))
656681
{
657-
byte _;
658-
while (!declarations.TryRemove(declaration, out _))
682+
while (!declarations.TryRemove(declaration, out var _))
659683
{
660684
Logger.Warn("Could not remove existing unresolved member declaration for '{0}' ({1}). Retrying.", declaration.IdentifierName, declaration.DeclarationType);
661685
}
@@ -666,7 +690,7 @@ public void AddUnresolvedMemberDeclaration(UnboundMemberDeclaration declaration)
666690
}
667691
}
668692

669-
public void ClearStateCache(string projectId, bool notifyStateChanged = false)
693+
public void ClearStateCache(string projectId)
670694
{
671695
try
672696
{
@@ -696,16 +720,10 @@ public void ClearStateCache(string projectId, bool notifyStateChanged = false)
696720
Logger.Error(exception, $"Unexpected COMException while clearing the project with projectId {projectId}. Clearing all modules.");
697721
_moduleStates.Clear();
698722
}
699-
700-
if (notifyStateChanged)
701-
{
702-
OnStateChanged(this, ParserState.ResolvedDeclarations); // trigger test explorer and code explorer updates
703-
OnStateChanged(this, ParserState.Ready); // trigger find all references &c. updates
704-
}
705723
}
706724

707725

708-
public bool ClearStateCache(QualifiedModuleName module, bool notifyStateChanged = false)
726+
public bool ClearStateCache(QualifiedModuleName module)
709727
{
710728
var keys = new List<QualifiedModuleName> { module };
711729
foreach (var key in _moduleStates.Keys)
@@ -718,12 +736,6 @@ public bool ClearStateCache(QualifiedModuleName module, bool notifyStateChanged
718736

719737
var success = RemoveKeysFromCollections(keys);
720738

721-
if (notifyStateChanged)
722-
{
723-
OnStateChanged(this, ParserState.ResolvedDeclarations); // trigger test explorer and code explorer updates
724-
OnStateChanged(this, ParserState.Ready); // trigger find all references &c. updates
725-
}
726-
727739
return success;
728740
}
729741

0 commit comments

Comments
 (0)