diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs index dedcd3e3ce..816e21bbfe 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs @@ -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)) diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs index 0ef27cad70..ecb42b2067 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs @@ -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(), + new DefaultErrorReporter(), + Mock.Of()); + parser.Dispose(); + + // Act & Assert + parser.ReparseOnForeground(null); + } + + [ForegroundFact] + public void OnIdle_NoopsIfDisposed() + { + // Arrange + var parser = new DefaultVisualStudioRazorParser( + Dispatcher, + CreateDocumentTracker(), + Mock.Of(), + new DefaultErrorReporter(), + Mock.Of()); + parser.Dispose(); + + // Act & Assert + parser.OnIdle(null); + } + + [ForegroundFact] + public void OnDocumentStructureChanged_NoopsIfDisposed() + { + // Arrange + var parser = new DefaultVisualStudioRazorParser( + Dispatcher, + CreateDocumentTracker(), + Mock.Of(), + new DefaultErrorReporter(), + Mock.Of()); + parser.Dispose(); + + // Act & Assert + parser.OnDocumentStructureChanged(new object()); + } + [ForegroundFact] public void OnDocumentStructureChanged_IgnoresEditsThatAreOld() {