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

Remove usages of ForegroundNotificationService in favor of JTF. #52812

Merged
merged 14 commits into from
Apr 22, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

using System.Linq;
using System.Runtime.ExceptionServices;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Shared.TestHooks;
Expand Down Expand Up @@ -41,7 +40,6 @@ public static (TestWorkspace workspace, VisualStudioWorkspace extraWorkspaceToDi

var visualStudioWorkspaceMock = new MockVisualStudioWorkspace(workspace);
var threadingContext = workspace.ExportProvider.GetExportedValue<IThreadingContext>();
var notificationService = workspace.ExportProvider.GetExportedValue<IForegroundNotificationService>();
var listenerProvider = workspace.ExportProvider.GetExportedValue<AsynchronousOperationListenerProvider>();

var state = new CodeModelState(
Expand All @@ -53,7 +51,6 @@ public static (TestWorkspace workspace, VisualStudioWorkspace extraWorkspaceToDi
visualStudioWorkspaceMock,
serviceProvider,
threadingContext,
notificationService,
listenerProvider));

var codeModel = FileCodeModel.Create(state, null, document, new MockTextManagerAdapter()).Handle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,17 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation
internal class VisualStudioInfoBarService : ForegroundThreadAffinitizedObject, IInfoBarService
{
private readonly SVsServiceProvider _serviceProvider;
private readonly IForegroundNotificationService _foregroundNotificationService;
private readonly IAsynchronousOperationListener _listener;

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public VisualStudioInfoBarService(
IThreadingContext threadingContext,
SVsServiceProvider serviceProvider,
IForegroundNotificationService foregroundNotificationService,
IAsynchronousOperationListenerProvider listenerProvider)
: base(threadingContext)
{
_serviceProvider = serviceProvider;
_foregroundNotificationService = foregroundNotificationService;
_listener = listenerProvider.GetListener(FeatureAttribute.InfoBar);
}

Expand All @@ -46,13 +43,12 @@ public void ShowInfoBar(string message, params InfoBarUI[] items)
ThisCanBeCalledOnAnyThread();

// We can be called from any thread since errors can occur anywhere, however we can only construct and InfoBar from the UI thread.
_foregroundNotificationService.RegisterNotification(() =>
System.Threading.Tasks.Task.Run(async () =>
sharwell marked this conversation as resolved.
Show resolved Hide resolved
{
await this.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(ThreadingContext.DisposalToken);
if (TryGetInfoBarData(out var infoBarHost))
{
CreateInfoBar(infoBarHost, message, items);
}
}, _listener.BeginAsyncOperation(nameof(ShowInfoBar)), ThreadingContext.DisposalToken);
}, ThreadingContext.DisposalToken).CompletesAsyncOperation(_listener.BeginAsyncOperation(nameof(ShowInfoBar)));
}

private bool TryGetInfoBarData(out IVsInfoBarHost infoBarHost)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Shared.TestHooks;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
{
Expand Down Expand Up @@ -177,8 +179,11 @@ private void IncludeUpdated(object sender, string fileChanged)
// waiting for the foreground thread to release its lock on the file change service.
// To avoid this, just queue up a Task to do the work on the foreground thread later, after
// the lock on the file change service has been released.
_ruleSetManager._foregroundNotificationService.RegisterNotification(
() => IncludeUpdateCore(), _ruleSetManager._listener.BeginAsyncOperation("IncludeUpdated"), _disposalToken);
Task.Run(async () =>
sharwell marked this conversation as resolved.
Show resolved Hide resolved
{
await _ruleSetManager._threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(_disposalToken);
IncludeUpdateCore();
}, _disposalToken).CompletesAsyncOperation(_ruleSetManager._listener.BeginAsyncOperation("IncludeUpdated"));
}

private void IncludeUpdateCore()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#nullable disable

