|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Composition;
using System.Threading;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion.Data;
namespace Microsoft.VisualStudio.IntegrationTest.Setup
{
[Export]
[Shared]
internal class AsyncCompletionTracker
{
private readonly IAsynchronousOperationListenerProvider _asynchronousOperationListenerProvider;
private readonly IAsyncCompletionBroker _asyncCompletionBroker;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public AsyncCompletionTracker(
IAsynchronousOperationListenerProvider asynchronousOperationListenerProvider,
IAsyncCompletionBroker asyncCompletionBroker)
{
// Store the listener provider, but delay accessing the listener itself since tracking could still be
// disabled during the initialization sequence for integration tests.
_asynchronousOperationListenerProvider = asynchronousOperationListenerProvider;
_asyncCompletionBroker = asyncCompletionBroker;
}
internal void StartListening()
{
_asyncCompletionBroker.CompletionTriggered += HandleAsyncCompletionTriggered;
}
internal void StopListening()
{
_asyncCompletionBroker.CompletionTriggered -= HandleAsyncCompletionTriggered;
}
private void HandleAsyncCompletionTriggered(object sender, CompletionTriggeredEventArgs e)
{
var listener = _asynchronousOperationListenerProvider.GetListener(FeatureAttribute.CompletionSet);
var token = listener.BeginAsyncOperation(nameof(IAsyncCompletionBroker.CompletionTriggered));
e.CompletionSession.Dismissed += ReleaseToken;
e.CompletionSession.ItemCommitted += ReleaseToken;
e.CompletionSession.ItemsUpdated += ReleaseToken;
return;
// Local function
void ReleaseToken(object sender, EventArgs e)
=> Interlocked.Exchange<IAsyncToken?>(ref token, null)?.Dispose();
}
}
}
|