From 8b51a85d61869f4d4e224c87c533ea8adbef8b84 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 27 Jun 2021 13:23:30 -0700 Subject: [PATCH 1/6] Simplify delay --- .../NavigationBar/NavigationBarController.cs | 4 ++-- .../NavigationBarController_ModelComputation.cs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs index a645f439539ea..209a42967370e 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs @@ -221,13 +221,13 @@ private void OnSubjectBufferPostChanged(object? sender, EventArgs e) private void OnCaretMoved(object? sender, EventArgs e) { AssertIsForeground(); - StartSelectedItemUpdateTask(delay: TaggerConstants.NearImmediateDelay); + StartSelectedItemUpdateTask(); } private void OnViewFocused(object? sender, EventArgs e) { AssertIsForeground(); - StartSelectedItemUpdateTask(delay: TaggerConstants.ShortDelay); + StartSelectedItemUpdateTask(); } private void OnDropDownFocused(object? sender, EventArgs e) diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs index cc6ddd26ee71f..e54f627f50641 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; +using Microsoft.CodeAnalysis.Editor.Shared.Tagging; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -51,7 +52,7 @@ private void StartModelUpdateAndSelectedItemUpdateTasks(int modelUpdateDelay) _modelTask = ComputeModelAfterDelayAsync(_modelTask, textSnapshot, modelUpdateDelay, cancellationToken); _modelTask.CompletesAsyncOperation(asyncToken); - StartSelectedItemUpdateTask(delay: 0); + StartSelectedItemUpdateTask(); } private static async Task ComputeModelAfterDelayAsync( @@ -128,7 +129,7 @@ private static async Task ComputeModelAsync( /// /// Starts a new task to compute what item should be selected. /// - private void StartSelectedItemUpdateTask(int delay) + private void StartSelectedItemUpdateTask() { AssertIsForeground(); @@ -143,19 +144,18 @@ private void StartSelectedItemUpdateTask(int delay) var cancellationToken = _selectedItemInfoTaskCancellationSource.Token; var asyncToken = _asyncListener.BeginAsyncOperation(GetType().Name + ".StartSelectedItemUpdateTask"); - var selectedItemInfoTask = DetermineSelectedItemInfoAsync(_modelTask, delay, subjectBufferCaretPosition.Value, cancellationToken); + var selectedItemInfoTask = DetermineSelectedItemInfoAsync(_modelTask, subjectBufferCaretPosition.Value, cancellationToken); selectedItemInfoTask.CompletesAsyncOperation(asyncToken); } private async Task DetermineSelectedItemInfoAsync( Task lastModelTask, - int delay, SnapshotPoint caretPosition, CancellationToken cancellationToken) { // First wait the delay before doing any other work. That way if we get canceled due to other events (like // the user moving around), we don't end up doing anything, and the next task can take over. - await Task.Delay(delay, cancellationToken).ConfigureAwait(false); + await Task.Delay(TaggerConstants.NearImmediateDelay, cancellationToken).ConfigureAwait(false); var lastModel = await lastModelTask.ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) From aa4b86f2f72fc8f04092c426b15d5ae11167cf8e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 27 Jun 2021 13:29:14 -0700 Subject: [PATCH 2/6] Simplify delay --- .../NavigationBar/NavigationBarController.cs | 14 +++++++------- .../NavigationBarController_ModelComputation.cs | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs index 209a42967370e..4c43c284aa2d3 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs @@ -123,8 +123,8 @@ private void ConnectToWorkspace(Workspace workspace) void ConnectToNewWorkspace() { - // For the first time you open the file, we'll start immediately - StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0); + // For the first time you open the file, kick off the work to determine the nav bars. + StartModelUpdateAndSelectedItemUpdateTasks(); } } @@ -180,7 +180,7 @@ private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs args) if (currentContextDocumentId != null && currentContextDocumentId.ProjectId == args.ProjectId) { - StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0); + StartModelUpdateAndSelectedItemUpdateTasks(); } } } @@ -192,7 +192,7 @@ private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs args) if (currentContextDocumentId != null && currentContextDocumentId == args.DocumentId) { // The context has changed, so update everything. - StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0); + StartModelUpdateAndSelectedItemUpdateTasks(); } } } @@ -208,14 +208,14 @@ private void OnDocumentActiveContextChanged(object? sender, DocumentActiveContex args.OldActiveContextDocumentId == currentContextDocumentId) { // if the active context changed, recompute the types/member as they may be changed as well. - StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0); + StartModelUpdateAndSelectedItemUpdateTasks(); } } private void OnSubjectBufferPostChanged(object? sender, EventArgs e) { AssertIsForeground(); - StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: TaggerConstants.MediumDelay); + StartModelUpdateAndSelectedItemUpdateTasks(); } private void OnCaretMoved(object? sender, EventArgs e) @@ -395,7 +395,7 @@ private async Task ProcessItemSelectionAsync(NavigationBarItem item, Cancellatio // Now that the edit has been done, refresh to make sure everything is up-to-date. // Have to make sure we come back to the main thread for this. AssertIsForeground(); - StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0); + StartModelUpdateAndSelectedItemUpdateTasks(); } } } diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs index e54f627f50641..ece6e7c039a88 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs @@ -35,7 +35,7 @@ internal partial class NavigationBarController /// /// Starts a new task to compute the model based on the current text. /// - private void StartModelUpdateAndSelectedItemUpdateTasks(int modelUpdateDelay) + private void StartModelUpdateAndSelectedItemUpdateTasks() { AssertIsForeground(); @@ -49,21 +49,21 @@ private void StartModelUpdateAndSelectedItemUpdateTasks(int modelUpdateDelay) // Enqueue a new computation for the model var asyncToken = _asyncListener.BeginAsyncOperation(GetType().Name + ".StartModelUpdateTask"); - _modelTask = ComputeModelAfterDelayAsync(_modelTask, textSnapshot, modelUpdateDelay, cancellationToken); + _modelTask = ComputeModelAfterDelayAsync(_modelTask, textSnapshot, cancellationToken); _modelTask.CompletesAsyncOperation(asyncToken); StartSelectedItemUpdateTask(); } private static async Task ComputeModelAfterDelayAsync( - Task modelTask, ITextSnapshot textSnapshot, int modelUpdateDelay, CancellationToken cancellationToken) + Task modelTask, ITextSnapshot textSnapshot, CancellationToken cancellationToken) { var previousModel = await modelTask.ConfigureAwait(false); if (!cancellationToken.IsCancellationRequested) { try { - await Task.Delay(modelUpdateDelay, cancellationToken).ConfigureAwait(false); + await Task.Delay(TaggerConstants.ShortDelay, cancellationToken).ConfigureAwait(false); return await ComputeModelAsync(previousModel, textSnapshot, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) From 16b2d20e6238fa879ad3542a2763e45abee43832 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 27 Jun 2021 16:37:03 -0700 Subject: [PATCH 3/6] Move to a simpler event source system for nav bars. --- .../NavigationBar/NavigationBarController.cs | 123 ++++-------------- ...avigationBarController_ModelComputation.cs | 2 +- 2 files changed, 27 insertions(+), 98 deletions(-) diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs index 4c43c284aa2d3..62c9950eb6d40 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs @@ -7,9 +7,11 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Implementation.Classification; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Tagging; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Editor.Tagging; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -36,7 +38,6 @@ internal partial class NavigationBarController : ForegroundThreadAffinitizedObje private readonly IAsynchronousOperationListener _asyncListener; private bool _disconnected = false; - private Workspace? _workspace; /// /// Latest model and selected items produced once completes and @@ -51,6 +52,8 @@ internal partial class NavigationBarController : ForegroundThreadAffinitizedObje /// private (ImmutableArray projectItems, NavigationBarProjectItem? selectedProjectItem, NavigationBarModel model, NavigationBarSelectedTypeAndMember selectedInfo) _lastPresentedInfo; + private readonly ITaggerEventSource _eventSource; + public NavigationBarController( IThreadingContext threadingContext, INavigationBarPresenter presenter, @@ -70,8 +73,6 @@ public NavigationBarController( presenter.DropDownFocused += OnDropDownFocused; presenter.ItemSelected += OnItemSelected; - subjectBuffer.PostChanged += OnSubjectBufferPostChanged; - // Initialize the tasks to be an empty model so we never have to deal with a null case. _latestModelAndSelectedInfo_OnlyAccessOnUIThread.model = new( ImmutableArray.Empty, @@ -80,70 +81,53 @@ public NavigationBarController( _latestModelAndSelectedInfo_OnlyAccessOnUIThread.selectedInfo = new(typeItem: null, memberItem: null); _modelTask = Task.FromResult(_latestModelAndSelectedInfo_OnlyAccessOnUIThread.model); + + _eventSource = new CompilationAvailableTaggerEventSource( + subjectBuffer, + asyncListener, + TaggerEventSources.OnTextChanged(subjectBuffer), + TaggerEventSources.OnDocumentActiveContextChanged(subjectBuffer), + TaggerEventSources.OnWorkspaceChanged(subjectBuffer, asyncListener), + TaggerEventSources.OnWorkspaceRegistrationChanged(subjectBuffer)); + _eventSource.Changed += OnEventSourceChanged; + _eventSource.Connect(); } public void SetWorkspace(Workspace? newWorkspace) { - DisconnectFromWorkspace(); - if (newWorkspace != null) - { - ConnectToWorkspace(newWorkspace); - } + StartModelUpdateAndSelectedItemUpdateTasks(); } - private void ConnectToWorkspace(Workspace workspace) + private void StartModelUpdateAndSelectedItemUpdateTasks() { - // If we disconnected before the workspace ever connected, just disregard + // If we're disconnected , just disregard if (_disconnected) - { return; - } - - _workspace = workspace; - _workspace.WorkspaceChanged += this.OnWorkspaceChanged; - _workspace.DocumentActiveContextChanged += this.OnDocumentActiveContextChanged; if (IsForeground()) { - ConnectToNewWorkspace(); + StartModelUpdateAndSelectedItemUpdateTasksOnUIThread(); } else { - var asyncToken = _asyncListener.BeginAsyncOperation(nameof(ConnectToWorkspace)); + var asyncToken = _asyncListener.BeginAsyncOperation(nameof(StartModelUpdateAndSelectedItemUpdateTasks)); Task.Run(async () => { await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); - - ConnectToNewWorkspace(); + StartModelUpdateAndSelectedItemUpdateTasksOnUIThread(); }).CompletesAsyncOperation(asyncToken); } - - return; - - void ConnectToNewWorkspace() - { - // For the first time you open the file, kick off the work to determine the nav bars. - StartModelUpdateAndSelectedItemUpdateTasks(); - } } - private void DisconnectFromWorkspace() + private void OnEventSourceChanged(object? sender, TaggerEventArgs e) { - if (_workspace != null) - { - _workspace.DocumentActiveContextChanged -= this.OnDocumentActiveContextChanged; - _workspace.WorkspaceChanged -= this.OnWorkspaceChanged; - _workspace = null; - } + StartModelUpdateAndSelectedItemUpdateTasks(); } public void Disconnect() { AssertIsForeground(); - DisconnectFromWorkspace(); - - _subjectBuffer.PostChanged -= OnSubjectBufferPostChanged; _presenter.CaretMoved -= OnCaretMoved; _presenter.ViewFocused -= OnViewFocused; @@ -153,6 +137,9 @@ public void Disconnect() _presenter.Disconnect(); + _eventSource.Changed -= OnEventSourceChanged; + _eventSource.Disconnect(); + _disconnected = true; // Cancel off any remaining background work @@ -160,64 +147,6 @@ public void Disconnect() _selectedItemInfoTaskCancellationSource.Cancel(); } - private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs args) - { - // We're getting an event for a workspace we already disconnected from - if (args.NewSolution.Workspace != _workspace) - { - return; - } - - // If the displayed project is being renamed, retrigger the update - if (args.Kind == WorkspaceChangeKind.ProjectChanged && args.ProjectId != null) - { - var oldProject = args.OldSolution.GetRequiredProject(args.ProjectId); - var newProject = args.NewSolution.GetRequiredProject(args.ProjectId); - - if (oldProject.Name != newProject.Name) - { - var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer()); - - if (currentContextDocumentId != null && currentContextDocumentId.ProjectId == args.ProjectId) - { - StartModelUpdateAndSelectedItemUpdateTasks(); - } - } - } - - if (args.Kind == WorkspaceChangeKind.DocumentChanged && - args.OldSolution == args.NewSolution) - { - var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer()); - if (currentContextDocumentId != null && currentContextDocumentId == args.DocumentId) - { - // The context has changed, so update everything. - StartModelUpdateAndSelectedItemUpdateTasks(); - } - } - } - - private void OnDocumentActiveContextChanged(object? sender, DocumentActiveContextChangedEventArgs args) - { - AssertIsForeground(); - if (args.Solution.Workspace != _workspace) - return; - - var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer()); - if (args.NewActiveContextDocumentId == currentContextDocumentId || - args.OldActiveContextDocumentId == currentContextDocumentId) - { - // if the active context changed, recompute the types/member as they may be changed as well. - StartModelUpdateAndSelectedItemUpdateTasks(); - } - } - - private void OnSubjectBufferPostChanged(object? sender, EventArgs e) - { - AssertIsForeground(); - StartModelUpdateAndSelectedItemUpdateTasks(); - } - private void OnCaretMoved(object? sender, EventArgs e) { AssertIsForeground(); @@ -395,7 +324,7 @@ private async Task ProcessItemSelectionAsync(NavigationBarItem item, Cancellatio // Now that the edit has been done, refresh to make sure everything is up-to-date. // Have to make sure we come back to the main thread for this. AssertIsForeground(); - StartModelUpdateAndSelectedItemUpdateTasks(); + StartModelUpdateAndSelectedItemUpdateTasksOnUIThread(); } } } diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs index ece6e7c039a88..021c719c3bb71 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs @@ -35,7 +35,7 @@ internal partial class NavigationBarController /// /// Starts a new task to compute the model based on the current text. /// - private void StartModelUpdateAndSelectedItemUpdateTasks() + private void StartModelUpdateAndSelectedItemUpdateTasksOnUIThread() { AssertIsForeground(); From b97477b5520d5e063b62dd18b0d210ae04d60342 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 27 Jun 2021 16:40:50 -0700 Subject: [PATCH 4/6] remove semantic version check --- .../NavigationBar/NavigationBarController.cs | 5 +---- ...avigationBarController_ModelComputation.cs | 21 ++++--------------- .../NavigationBar/NavigationBarModel.cs | 11 +--------- 3 files changed, 6 insertions(+), 31 deletions(-) diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs index 62c9950eb6d40..ae6d72a17c4df 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs @@ -74,10 +74,7 @@ public NavigationBarController( presenter.ItemSelected += OnItemSelected; // Initialize the tasks to be an empty model so we never have to deal with a null case. - _latestModelAndSelectedInfo_OnlyAccessOnUIThread.model = new( - ImmutableArray.Empty, - semanticVersionStamp: default, - itemService: null!); + _latestModelAndSelectedInfo_OnlyAccessOnUIThread.model = new(ImmutableArray.Empty, itemService: null!); _latestModelAndSelectedInfo_OnlyAccessOnUIThread.selectedInfo = new(typeItem: null, memberItem: null); _modelTask = Task.FromResult(_latestModelAndSelectedInfo_OnlyAccessOnUIThread.model); diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs index 021c719c3bb71..c1d503ef55da3 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController_ModelComputation.cs @@ -64,7 +64,7 @@ private static async Task ComputeModelAfterDelayAsync( try { await Task.Delay(TaggerConstants.ShortDelay, cancellationToken).ConfigureAwait(false); - return await ComputeModelAsync(previousModel, textSnapshot, cancellationToken).ConfigureAwait(false); + return await ComputeModelAsync(textSnapshot, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -83,8 +83,7 @@ private static async Task ComputeModelAfterDelayAsync( /// /// Computes a model for the given snapshot. /// - private static async Task ComputeModelAsync( - NavigationBarModel lastCompletedModel, ITextSnapshot snapshot, CancellationToken cancellationToken) + private static async Task ComputeModelAsync(ITextSnapshot snapshot, CancellationToken cancellationToken) { // Ensure we switch to the threadpool before calling GetDocumentWithFrozenPartialSemantics. It ensures // that any IO that performs is not potentially on the UI thread. @@ -103,27 +102,15 @@ private static async Task ComputeModelAsync( var languageService = document.GetLanguageService(); if (languageService != null) { - // check whether we can re-use lastCompletedModel. otherwise, update lastCompletedModel here. - // the model should be only updated here - if (lastCompletedModel != null) - { - var semanticVersion = await document.Project.GetDependentSemanticVersionAsync(CancellationToken.None).ConfigureAwait(false); - if (lastCompletedModel.SemanticVersionStamp == semanticVersion && SpanStillValid(lastCompletedModel, snapshot, cancellationToken)) - { - // it looks like we can re-use previous model - return lastCompletedModel; - } - } - using (Logger.LogBlock(FunctionId.NavigationBar_ComputeModelAsync, cancellationToken)) { var items = await languageService.GetItemsAsync(document, snapshot, cancellationToken).ConfigureAwait(false); var version = await document.Project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false); - return new NavigationBarModel(items, version, languageService); + return new NavigationBarModel(items, languageService); } } - return new NavigationBarModel(ImmutableArray.Empty, new VersionStamp(), null); + return new NavigationBarModel(ImmutableArray.Empty, itemService: null); } /// diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarModel.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarModel.cs index 99faf5fad32cd..eab226b7868c9 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarModel.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarModel.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Editor.Implementation.NavigationBar { @@ -11,19 +10,11 @@ internal sealed class NavigationBarModel { public ImmutableArray Types { get; } - /// - /// The VersionStamp of the project when this model was computed. - /// - public VersionStamp SemanticVersionStamp { get; } - public INavigationBarItemService ItemService { get; } - public NavigationBarModel(ImmutableArray types, VersionStamp semanticVersionStamp, INavigationBarItemService itemService) + public NavigationBarModel(ImmutableArray types, INavigationBarItemService itemService) { - Contract.ThrowIfNull(types); - this.Types = types; - this.SemanticVersionStamp = semanticVersionStamp; this.ItemService = itemService; } } From e3ea8d99e57f39baa119a2e54c004fceae1def0d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 27 Jun 2021 16:48:07 -0700 Subject: [PATCH 5/6] Docs --- .../NavigationBar/NavigationBarController.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs index ae6d72a17c4df..7fb36711f61e3 100644 --- a/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs +++ b/src/EditorFeatures/Core/Implementation/NavigationBar/NavigationBarController.cs @@ -52,6 +52,9 @@ internal partial class NavigationBarController : ForegroundThreadAffinitizedObje /// private (ImmutableArray projectItems, NavigationBarProjectItem? selectedProjectItem, NavigationBarModel model, NavigationBarSelectedTypeAndMember selectedInfo) _lastPresentedInfo; + /// + /// Source of events that should cause us to update the nav bar model with new information. + /// private readonly ITaggerEventSource _eventSource; public NavigationBarController( @@ -79,12 +82,18 @@ public NavigationBarController( _modelTask = Task.FromResult(_latestModelAndSelectedInfo_OnlyAccessOnUIThread.model); + // Use 'compilation available' as that may produce different results from the initial 'frozen partial' + // snapshot we use. _eventSource = new CompilationAvailableTaggerEventSource( subjectBuffer, asyncListener, + // Any time an edit happens, recompute as the nav bar items may have changed. TaggerEventSources.OnTextChanged(subjectBuffer), + // Switching what is the active context may change the nav bar contents. TaggerEventSources.OnDocumentActiveContextChanged(subjectBuffer), + // Many workspace changes may need us to change the items (like options changing, or project renaming). TaggerEventSources.OnWorkspaceChanged(subjectBuffer, asyncListener), + // Once we hook this buffer up to the workspace, then we can start computing the nav bar items. TaggerEventSources.OnWorkspaceRegistrationChanged(subjectBuffer)); _eventSource.Changed += OnEventSourceChanged; _eventSource.Connect(); @@ -98,7 +107,7 @@ public void SetWorkspace(Workspace? newWorkspace) private void StartModelUpdateAndSelectedItemUpdateTasks() { - // If we're disconnected , just disregard + // If we're disconnected, just disregard. if (_disconnected) return; From ba968b8ec632d097b7331a719821b6f7f9abf9bc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 28 Jun 2021 09:26:47 -0700 Subject: [PATCH 6/6] Fix test --- src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb b/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb index c408f4ca61337..0e2fbcb18e492 100644 --- a/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb +++ b/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb @@ -59,7 +59,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.NavigationBar Dim items = Await service.GetItemsAsync(document, snapshot, Nothing) Dim hostDocument = workspace.Documents.Single(Function(d) d.CursorPosition.HasValue) - Dim model As New NavigationBarModel(items.ToImmutableArray(), VersionStamp.Create(), service) + Dim model As New NavigationBarModel(items.ToImmutableArray(), service) Dim selectedItems = NavigationBarController.ComputeSelectedTypeAndMember(model, New SnapshotPoint(hostDocument.GetTextBuffer().CurrentSnapshot, hostDocument.CursorPosition.Value), Nothing) Dim isCaseSensitive = document.GetLanguageService(Of ISyntaxFactsService)().IsCaseSensitive