Make Foreground dispatchable methods noop if parser is disposed.

- Added tests to validate each of the new noopable methods.

#1750
This commit is contained in:
N. Taylor Mullen 2017-11-06 15:52:34 -08:00
parent 834fd5a5d0
commit 399dcca4f2
2 changed files with 66 additions and 4 deletions

View File

@ -38,6 +38,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
private RazorTemplateEngine _templateEngine;
private RazorCodeDocument _codeDocument;
private ITextSnapshot _snapshot;
private bool _disposed;
// For testing only
internal DefaultVisualStudioRazorParser(RazorCodeDocument codeDocument)
@ -127,6 +128,8 @@ namespace Microsoft.VisualStudio.Editor.Razor
_documentTracker.ContextChanged -= DocumentTracker_ContextChanged;
StopIdleTimer();
_disposed = true;
}
// Internal for testing
@ -264,10 +267,16 @@ namespace Microsoft.VisualStudio.Editor.Razor
}
}
private void OnIdle(object state)
// Internal for testing
internal void OnIdle(object state)
{
_dispatcher.AssertForegroundThread();
if (_disposed)
{
return;
}
OnNotifyForegroundIdle();
foreach (var textView in _documentTracker.TextViews)
@ -283,13 +292,13 @@ namespace Microsoft.VisualStudio.Editor.Razor
QueueReparse();
}
private void ReparseOnForeground(object state)
// Internal for testing
internal void ReparseOnForeground(object state)
{
_dispatcher.AssertForegroundThread();
if (_parser == null)
if (_disposed)
{
Debug.Fail("Reparse being attempted after the parser has been disposed.");
return;
}
@ -354,6 +363,11 @@ namespace Microsoft.VisualStudio.Editor.Razor
{
_dispatcher.AssertForegroundThread();
if (_disposed)
{
return;
}
var args = (DocumentStructureChangedEventArgs)state;
if (_latestChangeReference == null || // extra hardening
!_latestChangeReference.IsAssociatedWith(args))

View File

@ -27,6 +27,54 @@ namespace Microsoft.VisualStudio.Editor.Razor
return documentTracker;
}
[ForegroundFact]
public void ReparseOnForeground_NoopsIfDisposed()
{
// Arrange
var parser = new DefaultVisualStudioRazorParser(
Dispatcher,
CreateDocumentTracker(),
Mock.Of<RazorTemplateEngineFactoryService>(),
new DefaultErrorReporter(),
Mock.Of<ICompletionBroker>());
parser.Dispose();
// Act & Assert
parser.ReparseOnForeground(null);
}
[ForegroundFact]
public void OnIdle_NoopsIfDisposed()
{
// Arrange
var parser = new DefaultVisualStudioRazorParser(
Dispatcher,
CreateDocumentTracker(),
Mock.Of<RazorTemplateEngineFactoryService>(),
new DefaultErrorReporter(),
Mock.Of<ICompletionBroker>());
parser.Dispose();
// Act & Assert
parser.OnIdle(null);
}
[ForegroundFact]
public void OnDocumentStructureChanged_NoopsIfDisposed()
{
// Arrange
var parser = new DefaultVisualStudioRazorParser(
Dispatcher,
CreateDocumentTracker(),
Mock.Of<RazorTemplateEngineFactoryService>(),
new DefaultErrorReporter(),
Mock.Of<ICompletionBroker>());
parser.Dispose();
// Act & Assert
parser.OnDocumentStructureChanged(new object());
}
[ForegroundFact]
public void OnDocumentStructureChanged_IgnoresEditsThatAreOld()
{