Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only start scanning for task-list items once the Task-List window is actually open. #64543

Merged
merged 7 commits into from
Oct 6, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from Dabid Pugh, this is the correct way to both determine if hte task-list is actually visible, and register to find out if it is visible if not.

{
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