using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Roslyn.Utilities;
Expand All @@ -13,17 +13,19 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
{
internal sealed partial class VisualStudioRuleSetManager : IWorkspaceService
{
private readonly IThreadingContext _threadingContext;
private readonly FileChangeWatcher _fileChangeWatcher;
private readonly IForegroundNotificationService _foregroundNotificationService;
private readonly IAsynchronousOperationListener _listener;

private readonly ReferenceCountedDisposableCache<string, RuleSetFile> _ruleSetFileMap = new();

public VisualStudioRuleSetManager(
FileChangeWatcher fileChangeWatcher, IForegroundNotificationService foregroundNotificationService, IAsynchronousOperationListener listener)
IThreadingContext threadingContext,
FileChangeWatcher fileChangeWatcher,
IAsynchronousOperationListener listener)
{
_threadingContext = threadingContext;
_fileChangeWatcher = fileChangeWatcher;
_foregroundNotificationService = foregroundNotificationService;
_listener = listener;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,35 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.Collections.Generic;
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
{
[ExportWorkspaceServiceFactory(typeof(VisualStudioRuleSetManager), ServiceLayer.Host), Shared]
internal sealed class VisualStudioRuleSetManagerFactory : IWorkspaceServiceFactory
{
private readonly IThreadingContext _threadingContext;
private readonly FileChangeWatcherProvider _fileChangeWatcherProvider;
private readonly IForegroundNotificationService _foregroundNotificationService;
private readonly IAsynchronousOperationListener _listener;

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public VisualStudioRuleSetManagerFactory(
IThreadingContext threadingContext,
FileChangeWatcherProvider fileChangeWatcherProvider,
IForegroundNotificationService foregroundNotificationService,
IAsynchronousOperationListenerProvider listenerProvider)
{
_threadingContext = threadingContext;
_fileChangeWatcherProvider = fileChangeWatcherProvider;
_foregroundNotificationService = foregroundNotificationService;
_listener = listenerProvider.GetListener(FeatureAttribute.RuleSetEditor);
}

public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
=> new VisualStudioRuleSetManager(_fileChangeWatcherProvider.Watcher, _foregroundNotificationService, _listener);
=> new VisualStudioRuleSetManager(_threadingContext, _fileChangeWatcherProvider.Watcher, _listener);
}
}
14 changes: 6 additions & 8 deletions src/VisualStudio/Core/Impl/CodeModel/ProjectCodeModelFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ internal sealed class ProjectCodeModelFactory : IProjectCodeModelFactory

private readonly IThreadingContext _threadingContext;

private readonly IForegroundNotificationService _notificationService;
private readonly IAsynchronousOperationListener _listener;
private readonly AsyncBatchingWorkQueue<DocumentId> _documentsToFireEventsFor;

Expand All @@ -41,14 +40,12 @@ public ProjectCodeModelFactory(
VisualStudioWorkspace visualStudioWorkspace,
[Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider,
IThreadingContext threadingContext,
IForegroundNotificationService notificationService,
IAsynchronousOperationListenerProvider listenerProvider)
{
_visualStudioWorkspace = visualStudioWorkspace;
_serviceProvider = serviceProvider;
_threadingContext = threadingContext;

_notificationService = notificationService;
_listener = listenerProvider.GetListener(FeatureAttribute.CodeModel);

// Queue up notifications we hear about docs changing. that way we don't have to fire events multiple times
Expand All @@ -66,18 +63,19 @@ public ProjectCodeModelFactory(
_visualStudioWorkspace.WorkspaceChanged += OnWorkspaceChanged;
}

private System.Threading.Tasks.Task ProcessNextDocumentBatchAsync(
private Task ProcessNextDocumentBatchAsync(
ImmutableArray<DocumentId> documentIds, CancellationToken cancellationToken)
{
foreach (var documentId in documentIds)
{
// Now, enqueue foreground work to actually process these documents in a serialized and incremental
// fashion. FireEventsForDocument will actually limit how much time it spends firing events so that it
// doesn't saturate the UI thread.
_notificationService.RegisterNotification(
() => FireEventsForDocument(documentId),
_listener.BeginAsyncOperation("CodeModelEvent"),
cancellationToken);
Task.Run(async () =>
{
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
FireEventsForDocument(documentId);
}, cancellationToken).CompletesAsyncOperation(_listener.BeginAsyncOperation("CodeModelEvent"));
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved
}

return System.Threading.Tasks.Task.CompletedTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Imports System.IO
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editor
Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Shared.TestHooks
Imports Microsoft.CodeAnalysis.Test.Utilities
Expand Down Expand Up @@ -48,7 +49,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim

Dim fileChangeService = New MockVsFileChangeEx
Dim fileChangeWatcher = New FileChangeWatcher(Task.FromResult(Of IVsAsyncFileChangeEx)(fileChangeService))
Dim ruleSetManager = New VisualStudioRuleSetManager(fileChangeWatcher, workspace.ExportProvider.GetExportedValue(Of IForegroundNotificationService)(), AsynchronousOperationListenerProvider.NullListener)
Dim ruleSetManager = New VisualStudioRuleSetManager(workspace.ExportProvider.GetExportedValue(Of IThreadingContext), fileChangeWatcher, AsynchronousOperationListenerProvider.NullListener)
Using visualStudioRuleSet = ruleSetManager.GetOrCreateRuleSet(ruleSetPath)

' Signing up for file change notifications is lazy, so read the rule set to force it.
Expand Down Expand Up @@ -92,7 +93,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim
Using workspace = New TestWorkspace()
Dim fileChangeService = New MockVsFileChangeEx
Dim fileChangeWatcher = New FileChangeWatcher(Task.FromResult(Of IVsAsyncFileChangeEx)(fileChangeService))
Dim ruleSetManager = New VisualStudioRuleSetManager(fileChangeWatcher, workspace.ExportProvider.GetExportedValue(Of IForegroundNotificationService)(), AsynchronousOperationListenerProvider.NullListener)
Dim ruleSetManager = New VisualStudioRuleSetManager(workspace.ExportProvider.GetExportedValue(Of IThreadingContext), fileChangeWatcher, AsynchronousOperationListenerProvider.NullListener)
Using visualStudioRuleSet = ruleSetManager.GetOrCreateRuleSet(ruleSetPath)

' Signing up for file change notifications is lazy, so read the rule set to force it.
Expand Down Expand Up @@ -140,7 +141,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim
Dim listenerProvider = workspace.ExportProvider.GetExportedValue(Of IAsynchronousOperationListenerProvider)
Dim listener = listenerProvider.GetListener("test")

Dim ruleSetManager = New VisualStudioRuleSetManager(fileChangeWatcher, workspace.ExportProvider.GetExportedValue(Of IForegroundNotificationService)(), listener)
Dim ruleSetManager = New VisualStudioRuleSetManager(workspace.ExportProvider.GetExportedValue(Of IThreadingContext), fileChangeWatcher, listener)
Using ruleSet1 = ruleSetManager.GetOrCreateRuleSet(ruleSetPath)
Dim handlerCalled As Boolean = False
AddHandler ruleSet1.Target.Value.UpdatedOnDisk, Sub() handlerCalled = True
Expand Down Expand Up @@ -181,7 +182,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim
Dim listenerProvider = workspace.ExportProvider.GetExportedValue(Of IAsynchronousOperationListenerProvider)
Dim listener = listenerProvider.GetListener("test")

Dim ruleSetManager = New VisualStudioRuleSetManager(fileChangeWatcher, workspace.ExportProvider.GetExportedValue(Of IForegroundNotificationService)(), listener)
Dim ruleSetManager = New VisualStudioRuleSetManager(workspace.ExportProvider.GetExportedValue(Of IThreadingContext), fileChangeWatcher, listener)
Using ruleSet1 = ruleSetManager.GetOrCreateRuleSet(ruleSetPath)

' Signing up for file change notifications is lazy, so read the rule set to force it.
Expand Down Expand Up @@ -226,7 +227,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim
Using workspace = New TestWorkspace()
Dim fileChangeService = New MockVsFileChangeEx
Dim fileChangeWatcher = New FileChangeWatcher(Task.FromResult(Of IVsAsyncFileChangeEx)(fileChangeService))
Dim ruleSetManager = New VisualStudioRuleSetManager(fileChangeWatcher, workspace.ExportProvider.GetExportedValue(Of IForegroundNotificationService)(), AsynchronousOperationListenerProvider.NullListener)
Dim ruleSetManager = New VisualStudioRuleSetManager(workspace.ExportProvider.GetExportedValue(Of IThreadingContext), fileChangeWatcher, AsynchronousOperationListenerProvider.NullListener)
Using ruleSet1 = ruleSetManager.GetOrCreateRuleSet(ruleSetPath)

' Signing up for file change notifications is lazy, so read the rule set to force it.
Expand Down Expand Up @@ -264,7 +265,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim
Using workspace = New TestWorkspace()
Dim fileChangeService = New MockVsFileChangeEx
Dim fileChangeWatcher = New FileChangeWatcher(Task.FromResult(Of IVsAsyncFileChangeEx)(fileChangeService))
Dim ruleSetManager = New VisualStudioRuleSetManager(fileChangeWatcher, workspace.ExportProvider.GetExportedValue(Of IForegroundNotificationService)(), AsynchronousOperationListenerProvider.NullListener)
Dim ruleSetManager = New VisualStudioRuleSetManager(workspace.ExportProvider.GetExportedValue(Of IThreadingContext), fileChangeWatcher, AsynchronousOperationListenerProvider.NullListener)
Using ruleSet = ruleSetManager.GetOrCreateRuleSet(ruleSetPath)

Dim generalDiagnosticOption = ruleSet.Target.Value.GetGeneralDiagnosticOption()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ Imports System.Runtime.CompilerServices
Imports System.Runtime.ExceptionServices
Imports System.Runtime.InteropServices
Imports EnvDTE
Imports EnvDTE80
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editor
Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Shared.TestHooks
Expand Down Expand Up @@ -58,7 +56,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Dim project = workspace.CurrentSolution.Projects.Single()

Dim threadingContext = workspace.ExportProvider.GetExportedValue(Of IThreadingContext)
Dim notificationService = workspace.ExportProvider.GetExportedValue(Of IForegroundNotificationService)
Dim listenerProvider = workspace.ExportProvider.GetExportedValue(Of AsynchronousOperationListenerProvider)()

Dim state = New CodeModelState(
Expand All @@ -70,7 +67,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
mockVisualStudioWorkspace,
mockServiceProvider,
threadingContext,
notificationService,
listenerProvider))

Dim projectCodeModel = DirectCast(state.ProjectCodeModelFactory.CreateProjectCodeModel(project.Id, Nothing), ProjectCodeModel)
Expand Down