From 2885b4b13804511a76836f63fc5bdf732ab800dc Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 27 Apr 2018 11:47:34 -0700 Subject: [PATCH] Make document tracker resilient to multiple subscribes. - Added tests to verify new functionality. #2314 --- .../DefaultVisualStudioDocumentTracker.cs | 12 ++++ .../DefaultVisualStudioDocumentTrackerTest.cs | 66 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs index bc31eba667..b9c976bdb9 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs @@ -29,6 +29,7 @@ namespace Microsoft.VisualStudio.Editor.Razor private readonly Workspace _workspace; private bool _isSupportedProject; private ProjectSnapshot _projectSnapshot; + private int _subscribeCount; // Only allow a single tag helper computation task at a time. private (ProjectSnapshot project, Task task) _computingTagHelpers; @@ -177,12 +178,18 @@ namespace Microsoft.VisualStudio.Editor.Razor { _foregroundDispatcher.AssertForegroundThread(); + if (_subscribeCount++ > 0) + { + return; + } + _projectSnapshot = _projectManager.GetOrCreateProject(_projectPath); _isSupportedProject = true; _projectManager.Changed += ProjectManager_Changed; _workspaceEditorSettings.Changed += EditorSettingsManager_Changed; _importDocumentManager.Changed += Import_Changed; + _importDocumentManager.OnSubscribed(this); OnContextChanged(ContextChangeKind.ProjectChanged); @@ -192,6 +199,11 @@ namespace Microsoft.VisualStudio.Editor.Razor { _foregroundDispatcher.AssertForegroundThread(); + if (_subscribeCount == 0 || _subscribeCount-- > 1) + { + return; + } + _importDocumentManager.OnUnsubscribed(this); _projectManager.Changed -= ProjectManager_Changed; diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs index 0e47ecfe9c..f14f8bbfd8 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs @@ -98,6 +98,72 @@ namespace Microsoft.VisualStudio.Editor.Razor private DefaultVisualStudioDocumentTracker DocumentTracker { get; } + [ForegroundFact] + public void Subscribe_NoopsIfAlreadySubscribed() + { + // Arrange + var callCount = 0; + DocumentTracker.ContextChanged += (sender, args) => + { + callCount++; + }; + DocumentTracker.Subscribe(); + + // Call count is 2 right now: + // 1 trigger for initial subscribe context changed. + // 1 trigger for TagHelpers being changed (computed). + + // Act + DocumentTracker.Subscribe(); + + // Assert + Assert.Equal(2, callCount); + } + + [ForegroundFact] + public void Unsubscribe_NoopsIfAlreadyUnsubscribed() + { + // Arrange + var callCount = 0; + DocumentTracker.Subscribe(); + DocumentTracker.ContextChanged += (sender, args) => + { + callCount++; + }; + DocumentTracker.Unsubscribe(); + + // Act + DocumentTracker.Unsubscribe(); + + // Assert + Assert.Equal(1, callCount); + } + + [ForegroundFact] + public void Unsubscribe_NoopsIfSubscribeHasBeenCalledMultipleTimes() + { + // Arrange + var callCount = 0; + DocumentTracker.Subscribe(); + DocumentTracker.Subscribe(); + DocumentTracker.ContextChanged += (sender, args) => + { + callCount++; + }; + + // Act - 1 + DocumentTracker.Unsubscribe(); + + // Assert - 1 + Assert.Equal(0, callCount); + + // Act - 2 + DocumentTracker.Unsubscribe(); + + // Assert - 2 + Assert.Equal(1, callCount); + } + [ForegroundFact] public void EditorSettingsManager_Changed_TriggersContextChanged() {