Skip to content

Commit

Permalink
Merge pull request #64543 from CyrusNajmabadi/taskSubscribe
Browse files Browse the repository at this point in the history
Only start scanning for task-list items once the Task-List window is actually open.
  • Loading branch information
CyrusNajmabadi committed Oct 6, 2022
2 parents 1f50f9a + b073157 commit 75bbc51
Showing 1 changed file with 42 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.TaskList;
using Microsoft.VisualStudio.LanguageServices.ExternalAccess.VSTypeScript.Api;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using TaskListItem = Microsoft.CodeAnalysis.TaskList.TaskListItem;

namespace Microsoft.VisualStudio.LanguageServices.TaskList
{
Expand All @@ -30,6 +32,7 @@ internal class VisualStudioTaskListService :
{
private readonly IThreadingContext _threadingContext;
private readonly VisualStudioWorkspaceImpl _workspace;
private readonly IAsyncServiceProvider _asyncServiceProvider;
private readonly EventListenerTracker<ITaskListProvider> _eventListenerTracker;
private readonly TaskListListener _listener;

Expand All @@ -42,10 +45,12 @@ public VisualStudioTaskListService(
VisualStudioWorkspaceImpl workspace,
IGlobalOptionService globalOptions,
IAsynchronousOperationListenerProvider asynchronousOperationListenerProvider,
SVsServiceProvider asyncServiceProvider,
[ImportMany] IEnumerable<Lazy<IEventListener, EventListenerMetadata>> eventListeners)
{
_threadingContext = threadingContext;
_workspace = workspace;
_asyncServiceProvider = (IAsyncServiceProvider)asyncServiceProvider;
_eventListenerTracker = new EventListenerTracker<ITaskListProvider>(eventListeners, WellKnownEventListeners.TaskListProvider);

_listener = new TaskListListener(
Expand Down Expand Up @@ -77,6 +82,12 @@ private async Task StartAsync(Workspace workspace)
var workspaceStatus = workspace.Services.GetRequiredService<IWorkspaceStatusService>();
await workspaceStatus.WaitUntilFullyLoadedAsync(_threadingContext.DisposalToken).ConfigureAwait(false);

// Wait until the task list is actually visible so that we don't perform pointless work analyzing files
// when the user would not even see the results. When we actually do register the analyer (in
// _listener.Start below), solution-crawler will reanalyze everything with this analayzer, so it will
// still find and present all the relevant items to the user.
await WaitUntilTaskListActivatedAsync().ConfigureAwait(false);

// Now that we've started, let the VS todo list know to start listening to us
_eventListenerTracker.EnsureEventListener(_workspace, this);

Expand All @@ -93,6 +104,36 @@ private async Task StartAsync(Workspace workspace)
}
}

private async Task WaitUntilTaskListActivatedAsync()
{
var cancellationToken = _threadingContext.DisposalToken;
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
var taskList = await _asyncServiceProvider.GetServiceAsync<SVsTaskList, ITaskList>(_threadingContext.JoinableTaskFactory).ConfigureAwait(true);

var control = taskList.TableControl.Control;

// if control is already visible, we can proceed to collect task list items.
if (control.IsVisible)
return;

// otherwise, wait for it to become visible.
var taskSource = new TaskCompletionSource<bool>();
control.IsVisibleChanged += Control_IsVisibleChanged;

await taskSource.Task.ConfigureAwait(false);

return;

void Control_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
if (control.IsVisible)
{
control.IsVisibleChanged -= Control_IsVisibleChanged;
taskSource.TrySetResult(true);
}
}
}

public ImmutableArray<TaskListItem> GetTaskListItems(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken)
=> _listener.GetTaskListItems(documentId);
}
Expand Down

0 comments on commit 75bbc51

Please sign in to comment.