From 494ef047503e729fda923542c13c978e303ee755 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 16 Mar 2022 14:41:24 -0700 Subject: [PATCH 01/36] Move more package initialization to BG. --- .../Diagnostics/DiagnosticProgressReporter.cs | 32 ++++++++-------- .../IVisualStudioDiagnosticAnalyzerService.cs | 6 ++- .../VisualStudioDiagnosticAnalyzerService.cs | 7 ++-- .../Core/Def/IAnalyzerNodeSetup.cs | 6 ++- ...tudioMetadataAsSourceFileSupportService.cs | 21 ++++++---- .../MiscellaneousFilesWorkspace.cs | 34 ++++++++++------- .../RuleSets/RuleSetEventHandler.cs | 3 +- .../VisualStudioAddSolutionItemService.cs | 6 +-- src/VisualStudio/Core/Def/RoslynPackage.cs | 38 +++++++++---------- .../SyncNamespacesCommandHandler.cs | 13 +++++-- ...StudioDiagnosticListTableCommandHandler.cs | 20 +++++++--- .../RemoveUnusedReferencesCommandHandler.cs | 21 ++++++---- .../SolutionExplorer/AnalyzerItemTracker.cs | 33 +++------------- .../SolutionExplorer/AnalyzerNodeSetup.cs | 11 ++++-- .../AnalyzersCommandHandler.cs | 5 ++- 15 files changed, 142 insertions(+), 114 deletions(-) diff --git a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs index 0e53c1bd6904d..bc9995d927682 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs @@ -6,9 +6,9 @@ using System.ComponentModel.Composition; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.SolutionCrawler; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.TaskStatusCenter; using Roslyn.Utilities; @@ -18,9 +18,13 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics internal sealed class TaskCenterSolutionAnalysisProgressReporter { private static readonly TimeSpan s_minimumInterval = TimeSpan.FromMilliseconds(200); + private static readonly TaskHandlerOptions _options = new() + { + Title = ServicesVSResources.Running_low_priority_background_processes, + ActionsAfterCompletion = CompletionActions.None + }; - private readonly IVsTaskStatusCenterService _taskCenterService; - private readonly TaskHandlerOptions _options; + private IVsTaskStatusCenterService? _taskCenterService; #region Fields protected by _lock @@ -29,6 +33,7 @@ internal sealed class TaskCenterSolutionAnalysisProgressReporter /// report UI changes concurrently. /// private readonly object _lock = new(); + private readonly VisualStudioWorkspace _workspace; /// /// Task used to trigger throttled UI updates in an interval @@ -79,20 +84,17 @@ internal sealed class TaskCenterSolutionAnalysisProgressReporter [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public TaskCenterSolutionAnalysisProgressReporter( - SVsTaskStatusCenterService taskStatusCenterService, - IDiagnosticService diagnosticService, - VisualStudioWorkspace workspace) + public TaskCenterSolutionAnalysisProgressReporter(VisualStudioWorkspace workspace) { - _taskCenterService = (IVsTaskStatusCenterService)taskStatusCenterService; - _options = new TaskHandlerOptions() - { - Title = ServicesVSResources.Running_low_priority_background_processes, - ActionsAfterCompletion = CompletionActions.None - }; + _workspace = workspace; + } + + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) + { + _taskCenterService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); - var crawlerService = workspace.Services.GetRequiredService(); - var reporter = crawlerService.GetProgressReporter(workspace); + var crawlerService = _workspace.Services.GetRequiredService(); + var reporter = crawlerService.GetProgressReporter(_workspace); if (reporter.InProgress) { diff --git a/src/VisualStudio/Core/Def/Diagnostics/IVisualStudioDiagnosticAnalyzerService.cs b/src/VisualStudio/Core/Def/Diagnostics/IVisualStudioDiagnosticAnalyzerService.cs index cde726c388d86..14912beeb9c16 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/IVisualStudioDiagnosticAnalyzerService.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/IVisualStudioDiagnosticAnalyzerService.cs @@ -2,9 +2,11 @@ // 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.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; namespace Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics @@ -34,6 +36,6 @@ internal interface IVisualStudioDiagnosticAnalyzerService /// /// Initializes the service. /// - void Initialize(IServiceProvider serviceProvider); + Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken); } } diff --git a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs index a54b89aef1dde..e6e1a14815e45 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs @@ -65,14 +65,15 @@ public VisualStudioDiagnosticAnalyzerService( _globalOptions = globalOptions; } - public void Initialize(IServiceProvider serviceProvider) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _serviceProvider = serviceProvider; + _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Run Code Analysis" menu command for CPS based managed projects. - var menuCommandService = (IMenuCommandService)_serviceProvider.GetService(typeof(IMenuCommandService)); + var menuCommandService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); if (menuCommandService != null) { + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); VisualStudioCommandHandlerHelpers.AddCommand(menuCommandService, RunCodeAnalysisForSelectedProjectCommandId, VSConstants.VSStd2K, OnRunCodeAnalysisForSelectedProject, OnRunCodeAnalysisForSelectedProjectStatus); VisualStudioCommandHandlerHelpers.AddCommand(menuCommandService, ID.RoslynCommands.RunCodeAnalysisForProject, Guids.RoslynGroupId, OnRunCodeAnalysisForSelectedProject, OnRunCodeAnalysisForSelectedProjectStatus); VisualStudioCommandHandlerHelpers.AddCommand(menuCommandService, ID.RoslynCommands.AnalysisScopeDefault, Guids.RoslynGroupId, OnSetAnalysisScopeDefault, OnSetAnalysisScopeDefaultStatus); diff --git a/src/VisualStudio/Core/Def/IAnalyzerNodeSetup.cs b/src/VisualStudio/Core/Def/IAnalyzerNodeSetup.cs index 773de549137f4..8dbac5b13a673 100644 --- a/src/VisualStudio/Core/Def/IAnalyzerNodeSetup.cs +++ b/src/VisualStudio/Core/Def/IAnalyzerNodeSetup.cs @@ -4,7 +4,9 @@ #nullable disable -using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Shell; namespace Microsoft.VisualStudio.LanguageServices { @@ -13,7 +15,7 @@ namespace Microsoft.VisualStudio.LanguageServices /// internal interface IAnalyzerNodeSetup { - void Initialize(IServiceProvider serviceProvider); + Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken); void Unregister(); } } diff --git a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs index fb0c644ca17c1..d9abf55bd9665 100644 --- a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs +++ b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs @@ -6,6 +6,9 @@ using System; using System.ComponentModel.Composition; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.MetadataAsSource; using Microsoft.VisualStudio.Shell; @@ -16,20 +19,24 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation [Export(typeof(VisualStudioMetadataAsSourceFileSupportService))] internal sealed class VisualStudioMetadataAsSourceFileSupportService : IVsSolutionEvents { + private readonly IThreadingContext _threadingContext; private readonly IMetadataAsSourceFileService _metadataAsSourceFileService; -#pragma warning disable IDE0052 // Remove unread private members - Used to store the AdviseSolutionEvents cookie. - private readonly uint _eventCookie; -#pragma warning restore IDE0052 // Remove unread private members - [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VisualStudioMetadataAsSourceFileSupportService(SVsServiceProvider serviceProvider, IMetadataAsSourceFileService metadataAsSourceFileService) + public VisualStudioMetadataAsSourceFileSupportService( + IThreadingContext threadingContext, + IMetadataAsSourceFileService metadataAsSourceFileService) { + _threadingContext = threadingContext; _metadataAsSourceFileService = metadataAsSourceFileService; + } - var solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution)); - ErrorHandler.ThrowOnFailure(solution.AdviseSolutionEvents(this, out _eventCookie)); + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) + { + var solution = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + ErrorHandler.ThrowOnFailure(solution.AdviseSolutionEvents(this, out _)); } public int OnAfterCloseSolution(object pUnkReserved) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs index c4a3abf31ebce..b7f14fe8417e6 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs @@ -12,6 +12,8 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Features.Workspaces; @@ -33,10 +35,12 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem [Export(typeof(MiscellaneousFilesWorkspace))] internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IRunningDocumentTableEventListener { + private readonly IThreadingContext _threadingContext; + private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactoryService; private readonly IMetadataAsSourceFileService _fileTrackingMetadataAsSourceService; - private readonly Lazy _lazyTextManager; - private readonly RunningDocumentTableEventTracker _runningDocumentTableEventTracker; + private IVsTextManager _textManager; + private RunningDocumentTableEventTracker _runningDocumentTableEventTracker; private readonly Dictionary _languageInformationByLanguageGuid = new(); @@ -62,25 +66,29 @@ public MiscellaneousFilesWorkspace( IThreadingContext threadingContext, IVsEditorAdaptersFactoryService editorAdaptersFactoryService, IMetadataAsSourceFileService fileTrackingMetadataAsSourceService, - VisualStudioWorkspace visualStudioWorkspace, - SVsServiceProvider serviceProvider) + VisualStudioWorkspace visualStudioWorkspace) : base(visualStudioWorkspace.Services.HostServices, WorkspaceKind.MiscellaneousFiles) { _foregroundThreadAffinitization = new ForegroundThreadAffinitizedObject(threadingContext, assertIsForeground: false); + _threadingContext = threadingContext; + _editorAdaptersFactoryService = editorAdaptersFactoryService; _fileTrackingMetadataAsSourceService = fileTrackingMetadataAsSourceService; - _lazyTextManager = new Lazy(() => - { - _foregroundThreadAffinitization.AssertIsForeground(); - return (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager)); - }); - - var runningDocumentTable = (IVsRunningDocumentTable)serviceProvider.GetService(typeof(SVsRunningDocumentTable)); - _runningDocumentTableEventTracker = new RunningDocumentTableEventTracker(threadingContext, editorAdaptersFactoryService, runningDocumentTable, this); _metadataReferences = ImmutableArray.CreateRange(CreateMetadataReferences()); } + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) + { + _textManager = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var runningDocumentTable = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + + _runningDocumentTableEventTracker = new RunningDocumentTableEventTracker( + _threadingContext, _editorAdaptersFactoryService, runningDocumentTable, this); + } + void IRunningDocumentTableEventListener.OnOpenDocument(string moniker, ITextBuffer textBuffer, IVsHierarchy _, IVsWindowFrame __) => TrackOpenedDocument(moniker, textBuffer); void IRunningDocumentTableEventListener.OnCloseDocument(string moniker) => TryUntrackClosingDocument(moniker); @@ -113,7 +121,7 @@ private LanguageInformation TryGetLanguageInformation(string filename) { LanguageInformation languageInformation = null; - if (ErrorHandler.Succeeded(_lazyTextManager.Value.MapFilenameToLanguageSID(filename, out var fileLanguageGuid))) + if (ErrorHandler.Succeeded(_textManager.MapFilenameToLanguageSID(filename, out var fileLanguageGuid))) { _languageInformationByLanguageGuid.TryGetValue(fileLanguageGuid, out languageInformation); } diff --git a/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs b/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs index aa3a08a88213c..e79de55df864a 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs @@ -10,6 +10,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Shell; @@ -34,7 +35,7 @@ public RuleSetEventHandler( _serviceProvider = serviceProvider; } - public void Register() + public async Task RegisterAsync(CancellationToken cancellationToken) { if (!_eventsHookedUp) { diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs index 4f4b86b9a9e43..681a1d7a82666 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs @@ -41,10 +41,10 @@ public VisualStudioAddSolutionItemService( _fileChangeTrackers = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); } - public void Initialize(IServiceProvider serviceProvider) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - _dte = (DTE)serviceProvider.GetService(typeof(DTE)); - _fileChangeService = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx)); + _dte = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _fileChangeService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); } public void TrackFilePathAndAddSolutionItemWhenFileCreated(string filePath) diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 1c0fae5a5d8f0..e276387dd4e07 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -191,34 +191,34 @@ private void InitializeColors() protected override async Task LoadComponentsAsync(CancellationToken cancellationToken) { - await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + await TaskScheduler.Default; - await GetServiceAsync(typeof(SVsTaskStatusCenterService)).ConfigureAwait(true); - await GetServiceAsync(typeof(SVsErrorList)).ConfigureAwait(true); - await GetServiceAsync(typeof(SVsSolution)).ConfigureAwait(true); - await GetServiceAsync(typeof(SVsShell)).ConfigureAwait(true); - await GetServiceAsync(typeof(SVsRunningDocumentTable)).ConfigureAwait(true); - await GetServiceAsync(typeof(SVsTextManager)).ConfigureAwait(true); + await GetServiceAsync(typeof(SVsTaskStatusCenterService)).ConfigureAwait(false); + await GetServiceAsync(typeof(SVsErrorList)).ConfigureAwait(false); + await GetServiceAsync(typeof(SVsSolution)).ConfigureAwait(false); + await GetServiceAsync(typeof(SVsShell)).ConfigureAwait(false); + await GetServiceAsync(typeof(SVsRunningDocumentTable)).ConfigureAwait(false); + await GetServiceAsync(typeof(SVsTextManager)).ConfigureAwait(false); // we need to load it as early as possible since we can have errors from // package from each language very early - this.ComponentModel.GetService(); - this.ComponentModel.GetService().Initialize(this); + await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); - this.ComponentModel.GetService(); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); // The misc files workspace needs to be loaded on the UI thread. This way it will have // the appropriate task scheduler to report events on. this.ComponentModel.GetService(); // Load and initialize the add solution item service so ConfigurationUpdater can use it to create editorconfig files. - this.ComponentModel.GetService().Initialize(this); + await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); - this.ComponentModel.GetService().Initialize(this); - this.ComponentModel.GetService().Initialize(this); - this.ComponentModel.GetService().Initialize(this); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); - LoadAnalyzerNodeComponents(); + await LoadAnalyzerNodeComponentsAsync(cancellationToken).ConfigureAwait(false); LoadComponentsBackgroundAsync(cancellationToken).Forget(); } @@ -320,15 +320,13 @@ private void DisposeVisualStudioServices() } } - private void LoadAnalyzerNodeComponents() + private async Task LoadAnalyzerNodeComponentsAsync(CancellationToken cancellationToken) { - this.ComponentModel.GetService().Initialize(this); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); _ruleSetEventHandler = this.ComponentModel.GetService(); if (_ruleSetEventHandler != null) - { - _ruleSetEventHandler.Register(); - } + await _ruleSetEventHandler.RegisterAsync(cancellationToken).ConfigureAwait(false); } private void UnregisterAnalyzerTracker() diff --git a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs index 431282f6f70d9..60f398f75e12c 100644 --- a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs @@ -7,8 +7,11 @@ using System.ComponentModel.Design; using System.Composition; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -26,6 +29,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.SyncNamespaces internal sealed class SyncNamespacesCommandHandler { private readonly VisualStudioWorkspace _workspace; + private readonly IThreadingContext _threadingContext; private readonly IUIThreadOperationExecutor _threadOperationExecutor; private readonly IGlobalOptionService _globalOptions; private IServiceProvider? _serviceProvider; @@ -33,25 +37,28 @@ internal sealed class SyncNamespacesCommandHandler [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public SyncNamespacesCommandHandler( + IThreadingContext threadingContext, IUIThreadOperationExecutor threadOperationExecutor, VisualStudioWorkspace workspace, IGlobalOptionService globalOptions) { + _threadingContext = threadingContext; _threadOperationExecutor = threadOperationExecutor; _workspace = workspace; _globalOptions = globalOptions; } - public void Initialize(IServiceProvider serviceProvider) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { Contract.ThrowIfNull(serviceProvider); - _serviceProvider = serviceProvider; + _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = (IMenuCommandService)_serviceProvider.GetService(typeof(IMenuCommandService)); + var menuCommandService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); if (menuCommandService != null) { + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); VisualStudioCommandHandlerHelpers.AddCommand(menuCommandService, ID.RoslynCommands.SyncNamespaces, Guids.RoslynGroupId, OnSyncNamespacesForSelectedProject, OnSyncNamespacesForSelectedProjectStatus); } } diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs index 722578c8fa93a..8dc4983b31034 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.CodeFixes.Suppression; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.Implementation; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -32,18 +33,21 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource [Export(typeof(VisualStudioDiagnosticListTableCommandHandler))] internal partial class VisualStudioDiagnosticListTableCommandHandler { + private readonly IThreadingContext _threadingContext; private readonly VisualStudioWorkspace _workspace; private readonly VisualStudioSuppressionFixService _suppressionFixService; private readonly VisualStudioDiagnosticListSuppressionStateService _suppressionStateService; private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor; private readonly IDiagnosticAnalyzerService _diagnosticService; private readonly ICodeActionEditHandlerService _editHandlerService; - private readonly IWpfTableControl? _tableControl; + + private IWpfTableControl? _tableControl; private readonly IAsynchronousOperationListener _listener; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public VisualStudioDiagnosticListTableCommandHandler( + IThreadingContext threadingContext, SVsServiceProvider serviceProvider, VisualStudioWorkspace workspace, IVisualStudioSuppressionFixService suppressionFixService, @@ -53,24 +57,26 @@ public VisualStudioDiagnosticListTableCommandHandler( ICodeActionEditHandlerService editHandlerService, IAsynchronousOperationListenerProvider listenerProvider) { + _threadingContext = threadingContext; _workspace = workspace; _suppressionFixService = (VisualStudioSuppressionFixService)suppressionFixService; _suppressionStateService = (VisualStudioDiagnosticListSuppressionStateService)suppressionStateService; _uiThreadOperationExecutor = uiThreadOperationExecutor; _diagnosticService = diagnosticService; _editHandlerService = editHandlerService; - - var errorList = serviceProvider.GetService(typeof(SVsErrorList)) as IErrorList; - _tableControl = errorList?.TableControl; _listener = listenerProvider.GetListener(FeatureAttribute.ErrorList); } - public void Initialize(IServiceProvider serviceProvider) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { + var errorList = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _tableControl = errorList?.TableControl; + // Add command handlers for bulk suppression commands. - var menuCommandService = (IMenuCommandService)serviceProvider.GetService(typeof(IMenuCommandService)); + var menuCommandService = (IMenuCommandService?)await serviceProvider.GetServiceAsync(typeof(IMenuCommandService)).ConfigureAwait(false); if (menuCommandService != null) { + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); AddErrorListSetSeverityMenuHandlers(menuCommandService); // The Add/Remove suppression(s) have been moved to the VS code analysis layer, so we don't add the commands here. @@ -84,6 +90,8 @@ public void Initialize(IServiceProvider serviceProvider) private void AddErrorListSetSeverityMenuHandlers(IMenuCommandService menuCommandService) { + Contract.ThrowIfFalse(_threadingContext.HasMainThread); + AddCommand(menuCommandService, ID.RoslynCommands.ErrorListSetSeveritySubMenu, delegate { }, OnErrorListSetSeveritySubMenuStatus); // Severity menu items diff --git a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs index 1fad69beb7021..14bcc3cd1ca61 100644 --- a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs @@ -9,8 +9,10 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Options; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.UnusedReferences; @@ -30,40 +32,43 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.UnusedReference internal sealed class RemoveUnusedReferencesCommandHandler { private const string ProjectAssetsFilePropertyName = "ProjectAssetsFile"; - - private readonly Lazy _lazyReferenceCleanupService; + private readonly IThreadingContext _threadingContext; private readonly RemoveUnusedReferencesDialogProvider _unusedReferenceDialogProvider; private readonly VisualStudioWorkspace _workspace; private readonly IGlobalOptionService _globalOptions; private readonly IUIThreadOperationExecutor _threadOperationExecutor; private IServiceProvider? _serviceProvider; + private IReferenceCleanupService ReferenceCleanupService + => _workspace.Services.GetRequiredService(); + [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public RemoveUnusedReferencesCommandHandler( + IThreadingContext threadingContext, RemoveUnusedReferencesDialogProvider unusedReferenceDialogProvider, IUIThreadOperationExecutor threadOperationExecutor, VisualStudioWorkspace workspace, IGlobalOptionService globalOptions) { + _threadingContext = threadingContext; _unusedReferenceDialogProvider = unusedReferenceDialogProvider; _threadOperationExecutor = threadOperationExecutor; _workspace = workspace; _globalOptions = globalOptions; - - _lazyReferenceCleanupService = new(() => workspace.Services.GetRequiredService()); } - public void Initialize(IServiceProvider serviceProvider) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { Contract.ThrowIfNull(serviceProvider); - _serviceProvider = serviceProvider; + _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = (IMenuCommandService)_serviceProvider.GetService(typeof(IMenuCommandService)); + var menuCommandService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); if (menuCommandService != null) { + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); VisualStudioCommandHandlerHelpers.AddCommand(menuCommandService, ID.RoslynCommands.RemoveUnusedReferences, Guids.RoslynGroupId, OnRemoveUnusedReferencesForSelectedProject, OnRemoveUnusedReferencesForSelectedProjectStatus); } } @@ -185,7 +190,7 @@ private ImmutableArray GetUnusedReferencesForProject(Solution s { var unusedReferences = ThreadHelper.JoinableTaskFactory.Run(async () => { - var projectReferences = await _lazyReferenceCleanupService.Value.GetProjectReferencesAsync(projectFilePath, cancellationToken).ConfigureAwait(true); + var projectReferences = await this.ReferenceCleanupService.GetProjectReferencesAsync(projectFilePath, cancellationToken).ConfigureAwait(true); var unusedReferenceAnalysisService = solution.Workspace.Services.GetRequiredService(); return await unusedReferenceAnalysisService.GetUnusedReferencesAsync(solution, projectFilePath, projectAssetsFile, projectReferences, cancellationToken).ConfigureAwait(true); }); diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs index d786d06ae5491..bcd8fb0bf165a 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.ComponentModel.Composition; using System.Linq; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -20,7 +21,6 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplore [Export] internal class AnalyzerItemsTracker : IVsSelectionEvents { - private readonly IServiceProvider _serviceProvider; private IVsMonitorSelection? _vsMonitorSelection = null; private uint _selectionEventsCookie = 0; @@ -28,30 +28,19 @@ internal class AnalyzerItemsTracker : IVsSelectionEvents [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public AnalyzerItemsTracker( - [Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) + public AnalyzerItemsTracker() { - _serviceProvider = serviceProvider; } - public void Register() + public async Task RegisterAsync(IAsyncServiceProvider serviceProvider) { - var vsMonitorSelection = GetMonitorSelection(); - - if (vsMonitorSelection != null) - { - vsMonitorSelection.AdviseSelectionEvents(this, out _selectionEventsCookie); - } + _vsMonitorSelection ??= await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _vsMonitorSelection?.AdviseSelectionEvents(this, out _selectionEventsCookie); } public void Unregister() { - var vsMonitorSelection = GetMonitorSelection(); - - if (vsMonitorSelection != null) - { - vsMonitorSelection.UnadviseSelectionEvents(_selectionEventsCookie); - } + _vsMonitorSelection?.UnadviseSelectionEvents(_selectionEventsCookie); } public IVsHierarchy? SelectedHierarchy { get; private set; } @@ -132,15 +121,5 @@ private static object[] GetSelectedObjects(ISelectionContainer? selectionContain return selectedObjects; } - - private IVsMonitorSelection? GetMonitorSelection() - { - if (_vsMonitorSelection == null) - { - _vsMonitorSelection = _serviceProvider.GetService(typeof(SVsShellMonitorSelection)) as IVsMonitorSelection; - } - - return _vsMonitorSelection; - } } } diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs index fb752c36ba7ae..3b6e5e3026340 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs @@ -5,7 +5,10 @@ using System; using System.ComponentModel.Composition; using System.ComponentModel.Design; +using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.VisualStudio.Shell; namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer { @@ -23,10 +26,12 @@ public AnalyzerNodeSetup(AnalyzerItemsTracker analyzerTracker, AnalyzersCommandH _analyzerCommandHandler = analyzerCommandHandler; } - public void Initialize(IServiceProvider serviceProvider) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _analyzerTracker.Register(); - _analyzerCommandHandler.Initialize((IMenuCommandService)serviceProvider.GetService(typeof(IMenuCommandService))); + await _analyzerTracker.RegisterAsync(serviceProvider).ConfigureAwait(false); + await _analyzerCommandHandler.InitializeAsync( + await serviceProvider.GetServiceAsync().ConfigureAwait(false), + cancellationToken).ConfigureAwait(false); } public void Unregister() diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs index 9bb3f34a2df6b..a2f36a1e8df05 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs @@ -13,6 +13,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using EnvDTE; using Microsoft.CodeAnalysis; @@ -94,10 +95,12 @@ public AnalyzersCommandHandler( /// /// Hook up the context menu handlers. /// - public void Initialize(IMenuCommandService menuCommandService) + public async Task InitializeAsync(IMenuCommandService menuCommandService, CancellationToken cancellationToken) { if (menuCommandService != null) { + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + // Analyzers folder context menu items _addMenuItem = AddCommandHandler(menuCommandService, ID.RoslynCommands.AddAnalyzer, AddAnalyzerHandler); _ = AddCommandHandler(menuCommandService, ID.RoslynCommands.OpenRuleSet, OpenRuleSetHandler); From 22d7247b40f26f2bbf53485297a95109f1686429 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 17 Mar 2022 17:38:47 -0700 Subject: [PATCH 02/36] Lint --- .../Def/Diagnostics/DiagnosticProgressReporter.cs | 2 ++ .../ProjectSystem/RuleSets/RuleSetEventHandler.cs | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs index bc9995d927682..49b7321a769c1 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs @@ -159,6 +159,8 @@ private void UpdateUI(ProgressData progressData) // Start the task center task if not already running. if (_taskHandler == null) { + Contract.ThrowIfNull(_taskCenterService); + // Register a new task handler to handle a new task center task. // Each task handler can only register one task, so we must create a new one each time we start. _taskHandler = _taskCenterService.PreRegister(_options, data: default); diff --git a/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs b/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs index e79de55df864a..dd97f6399c1fe 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs @@ -12,6 +12,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -23,6 +24,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.R [Export(typeof(RuleSetEventHandler))] internal sealed class RuleSetEventHandler : IVsTrackProjectDocumentsEvents2, IVsTrackProjectDocumentsEvents3, IVsTrackProjectDocumentsEvents4 { + private readonly IThreadingContext _threadingContext; private readonly IServiceProvider _serviceProvider; private bool _eventsHookedUp = false; private uint _cookie = 0; @@ -30,8 +32,10 @@ internal sealed class RuleSetEventHandler : IVsTrackProjectDocumentsEvents2, IVs [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public RuleSetEventHandler( + IThreadingContext threadingContext, [Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) { + _threadingContext = threadingContext; _serviceProvider = serviceProvider; } @@ -39,11 +43,14 @@ public async Task RegisterAsync(CancellationToken cancellationToken) { if (!_eventsHookedUp) { - var trackProjectDocuments = (IVsTrackProjectDocuments2)_serviceProvider.GetService(typeof(SVsTrackProjectDocuments)); + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); - if (ErrorHandler.Succeeded(trackProjectDocuments.AdviseTrackProjectDocumentsEvents(this, out _cookie))) + if (!_eventsHookedUp) { - _eventsHookedUp = true; + var trackProjectDocuments = (IVsTrackProjectDocuments2)_serviceProvider.GetService(typeof(SVsTrackProjectDocuments)); + + if (ErrorHandler.Succeeded(trackProjectDocuments.AdviseTrackProjectDocumentsEvents(this, out _cookie))) + _eventsHookedUp = true; } } } From 306b35decf1db0a24b1e9214a33042d4e793bf7f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 17 Mar 2022 20:02:52 -0700 Subject: [PATCH 03/36] More cases --- ...sticListSuppressionStateServiceAccessor.cs | 2 -- src/VisualStudio/Core/Def/RoslynPackage.cs | 1 + ...osticTableControlEventProcessorProvider.cs | 4 ++-- ...ioDiagnosticListSuppressionStateService.cs | 21 ++++++++++++++----- ...StudioDiagnosticListTableCommandHandler.cs | 4 ++-- .../VisualStudioSuppressionFixService.cs | 4 ++-- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/VisualStudio/Core/Def/ExternalAccess/LegacyCodeAnalysis/LegacyCodeAnalysisVisualStudioDiagnosticListSuppressionStateServiceAccessor.cs b/src/VisualStudio/Core/Def/ExternalAccess/LegacyCodeAnalysis/LegacyCodeAnalysisVisualStudioDiagnosticListSuppressionStateServiceAccessor.cs index 934560687eed9..05378f08b14f1 100644 --- a/src/VisualStudio/Core/Def/ExternalAccess/LegacyCodeAnalysis/LegacyCodeAnalysisVisualStudioDiagnosticListSuppressionStateServiceAccessor.cs +++ b/src/VisualStudio/Core/Def/ExternalAccess/LegacyCodeAnalysis/LegacyCodeAnalysisVisualStudioDiagnosticListSuppressionStateServiceAccessor.cs @@ -2,8 +2,6 @@ // 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.Composition; using Microsoft.CodeAnalysis.ExternalAccess.LegacyCodeAnalysis.Api; diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 819bb2fd9ac42..25264ef1ad2bd 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -204,6 +204,7 @@ protected override async Task LoadComponentsAsync(CancellationToken cancellation // package from each language very early await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); diff --git a/src/VisualStudio/Core/Def/TableDataSource/DiagnosticTableControlEventProcessorProvider.cs b/src/VisualStudio/Core/Def/TableDataSource/DiagnosticTableControlEventProcessorProvider.cs index 6d3ebbe4577c9..9e00dbbe68ad9 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/DiagnosticTableControlEventProcessorProvider.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/DiagnosticTableControlEventProcessorProvider.cs @@ -24,9 +24,9 @@ internal partial class DiagnosticTableControlEventProcessorProvider : AbstractTa [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public DiagnosticTableControlEventProcessorProvider( - IVisualStudioDiagnosticListSuppressionStateService suppressionStateService) + VisualStudioDiagnosticListSuppressionStateService suppressionStateService) { - _suppressionStateService = (VisualStudioDiagnosticListSuppressionStateService)suppressionStateService; + _suppressionStateService = suppressionStateService; } protected override EventProcessor CreateEventProcessor() diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs index e34b66bd51341..0c3e101690c6a 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes.Suppression; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -29,11 +30,14 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource /// Service to maintain information about the suppression state of specific set of items in the error list. /// [Export(typeof(IVisualStudioDiagnosticListSuppressionStateService))] + [Export(typeof(VisualStudioDiagnosticListSuppressionStateService))] internal class VisualStudioDiagnosticListSuppressionStateService : IVisualStudioDiagnosticListSuppressionStateService { + private readonly IThreadingContext _threadingContext; private readonly VisualStudioWorkspace _workspace; - private readonly IVsUIShell _shellService; - private readonly IWpfTableControl? _tableControl; + + private IVsUIShell? _shellService; + private IWpfTableControl? _tableControl; private int _selectedActiveItems; private int _selectedSuppressedItems; @@ -45,14 +49,21 @@ internal class VisualStudioDiagnosticListSuppressionStateService : IVisualStudio [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public VisualStudioDiagnosticListSuppressionStateService( - SVsServiceProvider serviceProvider, + IThreadingContext threadingContext, VisualStudioWorkspace workspace) { + _threadingContext = threadingContext; _workspace = workspace; - _shellService = (IVsUIShell)serviceProvider.GetService(typeof(SVsUIShell)); - var errorList = serviceProvider.GetService(typeof(SVsErrorList)) as IErrorList; + } + + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) + { + _shellService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync(throwOnFailure: false).ConfigureAwait(false); _tableControl = errorList?.TableControl; + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + ClearState(); InitializeFromTableControlIfNeeded(); } diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs index 8dc4983b31034..e46001557b69d 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs @@ -51,7 +51,7 @@ public VisualStudioDiagnosticListTableCommandHandler( SVsServiceProvider serviceProvider, VisualStudioWorkspace workspace, IVisualStudioSuppressionFixService suppressionFixService, - IVisualStudioDiagnosticListSuppressionStateService suppressionStateService, + VisualStudioDiagnosticListSuppressionStateService suppressionStateService, IUIThreadOperationExecutor uiThreadOperationExecutor, IDiagnosticAnalyzerService diagnosticService, ICodeActionEditHandlerService editHandlerService, @@ -60,7 +60,7 @@ public VisualStudioDiagnosticListTableCommandHandler( _threadingContext = threadingContext; _workspace = workspace; _suppressionFixService = (VisualStudioSuppressionFixService)suppressionFixService; - _suppressionStateService = (VisualStudioDiagnosticListSuppressionStateService)suppressionStateService; + _suppressionStateService = suppressionStateService; _uiThreadOperationExecutor = uiThreadOperationExecutor; _diagnosticService = diagnosticService; _editHandlerService = editHandlerService; diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index c0603edd00fbe..25e42d0db9d70 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -62,7 +62,7 @@ public VisualStudioSuppressionFixService( IDiagnosticAnalyzerService diagnosticService, ICodeFixService codeFixService, ICodeActionEditHandlerService editHandlerService, - IVisualStudioDiagnosticListSuppressionStateService suppressionStateService, + VisualStudioDiagnosticListSuppressionStateService suppressionStateService, IUIThreadOperationExecutor uiThreadOperationExecutor, IVsHierarchyItemManager vsHierarchyItemManager, IAsynchronousOperationListenerProvider listenerProvider, @@ -72,7 +72,7 @@ public VisualStudioSuppressionFixService( _diagnosticService = diagnosticService; _buildErrorDiagnosticService = workspace.ExternalErrorDiagnosticUpdateSource; _codeFixService = codeFixService; - _suppressionStateService = (VisualStudioDiagnosticListSuppressionStateService)suppressionStateService; + _suppressionStateService = suppressionStateService; _editHandlerService = editHandlerService; _uiThreadOperationExecutor = uiThreadOperationExecutor; _vsHierarchyItemManager = vsHierarchyItemManager; From 235b7f8d04b9a3f928ea704150ccd0f8ae8de489 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 17 Mar 2022 21:53:34 -0700 Subject: [PATCH 04/36] Come back to UI thread before calling vs interface --- src/VisualStudio/Core/Def/RoslynPackage.cs | 2 ++ .../VisualStudioSuppressionFixService.cs | 13 +++++++++---- .../Impl/SolutionExplorer/AnalyzerItemTracker.cs | 9 +++++++-- .../Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 25264ef1ad2bd..c96349cf7b4f8 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -28,6 +28,7 @@ using Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.RuleSets; +using Microsoft.VisualStudio.LanguageServices.Implementation.Suppression; using Microsoft.VisualStudio.LanguageServices.Implementation.SyncNamespaces; using Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource; using Microsoft.VisualStudio.LanguageServices.Implementation.UnusedReferences; @@ -203,6 +204,7 @@ protected override async Task LoadComponentsAsync(CancellationToken cancellation // we need to load it as early as possible since we can have errors from // package from each language very early await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index 25e42d0db9d70..9401a561d9e0e 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -38,10 +38,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Suppression /// Service to compute and apply bulk suppression fixes. /// [Export(typeof(IVisualStudioSuppressionFixService))] + [Export(typeof(VisualStudioSuppressionFixService))] internal sealed class VisualStudioSuppressionFixService : IVisualStudioSuppressionFixService { private readonly VisualStudioWorkspaceImpl _workspace; - private readonly IWpfTableControl? _tableControl; private readonly IAsynchronousOperationListener _listener; private readonly IDiagnosticAnalyzerService _diagnosticService; private readonly ExternalErrorDiagnosticUpdateSource _buildErrorDiagnosticService; @@ -54,6 +54,8 @@ internal sealed class VisualStudioSuppressionFixService : IVisualStudioSuppressi private readonly IHierarchyItemToProjectIdMap _projectMap; private readonly IGlobalOptionService _globalOptions; + private IWpfTableControl? _tableControl; + [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public VisualStudioSuppressionFixService( @@ -78,13 +80,16 @@ public VisualStudioSuppressionFixService( _vsHierarchyItemManager = vsHierarchyItemManager; _fixMultipleOccurencesService = workspace.Services.GetRequiredService(); _projectMap = workspace.Services.GetRequiredService(); - - var errorList = serviceProvider.GetService(typeof(SVsErrorList)) as IErrorList; - _tableControl = errorList?.TableControl; _listener = listenerProvider.GetListener(FeatureAttribute.ErrorList); _globalOptions = globalOptions; } + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) + { + var errorList = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _tableControl = errorList?.TableControl; + } + public bool AddSuppressions(IVsHierarchy? projectHierarchy) { if (_tableControl == null) diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs index bcd8fb0bf165a..83f4f8550663b 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs @@ -6,7 +6,9 @@ using System.Collections.Immutable; using System.ComponentModel.Composition; using System.Linq; +using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -23,18 +25,21 @@ internal class AnalyzerItemsTracker : IVsSelectionEvents { private IVsMonitorSelection? _vsMonitorSelection = null; private uint _selectionEventsCookie = 0; + private readonly IThreadingContext _threadingContext; public event EventHandler? SelectedHierarchyItemChanged; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public AnalyzerItemsTracker() + public AnalyzerItemsTracker(IThreadingContext threadingContext) { + _threadingContext = threadingContext; } - public async Task RegisterAsync(IAsyncServiceProvider serviceProvider) + public async Task RegisterAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { _vsMonitorSelection ??= await serviceProvider.GetServiceAsync().ConfigureAwait(false); + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); _vsMonitorSelection?.AdviseSelectionEvents(this, out _selectionEventsCookie); } diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs index 3b6e5e3026340..3bc2241efcc25 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs @@ -28,7 +28,7 @@ public AnalyzerNodeSetup(AnalyzerItemsTracker analyzerTracker, AnalyzersCommandH public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - await _analyzerTracker.RegisterAsync(serviceProvider).ConfigureAwait(false); + await _analyzerTracker.RegisterAsync(serviceProvider, cancellationToken).ConfigureAwait(false); await _analyzerCommandHandler.InitializeAsync( await serviceProvider.GetServiceAsync().ConfigureAwait(false), cancellationToken).ConfigureAwait(false); From cc292553679833b3b04c6df3bfdd54ec13960efe Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 17 Mar 2022 22:20:24 -0700 Subject: [PATCH 05/36] actually initialize --- src/VisualStudio/Core/Def/RoslynPackage.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index c96349cf7b4f8..41ddff8f52d2f 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -209,10 +209,7 @@ protected override async Task LoadComponentsAsync(CancellationToken cancellation await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); - - // The misc files workspace needs to be loaded on the UI thread. This way it will have - // the appropriate task scheduler to report events on. - this.ComponentModel.GetService(); + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); // Load and initialize the add solution item service so ConfigurationUpdater can use it to create editorconfig files. await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); From 2d279efdf99c64c1cd1efe8113cff387a5b56658 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 17 Mar 2022 22:24:24 -0700 Subject: [PATCH 06/36] front load workspace --- src/VisualStudio/Core/Def/RoslynPackage.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 41ddff8f52d2f..5594564a83199 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -164,6 +164,8 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke var settingsEditorFactory = this.ComponentModel.GetService(); RegisterEditorFactory(settingsEditorFactory); + + await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); } private async Task LoadOptionPersistersAsync(IComponentModel componentModel, CancellationToken cancellationToken) @@ -209,7 +211,6 @@ protected override async Task LoadComponentsAsync(CancellationToken cancellation await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); - await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); // Load and initialize the add solution item service so ConfigurationUpdater can use it to create editorconfig files. await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); From 577a04b95e47add1219b088c13f3e3c20a5a8900 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 17 Mar 2022 23:33:42 -0700 Subject: [PATCH 07/36] REmove arg --- src/VisualStudio/Core/Def/RoslynPackage.cs | 2 +- .../Suppression/VisualStudioSuppressionFixService.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 5594564a83199..d6e363e1c5525 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -206,7 +206,7 @@ protected override async Task LoadComponentsAsync(CancellationToken cancellation // we need to load it as early as possible since we can have errors from // package from each language very early await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); - await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); + await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index 9401a561d9e0e..5ee25d35ef426 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -84,7 +84,7 @@ public VisualStudioSuppressionFixService( _globalOptions = globalOptions; } - public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { var errorList = await serviceProvider.GetServiceAsync().ConfigureAwait(false); _tableControl = errorList?.TableControl; From c62d81c1ca36928405af042f5982a4a661c7af3b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 19 Mar 2022 14:36:55 -0700 Subject: [PATCH 08/36] Use extension --- .../Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs index 83f4f8550663b..368a2956b1e50 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs @@ -38,7 +38,8 @@ public AnalyzerItemsTracker(IThreadingContext threadingContext) public async Task RegisterAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _vsMonitorSelection ??= await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _vsMonitorSelection ??= await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); _vsMonitorSelection?.AdviseSelectionEvents(this, out _selectionEventsCookie); } From db462afeceda1973fc4c8fbb626e4a8363bd1e70 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 19 Mar 2022 14:37:42 -0700 Subject: [PATCH 09/36] Use extension --- .../Core/Def/Diagnostics/DiagnosticProgressReporter.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs index 49b7321a769c1..1e37aa920dd51 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs @@ -6,6 +6,7 @@ using System.ComponentModel.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.VisualStudio.Shell; @@ -33,6 +34,7 @@ internal sealed class TaskCenterSolutionAnalysisProgressReporter /// report UI changes concurrently. /// private readonly object _lock = new(); + private readonly IThreadingContext _threadingContext; private readonly VisualStudioWorkspace _workspace; /// @@ -84,14 +86,18 @@ internal sealed class TaskCenterSolutionAnalysisProgressReporter [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public TaskCenterSolutionAnalysisProgressReporter(VisualStudioWorkspace workspace) + public TaskCenterSolutionAnalysisProgressReporter( + IThreadingContext threadingContext, + VisualStudioWorkspace workspace) { + _threadingContext = threadingContext; _workspace = workspace; } public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - _taskCenterService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _taskCenterService = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); var crawlerService = _workspace.Services.GetRequiredService(); var reporter = crawlerService.GetProgressReporter(_workspace); From d577e8c36861aa5dcf7f2de95395451c6406954e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 19 Mar 2022 14:39:04 -0700 Subject: [PATCH 10/36] Use extension --- .../Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs | 6 ++++-- .../VisualStudioDiagnosticListTableCommandHandler.cs | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs index b7f14fe8417e6..6d31132d379f1 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs @@ -80,8 +80,10 @@ public MiscellaneousFilesWorkspace( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _textManager = await serviceProvider.GetServiceAsync().ConfigureAwait(false); - var runningDocumentTable = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _textManager = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var runningDocumentTable = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs index e46001557b69d..48a417284f726 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs @@ -69,7 +69,8 @@ public VisualStudioDiagnosticListTableCommandHandler( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - var errorList = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); _tableControl = errorList?.TableControl; // Add command handlers for bulk suppression commands. From c11df69aea115de6744c29e97c75a4c2ee65d1a3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 19 Mar 2022 14:42:49 -0700 Subject: [PATCH 11/36] Use extension --- .../VisualStudioDiagnosticAnalyzerService.cs | 3 ++- .../VisualStudioAddSolutionItemService.cs | 3 ++- .../SyncNamespaces/SyncNamespacesCommandHandler.cs | 3 ++- .../RemoveUnusedReferencesCommandHandler.cs | 3 ++- .../Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs | 11 +++++++++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs index 494584e2306c2..e3c6c9a8b0035 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs @@ -70,7 +70,8 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Run Code Analysis" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs index 681a1d7a82666..2dc392a65a218 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs @@ -43,7 +43,8 @@ public VisualStudioAddSolutionItemService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - _dte = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _dte = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); _fileChangeService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); } diff --git a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs index 3f569e135c665..e3089658e394c 100644 --- a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs @@ -55,7 +55,8 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs index 1a781cabc25d6..202a0366f0ffb 100644 --- a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs @@ -65,7 +65,8 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs index 3bc2241efcc25..73fdeba2e070c 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs @@ -7,6 +7,7 @@ using System.ComponentModel.Design; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Shell; @@ -15,13 +16,18 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplore [Export(typeof(IAnalyzerNodeSetup))] internal sealed class AnalyzerNodeSetup : IAnalyzerNodeSetup { + private readonly IThreadingContext _threadingContext; private readonly AnalyzerItemsTracker _analyzerTracker; private readonly AnalyzersCommandHandler _analyzerCommandHandler; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public AnalyzerNodeSetup(AnalyzerItemsTracker analyzerTracker, AnalyzersCommandHandler analyzerCommandHandler) + public AnalyzerNodeSetup( + IThreadingContext threadingContext, + AnalyzerItemsTracker analyzerTracker, + AnalyzersCommandHandler analyzerCommandHandler) { + _threadingContext = threadingContext; _analyzerTracker = analyzerTracker; _analyzerCommandHandler = analyzerCommandHandler; } @@ -30,7 +36,8 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell { await _analyzerTracker.RegisterAsync(serviceProvider, cancellationToken).ConfigureAwait(false); await _analyzerCommandHandler.InitializeAsync( - await serviceProvider.GetServiceAsync().ConfigureAwait(false), + await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); } From 8c11d45d343ec97d3fca005c5ba85a418b46dad3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 19 Mar 2022 14:47:22 -0700 Subject: [PATCH 12/36] Use extension --- .../VisualStudioMetadataAsSourceFileSupportService.cs | 3 ++- .../VisualStudioDiagnosticListSuppressionStateService.cs | 6 ++++-- .../Suppression/VisualStudioSuppressionFixService.cs | 7 ++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs index d9abf55bd9665..3fac6189f742d 100644 --- a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs +++ b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs @@ -34,7 +34,8 @@ public VisualStudioMetadataAsSourceFileSupportService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - var solution = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var solution = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); ErrorHandler.ThrowOnFailure(solution.AdviseSolutionEvents(this, out _)); } diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs index 0c3e101690c6a..d2efa80e7f3bc 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs @@ -58,8 +58,10 @@ public VisualStudioDiagnosticListSuppressionStateService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _shellService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); - var errorList = await serviceProvider.GetServiceAsync(throwOnFailure: false).ConfigureAwait(false); + _shellService = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); _tableControl = errorList?.TableControl; await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index 5ee25d35ef426..ba96088d74752 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -16,6 +16,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.Implementation; using Microsoft.CodeAnalysis.Editor.Implementation.Suggestions; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; @@ -41,6 +42,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Suppression [Export(typeof(VisualStudioSuppressionFixService))] internal sealed class VisualStudioSuppressionFixService : IVisualStudioSuppressionFixService { + private readonly IThreadingContext _threadingContext; private readonly VisualStudioWorkspaceImpl _workspace; private readonly IAsynchronousOperationListener _listener; private readonly IDiagnosticAnalyzerService _diagnosticService; @@ -59,6 +61,7 @@ internal sealed class VisualStudioSuppressionFixService : IVisualStudioSuppressi [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public VisualStudioSuppressionFixService( + IThreadingContext threadingContext, SVsServiceProvider serviceProvider, VisualStudioWorkspaceImpl workspace, IDiagnosticAnalyzerService diagnosticService, @@ -70,6 +73,7 @@ public VisualStudioSuppressionFixService( IAsynchronousOperationListenerProvider listenerProvider, IGlobalOptionService globalOptions) { + _threadingContext = threadingContext; _workspace = workspace; _diagnosticService = diagnosticService; _buildErrorDiagnosticService = workspace.ExternalErrorDiagnosticUpdateSource; @@ -86,7 +90,8 @@ public VisualStudioSuppressionFixService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - var errorList = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); _tableControl = errorList?.TableControl; } From 966d478ffa525f4299d53009dec9a9fd11a8b03d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 19 Mar 2022 14:48:11 -0700 Subject: [PATCH 13/36] Use extension --- .../Def/ProjectSystem/VisualStudioAddSolutionItemService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs index 2dc392a65a218..173094b61ba66 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs @@ -45,7 +45,8 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { _dte = await serviceProvider.GetServiceAsync( _threadingContext.JoinableTaskFactory).ConfigureAwait(false); - _fileChangeService = await serviceProvider.GetServiceAsync().ConfigureAwait(false); + _fileChangeService = await serviceProvider.GetServiceAsync( + _threadingContext.JoinableTaskFactory).ConfigureAwait(false); } public void TrackFilePathAndAddSolutionItemWhenFileCreated(string filePath) From 288d45e85a29b04ab8f9384086b88dda124c56e3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 20 Mar 2022 20:43:11 -0700 Subject: [PATCH 14/36] move --- .../Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs index 6d31132d379f1..041ba747da2f2 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs @@ -39,9 +39,6 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IRunningD private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactoryService; private readonly IMetadataAsSourceFileService _fileTrackingMetadataAsSourceService; - private IVsTextManager _textManager; - private RunningDocumentTableEventTracker _runningDocumentTableEventTracker; - private readonly Dictionary _languageInformationByLanguageGuid = new(); /// @@ -60,6 +57,9 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IRunningD private readonly ForegroundThreadAffinitizedObject _foregroundThreadAffinitization; + private IVsTextManager _textManager; + private RunningDocumentTableEventTracker _runningDocumentTableEventTracker; + [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public MiscellaneousFilesWorkspace( From 067879a6e7b17d252572e40bd62ed7c36c38b14b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 20 Mar 2022 20:44:52 -0700 Subject: [PATCH 15/36] Add comment --- src/VisualStudio/Core/Def/RoslynPackage.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index d4b53d1769aa0..4786fc171d2d1 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -165,6 +165,9 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke var settingsEditorFactory = this.ComponentModel.GetService(); RegisterEditorFactory(settingsEditorFactory); + // Misc workspace has to be up and running by the time our package is usable so that it can track running + // doc events and appropriately map files to/from it and other relevant workspaces (like the + // metadata-as-source workspace). await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); } From 4f9912785c436335480cd94b0de6dcc63f0b23b5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 20 Mar 2022 20:45:44 -0700 Subject: [PATCH 16/36] REvert --- .../Def/SyncNamespaces/SyncNamespacesCommandHandler.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs index e3089658e394c..6f10de75ce194 100644 --- a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs @@ -29,23 +29,23 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.SyncNamespaces internal sealed class SyncNamespacesCommandHandler { private readonly VisualStudioWorkspace _workspace; - private readonly IThreadingContext _threadingContext; private readonly IUIThreadOperationExecutor _threadOperationExecutor; private readonly IGlobalOptionService _globalOptions; + private readonly IThreadingContext _threadingContext; private IServiceProvider? _serviceProvider; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public SyncNamespacesCommandHandler( - IThreadingContext threadingContext, IUIThreadOperationExecutor threadOperationExecutor, VisualStudioWorkspace workspace, - IGlobalOptionService globalOptions) + IGlobalOptionService globalOptions, + IThreadingContext threadingContext) { - _threadingContext = threadingContext; _threadOperationExecutor = threadOperationExecutor; _workspace = workspace; _globalOptions = globalOptions; + _threadingContext = threadingContext; } public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) From 1312d328b615eee14d591a64f387d40a3520409b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 20 Mar 2022 20:49:12 -0700 Subject: [PATCH 17/36] Cleanup --- .../Core/Def/Diagnostics/DiagnosticProgressReporter.cs | 3 +-- .../Diagnostics/VisualStudioDiagnosticAnalyzerService.cs | 3 +-- .../VisualStudioMetadataAsSourceFileSupportService.cs | 3 +-- .../Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs | 6 ++---- .../Def/ProjectSystem/VisualStudioAddSolutionItemService.cs | 6 ++---- .../Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs | 3 +-- .../VisualStudioDiagnosticListSuppressionStateService.cs | 6 ++---- .../VisualStudioDiagnosticListTableCommandHandler.cs | 3 +-- .../Suppression/VisualStudioSuppressionFixService.cs | 3 +-- .../RemoveUnusedReferencesCommandHandler.cs | 3 +-- .../Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs | 3 +-- .../Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs | 3 +-- 12 files changed, 15 insertions(+), 30 deletions(-) diff --git a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs index 1e37aa920dd51..668e1c63e7e01 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/DiagnosticProgressReporter.cs @@ -96,8 +96,7 @@ public TaskCenterSolutionAnalysisProgressReporter( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - _taskCenterService = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + _taskCenterService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); var crawlerService = _workspace.Services.GetRequiredService(); var reporter = crawlerService.GetProgressReporter(_workspace); diff --git a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs index e3c6c9a8b0035..8414e55aa0bb8 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs @@ -70,8 +70,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Run Code Analysis" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs index 3fac6189f742d..509ce6ff28aae 100644 --- a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs +++ b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs @@ -34,8 +34,7 @@ public VisualStudioMetadataAsSourceFileSupportService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - var solution = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var solution = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); ErrorHandler.ThrowOnFailure(solution.AdviseSolutionEvents(this, out _)); } diff --git a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs index 041ba747da2f2..3088cb61a357a 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs @@ -80,10 +80,8 @@ public MiscellaneousFilesWorkspace( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _textManager = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); - var runningDocumentTable = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + _textManager = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var runningDocumentTable = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs index 173094b61ba66..89959bb687a0b 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioAddSolutionItemService.cs @@ -43,10 +43,8 @@ public VisualStudioAddSolutionItemService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - _dte = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); - _fileChangeService = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + _dte = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + _fileChangeService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); } public void TrackFilePathAndAddSolutionItemWhenFileCreated(string filePath) diff --git a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs index 6f10de75ce194..33e8e73bbf733 100644 --- a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs @@ -55,8 +55,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs index d2efa80e7f3bc..d7bf1e20f3912 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs @@ -58,10 +58,8 @@ public VisualStudioDiagnosticListSuppressionStateService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _shellService = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); - var errorList = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); + _shellService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); _tableControl = errorList?.TableControl; await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs index 48a417284f726..8ccc2ba69aea8 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs @@ -69,8 +69,7 @@ public VisualStudioDiagnosticListTableCommandHandler( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - var errorList = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); _tableControl = errorList?.TableControl; // Add command handlers for bulk suppression commands. diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index ba96088d74752..4d371d414d905 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -90,8 +90,7 @@ public VisualStudioSuppressionFixService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - var errorList = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); _tableControl = errorList?.TableControl; } diff --git a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs index 202a0366f0ffb..b3372f97129dc 100644 --- a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs @@ -65,8 +65,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs index 368a2956b1e50..2bcf7456dd0da 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs @@ -38,8 +38,7 @@ public AnalyzerItemsTracker(IThreadingContext threadingContext) public async Task RegisterAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _vsMonitorSelection ??= await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false); + _vsMonitorSelection ??= await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); _vsMonitorSelection?.AdviseSelectionEvents(this, out _selectionEventsCookie); } diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs index 73fdeba2e070c..99fd0e62bd282 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs @@ -36,8 +36,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell { await _analyzerTracker.RegisterAsync(serviceProvider, cancellationToken).ConfigureAwait(false); await _analyzerCommandHandler.InitializeAsync( - await serviceProvider.GetServiceAsync( - _threadingContext.JoinableTaskFactory).ConfigureAwait(false), + await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); } From c00d7f3272c140bb236ccbcefe5fa45533c6d338 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 20 Mar 2022 20:51:17 -0700 Subject: [PATCH 18/36] Add comment --- .../VisualStudioMetadataAsSourceFileSupportService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs index 509ce6ff28aae..73e6586c4d365 100644 --- a/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs +++ b/src/VisualStudio/Core/Def/Implementation/VisualStudioMetadataAsSourceFileSupportService.cs @@ -36,6 +36,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell { var solution = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + // Intentionally ignore the event-cookie we get back out. We never stop listening to solution events. ErrorHandler.ThrowOnFailure(solution.AdviseSolutionEvents(this, out _)); } From 21778974ef828693e8d167f34256ad550b4610b8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 20 Mar 2022 20:52:33 -0700 Subject: [PATCH 19/36] reorder --- .../VisualStudioDiagnosticListTableCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs index 8ccc2ba69aea8..cc1337b280315 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs @@ -40,9 +40,9 @@ internal partial class VisualStudioDiagnosticListTableCommandHandler private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor; private readonly IDiagnosticAnalyzerService _diagnosticService; private readonly ICodeActionEditHandlerService _editHandlerService; + private readonly IAsynchronousOperationListener _listener; private IWpfTableControl? _tableControl; - private readonly IAsynchronousOperationListener _listener; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] From 7e143400c03777cba84c00395aec973782c8b82f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 20 Mar 2022 20:53:39 -0700 Subject: [PATCH 20/36] reorder --- .../Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs index 2bcf7456dd0da..a5d14f43750f0 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs @@ -23,9 +23,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplore [Export] internal class AnalyzerItemsTracker : IVsSelectionEvents { + private readonly IThreadingContext _threadingContext; + private IVsMonitorSelection? _vsMonitorSelection = null; private uint _selectionEventsCookie = 0; - private readonly IThreadingContext _threadingContext; public event EventHandler? SelectedHierarchyItemChanged; From f65727c24c5cfa20b080c4ce2f819f0d692454e4 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 23 Mar 2022 11:27:35 -0700 Subject: [PATCH 21/36] Remove unnecessary switch to UI thread --- .../Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs | 5 ++--- .../Def/ProjectSystem/RunningDocumentTableEventTracker.cs | 6 +++++- src/VisualStudio/Core/Def/RoslynPackage.cs | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs index 3088cb61a357a..98025ac542f43 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs @@ -78,13 +78,12 @@ public MiscellaneousFilesWorkspace( _metadataReferences = ImmutableArray.CreateRange(CreateMetadataReferences()); } - public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) + public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { + await TaskScheduler.Default; _textManager = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); var runningDocumentTable = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); - await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); - _runningDocumentTableEventTracker = new RunningDocumentTableEventTracker( _threadingContext, _editorAdaptersFactoryService, runningDocumentTable, this); } diff --git a/src/VisualStudio/Core/Def/ProjectSystem/RunningDocumentTableEventTracker.cs b/src/VisualStudio/Core/Def/ProjectSystem/RunningDocumentTableEventTracker.cs index 6a5472bbc838e..3b869fe35f369 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/RunningDocumentTableEventTracker.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/RunningDocumentTableEventTracker.cs @@ -29,6 +29,9 @@ internal sealed class RunningDocumentTableEventTracker : IVsRunningDocTableEvent private readonly IRunningDocumentTableEventListener _listener; private uint _runningDocumentTableEventsCookie; + /// + /// This constructor can be called on any thread. + /// public RunningDocumentTableEventTracker(IThreadingContext threadingContext, IVsEditorAdaptersFactoryService editorAdaptersFactoryService, IVsRunningDocumentTable runningDocumentTable, IRunningDocumentTableEventListener listener) { @@ -38,12 +41,13 @@ public RunningDocumentTableEventTracker(IThreadingContext threadingContext, IVsE Contract.ThrowIfNull(listener); _foregroundAffinitization = new ForegroundThreadAffinitizedObject(threadingContext, assertIsForeground: false); + // casting is free threaded past 16.0 _runningDocumentTable = (IVsRunningDocumentTable4)runningDocumentTable; _editorAdaptersFactoryService = editorAdaptersFactoryService; _listener = listener; // Advise / Unadvise for the RDT is free threaded past 16.0 - ((IVsRunningDocumentTable)_runningDocumentTable).AdviseRunningDocTableEvents(this, out _runningDocumentTableEventsCookie); + runningDocumentTable.AdviseRunningDocTableEvents(this, out _runningDocumentTableEventsCookie); } public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 4786fc171d2d1..cd202ef736c4a 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -168,7 +168,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke // Misc workspace has to be up and running by the time our package is usable so that it can track running // doc events and appropriately map files to/from it and other relevant workspaces (like the // metadata-as-source workspace). - await this.ComponentModel.GetService().InitializeAsync(this, cancellationToken).ConfigureAwait(false); + await this.ComponentModel.GetService().InitializeAsync(this).ConfigureAwait(false); } private async Task LoadOptionPersistersAsync(IComponentModel componentModel, CancellationToken cancellationToken) From 0dd1dedc6d4f32393af32aa381475633e540aac0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 23 Mar 2022 11:30:02 -0700 Subject: [PATCH 22/36] Async load --- .../Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs | 1 + .../Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs | 5 ++--- src/VisualStudio/Core/Def/RoslynPackage.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs index 98025ac542f43..981767452bd41 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/MiscellaneousFilesWorkspace.cs @@ -28,6 +28,7 @@ using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Threading; using Roslyn.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem diff --git a/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs b/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs index dd97f6399c1fe..8799a4bfae112 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs @@ -39,16 +39,15 @@ public RuleSetEventHandler( _serviceProvider = serviceProvider; } - public async Task RegisterAsync(CancellationToken cancellationToken) + public async Task RegisterAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { if (!_eventsHookedUp) { + var trackProjectDocuments = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); if (!_eventsHookedUp) { - var trackProjectDocuments = (IVsTrackProjectDocuments2)_serviceProvider.GetService(typeof(SVsTrackProjectDocuments)); - if (ErrorHandler.Succeeded(trackProjectDocuments.AdviseTrackProjectDocumentsEvents(this, out _cookie))) _eventsHookedUp = true; } diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index cd202ef736c4a..ccead2d180960 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -332,7 +332,7 @@ private async Task LoadAnalyzerNodeComponentsAsync(CancellationToken cancellatio _ruleSetEventHandler = this.ComponentModel.GetService(); if (_ruleSetEventHandler != null) - await _ruleSetEventHandler.RegisterAsync(cancellationToken).ConfigureAwait(false); + await _ruleSetEventHandler.RegisterAsync(this, cancellationToken).ConfigureAwait(false); } private void UnregisterAnalyzerTracker() From 77deef2eb7750d1e8445744249e86904d5ee4c10 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 23 Mar 2022 11:32:02 -0700 Subject: [PATCH 23/36] do not throw on failure --- .../VisualStudioDiagnosticListTableCommandHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs index cc1337b280315..7d0b1ee59b307 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs @@ -69,11 +69,11 @@ public VisualStudioDiagnosticListTableCommandHandler( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); _tableControl = errorList?.TableControl; // Add command handlers for bulk suppression commands. - var menuCommandService = (IMenuCommandService?)await serviceProvider.GetServiceAsync(typeof(IMenuCommandService)).ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); From ae60cbf7a021a36f1413090ca0e20cef559c8987 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 23 Mar 2022 11:35:31 -0700 Subject: [PATCH 24/36] Add throwOnFailure: False --- .../Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs | 2 +- .../Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs | 2 +- .../Suppression/VisualStudioSuppressionFixService.cs | 2 +- .../UnusedReferences/RemoveUnusedReferencesCommandHandler.cs | 2 +- .../Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs | 2 +- .../Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs | 2 +- .../Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs index 8414e55aa0bb8..900ee36be1bd1 100644 --- a/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs +++ b/src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs @@ -70,7 +70,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Run Code Analysis" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs index 33e8e73bbf733..b5b17572123e8 100644 --- a/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs @@ -55,7 +55,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index 4d371d414d905..d835b1f65e8d9 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -90,7 +90,7 @@ public VisualStudioSuppressionFixService( public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { - var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); _tableControl = errorList?.TableControl; } diff --git a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs index b3372f97129dc..0423ee6898abf 100644 --- a/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs +++ b/src/VisualStudio/Core/Def/UnusedReferences/RemoveUnusedReferencesCommandHandler.cs @@ -65,7 +65,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell _serviceProvider = (IServiceProvider)serviceProvider; // Hook up the "Remove Unused References" menu command for CPS based managed projects. - var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + var menuCommandService = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); if (menuCommandService != null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs index a5d14f43750f0..b1ff07aae803e 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItemTracker.cs @@ -39,7 +39,7 @@ public AnalyzerItemsTracker(IThreadingContext threadingContext) public async Task RegisterAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken) { - _vsMonitorSelection ??= await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); + _vsMonitorSelection ??= await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); _vsMonitorSelection?.AdviseSelectionEvents(this, out _selectionEventsCookie); } diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs index 99fd0e62bd282..76729d0e538b5 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerNodeSetup.cs @@ -36,7 +36,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell { await _analyzerTracker.RegisterAsync(serviceProvider, cancellationToken).ConfigureAwait(false); await _analyzerCommandHandler.InitializeAsync( - await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false), + await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); } diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs index a2f36a1e8df05..2f864f7978726 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs @@ -95,7 +95,7 @@ public AnalyzersCommandHandler( /// /// Hook up the context menu handlers. /// - public async Task InitializeAsync(IMenuCommandService menuCommandService, CancellationToken cancellationToken) + public async Task InitializeAsync(IMenuCommandService? menuCommandService, CancellationToken cancellationToken) { if (menuCommandService != null) { From 14291475e62aa6780c17f0e532bcf6f496656bf1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 23 Mar 2022 13:03:19 -0700 Subject: [PATCH 25/36] lint --- .../Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs index 2f864f7978726..a2f36a1e8df05 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs @@ -95,7 +95,7 @@ public AnalyzersCommandHandler( /// /// Hook up the context menu handlers. /// - public async Task InitializeAsync(IMenuCommandService? menuCommandService, CancellationToken cancellationToken) + public async Task InitializeAsync(IMenuCommandService menuCommandService, CancellationToken cancellationToken) { if (menuCommandService != null) { From ef6f2fda64e5b1ae5c718ac00411a7ba5b2d6835 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Wed, 23 Mar 2022 15:36:16 -0700 Subject: [PATCH 26/36] Don't eagerly load services Loading these services during the VisualStudioProject constructor means they're being loaded during the initial project creation which is earlier than they're needed and can hold up other work. Let's not ask for them until we actually need them. --- .../Def/ProjectSystem/VisualStudioProject.cs | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProject.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProject.cs index 7beec9db272fe..e7474a7aa84fb 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProject.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProject.cs @@ -29,8 +29,6 @@ internal sealed partial class VisualStudioProject private readonly VisualStudioWorkspaceImpl _workspace; private readonly HostDiagnosticUpdateSource _hostDiagnosticUpdateSource; - private readonly IWorkspaceTelemetryService? _telemetryService; - private readonly IWorkspaceStatusService? _workspaceStatusService; /// /// Provides dynamic source files for files added through . @@ -158,9 +156,6 @@ internal VisualStudioProject( _dynamicFileInfoProviders = dynamicFileInfoProviders; _hostDiagnosticUpdateSource = hostDiagnosticUpdateSource; - _telemetryService = _workspace.Services.GetService(); - _workspaceStatusService = _workspace.Services.GetService(); - Id = id; Language = language; _displayName = displayName; @@ -239,18 +234,29 @@ private void ChangeProjectProperty(ref T field, T newValue, Action(); + + if (telemetryService?.HasActiveSession == true) + { + var workspaceStatusService = _workspace.Services.GetService(); + + // We only log telemetry during solution open + + // Importantly, we do not await/wait on the fullyLoadedStateTask. We do not want to ever be waiting on work + // that may end up touching the UI thread (As we can deadlock if GetTagsSynchronous waits on us). Instead, + // we only check if the Task is completed. Prior to that we will assume we are still loading. Once this + // task is completed, we know that the WaitUntilFullyLoadedAsync call will have actually finished and we're + // fully loaded. + var isFullyLoadedTask = workspaceStatusService?.IsFullyLoadedAsync(CancellationToken.None); + var isFullyLoaded = isFullyLoadedTask is { IsCompleted: true } && isFullyLoadedTask.GetAwaiter().GetResult(); + + if (!isFullyLoaded) + { + TryReportCompilationThrownAway(_workspace.CurrentSolution.State, Id); + } + } } if (_activeBatchScopes > 0) From 954a6ab0661815d66975278a9debf1222459138e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 23 Mar 2022 16:17:09 -0700 Subject: [PATCH 27/36] Cleanup --- .../SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs b/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs index 5b8c3138c167d..d355eed9bf548 100644 --- a/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs +++ b/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs @@ -531,9 +531,7 @@ private async Task TryDownloadFileAsync(IRemoteControlClient client, C { await LogInfoAsync("Read file from client", cancellationToken).ConfigureAwait(false); - // "ReturnsNull": Only return a file if we have it locally *and* it's not older than our polling time (1 day). - - using var stream = await client.ReadFileAsync(BehaviorOnStale.ReturnNull).ConfigureAwait(false); + using var stream = await client.ReadFileAsync(BehaviorOnStale.ReturnStale).ConfigureAwait(false); if (stream == null) { From 8c243095595e627e11106cb0961359566233c4c0 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 24 Mar 2022 10:10:03 -0700 Subject: [PATCH 28/36] Fix a race condition in IDE diagnostic service for stale diagnostics Fixes [AB#1487574](https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1487574/) If you edit a document, which either fixes or introduces compiler diagnostics in another open document, but you do a tab switch to that open document before diagnostic computation kicked off by prior edit finishes, than we end up cancelling existing tasks queued for diagnostic computation from that prior edit. We kick off new tasks for diagnostic computation for the new active document, but the newly active document did not have any code change, so has identical text and semantic version and we end up skipping diagnostics computation for it, leaving behind stale diagnostics OR not showing new diagnostics that were introduced from the edit in prior active document. Fix is to always recompute the active document diagnostics on switching active documents and avoid any possible race conditions --- ...sticIncrementalAnalyzer_IncrementalAnalyzer.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs index 34faa68d9cef3..bb8a2c3b518bf 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs @@ -267,14 +267,13 @@ private void RaiseDiagnosticsRemovedIfRequiredForClosedOrResetDocument(TextDocum public async Task ActiveDocumentSwitchedAsync(TextDocument document, CancellationToken cancellationToken) { - // When the analysis scope is set to 'ActiveFile' and the active document is switched, - // we retrigger analysis of newly active document. - // For the remaining analysis scopes, we always analyze all the open files, so switching active - // documents between two open files doesn't require us to retrigger analysis of the newly active document. - if (GlobalOptions.GetBackgroundAnalysisScope(document.Project.Language) != BackgroundAnalysisScope.ActiveFile) - { - return; - } + // Retrigger analysis of newly active document to always get up-to-date diagnostics. + // Note that we do so regardless of the current background analysis scope, + // as we might have switched the document _while_ the diagnostic refresh was in progress for + // all open documents, which can lead to cancellation of diagnostic recomputation task + // for the newly active document. This can lead to a race condition where we end up with + // stale diagnostics for the active document. We avoid that by always recomputing + // the diagnostics for the newly active document whenever active document is switched. // First reset the document states. await TextDocumentResetAsync(document, cancellationToken).ConfigureAwait(false); From e05579fd1722e9ea6d1d36fab78dce8e998311cd Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Wed, 23 Mar 2022 15:42:20 -0700 Subject: [PATCH 29/36] Swich off the UI thread when our work doesn't need it anymore --- .../Core/Def/ProjectSystem/VisualStudioProjectFactory.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProjectFactory.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProjectFactory.cs index e5eee81510868..5590cb6405044 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProjectFactory.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioProjectFactory.cs @@ -74,7 +74,10 @@ public async Task CreateAndAddToWorkspaceAsync( ? filePath : null; - await _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitializedAsync(cancellationToken).ConfigureAwait(true); + // After the call to EnsureDocumentOptionProvidersInitializedAsync, everything can be off the UI thread. + // Thus, we have a ConfigureAwait(false) on the call and switch explicitly after. + await _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitializedAsync(cancellationToken).ConfigureAwait(false); + await TaskScheduler.Default; // From this point on, we start mutating the solution. So make us non cancellable. cancellationToken = CancellationToken.None; From c15cde510b7773d71580d734ffc183b17fd1b61c Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 25 Mar 2022 12:31:35 +0200 Subject: [PATCH 30/36] Move IDE0078 codefix to Analyzers --- src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems | 3 ++- .../CSharpUsePatternCombinatorsCodeFixProvider.cs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) rename src/{Features/CSharp/Portable => Analyzers/CSharp/CodeFixes}/UsePatternCombinators/CSharpUsePatternCombinatorsCodeFixProvider.cs (97%) diff --git a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems index 80e167d2963a9..9be7985bbe7cb 100644 --- a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems +++ b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems @@ -19,6 +19,7 @@ + @@ -80,4 +81,4 @@ - \ No newline at end of file + diff --git a/src/Features/CSharp/Portable/UsePatternCombinators/CSharpUsePatternCombinatorsCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UsePatternCombinators/CSharpUsePatternCombinatorsCodeFixProvider.cs similarity index 97% rename from src/Features/CSharp/Portable/UsePatternCombinators/CSharpUsePatternCombinatorsCodeFixProvider.cs rename to src/Analyzers/CSharp/CodeFixes/UsePatternCombinators/CSharpUsePatternCombinatorsCodeFixProvider.cs index 9a02160af5a77..8dff5954c094b 100644 --- a/src/Features/CSharp/Portable/UsePatternCombinators/CSharpUsePatternCombinatorsCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UsePatternCombinators/CSharpUsePatternCombinatorsCodeFixProvider.cs @@ -118,7 +118,7 @@ private static PatternSyntax AsPatternSyntax(AnalyzedPattern pattern) private static ExpressionSyntax AsExpressionSyntax(ExpressionSyntax expr, AnalyzedPattern p) { var semanticModel = p.Target.SemanticModel; - Debug.Assert(semanticModel != null); + RoslynDebug.Assert(semanticModel != null); var type = semanticModel.GetTypeInfo(expr).Type; if (type != null) { @@ -148,7 +148,9 @@ public MyCodeAction(string title, Func> create { } +#if !CODE_STYLE // 'CodeActionPriority' is not a public API, hence not supported in CodeStyle layer. internal override CodeActionPriority Priority => CodeActionPriority.Low; +#endif } } } From f56bf04e745fd1f209eb17c71283b496503dc160 Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Sun, 27 Mar 2022 20:09:23 +0300 Subject: [PATCH 31/36] Do not recommend async if such modifier is already present --- .../AsyncKeywordRecommenderTests.cs | 35 ++++++++++++++++++- .../AsyncKeywordRecommender.cs | 3 +- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs index 087ed6b5f5ebb..5263fa23ec4f1 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs @@ -40,6 +40,15 @@ await VerifyKeywordAsync(@"class C }"); } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestMethodDeclarationAsyncAfterCursor() + { + await VerifyKeywordAsync(@"class C +{ + public $$ async void goo() { } +}"); + } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestInsideInterface() { @@ -219,7 +228,7 @@ static void Main(string[] args) } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotIfAlreadyAsync2() + public async Task TestNotIfAlreadyAsyncInLambda() { await VerifyAbsenceAsync(@" class Program @@ -231,6 +240,30 @@ static void Main(string[] args) }"); } + [WorkItem(60340, "https://github.com/dotnet/roslyn/issues/60340")] + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotIfAlreadyAsyncBeforeOtherMember() + { + await VerifyAbsenceAsync(@" +class Program +{ + async $$ + + public void M() {} +}"); + } + + [WorkItem(60340, "https://github.com/dotnet/roslyn/issues/60340")] + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotIfAlreadyAsyncAsLastMember() + { + await VerifyAbsenceAsync(@" +class Program +{ + async $$ +}"); + } + [WorkItem(578061, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578061")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestNotInNamespace() diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AsyncKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AsyncKeywordRecommender.cs index 352a3008eb108..f4f7c4fd92320 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AsyncKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AsyncKeywordRecommender.cs @@ -27,7 +27,8 @@ public AsyncKeywordRecommender() protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { - if (context.TargetToken.IsKindOrHasMatchingText(SyntaxKind.PartialKeyword)) + if (context.TargetToken.IsKindOrHasMatchingText(SyntaxKind.PartialKeyword) || + context.PrecedingModifiers.Contains(SyntaxKind.AsyncKeyword)) { return false; } From 2aed89bfee5d5318cb62108be76365befb656c38 Mon Sep 17 00:00:00 2001 From: DoctorKrolic <70431552+DoctorKrolic@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:53:32 +0300 Subject: [PATCH 32/36] Highlight `await` and `return` in top-level statements (#60401) --- .../KeywordHighlighting/AwaitHighlighterTests.cs | 9 +++++++++ .../ReturnStatementHighlighterTests.cs | 8 ++++++++ .../KeywordHighlighters/AsyncAwaitHighlighter.cs | 2 +- .../KeywordHighlighters/ReturnStatementHighlighter.cs | 2 +- .../Highlighting/Keywords/AbstractKeywordHighlighter.cs | 2 -- .../Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs | 3 +++ 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/KeywordHighlighting/AwaitHighlighterTests.cs b/src/EditorFeatures/CSharpTest/KeywordHighlighting/AwaitHighlighterTests.cs index 300f1103c6e8e..2f97ca1e1ce4d 100644 --- a/src/EditorFeatures/CSharpTest/KeywordHighlighting/AwaitHighlighterTests.cs +++ b/src/EditorFeatures/CSharpTest/KeywordHighlighting/AwaitHighlighterTests.cs @@ -323,5 +323,14 @@ class C } }"); } + + [WorkItem(60400, "https://github.com/dotnet/roslyn/issues/60400")] + [Fact, Trait(Traits.Feature, Traits.Features.KeywordHighlighting)] + public async Task TestTopLevelStatements() + { + await TestAsync( +@"[|await|] Task.Delay(1000); +{|Cursor:[|await|]|} Task.Run(() => { })"); + } } } diff --git a/src/EditorFeatures/CSharpTest/KeywordHighlighting/ReturnStatementHighlighterTests.cs b/src/EditorFeatures/CSharpTest/KeywordHighlighting/ReturnStatementHighlighterTests.cs index cf65cd3e02634..2c98a44fd523a 100644 --- a/src/EditorFeatures/CSharpTest/KeywordHighlighting/ReturnStatementHighlighterTests.cs +++ b/src/EditorFeatures/CSharpTest/KeywordHighlighting/ReturnStatementHighlighterTests.cs @@ -462,5 +462,13 @@ void M() } }"); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordHighlighting)] + public async Task TestInTopLevelStatements() + { + await TestAsync( +@"if (args.Length > 0) [|return|] 0; +{|Cursor:[|return|]|} 1;"); + } } } diff --git a/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/AsyncAwaitHighlighter.cs b/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/AsyncAwaitHighlighter.cs index 0ab3840d6ee87..ceeda438aa24a 100644 --- a/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/AsyncAwaitHighlighter.cs +++ b/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/AsyncAwaitHighlighter.cs @@ -31,7 +31,7 @@ public AsyncAwaitHighlighter() } protected override bool IsHighlightableNode(SyntaxNode node) - => node.IsReturnableConstruct(); + => node.IsReturnableConstructOrTopLevelCompilationUnit(); protected override void AddHighlightsForNode(SyntaxNode node, List highlights, CancellationToken cancellationToken) { diff --git a/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/ReturnStatementHighlighter.cs b/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/ReturnStatementHighlighter.cs index 53f181f0c3a32..343aebba09a6f 100644 --- a/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/ReturnStatementHighlighter.cs +++ b/src/Features/CSharp/Portable/Highlighting/KeywordHighlighters/ReturnStatementHighlighter.cs @@ -32,7 +32,7 @@ protected override void AddHighlights( { var parent = returnStatement .GetAncestorsOrThis() - .FirstOrDefault(n => n.IsReturnableConstruct()); + .FirstOrDefault(n => n.IsReturnableConstructOrTopLevelCompilationUnit()); if (parent == null) { diff --git a/src/Features/Core/Portable/Highlighting/Keywords/AbstractKeywordHighlighter.cs b/src/Features/Core/Portable/Highlighting/Keywords/AbstractKeywordHighlighter.cs index aa1183be975bb..b5bc18acf5efb 100644 --- a/src/Features/Core/Portable/Highlighting/Keywords/AbstractKeywordHighlighter.cs +++ b/src/Features/Core/Portable/Highlighting/Keywords/AbstractKeywordHighlighter.cs @@ -5,11 +5,9 @@ #nullable disable using System.Collections.Generic; -using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Highlighting { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs index 01d10b131eafe..f871109bd3457 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs @@ -626,6 +626,9 @@ public static bool IsReturnableConstruct(this SyntaxNode node) return false; } + public static bool IsReturnableConstructOrTopLevelCompilationUnit(this SyntaxNode node) + => node.IsReturnableConstruct() || (node is CompilationUnitSyntax compilationUnit && compilationUnit.Members.Any(SyntaxKind.GlobalStatement)); + public static bool SpansPreprocessorDirective(this IEnumerable list) where TSyntaxNode : SyntaxNode => CSharpSyntaxFacts.Instance.SpansPreprocessorDirective(list); From a838dcfc37a7f22018fddcf7d36b241254f14d58 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 29 Mar 2022 09:05:22 +1100 Subject: [PATCH 33/36] Don't complete quotes if they complete a valid string (#60227) --- .../AutomaticLiteralCompletionTests.cs | 65 +++++++++++++++++++ .../StringLiteralBraceCompletionService.cs | 38 +++++++++++ 2 files changed, 103 insertions(+) diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs index cb7076a293295..da05f60f93d59 100644 --- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs +++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs @@ -429,6 +429,71 @@ void Method() CheckStart(session.Session, expectValidSession: false); } + [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(59178, "https://github.com/dotnet/roslyn/issues/59178")] + public void String_CompleteLiteral() + { + var code = @"class C +{ + void Method() + { + var s = ""this"" + $$that""; + } +}"; + using var session = CreateSessionDoubleQuote(code); + Assert.NotNull(session); + CheckStart(session.Session, expectValidSession: false); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(59178, "https://github.com/dotnet/roslyn/issues/59178")] + public void String_BeforeOtherString1() + { + var code = @"class C +{ + void Method() + { + var s = $$ + "" + bar""; + } +}"; + using var session = CreateSessionDoubleQuote(code); + Assert.NotNull(session); + CheckStart(session.Session); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(59178, "https://github.com/dotnet/roslyn/issues/59178")] + public void String_BeforeOtherString2() + { + var code = @"class C +{ + void Method() + { + var s = $$ + ""; } ""; + } +}"; + using var session = CreateSessionDoubleQuote(code); + Assert.NotNull(session); + CheckStart(session.Session); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(59178, "https://github.com/dotnet/roslyn/issues/59178")] + public void String_DontCompleteVerbatim() + { + var code = @"class C +{ + void Method() + { + var s = ""this"" + @$$that + and this""; + } +}"; + using var session = CreateSessionDoubleQuote(code); + Assert.NotNull(session); + CheckStart(session.Session); + } + internal static Holder CreateSessionSingleQuote(string code) { return CreateSession( diff --git a/src/Features/CSharp/Portable/BraceCompletion/StringLiteralBraceCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/StringLiteralBraceCompletionService.cs index 0ae0c5025aea4..106fa4d11fdd4 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/StringLiteralBraceCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/StringLiteralBraceCompletionService.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.BraceCompletion; +using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -53,6 +54,27 @@ protected override Task IsValidOpenBraceTokenAtPositionAsync(SyntaxToken t return SpecializedTasks.False; } + // If the single token that the user typed is a string literal that is more than just + // the one double quote character they typed, and the line doesn't have errors, then + // it means it is completing an existing token, from the start. For example given: + // + // var s = "te$$st"; + // + // When the user types `" + "` to split the string into two literals, the first + // quote won't be completed (because its in a string literal), and with this check + // the second quote won't either. + // + // We don't do this optimization for verbatim strings because they are multi-line so + // the flow on effects from us getting it wrong are much greater, and it can really change + // the tree. + if (token.IsKind(SyntaxKind.StringLiteralToken) && + !token.IsVerbatimStringLiteral() && + token.Span.Length > 1 && + !RestOfLineContainsDiagnostics(token)) + { + return SpecializedTasks.False; + } + if (token.SpanStart == position) { return SpecializedTasks.True; @@ -63,5 +85,21 @@ protected override Task IsValidOpenBraceTokenAtPositionAsync(SyntaxToken t // is the @ character and the " is one past the token start. return Task.FromResult(token.SpanStart + 1 == position && token.IsVerbatimStringLiteral()); } + + private static bool RestOfLineContainsDiagnostics(SyntaxToken token) + { + while (!token.TrailingTrivia.Contains(t => t.IsEndOfLine())) + { + if (token.ContainsDiagnostics) + return true; + + token = token.GetNextToken(); + } + + if (token.ContainsDiagnostics) + return true; + + return false; + } } } From dc763481eec978fa4f6d024ac0e508ba3ab14422 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 29 Mar 2022 09:41:02 +1100 Subject: [PATCH 34/36] Don't offer to use patterns when they won't work (#60370) Co-authored-by: Youssef1313 --- .../UsePatternCombinators/AnalyzedPattern.cs | 49 +++++- .../CSharpUsePatternCombinatorsAnalyzer.cs | 4 +- ...tternCombinatorsDiagnosticAnalyzerTests.cs | 147 ++++++++++++++++++ 3 files changed, 197 insertions(+), 3 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/AnalyzedPattern.cs b/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/AnalyzedPattern.cs index 31b610a0b1e66..5c001fbb29c90 100644 --- a/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/AnalyzedPattern.cs +++ b/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/AnalyzedPattern.cs @@ -2,6 +2,7 @@ // 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.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Operations; using Roslyn.Utilities; @@ -23,9 +24,55 @@ private AnalyzedPattern(IOperation target) /// internal sealed class Type : AnalyzedPattern { + private static readonly SyntaxAnnotation s_annotation = new(); + + public static Type? TryCreate(BinaryExpressionSyntax binaryExpression, IIsTypeOperation operation) + { + Contract.ThrowIfNull(operation.SemanticModel); + if (binaryExpression.Right is not TypeSyntax typeSyntax) + { + return null; + } + + // We are coming from a type pattern, which likes to bind to types, but converting to + // patters which like to bind to expressions. For example, given: + // + // if (T is C.X || T is Y) { } + // + // we would want to convert to: + // + // if (T is C.X or Y) + // + // In the first case the compiler will bind to types named C or Y that are in scope + // but in the second it will also bind to a fields, methods etc. which for 'Y' changes + // semantics, and for 'C.X' could be a compile error. + // + // So lets create a pattern syntax and make sure the result is the same + var dummyStatement = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + SyntaxFactory.IdentifierName("_"), + SyntaxFactory.IsPatternExpression( + binaryExpression.Left, + SyntaxFactory.ConstantPattern(SyntaxFactory.ParenthesizedExpression(binaryExpression.Right.WithAdditionalAnnotations(s_annotation))) + ) + )); + + if (operation.SemanticModel.TryGetSpeculativeSemanticModel(typeSyntax.SpanStart, dummyStatement, out var speculativeModel)) + { + var originalInfo = operation.SemanticModel.GetTypeInfo(binaryExpression.Right); + var newInfo = speculativeModel.GetTypeInfo(dummyStatement.GetAnnotatedNodes(s_annotation).Single()); + if (!originalInfo.Equals(newInfo)) + { + return null; + } + } + + return new Type(typeSyntax, operation.ValueOperand); + } + public readonly TypeSyntax TypeSyntax; - public Type(TypeSyntax type, IOperation target) : base(target) + private Type(TypeSyntax type, IOperation target) : base(target) => TypeSyntax = type; } diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsAnalyzer.cs index d809df97b04b0..f915fa2dd5d4f 100644 --- a/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsAnalyzer.cs @@ -59,8 +59,8 @@ private enum ConstantResult case IUnaryOperation { OperatorKind: UnaryOperatorKind.Not } op: return Not.TryCreate(ParsePattern(op.Operand)); - case IIsTypeOperation { Syntax: BinaryExpressionSyntax { Right: TypeSyntax type } } op: - return new Type(type, op.ValueOperand); + case IIsTypeOperation { Syntax: BinaryExpressionSyntax binaryExpression } op: + return Type.TryCreate(binaryExpression, op); case IIsPatternOperation { Pattern: { Syntax: PatternSyntax pattern } } op: return new Source(pattern, op.Value); diff --git a/src/EditorFeatures/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs b/src/EditorFeatures/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs index 6e5ab88b5a2af..a95c7375ac0d4 100644 --- a/src/EditorFeatures/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs +++ b/src/EditorFeatures/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs @@ -105,6 +105,8 @@ public async Task TestMissingOnExpression(string expression) [InlineData("i == default || i > default(int)", "i is default(int) or > (default(int))")] [InlineData("!(o is C c)", "o is not C c")] [InlineData("o is int ii && o is long jj", "o is int ii and long jj")] + [InlineData("o is string || o is Exception", "o is string or Exception")] + [InlineData("o is System.String || o is System.Exception", "o is System.String or System.Exception")] [InlineData("!(o is C)", "o is not C")] [InlineData("!(o is C _)", "o is not C _")] [InlineData("i == (0x02 | 0x04) || i != 0", "i is (0x02 | 0x04) or not 0")] @@ -477,6 +479,151 @@ void M(char c) } } } +"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUsePatternCombinators)] + [WorkItem(57199, "https://github.com/dotnet/roslyn/issues/57199")] + public async Task TestMissingInNonConvertibleTypePattern1() + { + await TestMissingAsync( +@" +static class C +{ + public struct S1 : I { } + public struct S2 : I { } + public interface I { } +} + +class Test +{ + public readonly T C; + bool P => [|C is C.S1 || C is C.S2|]; +} +"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUsePatternCombinators)] + [WorkItem(57199, "https://github.com/dotnet/roslyn/issues/57199")] + public async Task TestMissingInNonConvertibleTypePattern2() + { + await TestMissingAsync( +@" + class Goo + { + private class X { } + private class Y { } + + private void M(object o) + { + var X = 1; + var Y = 2; + + if [|(o is X || o is Y)|] + { + } + } + } +"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUsePatternCombinators)] + [WorkItem(57199, "https://github.com/dotnet/roslyn/issues/57199")] + public async Task TestMissingInNonConvertibleTypePattern3() + { + await TestMissingAsync( +@" + class Goo + { + private class X { } + private class Y { } + private void M(object o) + { + var X = 1; + var Y = 2; + if [|(o is global::Goo.X || o is Y)|] + { + } + } + } +"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUsePatternCombinators)] + [WorkItem(57199, "https://github.com/dotnet/roslyn/issues/57199")] + public async Task TestInConvertibleTypePattern() + { + await TestInRegularAndScriptAsync( +@" +static class C +{ + public struct S1 : I { } + public struct S2 : I { } + public interface I { } +} + +class Test +{ + bool P => [|C is C.S1 || C is C.S2|]; +} +", + +@" +static class C +{ + public struct S1 : I { } + public struct S2 : I { } + public interface I { } +} + +class Test +{ + bool P => C is C.S1 or C.S2; +} +"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUsePatternCombinators)] + [WorkItem(57199, "https://github.com/dotnet/roslyn/issues/57199")] + public async Task TestInConvertibleTypePattern2() + { + await TestInRegularAndScriptAsync( +@" +public class Goo +{ + private class X { } + private class Y { } + + private void M(object o) + { + var X = 1; + var Y = 2; + + var @int = 1; + var @long = 2; + if [|(o is int || o is long)|] + { + } + } +} +", @" +public class Goo +{ + private class X { } + private class Y { } + + private void M(object o) + { + var X = 1; + var Y = 2; + + var @int = 1; + var @long = 2; + if (o is int or long) + { + } + } +} "); } } From a1ca907c159b4d546b51fa4f2c8ca994f3b58382 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 28 Mar 2022 17:16:56 -0700 Subject: [PATCH 35/36] Add UnsignedRightShift feature to "Language Feature Status.md" (#60435) --- docs/Language Feature Status.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/Language Feature Status.md b/docs/Language Feature Status.md index 731ff614266a2..cfa43ae675dde 100644 --- a/docs/Language Feature Status.md +++ b/docs/Language Feature Status.md @@ -28,8 +28,10 @@ efforts behind them. | [nameof accessing instance members](https://github.com/dotnet/roslyn/issues/40229) | main | [In Progress](https://github.com/dotnet/roslyn/pull/48754) | [YairHalberstadt ](https://github.com/YairHalberstadt) | [333fred](https://github.com/333fred), [AlekseyTs](https://github.com/AlekseyTs) | [333fred](https://github.com/333fred) | | [Utf8 String Literals](https://github.com/dotnet/csharplang/issues/184) | [Utf8StringLiterals](https://github.com/dotnet/roslyn/tree/features/Utf8StringLiterals) | [In Progress](https://github.com/dotnet/roslyn/issues/58848) | [AlekseyTs](https://github.com/AlekseyTs) | [cston](https://github.com/cston), [RikkiGibson](https://github.com/RikkiGibson) | [MadsTorgersen](https://github.com/MadsTorgersen) | | [ref fields](https://github.com/dotnet/csharplang/blob/main/proposals/low-level-struct-improvements.md) | [ref-fields](https://github.com/dotnet/roslyn/tree/features/ref-fields) | [In Progress](https://github.com/dotnet/roslyn/issues/59194) | [cston](https://github.com/cston) | [RikkiGibson](https://github.com/RikkiGibson), [AlekseyTs](https://github.com/AlekseyTs) | [jaredpar](https://github.com/jaredpar) | -| [checked operators](https://github.com/dotnet/csharplang/issues/4665) | [CheckedUserDefinedOperators](https://github.com/dotnet/roslyn/tree/features/CheckedUserDefinedOperators) | [In Progress](https://github.com/dotnet/roslyn/issues/59458) | [AlekseyTs](https://github.com/AlekseyTs) | [333fred](https://github.com/333fred), [chsienki](https://github.com/chsienki) | [AlekseyTs](https://github.com/AlekseyTs) | +| [Checked Operators](https://github.com/dotnet/csharplang/issues/4665) | [CheckedUserDefinedOperators](https://github.com/dotnet/roslyn/tree/features/CheckedUserDefinedOperators) | [In Progress](https://github.com/dotnet/roslyn/issues/59458) | [AlekseyTs](https://github.com/AlekseyTs) | [333fred](https://github.com/333fred), [chsienki](https://github.com/chsienki) | [AlekseyTs](https://github.com/AlekseyTs) | | [auto-default structs](https://github.com/dotnet/csharplang/issues/5737) | main | [In Progress](https://github.com/dotnet/roslyn/issues/60167) | [RikkiGibson](https://github.com/RikkiGibson) | [cston](https://github.com/cston), [jcouv](https://github.com/jcouv) | +| [Unsigned Right Shift](https://github.com/dotnet/csharplang/issues/4682) | [UnsignedRightShift](https://github.com/dotnet/roslyn/tree/features/UnsignedRightShift) | [In Progress](https://github.com/dotnet/roslyn/issues/60433) | [AlekseyTs](https://github.com/AlekseyTs) | TBD | [AlekseyTs](https://github.com/AlekseyTs) | + # C# 10.0 From 0ead73d911285c4ff3ec57ab1584c491809d68df Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 28 Mar 2022 17:20:59 -0700 Subject: [PATCH 36/36] [LSP] Remove the majority of usages of client name. (#60357) * Remove the majority of usages of client name. The server should just return results for what it was asked for while the platform is responsible for asking for the correct buffers based on client name. * Remove unneeded extension * fix interface impl * Remove clientname from vsmac logger --- .../Lsp/VSMacLspLoggerFactoryWrapper.cs | 4 +- .../VSTypeScriptInProcLanguageClient.cs | 2 +- .../AbstractInProcLanguageClient.cs | 10 +--- .../AlwaysActivateInProcLanguageClient.cs | 2 +- .../Handlers/Completion/CompletionHandler.cs | 3 +- .../LiveShareInProcLanguageClient.cs | 2 +- .../RazorInProcLanguageClient.cs | 2 +- .../AbstractLanguageServerProtocolTests.cs | 5 +- .../CSharpVisualBasicLanguageServerFactory.cs | 1 - .../Protocol/Extensions/Extensions.cs | 49 +------------------ .../VSMac/API/VSMacLspLoggerFactory.cs | 2 +- .../AbstractPullDiagnosticHandler.cs | 23 ++------- .../DocumentPullDiagnosticHandler.cs | 3 +- ...alDocumentPullDiagnosticHandlerProvider.cs | 2 +- ...erimentalDocumentPullDiagnosticsHandler.cs | 3 +- ...lWorkspacePullDiagnosticHandlerProvider.cs | 2 +- ...rimentalWorkspacePullDiagnosticsHandler.cs | 3 +- .../PullDiagnosticHandlerProvider.cs | 4 +- .../WorkspacePullDiagnosticHandler.cs | 14 ++++-- .../OnAutoInsert/OnAutoInsertHandler.cs | 2 +- .../GetTextDocumentWithContextHandler.cs | 2 +- .../Protocol/Handler/RequestContext.cs | 16 +++--- .../RequestExecutionQueue.QueueItem.cs | 9 ---- .../Protocol/Handler/RequestExecutionQueue.cs | 7 +-- .../SemanticTokensRangeHandler.cs | 1 + .../Protocol/ILspLoggerFactory.cs | 2 +- .../Protocol/LanguageServerTarget.cs | 5 -- .../Protocol/RequestDispatcher.cs | 6 +-- .../Workspaces/LspWorkspaceManager.cs | 18 +++---- .../DocumentChangesTests.LinkedDocuments.cs | 2 +- .../OnAutoInsert/OnAutoInsertTests.cs | 19 ++++--- .../VSTypeScriptHandlerTests.cs | 1 - .../Workspaces/LspWorkspaceManagerTests.cs | 2 +- .../VisualStudioLogHubLoggerFactory.cs | 4 +- .../XamlInProcLanguageClient.cs | 2 +- .../XamlInProcLanguageClientDisableUX.cs | 2 +- .../AbstractPullDiagnosticHandler.cs | 2 +- .../XamlRequestDispatcherFactory.cs | 4 +- 38 files changed, 79 insertions(+), 163 deletions(-) diff --git a/src/EditorFeatures/Core.Cocoa/Lsp/VSMacLspLoggerFactoryWrapper.cs b/src/EditorFeatures/Core.Cocoa/Lsp/VSMacLspLoggerFactoryWrapper.cs index 00a6a4bc30d1a..4f33afef6eae2 100644 --- a/src/EditorFeatures/Core.Cocoa/Lsp/VSMacLspLoggerFactoryWrapper.cs +++ b/src/EditorFeatures/Core.Cocoa/Lsp/VSMacLspLoggerFactoryWrapper.cs @@ -29,9 +29,9 @@ public VSMacLspLoggerFactoryWrapper(IVSMacLspLoggerFactory loggerFactory) _loggerFactory = loggerFactory; } - public async Task CreateLoggerAsync(string serverTypeName, string? clientName, JsonRpc jsonRpc, CancellationToken cancellationToken) + public async Task CreateLoggerAsync(string serverTypeName, JsonRpc jsonRpc, CancellationToken cancellationToken) { - var vsMacLogger = await _loggerFactory.CreateLoggerAsync(serverTypeName, clientName, jsonRpc, cancellationToken).ConfigureAwait(false); + var vsMacLogger = await _loggerFactory.CreateLoggerAsync(serverTypeName, jsonRpc, cancellationToken).ConfigureAwait(false); return new VSMacLspLoggerWrapper(vsMacLogger); } } diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs index 581a73347d60f..abaab663d4662 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs @@ -45,7 +45,7 @@ public VSTypeScriptInProcLanguageClient( DefaultCapabilitiesProvider defaultCapabilitiesProvider, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(requestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext, diagnosticsClientName: null) + : base(requestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) { _typeScriptCapabilitiesProvider = typeScriptCapabilitiesProvider; } diff --git a/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs index 4d83d2f9e422b..3d8f6f3083604 100644 --- a/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs @@ -24,7 +24,6 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.LanguageClient { internal abstract partial class AbstractInProcLanguageClient : ILanguageClient, ILanguageServerFactory, ICapabilitiesProvider { - private readonly string? _diagnosticsClientName; private readonly IThreadingContext _threadingContext; private readonly ILspLoggerFactory _lspLoggerFactory; @@ -86,14 +85,12 @@ public AbstractInProcLanguageClient( IAsynchronousOperationListenerProvider listenerProvider, LspWorkspaceRegistrationService lspWorkspaceRegistrationService, ILspLoggerFactory lspLoggerFactory, - IThreadingContext threadingContext, - string? diagnosticsClientName) + IThreadingContext threadingContext) { _requestDispatcherFactory = requestDispatcherFactory; GlobalOptions = globalOptions; _listenerProvider = listenerProvider; _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; - _diagnosticsClientName = diagnosticsClientName; _lspLoggerFactory = lspLoggerFactory; _threadingContext = threadingContext; } @@ -146,7 +143,6 @@ public AbstractInProcLanguageClient( serverStream, serverStream, _lspLoggerFactory, - _diagnosticsClientName, cancellationToken).ConfigureAwait(false); return new Connection(clientStream, clientStream); @@ -180,7 +176,6 @@ internal static async Task CreateAsync( Stream inputStream, Stream outputStream, ILspLoggerFactory lspLoggerFactory, - string? clientName, CancellationToken cancellationToken) { var jsonMessageFormatter = new JsonMessageFormatter(); @@ -193,7 +188,7 @@ internal static async Task CreateAsync( var serverTypeName = languageClient.GetType().Name; - var logger = await lspLoggerFactory.CreateLoggerAsync(serverTypeName, clientName, jsonRpc, cancellationToken).ConfigureAwait(false); + var logger = await lspLoggerFactory.CreateLoggerAsync(serverTypeName, jsonRpc, cancellationToken).ConfigureAwait(false); var server = languageClient.Create( jsonRpc, @@ -219,7 +214,6 @@ public ILanguageServerTarget Create( _listenerProvider, logger, SupportedLanguages, - clientName: _diagnosticsClientName, ServerKind); } diff --git a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs index 00a02e18d5d98..211391339e227 100644 --- a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs @@ -43,7 +43,7 @@ public AlwaysActivateInProcLanguageClient( DefaultCapabilitiesProvider defaultCapabilitiesProvider, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext, diagnosticsClientName: null) + : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) { _defaultCapabilitiesProvider = defaultCapabilitiesProvider; } diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs index aa228551b3a21..a8b0632caa5d9 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs @@ -127,7 +127,7 @@ public CompletionHandler( var completionItemResolveData = supportsCompletionListData ? null : completionResolveData; var lspCompletionItem = await CreateLSPCompletionItemAsync( request, document, item, completionItemResolveData, lspVSClientCapability, commitCharactersRuleCache, - completionService, context.ClientName, returnTextEdits, snippetsSupported, stringBuilder, documentText, + completionService, returnTextEdits, snippetsSupported, stringBuilder, documentText, defaultSpan, defaultRange, cancellationToken).ConfigureAwait(false); lspCompletionItems.Add(lspCompletionItem); } @@ -177,7 +177,6 @@ bool IsValidTriggerCharacterForDocument(Document document, char triggerCharacter bool supportsVSExtensions, Dictionary, string[]> commitCharacterRulesCache, CompletionService completionService, - string? clientName, bool returnTextEdits, bool snippetsSupported, StringBuilder stringBuilder, diff --git a/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs index b7be5bf149e8c..231749f28b82f 100644 --- a/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs @@ -37,7 +37,7 @@ public LiveShareInProcLanguageClient( DefaultCapabilitiesProvider defaultCapabilitiesProvider, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext, diagnosticsClientName: null) + : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) { _defaultCapabilitiesProvider = defaultCapabilitiesProvider; } diff --git a/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs index cc71b2be6f93d..53ee0686aa249 100644 --- a/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs @@ -55,7 +55,7 @@ public RazorInProcLanguageClient( DefaultCapabilitiesProvider defaultCapabilitiesProvider, IThreadingContext threadingContext, ILspLoggerFactory lspLoggerFactory) - : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext, ClientName) + : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) { _defaultCapabilitiesProvider = defaultCapabilitiesProvider; } diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs index b81852b34b06e..29a69e5b506cb 100644 --- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs +++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs @@ -288,8 +288,8 @@ private protected static CodeActionResolveData CreateCodeActionResolveData(strin protected Task CreateTestLspServerAsync(string markup, LSP.ClientCapabilities? clientCapabilities = null) => CreateTestLspServerAsync(new string[] { markup }, Array.Empty(), LanguageNames.CSharp, clientCapabilities); - protected Task CreateVisualBasicTestLspServerAsync(string markup, LSP.ClientCapabilities? clientCapabilities = null) - => CreateTestLspServerAsync(new string[] { markup }, Array.Empty(), LanguageNames.VisualBasic, clientCapabilities); + private protected Task CreateVisualBasicTestLspServerAsync(string markup, LSP.ClientCapabilities? clientCapabilities = null, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.AlwaysActiveVSLspServer) + => CreateTestLspServerAsync(new string[] { markup }, Array.Empty(), LanguageNames.VisualBasic, clientCapabilities, serverKind); protected Task CreateMultiProjectLspServerAsync(string xmlMarkup, LSP.ClientCapabilities? clientCapabilities = null) => CreateTestLspServerAsync(TestWorkspace.Create(xmlMarkup, composition: Composition), clientCapabilities, WellKnownLspServerKinds.AlwaysActiveVSLspServer); @@ -579,7 +579,6 @@ private static LanguageServerTarget CreateLanguageServer(Stream inputStream, Str listenerProvider, NoOpLspLogger.Instance, ProtocolConstants.RoslynLspLanguages, - clientName: null, serverKind); jsonRpc.StartListening(); diff --git a/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs b/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs index 51c7ad4947537..c7acd08270e6b 100644 --- a/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs +++ b/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs @@ -51,7 +51,6 @@ public ILanguageServerTarget Create( _listenerProvider, logger, ProtocolConstants.RoslynLspLanguages, - clientName: null, WellKnownLspServerKinds.CSharpVisualBasicLspServer); } } diff --git a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs index d5c6eed1c5cde..95772c2492ecf 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs @@ -33,18 +33,12 @@ public static Uri GetURI(this TextDocument document) => ProtocolConversions.TryGetUriFromFilePath(document.FilePath, context); public static ImmutableArray GetDocuments(this Solution solution, Uri documentUri) - => GetDocuments(solution, documentUri, clientName: null, logger: null); - - public static ImmutableArray GetDocuments(this Solution solution, Uri documentUri, string? clientName) - => GetDocuments(solution, documentUri, clientName, logger: null); - - public static ImmutableArray GetDocuments(this Solution solution, Uri documentUri, string? clientName, ILspLogger? logger) { var documentIds = GetDocumentIds(solution, documentUri); var documents = documentIds.SelectAsArray(id => solution.GetRequiredDocument(id)); - return FilterDocumentsByClientName(documents, clientName, logger); + return documents; } public static ImmutableArray GetDocumentIds(this Solution solution, Uri documentUri) @@ -62,40 +56,9 @@ public static ImmutableArray GetDocumentIds(this Solution solution, return documentIds; } - private static ImmutableArray FilterDocumentsByClientName(ImmutableArray documents, string? clientName, ILspLogger? logger) - { - // If we don't have a client name, then we're done filtering - if (clientName == null) - { - return documents; - } - - // We have a client name, so we need to filter to only documents that match that name - return documents.WhereAsArray(document => - { - var documentPropertiesService = document.Services.GetService(); - - // When a client name is specified, only return documents that have a matching client name. - // Allows the razor lsp server to return results only for razor documents. - // This workaround should be removed when https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1106064/ - // is fixed (so that the razor language server is only asked about razor buffers). - var documentClientName = documentPropertiesService?.DiagnosticsLspClientName; - var clientNameMatch = Equals(documentClientName, clientName); - if (!clientNameMatch && logger is not null) - { - logger.TraceInformation($"Found matching document but it's client name '{documentClientName}' is not a match."); - } - - return clientNameMatch; - }); - } - public static Document? GetDocument(this Solution solution, TextDocumentIdentifier documentIdentifier) - => solution.GetDocument(documentIdentifier, clientName: null); - - public static Document? GetDocument(this Solution solution, TextDocumentIdentifier documentIdentifier, string? clientName) { - var documents = solution.GetDocuments(documentIdentifier.Uri, clientName, logger: null); + var documents = solution.GetDocuments(documentIdentifier.Uri); if (documents.Length == 0) { return null; @@ -193,14 +156,6 @@ public static string GetMarkdownLanguageName(this Document document) public static ClassifiedTextElement GetClassifiedText(this DefinitionItem definition) => new ClassifiedTextElement(definition.DisplayParts.Select(part => new ClassifiedTextRun(part.Tag.ToClassificationTypeName(), part.Text))); - public static bool IsRazorDocument(this Document document) - { - // Only razor docs have an ISpanMappingService, so we can use the presence of that to determine if this doc - // belongs to them. - var spanMapper = document.Services.GetService(); - return spanMapper != null; - } - private static bool TryGetVSCompletionListSetting(ClientCapabilities clientCapabilities, [NotNullWhen(returnValue: true)] out VSInternalCompletionListSetting? completionListSetting) { if (clientCapabilities is not VSInternalClientCapabilities vsClientCapabilities) diff --git a/src/Features/LanguageServer/Protocol/ExternalAccess/VSMac/API/VSMacLspLoggerFactory.cs b/src/Features/LanguageServer/Protocol/ExternalAccess/VSMac/API/VSMacLspLoggerFactory.cs index eb0db665211a4..d4d94e2f6f238 100644 --- a/src/Features/LanguageServer/Protocol/ExternalAccess/VSMac/API/VSMacLspLoggerFactory.cs +++ b/src/Features/LanguageServer/Protocol/ExternalAccess/VSMac/API/VSMacLspLoggerFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSMac.API; internal interface IVSMacLspLoggerFactory { - Task CreateLoggerAsync(string serverTypeName, string? clientName, JsonRpc jsonRpc, CancellationToken cancellationToken); + Task CreateLoggerAsync(string serverTypeName, JsonRpc jsonRpc, CancellationToken cancellationToken); } internal interface IVSMacLspLogger diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs index e732590154ece..00fa23941ee96 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs @@ -45,7 +45,6 @@ internal abstract class AbstractPullDiagnosticHandler true; protected AbstractPullDiagnosticHandler( - WellKnownLspServerKinds serverKind, IDiagnosticService diagnosticService, EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) { - _serverKind = serverKind; DiagnosticService = diagnosticService; _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; _versionedCache = new(this.GetType().Name); @@ -135,11 +132,8 @@ protected AbstractPullDiagnosticHandler( { context.TraceInformation($"Processing: {document.FilePath}"); - if (!IncludeDocument(document, context.ClientName)) - { - context.TraceInformation($"Ignoring document '{document.FilePath}' because of razor/client-name mismatch"); - continue; - } + // not be asked for workspace docs in razor. + // not send razor docs in workspace docs for c# var encVersion = _editAndContinueDiagnosticUpdateSource.Version; @@ -173,17 +167,6 @@ protected AbstractPullDiagnosticHandler( return CreateReturn(progress); } - private static bool IncludeDocument(Document document, string? clientName) - { - // Documents either belong to Razor or not. We can determine this by checking if the doc has a span-mapping - // service or not. If we're not in razor, we do not include razor docs. If we are in razor, we only - // include razor docs. - var isRazorDoc = document.IsRazorDocument(); - var wantsRazorDoc = clientName != null; - - return wantsRazorDoc == isRazorDoc; - } - private static Dictionary GetDocumentToPreviousDiagnosticParams( RequestContext context, ImmutableArray previousResults) { @@ -210,7 +193,7 @@ private async Task ComputeAndReportCurrentDiagnosticsAsync( ClientCapabilities clientCapabilities, CancellationToken cancellationToken) { - var diagnosticModeOption = _serverKind switch + var diagnosticModeOption = context.ServerKind switch { WellKnownLspServerKinds.LiveShareLspServer => s_liveShareDiagnosticMode, WellKnownLspServerKinds.RazorLspServer => s_razorDiagnosticMode, diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs index dd0988559aa32..2ddf9d4fddd12 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs @@ -21,11 +21,10 @@ internal class DocumentPullDiagnosticHandler : AbstractPullDiagnosticHandler CreateRequestHandlers(WellKnownLspServerKinds serverKind) { - return ImmutableArray.Create(new ExperimentalDocumentPullDiagnosticsHandler(serverKind, _diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource)); + return ImmutableArray.Create(new ExperimentalDocumentPullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource)); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs index d71b76622a563..313ee433ca8df 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs @@ -28,11 +28,10 @@ internal class ExperimentalDocumentPullDiagnosticsHandler : AbstractPullDiagnost private readonly IDiagnosticAnalyzerService _analyzerService; public ExperimentalDocumentPullDiagnosticsHandler( - WellKnownLspServerKinds serverKind, IDiagnosticService diagnosticService, IDiagnosticAnalyzerService analyzerService, EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - : base(serverKind, diagnosticService, editAndContinueDiagnosticUpdateSource) + : base(diagnosticService, editAndContinueDiagnosticUpdateSource) { _analyzerService = analyzerService; } diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs index 6bbc5487a01a9..e6d254afc8675 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs @@ -32,6 +32,6 @@ public ExperimentalWorkspacePullDiagnosticHandlerProvider( public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) { - return ImmutableArray.Create(new ExperimentalWorkspacePullDiagnosticsHandler(serverKind, _diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource)); + return ImmutableArray.Create(new ExperimentalWorkspacePullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource)); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs index 0bc9d43c5b765..0b3b5a89572df 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs @@ -23,11 +23,10 @@ internal class ExperimentalWorkspacePullDiagnosticsHandler : AbstractPullDiagnos private readonly IDiagnosticAnalyzerService _analyzerService; public ExperimentalWorkspacePullDiagnosticsHandler( - WellKnownLspServerKinds serverKind, IDiagnosticService diagnosticService, IDiagnosticAnalyzerService analyzerService, EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - : base(serverKind, diagnosticService, editAndContinueDiagnosticUpdateSource) + : base(diagnosticService, editAndContinueDiagnosticUpdateSource) { _analyzerService = analyzerService; } diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs index 6e9d442a5d027..5b3841aff441a 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs @@ -34,8 +34,8 @@ public PullDiagnosticHandlerProvider( public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) { return ImmutableArray.Create( - new DocumentPullDiagnosticHandler(serverKind, _diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource), - new WorkspacePullDiagnosticHandler(serverKind, _diagnosticService, _editAndContinueDiagnosticUpdateSource)); + new DocumentPullDiagnosticHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource), + new WorkspacePullDiagnosticHandler(_diagnosticService, _editAndContinueDiagnosticUpdateSource)); } } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs index 2cb25eeb59550..b87ae043f3d34 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.SolutionCrawler; @@ -19,8 +20,8 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics [Method(VSInternalMethods.WorkspacePullDiagnosticName)] internal class WorkspacePullDiagnosticHandler : AbstractPullDiagnosticHandler { - public WorkspacePullDiagnosticHandler(WellKnownLspServerKinds serverKind, IDiagnosticService diagnosticService, EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - : base(serverKind, diagnosticService, editAndContinueDiagnosticUpdateSource) + public WorkspacePullDiagnosticHandler(IDiagnosticService diagnosticService, EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) + : base(diagnosticService, editAndContinueDiagnosticUpdateSource) { } @@ -74,7 +75,7 @@ internal static async ValueTask> GetWorkspacePullDocume // If we're being called from razor, we do not support WorkspaceDiagnostics at all. For razor, workspace // diagnostics will be handled by razor itself, which will operate by calling into Roslyn and asking for // document-diagnostics instead. - if (context.ClientName != null) + if (context.ServerKind == WellKnownLspServerKinds.RazorLspServer) return ImmutableArray.Empty; using var _ = ArrayBuilder.GetInstance(out var result); @@ -145,6 +146,13 @@ async Task AddDocumentsFromProjectAsync(Project? project, ImmutableArray continue; } + // Do not attempt to get workspace diagnostics for Razor files, Razor will directly ask us for document diagnostics + // for any razor file they are interested in. + if (document.IsRazorDocument()) + { + continue; + } + result.Add(document); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs index 3a9b8d4488c5a..05c36bea493b7 100644 --- a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs @@ -77,7 +77,7 @@ public OnAutoInsertHandler( // Only support this for razor as LSP doesn't support overtype yet. // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1165179/ // Once LSP supports overtype we can move all of brace completion to LSP. - if (request.Character == "\n" && context.ClientName == document.Services.GetService()?.DiagnosticsLspClientName) + if (request.Character == "\n" && context.ServerKind == WellKnownLspServerKinds.RazorLspServer) { var indentationOptions = IndentationOptions.From(documentOptions, document.Project.Solution.Workspace.Services, document.Project.Language); diff --git a/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs b/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs index eb14e29a7de66..b3861712e345f 100644 --- a/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs @@ -35,7 +35,7 @@ public GetTextDocumentWithContextHandler() Contract.ThrowIfNull(context.Solution); // We specifically don't use context.Document here because we want multiple - var documents = context.Solution.GetDocuments(request.TextDocument.Uri, context.ClientName); + var documents = context.Solution.GetDocuments(request.TextDocument.Uri); if (!documents.Any()) { diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs b/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs index 12a03cebb76a5..a62a542f0dccd 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs @@ -43,9 +43,9 @@ internal readonly struct RequestContext public readonly ClientCapabilities ClientCapabilities; /// - /// The LSP client making the request + /// The LSP server handling the request. /// - public readonly string? ClientName; + public readonly WellKnownLspServerKinds ServerKind; /// /// The document that the request is for, if applicable. This comes from the returned from the handler itself via a call to . @@ -68,7 +68,7 @@ public RequestContext( Solution? solution, ILspLogger logger, ClientCapabilities clientCapabilities, - string? clientName, + WellKnownLspServerKinds serverKind, Document? document, IDocumentChangeTracker documentChangeTracker, ImmutableDictionary trackedDocuments, @@ -78,7 +78,7 @@ public RequestContext( Document = document; Solution = solution; ClientCapabilities = clientCapabilities; - ClientName = clientName; + ServerKind = serverKind; SupportedLanguages = supportedLanguages; GlobalOptions = globalOptions; _documentChangeTracker = documentChangeTracker; @@ -89,7 +89,7 @@ public RequestContext( public static RequestContext? Create( bool requiresLSPSolution, TextDocumentIdentifier? textDocument, - string? clientName, + WellKnownLspServerKinds serverKind, ILspLogger logger, ClientCapabilities clientCapabilities, LspWorkspaceManager lspWorkspaceManager, @@ -107,7 +107,7 @@ public RequestContext( // so they're not accidentally operating on stale solution state. if (!requiresLSPSolution) { - return new RequestContext(solution: null, logger, clientCapabilities, clientName, document: null, documentChangeTracker, trackedDocuments, supportedLanguages, globalOptions); + return new RequestContext(solution: null, logger, clientCapabilities, serverKind, document: null, documentChangeTracker, trackedDocuments, supportedLanguages, globalOptions); } // Go through each registered workspace, find the solution that contains the document that @@ -120,7 +120,7 @@ public RequestContext( { // we were given a request associated with a document. Find the corresponding roslyn // document for this. If we can't, we cannot proceed. - document = lspWorkspaceManager.GetLspDocument(textDocument, clientName); + document = lspWorkspaceManager.GetLspDocument(textDocument); if (document != null) workspaceSolution = document.Project.Solution; } @@ -135,7 +135,7 @@ public RequestContext( workspaceSolution, logger, clientCapabilities, - clientName, + serverKind, document, documentChangeTracker, trackedDocuments, diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs index 2aa44e881a3a3..0ec8109ecb26c 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs @@ -28,9 +28,6 @@ private interface IQueueItem /// bool MutatesSolutionState { get; } - /// - string? ClientName { get; } - string MethodName { get; } /// @@ -67,8 +64,6 @@ private class QueueItem : IQueueItem public bool MutatesSolutionState { get; } - public string? ClientName { get; } - public string MethodName { get; } public TextDocumentIdentifier? TextDocument { get; } @@ -83,7 +78,6 @@ public QueueItem( bool mutatesSolutionState, bool requiresLSPSolution, ClientCapabilities clientCapabilities, - string? clientName, string methodName, TextDocumentIdentifier? textDocument, TRequestType request, @@ -107,7 +101,6 @@ public QueueItem( MutatesSolutionState = mutatesSolutionState; RequiresLSPSolution = requiresLSPSolution; ClientCapabilities = clientCapabilities; - ClientName = clientName; MethodName = methodName; TextDocument = textDocument; } @@ -116,7 +109,6 @@ public static (IQueueItem, Task) Create( bool mutatesSolutionState, bool requiresLSPSolution, ClientCapabilities clientCapabilities, - string? clientName, string methodName, TextDocumentIdentifier? textDocument, TRequestType request, @@ -130,7 +122,6 @@ public static (IQueueItem, Task) Create( mutatesSolutionState, requiresLSPSolution, clientCapabilities, - clientName, methodName, textDocument, request, diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs index 02c373d8b5aba..1ab2635171c11 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs @@ -39,7 +39,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// /// /// Regardless of whether a request is mutating or not, or blocking or not, is an implementation detail of this class - /// and any consumers observing the results of the task returned from + /// and any consumers observing the results of the task returned from /// will see the results of the handling of the request, whenever it occurred. /// /// @@ -142,7 +142,6 @@ public void Shutdown() /// The handler that will handle the request. /// The request to handle. /// The client capabilities. - /// The client name. /// The name of the LSP method. /// A cancellation token that will cancel the handing of this request. /// The request could also be cancelled by the queue shutting down. @@ -153,7 +152,6 @@ public void Shutdown() IRequestHandler handler, TRequestType request, ClientCapabilities clientCapabilities, - string? clientName, string methodName, CancellationToken requestCancellationToken) where TRequestType : class @@ -171,7 +169,6 @@ public void Shutdown() mutatesSolutionState, requiresLSPSolution, clientCapabilities, - clientName, methodName, textDocument, request, @@ -275,7 +272,7 @@ private void OnRequestServerShutdown(string message) return RequestContext.Create( queueItem.RequiresLSPSolution, queueItem.TextDocument, - queueItem.ClientName, + _serverKind, _logger, queueItem.ClientCapabilities, _lspWorkspaceManager, diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs index bdd4c460a84e1..9313334d81b76 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Classification; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.LanguageServer.Protocol; diff --git a/src/Features/LanguageServer/Protocol/ILspLoggerFactory.cs b/src/Features/LanguageServer/Protocol/ILspLoggerFactory.cs index b7ad33aef7e3e..56a14a6eeebb5 100644 --- a/src/Features/LanguageServer/Protocol/ILspLoggerFactory.cs +++ b/src/Features/LanguageServer/Protocol/ILspLoggerFactory.cs @@ -10,6 +10,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer { internal interface ILspLoggerFactory { - Task CreateLoggerAsync(string serverTypeName, string? clientName, JsonRpc jsonRpc, CancellationToken cancellationToken); + Task CreateLoggerAsync(string serverTypeName, JsonRpc jsonRpc, CancellationToken cancellationToken); } } diff --git a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs index 3b7ae888b05b8..7ba7b416a1e0a 100644 --- a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs +++ b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs @@ -28,7 +28,6 @@ internal class LanguageServerTarget : ILanguageServerTarget private readonly RequestExecutionQueue _queue; private readonly IAsynchronousOperationListener _listener; private readonly ILspLogger _logger; - private readonly string? _clientName; // Set on first LSP initialize request. private ClientCapabilities? _clientCapabilities; @@ -49,7 +48,6 @@ internal LanguageServerTarget( IAsynchronousOperationListenerProvider listenerProvider, ILspLogger logger, ImmutableArray supportedLanguages, - string? clientName, WellKnownLspServerKinds serverKind) { _requestDispatcher = requestDispatcherFactory.CreateRequestDispatcher(serverKind); @@ -62,7 +60,6 @@ internal LanguageServerTarget( _jsonRpc.Disconnected += JsonRpc_Disconnected; _listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); - _clientName = clientName; _queue = new RequestExecutionQueue( logger, @@ -115,7 +112,6 @@ public DelegatingEntryPoint(string method, LanguageServerTarget target) _method, requestType, _target._clientCapabilities, - _target._clientName, _target._queue, cancellationToken).ConfigureAwait(false); return result; @@ -224,7 +220,6 @@ private void ExitImpl() requestMethod, request, _clientCapabilities, - _clientName, _queue, cancellationToken).ConfigureAwait(false); return result; diff --git a/src/Features/LanguageServer/Protocol/RequestDispatcher.cs b/src/Features/LanguageServer/Protocol/RequestDispatcher.cs index a19e9dcabfb9c..9c44acba729ee 100644 --- a/src/Features/LanguageServer/Protocol/RequestDispatcher.cs +++ b/src/Features/LanguageServer/Protocol/RequestDispatcher.cs @@ -91,7 +91,6 @@ private static (Type requestType, Type responseType) ConvertHandlerTypeToRequest string methodName, TRequestType request, LSP.ClientCapabilities clientCapabilities, - string? clientName, RequestExecutionQueue queue, CancellationToken cancellationToken) where TRequestType : class { @@ -106,7 +105,7 @@ private static (Type requestType, Type responseType) ConvertHandlerTypeToRequest var strongHandler = (IRequestHandler?)handler; Contract.ThrowIfNull(strongHandler, string.Format("Request handler not found for method {0}", methodName)); - var result = await ExecuteRequestAsync(queue, mutatesSolutionState, requiresLspSolution, strongHandler, request, clientCapabilities, clientName, methodName, cancellationToken).ConfigureAwait(false); + var result = await ExecuteRequestAsync(queue, mutatesSolutionState, requiresLspSolution, strongHandler, request, clientCapabilities, methodName, cancellationToken).ConfigureAwait(false); return result; } @@ -117,11 +116,10 @@ private static (Type requestType, Type responseType) ConvertHandlerTypeToRequest IRequestHandler handler, TRequestType request, LSP.ClientCapabilities clientCapabilities, - string? clientName, string methodName, CancellationToken cancellationToken) where TRequestType : class { - return queue.ExecuteAsync(mutatesSolutionState, requiresLSPSolution, handler, request, clientCapabilities, clientName, methodName, cancellationToken); + return queue.ExecuteAsync(mutatesSolutionState, requiresLSPSolution, handler, request, clientCapabilities, methodName, cancellationToken); } public ImmutableArray GetRegisteredMethods() diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs index 23aec47610146..d74f3af1b4511 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs @@ -238,7 +238,7 @@ public void UpdateTrackedDocument(Uri uri, SourceText newSourceText) // Get our current solutions and re-fork from the workspace as needed. var updatedSolutions = ComputeIncrementalLspSolutions_CalledUnderLock(); - var findDocumentResult = FindDocuments(uri, updatedSolutions, clientName: null, _requestTelemetryLogger, _logger); + var findDocumentResult = FindDocuments(uri, updatedSolutions, _requestTelemetryLogger, _logger); if (findDocumentResult.IsEmpty) { // We didn't find this document in a registered workspace or in the misc workspace. @@ -303,11 +303,7 @@ public ImmutableDictionary GetTrackedLspText() /// /// Returns a document with the LSP tracked text forked from the appropriate workspace solution. /// - /// - /// Returns documents that have a matching client name. In razor scenarios this is to ensure that the Razor C# server - /// only provides data for generated razor documents (which have a client name). - /// - public Document? GetLspDocument(TextDocumentIdentifier textDocumentIdentifier, string? clientName) + public Document? GetLspDocument(TextDocumentIdentifier textDocumentIdentifier) { lock (_gate) { @@ -315,7 +311,7 @@ public ImmutableDictionary GetTrackedLspText() var currentLspSolutions = ComputeIncrementalLspSolutions_CalledUnderLock(); // Search through the latest lsp solutions to find the document with matching uri and client name. - var findDocumentResult = FindDocuments(textDocumentIdentifier.Uri, currentLspSolutions, clientName, _requestTelemetryLogger, _logger); + var findDocumentResult = FindDocuments(textDocumentIdentifier.Uri, currentLspSolutions, _requestTelemetryLogger, _logger); if (findDocumentResult.IsEmpty) { return null; @@ -382,7 +378,6 @@ private ImmutableArray ComputeIncrementalLspSolutions_CalledUnderLock( private static ImmutableArray FindDocuments( Uri uri, ImmutableArray registeredSolutions, - string? clientName, RequestTelemetryLogger telemetryLogger, ILspLogger logger) { @@ -394,7 +389,7 @@ private static ImmutableArray FindDocuments( .Concat(registeredSolutions.Where(solution => solution.Workspace is LspMiscellaneousFilesWorkspace)).ToImmutableArray(); // First search the registered workspaces for documents with a matching URI. - if (TryGetDocumentsForUri(uri, registeredSolutions, clientName, out var documents, out var solution)) + if (TryGetDocumentsForUri(uri, registeredSolutions, out var documents, out var solution)) { telemetryLogger.UpdateFindDocumentTelemetryData(success: true, solution.Workspace.Kind); logger.TraceInformation($"{documents.Value.First().FilePath} found in workspace {solution.Workspace.Kind}"); @@ -404,20 +399,19 @@ private static ImmutableArray FindDocuments( // We didn't find the document in any workspace, record a telemetry notification that we did not find it. var searchedWorkspaceKinds = string.Join(";", registeredSolutions.SelectAsArray(s => s.Workspace.Kind)); - logger.TraceError($"Could not find '{uri}' with client name '{clientName}'. Searched {searchedWorkspaceKinds}"); + logger.TraceError($"Could not find '{uri}'. Searched {searchedWorkspaceKinds}"); telemetryLogger.UpdateFindDocumentTelemetryData(success: false, workspaceKind: null); return ImmutableArray.Empty; static bool TryGetDocumentsForUri( Uri uri, ImmutableArray registeredSolutions, - string? clientName, [NotNullWhen(true)] out ImmutableArray? documents, [NotNullWhen(true)] out Solution? solution) { foreach (var registeredSolution in registeredSolutions) { - var matchingDocuments = registeredSolution.GetDocuments(uri, clientName); + var matchingDocuments = registeredSolution.GetDocuments(uri); if (matchingDocuments.Any()) { documents = matchingDocuments; diff --git a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs index ca9b74b622a83..f66fb9664be95 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs @@ -101,7 +101,7 @@ void M() private static Solution GetLSPSolution(TestLspServer testLspServer, Uri uri) { - var lspDocument = testLspServer.GetManager().GetLspDocument(new TextDocumentIdentifier { Uri = uri }, null); + var lspDocument = testLspServer.GetManager().GetLspDocument(new TextDocumentIdentifier { Uri = uri }); Contract.ThrowIfNull(lspDocument); return lspDocument.Project.Solution; } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/OnAutoInsert/OnAutoInsertTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/OnAutoInsert/OnAutoInsertTests.cs index bd7594884af8f..8faf23f9e063b 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/OnAutoInsert/OnAutoInsertTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/OnAutoInsert/OnAutoInsertTests.cs @@ -268,7 +268,7 @@ void M() $0 } }"; - await VerifyMarkupAndExpected("\n", markup, expected); + await VerifyMarkupAndExpected("\n", markup, expected, serverKind: WellKnownLspServerKinds.RazorLspServer); } [Fact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] @@ -290,7 +290,7 @@ void M() $0 } }"; - await VerifyMarkupAndExpected("\n", markup, expected, insertSpaces: false, tabSize: 4); + await VerifyMarkupAndExpected("\n", markup, expected, insertSpaces: false, tabSize: 4, serverKind: WellKnownLspServerKinds.RazorLspServer); } [Fact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] @@ -316,7 +316,7 @@ void M() } } }"; - await VerifyMarkupAndExpected("\n", markup, expected); + await VerifyMarkupAndExpected("\n", markup, expected, serverKind: WellKnownLspServerKinds.RazorLspServer); } [Fact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] @@ -373,16 +373,23 @@ void M() await VerifyNoResult("\n", markup); } - private async Task VerifyMarkupAndExpected(string characterTyped, string markup, string expected, bool insertSpaces = true, int tabSize = 4, string languageName = LanguageNames.CSharp) + private async Task VerifyMarkupAndExpected( + string characterTyped, + string markup, + string expected, + bool insertSpaces = true, + int tabSize = 4, + string languageName = LanguageNames.CSharp, + WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.AlwaysActiveVSLspServer) { Task testLspServerTask; if (languageName == LanguageNames.CSharp) { - testLspServerTask = CreateTestLspServerAsync(markup); + testLspServerTask = CreateTestLspServerAsync(markup, CapabilitiesWithVSExtensions, serverKind); } else if (languageName == LanguageNames.VisualBasic) { - testLspServerTask = CreateVisualBasicTestLspServerAsync(markup); + testLspServerTask = CreateVisualBasicTestLspServerAsync(markup, CapabilitiesWithVSExtensions, serverKind); } else { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs index df39be93ed241..e4cefb78e85b8 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs @@ -103,7 +103,6 @@ private static LanguageServerTarget CreateLanguageServer(Stream inputStream, Str listenerProvider, NoOpLspLogger.Instance, ImmutableArray.Create(InternalLanguageNames.TypeScript), - clientName: null, WellKnownLspServerKinds.RoslynTypeScriptLspServer); jsonRpc.StartListening(); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs index 9ac86e8d92161..7210807fce5b3 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs @@ -523,7 +523,7 @@ private static async Task OpenDocumentAndVerifyLspTextAsync(Uri docume private static Document? GetLspDocument(Uri uri, TestLspServer testLspServer) { - return testLspServer.GetManager().GetLspDocument(CreateTextDocumentIdentifier(uri), clientName: null); + return testLspServer.GetManager().GetLspDocument(CreateTextDocumentIdentifier(uri)); } private static Solution? GetLspHostSolution(TestLspServer testLspServer) diff --git a/src/VisualStudio/Core/Def/LanguageClient/VisualStudioLogHubLoggerFactory.cs b/src/VisualStudio/Core/Def/LanguageClient/VisualStudioLogHubLoggerFactory.cs index 39b56b26546f8..721b71e1500c4 100644 --- a/src/VisualStudio/Core/Def/LanguageClient/VisualStudioLogHubLoggerFactory.cs +++ b/src/VisualStudio/Core/Def/LanguageClient/VisualStudioLogHubLoggerFactory.cs @@ -42,9 +42,9 @@ public VisualStudioLogHubLoggerFactory( _threadingContext = threadingContext; } - public async Task CreateLoggerAsync(string serverTypeName, string? clientName, JsonRpc jsonRpc, CancellationToken cancellationToken) + public async Task CreateLoggerAsync(string serverTypeName, JsonRpc jsonRpc, CancellationToken cancellationToken) { - var logName = $"Roslyn.{serverTypeName}.{clientName ?? "Default"}.{Interlocked.Increment(ref s_logHubSessionId)}"; + var logName = $"Roslyn.{serverTypeName}.{Interlocked.Increment(ref s_logHubSessionId)}"; var logId = new LogId(logName, new ServiceMoniker(typeof(LanguageServerTarget).FullName)); var serviceContainer = await _asyncServiceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory).ConfigureAwait(false); diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs index a9361d44b877e..1078566ab1676 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs @@ -38,7 +38,7 @@ public XamlInProcLanguageClient( LspWorkspaceRegistrationService lspWorkspaceRegistrationService, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(xamlDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext, diagnosticsClientName: null) + : base(xamlDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) { } diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs index 74d1feb458e20..bcdba101eca9f 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs @@ -41,7 +41,7 @@ public XamlInProcLanguageClientDisableUX( LspWorkspaceRegistrationService lspWorkspaceRegistrationService, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(xamlDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext, diagnosticsClientName: null) + : base(xamlDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) { } diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs index e51a125c65858..c830018864bbb 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs @@ -76,7 +76,7 @@ protected AbstractPullDiagnosticHandler(IXamlPullDiagnosticService xamlDiagnosti { if (previousResult.TextDocument != null) { - var document = context.Solution.GetDocument(previousResult.TextDocument, context.ClientName); + var document = context.Solution.GetDocument(previousResult.TextDocument); if (document == null) { // We can no longer get this document, return null for both diagnostics and resultId diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs index 1d3a3b4e67ef6..b9a08c4312801 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs @@ -61,7 +61,7 @@ public XamlRequestDispatcher( } protected override async Task ExecuteRequestAsync( - RequestExecutionQueue queue, bool mutatesSolutionState, bool requiresLSPSolution, IRequestHandler handler, TRequestType request, ClientCapabilities clientCapabilities, string? clientName, string methodName, CancellationToken cancellationToken) + RequestExecutionQueue queue, bool mutatesSolutionState, bool requiresLSPSolution, IRequestHandler handler, TRequestType request, ClientCapabilities clientCapabilities, string methodName, CancellationToken cancellationToken) where TRequestType : class where TResponseType : default { @@ -77,7 +77,7 @@ public XamlRequestDispatcher( { try { - return await base.ExecuteRequestAsync(queue, mutatesSolutionState, requiresLSPSolution, handler, request, clientCapabilities, clientName, methodName, cancellationToken).ConfigureAwait(false); + return await base.ExecuteRequestAsync(queue, mutatesSolutionState, requiresLSPSolution, handler, request, clientCapabilities, methodName, cancellationToken).ConfigureAwait(false); } catch (Exception e) when (e is not OperationCanceledException) {