From f202207b436433cc41c874b54b0c95028fcd0143 Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 24 Jan 2024 10:20:52 -0800 Subject: [PATCH 1/4] Remove dependency on IFindUsageContext from DefinitionItemExtensions --- .../FindUsages/BufferedFindUsagesContext.cs | 7 ++++- ...UsagesService.DefinitionTrackingContext.cs | 5 ++++ .../Portable/FindUsages/FindUsagesContext.cs | 5 ++++ .../Portable/FindUsages/FindUsagesOptions.cs | 20 +++++++------- .../IDefinitionsAndReferencesFactory.cs | 26 +++++++++---------- .../Portable/FindUsages/IFindUsagesContext.cs | 3 ++- .../Options/FindUsagesOptionsStorage.cs | 2 +- .../FindUsages/RemoteFindUsagesService.cs | 5 ++++ 8 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs b/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs index d69b5a6713412..aac1eb6f2cd40 100644 --- a/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs +++ b/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs @@ -6,6 +6,8 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Utilities; using Roslyn.Utilities; @@ -148,9 +150,12 @@ async ValueTask IStreamingProgressTracker.ItemsCompletedAsync(int count, Cancell #region IFindUsagesContext - ValueTask IFindUsagesContext.GetOptionsAsync(string language, CancellationToken cancellationToken) + public ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_globalOptions.GetFindUsagesOptions(language)); + async ValueTask OptionsProvider.GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => (await GetOptionsAsync(languageServices.Language, cancellationToken).ConfigureAwait(false)).ClassificationOptions; + async ValueTask IFindUsagesContext.ReportMessageAsync(string message, CancellationToken cancellationToken) { using var _ = await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs index 004287c7d1fa0..b446f874caf73 100644 --- a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs +++ b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs @@ -6,7 +6,9 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.FindUsages; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Shared.Utilities; namespace Microsoft.CodeAnalysis.FindUsages @@ -30,6 +32,9 @@ private sealed class DefinitionTrackingContext(IFindUsagesContext underlyingCont public ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) => _underlyingContext.GetOptionsAsync(language, cancellationToken); + public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => _underlyingContext.GetOptionsAsync(languageServices, cancellationToken); + public IStreamingProgressTracker ProgressTracker => _underlyingContext.ProgressTracker; diff --git a/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs b/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs index 64ccc1393cef3..bfbff56a847b2 100644 --- a/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs +++ b/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs @@ -4,6 +4,8 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Utilities; using Roslyn.Utilities; @@ -34,5 +36,8 @@ protected FindUsagesContext() public virtual ValueTask OnReferenceFoundAsync(SourceReferenceItem reference, CancellationToken cancellationToken) => default; protected virtual ValueTask ReportProgressAsync(int current, int maximum, CancellationToken cancellationToken) => default; + + async ValueTask OptionsProvider.GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => (await GetOptionsAsync(languageServices.Language, cancellationToken).ConfigureAwait(false)).ClassificationOptions; } } diff --git a/src/Features/Core/Portable/FindUsages/FindUsagesOptions.cs b/src/Features/Core/Portable/FindUsages/FindUsagesOptions.cs index 99c48595a6e8b..6e003860a8092 100644 --- a/src/Features/Core/Portable/FindUsages/FindUsagesOptions.cs +++ b/src/Features/Core/Portable/FindUsages/FindUsagesOptions.cs @@ -5,17 +5,17 @@ using System.Runtime.Serialization; using Microsoft.CodeAnalysis.Classification; -namespace Microsoft.CodeAnalysis.FindUsages +namespace Microsoft.CodeAnalysis.FindUsages; + +[DataContract] +internal readonly record struct FindUsagesOptions { - [DataContract] - internal readonly record struct FindUsagesOptions( - [property: DataMember(Order = 0)] ClassificationOptions ClassificationOptions) - { - public FindUsagesOptions() - : this(ClassificationOptions.Default) - { - } + [DataMember] public ClassificationOptions ClassificationOptions { get; init; } = ClassificationOptions.Default; - public static readonly FindUsagesOptions Default = new(); + public FindUsagesOptions() + { } + + public static readonly FindUsagesOptions Default = new(); } + diff --git a/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs b/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs index 2a181fe47a106..ecdf28c57b4da 100644 --- a/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs +++ b/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs @@ -79,7 +79,7 @@ private static DefinitionItem ToNonClassifiedDefinitionItem( public static async ValueTask ToClassifiedDefinitionItemAsync( this ISymbol definition, - IFindUsagesContext context, + OptionsProvider classificationOptions, Solution solution, FindReferencesSearchOptions options, bool isPrimary, @@ -87,20 +87,20 @@ public static async ValueTask ToClassifiedDefinitionItemAsync( CancellationToken cancellationToken) { var unclassifiedSpans = TryGetSourceLocations(definition, solution, definition.Locations, includeHiddenLocations); - var classifiedSpans = unclassifiedSpans.IsDefault ? default : await ClassifyDocumentSpansAsync(context, unclassifiedSpans, cancellationToken).ConfigureAwait(false); + var classifiedSpans = unclassifiedSpans.IsDefault ? default : await ClassifyDocumentSpansAsync(classificationOptions, unclassifiedSpans, cancellationToken).ConfigureAwait(false); return ToDefinitionItem(definition, unclassifiedSpans, classifiedSpans, solution, options, isPrimary); } public static async ValueTask ToClassifiedDefinitionItemAsync( - this SymbolGroup group, IFindUsagesContext context, Solution solution, FindReferencesSearchOptions options, bool isPrimary, bool includeHiddenLocations, CancellationToken cancellationToken) + this SymbolGroup group, OptionsProvider classificationOptions, Solution solution, FindReferencesSearchOptions options, bool isPrimary, bool includeHiddenLocations, CancellationToken cancellationToken) { // Make a single definition item that knows about all the locations of all the symbols in the group. var definition = group.Symbols.First(); var allLocations = group.Symbols.SelectManyAsArray(s => s.Locations); var unclassifiedSpans = TryGetSourceLocations(definition, solution, allLocations, includeHiddenLocations); - var classifiedSpans = unclassifiedSpans.IsDefault ? default : await ClassifyDocumentSpansAsync(context, unclassifiedSpans, cancellationToken).ConfigureAwait(false); + var classifiedSpans = unclassifiedSpans.IsDefault ? default : await ClassifyDocumentSpansAsync(classificationOptions, unclassifiedSpans, cancellationToken).ConfigureAwait(false); return ToDefinitionItem(definition, unclassifiedSpans, classifiedSpans, solution, options, isPrimary); } @@ -216,14 +216,12 @@ private static ImmutableArray TryGetSourceLocations(ISymbol defini return sourceLocations.ToImmutableAndClear(); } - private static ValueTask> ClassifyDocumentSpansAsync(IFindUsagesContext context, ImmutableArray unclassifiedSpans, CancellationToken cancellationToken) - => unclassifiedSpans.SelectAsArrayAsync(async (documentSpan, context, cancellationToken) => + private static ValueTask> ClassifyDocumentSpansAsync(OptionsProvider optionsProvider, ImmutableArray unclassifiedSpans, CancellationToken cancellationToken) + => unclassifiedSpans.SelectAsArrayAsync(async (documentSpan, optionsProvider, cancellationToken) => { - var options = await context.GetOptionsAsync(documentSpan.Document.Project.Language, cancellationToken).ConfigureAwait(false); - ClassifiedSpansAndHighlightSpan? result = await ClassifiedSpansAndHighlightSpanFactory.ClassifyAsync( - documentSpan, classifiedSpans: null, options.ClassificationOptions, cancellationToken).ConfigureAwait(false); - return result; - }, context, cancellationToken); + var options = await optionsProvider.GetOptionsAsync(documentSpan.Document.Project.Services, cancellationToken).ConfigureAwait(false); + return (ClassifiedSpansAndHighlightSpan?)await ClassifiedSpansAndHighlightSpanFactory.ClassifyAsync(documentSpan, classifiedSpans: null, options, cancellationToken).ConfigureAwait(false); + }, optionsProvider, cancellationToken); private static ImmutableDictionary GetProperties(ISymbol definition, bool isPrimary) { @@ -256,7 +254,7 @@ private static ImmutableDictionary GetProperties(ISymbol definit public static async Task TryCreateSourceReferenceItemAsync( this ReferenceLocation referenceLocation, - IFindUsagesContext context, + OptionsProvider optionsProvider, DefinitionItem definitionItem, bool includeHiddenLocations, CancellationToken cancellationToken) @@ -273,11 +271,11 @@ private static ImmutableDictionary GetProperties(ISymbol definit var document = referenceLocation.Document; var sourceSpan = location.SourceSpan; - var options = await context.GetOptionsAsync(document.Project.Language, cancellationToken).ConfigureAwait(false); + var options = await optionsProvider.GetOptionsAsync(document.Project.Services, cancellationToken).ConfigureAwait(false); var documentSpan = new DocumentSpan(document, sourceSpan); var classifiedSpans = await ClassifiedSpansAndHighlightSpanFactory.ClassifyAsync( - documentSpan, classifiedSpans: null, options.ClassificationOptions, cancellationToken).ConfigureAwait(false); + documentSpan, classifiedSpans: null, options, cancellationToken).ConfigureAwait(false); return new SourceReferenceItem( definitionItem, documentSpan, classifiedSpans, referenceLocation.SymbolUsageInfo, referenceLocation.AdditionalProperties); diff --git a/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs b/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs index 58ea91b8667da..1ae28d87eb640 100644 --- a/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs +++ b/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs @@ -5,11 +5,12 @@ using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Shared.Utilities; namespace Microsoft.CodeAnalysis.FindUsages { - internal interface IFindUsagesContext + internal interface IFindUsagesContext : OptionsProvider { /// /// Used for clients that are finding usages to push information about how far along they diff --git a/src/Features/LanguageServer/Protocol/Features/Options/FindUsagesOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/FindUsagesOptionsStorage.cs index da4c02aa5f3df..280a9ee9b85a4 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/FindUsagesOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/FindUsagesOptionsStorage.cs @@ -10,6 +10,6 @@ namespace Microsoft.CodeAnalysis.FindUsages internal static class FindUsagesOptionsStorage { public static FindUsagesOptions GetFindUsagesOptions(this IGlobalOptionService globalOptions, string language) - => new(ClassificationOptions: globalOptions.GetClassificationOptions(language)); + => new() { ClassificationOptions = globalOptions.GetClassificationOptions(language) }; } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs b/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs index 6be0ff85cb050..4ccb4c26982e3 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindUsages; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; @@ -101,6 +103,9 @@ public ValueTask ItemsCompletedAsync(int count, CancellationToken cancellationTo public ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) => _callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(_callbackId, language, cancellationToken), cancellationToken); + async ValueTask OptionsProvider.GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => (await GetOptionsAsync(languageServices.Language, cancellationToken).ConfigureAwait(false)).ClassificationOptions; + public ValueTask ReportMessageAsync(string message, CancellationToken cancellationToken) => _callback.InvokeAsync((callback, cancellationToken) => callback.ReportMessageAsync(_callbackId, message, cancellationToken), cancellationToken); From 53aefe0f0bd4c036c72ff2fc656eaee9c9bf7e1a Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 24 Jan 2024 18:12:26 -0800 Subject: [PATCH 2/4] Pass classification options separately --- .../VSTypeScriptFindUsagesService.cs | 5 ++- .../FindReferencesCommandHandler.cs | 4 +- .../FindUsages/BufferedFindUsagesContext.cs | 10 +---- .../Core/GoToBase/GoToBaseCommandHandler.cs | 2 +- .../AbstractGoToCommandHandler`2.cs | 7 ++- .../GoToImplementationCommandHandler.cs | 2 +- .../FindReferencesCommandHandlerTests.cs | 7 --- .../FindReferences/FindReferencesTests.vb | 8 ++-- .../Test2/GoToBase/GoToBaseTestsBase.vb | 4 +- .../GoToDefinition/GoToDefinitionTestsBase.vb | 2 +- .../Test2/GoToHelpers/GoToHelpers.vb | 2 +- .../GoToImplementationTests.vb | 4 +- .../MockNavigableItemsPresenter.vb | 5 +-- ...UsagesService.DefinitionTrackingContext.cs | 6 --- ...stractFindUsagesService.ProgressAdapter.cs | 26 +++++------ ...ctFindUsagesService_FindImplementations.cs | 15 ++++--- ...bstractFindUsagesService_FindReferences.cs | 44 ++++++++++--------- .../Portable/FindUsages/FindUsagesContext.cs | 9 ---- .../Portable/FindUsages/IFindUsagesContext.cs | 7 +-- .../FindUsages/IFindUsagesLSPService.cs | 6 +-- .../Portable/FindUsages/IFindUsagesService.cs | 6 +-- .../FindUsages/IRemoteFindUsagesService.cs | 14 +++--- .../GoToBase/AbstractGoToBaseService.cs | 5 ++- .../Portable/GoToBase/IGoToBaseService.cs | 3 +- .../FindUsages/SimpleFindUsagesContext.cs | 9 ---- .../Options/ClassificationOptionsStorage.cs | 5 ++- .../References/FindAllReferencesHandler.cs | 4 +- .../References/FindImplementationsHandler.cs | 6 ++- .../References/FindUsagesLSPContext.cs | 10 +---- ...odeAnalysis.LanguageServer.Protocol.csproj | 1 + .../Options/TestOptionsProvider.cs | 16 +++++++ .../Debugger/DebuggerFindReferencesService.cs | 25 +++++------ .../Debugger/InternalAPI.Unshipped.txt | 2 +- .../FindUsages/FSharpFindUsagesService.cs | 20 ++++----- ...bstractTableDataSourceFindUsagesContext.cs | 3 -- .../AbstractObjectBrowserLibraryManager.cs | 18 +++++--- .../GoToDefinition/GoToDefinitionApiTests.vb | 2 +- .../Venus/DocumentService_IntegrationTests.vb | 4 +- .../Fakes/StubStreamingFindUsagesPresenter.cs | 18 +++----- .../Services/ClientOptionProviders.cs | 31 +++---------- .../FindUsages/RemoteFindUsagesService.cs | 31 +++++++------ .../Workspace/Core/Options/OptionsProvider.cs | 15 +++++++ 42 files changed, 195 insertions(+), 228 deletions(-) create mode 100644 src/Features/TestUtilities/Options/TestOptionsProvider.cs diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptFindUsagesService.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptFindUsagesService.cs index ae5f92e5e2ec0..0fd1424d79d89 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptFindUsagesService.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptFindUsagesService.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.Utilities; using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Classification; namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript { @@ -22,10 +23,10 @@ internal sealed class VSTypeScriptFindUsagesService(IVSTypeScriptFindUsagesServi { private readonly IVSTypeScriptFindUsagesService _underlyingService = underlyingService; - public Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + public Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) => _underlyingService.FindReferencesAsync(document, position, new Context(context), cancellationToken); - public Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + public Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) => _underlyingService.FindImplementationsAsync(document, position, new Context(context), cancellationToken); private sealed class Context(IFindUsagesContext context) : IVSTypeScriptFindUsagesContext diff --git a/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs b/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs index f0f5225727b83..5448eec7b2adf 100644 --- a/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs +++ b/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs @@ -8,6 +8,7 @@ using System.ComponentModel.Composition; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Editor; using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; @@ -120,6 +121,7 @@ private async Task StreamingFindReferencesAsync( try { using var token = _asyncListener.BeginAsyncOperation(nameof(StreamingFindReferencesAsync)); + var classificationOptions = _globalOptions.GetClassificationOptionsProvider(); // Let the presented know we're starting a search. It will give us back the context object that the FAR // service will push results into. This operation is not externally cancellable. Instead, the find refs @@ -137,7 +139,7 @@ private async Task StreamingFindReferencesAsync( { try { - await findUsagesService.FindReferencesAsync(context, document, caretPosition, cancellationToken).ConfigureAwait(false); + await findUsagesService.FindReferencesAsync(context, document, caretPosition, classificationOptions, cancellationToken).ConfigureAwait(false); } finally { diff --git a/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs b/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs index aac1eb6f2cd40..f0523e4c971b7 100644 --- a/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs +++ b/src/EditorFeatures/Core/FindUsages/BufferedFindUsagesContext.cs @@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis.FindUsages; /// user immediately if the find command completes quickly, or which will be pushed into the streaming presenter /// if the search is taking too long. /// -internal sealed class BufferedFindUsagesContext(IGlobalOptionService globalOptions) : IFindUsagesContext, IStreamingProgressTracker +internal sealed class BufferedFindUsagesContext : IFindUsagesContext, IStreamingProgressTracker { private class State { @@ -31,8 +31,6 @@ private class State public ImmutableArray.Builder Definitions = ImmutableArray.CreateBuilder(); } - private readonly IGlobalOptionService _globalOptions = globalOptions; - /// /// Lock which controls access to all members below. /// @@ -150,12 +148,6 @@ async ValueTask IStreamingProgressTracker.ItemsCompletedAsync(int count, Cancell #region IFindUsagesContext - public ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(_globalOptions.GetFindUsagesOptions(language)); - - async ValueTask OptionsProvider.GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices.Language, cancellationToken).ConfigureAwait(false)).ClassificationOptions; - async ValueTask IFindUsagesContext.ReportMessageAsync(string message, CancellationToken cancellationToken) { using var _ = await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/EditorFeatures/Core/GoToBase/GoToBaseCommandHandler.cs b/src/EditorFeatures/Core/GoToBase/GoToBaseCommandHandler.cs index f2a987890f6c5..fdd4ad9c8b923 100644 --- a/src/EditorFeatures/Core/GoToBase/GoToBaseCommandHandler.cs +++ b/src/EditorFeatures/Core/GoToBase/GoToBaseCommandHandler.cs @@ -45,6 +45,6 @@ internal sealed class GoToBaseCommandHandler( protected override Task FindActionAsync(IFindUsagesContext context, Document document, int caretPosition, CancellationToken cancellationToken) => document.GetRequiredLanguageService() - .FindBasesAsync(context, document, caretPosition, cancellationToken); + .FindBasesAsync(context, document, caretPosition, ClassificationOptionsProvider, cancellationToken); } } diff --git a/src/EditorFeatures/Core/GoToDefinition/AbstractGoToCommandHandler`2.cs b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToCommandHandler`2.cs index ffdfc2b964ac2..5ecb0de0b743c 100644 --- a/src/EditorFeatures/Core/GoToDefinition/AbstractGoToCommandHandler`2.cs +++ b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToCommandHandler`2.cs @@ -5,6 +5,8 @@ using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Tagging; @@ -41,7 +43,8 @@ internal abstract class AbstractGoToCommandHandler ClassificationOptionsProvider = globalOptions.GetClassificationOptionsProvider(); /// /// The current go-to command that is in progress. Tracked so that if we issue multiple find-impl commands that @@ -165,7 +168,7 @@ private async Task ExecuteCommandWorkerAsync( // TLanguageService. Once we get the results back we'll then decide what to do with them. If we get only a // single result back, then we'll just go directly to it. Otherwise, we'll present the results in the // IStreamingFindUsagesPresenter. - var findContext = new BufferedFindUsagesContext(_globalOptions); + var findContext = new BufferedFindUsagesContext(); var cancellationToken = cancellationTokenSource.Token; var delayTask = DelayAsync(cancellationToken); diff --git a/src/EditorFeatures/Core/GoToImplementation/GoToImplementationCommandHandler.cs b/src/EditorFeatures/Core/GoToImplementation/GoToImplementationCommandHandler.cs index 97047f433877a..495625cf499c0 100644 --- a/src/EditorFeatures/Core/GoToImplementation/GoToImplementationCommandHandler.cs +++ b/src/EditorFeatures/Core/GoToImplementation/GoToImplementationCommandHandler.cs @@ -45,6 +45,6 @@ internal sealed class GoToImplementationCommandHandler( protected override Task FindActionAsync(IFindUsagesContext context, Document document, int caretPosition, CancellationToken cancellationToken) => document.GetRequiredLanguageService() - .FindImplementationsAsync(context, document, caretPosition, cancellationToken); + .FindImplementationsAsync(context, document, caretPosition, ClassificationOptionsProvider, cancellationToken); } } diff --git a/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs b/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs index b12a90a4377c1..e25f02ba174d9 100644 --- a/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs +++ b/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs @@ -31,13 +31,6 @@ private class MockFindUsagesContext : FindUsagesContext { public readonly List Result = new(); - public MockFindUsagesContext() - { - } - - public override ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(FindUsagesOptions.Default); - public override ValueTask OnDefinitionFoundAsync(DefinitionItem definition, CancellationToken cancellationToken) { lock (Result) diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb index de5159aee4c68..6ef0210d29af5 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb @@ -5,6 +5,7 @@ Imports System.Collections.Immutable Imports System.Threading Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Classification Imports Microsoft.CodeAnalysis.CSharp.Syntax Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.FindSymbols @@ -74,9 +75,10 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences Await workspace.CurrentSolution.GetSourceGeneratedDocumentAsync(cursorDocument.Id, CancellationToken.None)) Assert.NotNull(startDocument) + Dim classificationOptions = workspace.GlobalOptions.GetClassificationOptionsProvider() Dim findRefsService = startDocument.GetLanguageService(Of IFindUsagesService) Dim context = New TestContext() - Await findRefsService.FindReferencesAsync(context, startDocument, cursorPosition, CancellationToken.None) + Await findRefsService.FindReferencesAsync(context, startDocument, cursorPosition, classificationOptions, CancellationToken.None) Dim expectedDefinitions = workspace.Documents.Where(Function(d) d.AnnotatedSpans.ContainsKey(DefinitionKey) AndAlso d.AnnotatedSpans(DefinitionKey).Any()). @@ -230,10 +232,6 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences Public Sub New() End Sub - Public Overrides Function GetOptionsAsync(language As String, cancellationToken As CancellationToken) As ValueTask(Of FindUsagesOptions) - Return ValueTaskFactory.FromResult(FindUsagesOptions.Default) - End Function - Public Function ShouldShow(definition As DefinitionItem) As Boolean If References.Any(Function(r) r.Definition Is definition) Then Return True diff --git a/src/EditorFeatures/Test2/GoToBase/GoToBaseTestsBase.vb b/src/EditorFeatures/Test2/GoToBase/GoToBaseTestsBase.vb index 603229db9867c..e9ac8f39f49cb 100644 --- a/src/EditorFeatures/Test2/GoToBase/GoToBaseTestsBase.vb +++ b/src/EditorFeatures/Test2/GoToBase/GoToBaseTestsBase.vb @@ -3,6 +3,7 @@ ' See the LICENSE file in the project root for more information. Imports System.Threading +Imports Microsoft.CodeAnalysis.Classification Imports Microsoft.CodeAnalysis.FindUsages Imports Microsoft.CodeAnalysis.GoToBase Imports Microsoft.CodeAnalysis.Remote.Testing @@ -16,7 +17,8 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.GoToBase testHost:=TestHost.InProcess, Async Function(document As Document, position As Integer, context As SimpleFindUsagesContext) Dim gotoBaseService = document.GetLanguageService(Of IGoToBaseService) - Await gotoBaseService.FindBasesAsync(context, document, position, CancellationToken.None) + Dim options = New TestOptionsProvider(Of ClassificationOptions)(ClassificationOptions.Default) + Await gotoBaseService.FindBasesAsync(context, document, position, options, CancellationToken.None) End Function, shouldSucceed, metadataDefinitions) End Function diff --git a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTestsBase.vb b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTestsBase.vb index 6a3ab7e76e64b..3fdd31f5428d8 100644 --- a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTestsBase.vb +++ b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTestsBase.vb @@ -38,7 +38,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.GoToDefinition Dim presenterCalled As Boolean = False Dim threadingContext = workspace.ExportProvider.GetExportedValue(Of IThreadingContext)() - Dim presenter = New MockStreamingFindUsagesPresenter(workspace.GlobalOptions, Sub() presenterCalled = True) + Dim presenter = New MockStreamingFindUsagesPresenter(Sub() presenterCalled = True) Dim goToDefService = If(document.Project.Language = LanguageNames.CSharp, DirectCast(New CSharpDefinitionLocationService(threadingContext, presenter), IDefinitionLocationService), diff --git a/src/EditorFeatures/Test2/GoToHelpers/GoToHelpers.vb b/src/EditorFeatures/Test2/GoToHelpers/GoToHelpers.vb index 26648f354b399..b1589c5363aec 100644 --- a/src/EditorFeatures/Test2/GoToHelpers/GoToHelpers.vb +++ b/src/EditorFeatures/Test2/GoToHelpers/GoToHelpers.vb @@ -24,7 +24,7 @@ Friend Class GoToHelpers Dim solution = workspace.CurrentSolution Dim document = Await solution.GetRequiredDocumentAsync(documentWithCursor.Id, includeSourceGenerated:=True) - Dim context = New SimpleFindUsagesContext(workspace.GlobalOptions) + Dim context = New SimpleFindUsagesContext() Await testingMethod(document, position, context) If Not shouldSucceed Then diff --git a/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb b/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb index 33f00aac00595..3f745a8900df5 100644 --- a/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb +++ b/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb @@ -5,6 +5,7 @@ Imports Microsoft.CodeAnalysis.Remote.Testing Imports Microsoft.CodeAnalysis.FindUsages Imports System.Threading +Imports Microsoft.CodeAnalysis.Classification Namespace Microsoft.CodeAnalysis.Editor.UnitTests.GoToImplementation <[UseExportProvider]> @@ -17,7 +18,8 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.GoToImplementation host, Async Function(document As Document, position As Integer, context As SimpleFindUsagesContext) As Task Dim findUsagesService = document.GetLanguageService(Of IFindUsagesService) - Await findUsagesService.FindImplementationsAsync(context, document, position, CancellationToken.None).ConfigureAwait(False) + Dim options = New TestOptionsProvider(Of ClassificationOptions)(ClassificationOptions.Default) + Await findUsagesService.FindImplementationsAsync(context, document, position, options, CancellationToken.None).ConfigureAwait(False) End Function, shouldSucceed, metadataDefinitions) diff --git a/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/MockNavigableItemsPresenter.vb b/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/MockNavigableItemsPresenter.vb index 4297c81ee498e..3d703492872f5 100644 --- a/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/MockNavigableItemsPresenter.vb +++ b/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/MockNavigableItemsPresenter.vb @@ -5,7 +5,6 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.Editor.Host Imports Microsoft.CodeAnalysis.FindUsages -Imports Microsoft.CodeAnalysis.Options Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers Friend Class MockStreamingFindUsagesPresenter @@ -14,9 +13,9 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers Public ReadOnly Context As SimpleFindUsagesContext Private ReadOnly _action As Action - Public Sub New(globalOptions As IGlobalOptionService, action As Action) + Public Sub New(action As Action) _action = action - Context = New SimpleFindUsagesContext(globalOptions) + Context = New SimpleFindUsagesContext() End Sub Public Sub ClearAll() Implements IStreamingFindUsagesPresenter.ClearAll diff --git a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs index b446f874caf73..d46645e03724d 100644 --- a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs +++ b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.DefinitionTrackingContext.cs @@ -29,12 +29,6 @@ private sealed class DefinitionTrackingContext(IFindUsagesContext underlyingCont private readonly object _gate = new(); private readonly List _definitions = new(); - public ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => _underlyingContext.GetOptionsAsync(language, cancellationToken); - - public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => _underlyingContext.GetOptionsAsync(languageServices, cancellationToken); - public IStreamingProgressTracker ProgressTracker => _underlyingContext.ProgressTracker; diff --git a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs index bfe4cfc4c369c..246ecda2245e6 100644 --- a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs +++ b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs @@ -25,7 +25,7 @@ internal abstract partial class AbstractFindUsagesService /// instance. /// private sealed class FindLiteralsProgressAdapter( - IFindUsagesContext context, DefinitionItem definition) : IStreamingFindLiteralReferencesProgress + IFindUsagesContext context, OptionsProvider classificationOptions, DefinitionItem definition) : IStreamingFindLiteralReferencesProgress { private readonly IFindUsagesContext _context = context; private readonly DefinitionItem _definition = definition; @@ -35,11 +35,11 @@ public IStreamingProgressTracker ProgressTracker public async ValueTask OnReferenceFoundAsync(Document document, TextSpan span, CancellationToken cancellationToken) { - var options = await _context.GetOptionsAsync(document.Project.Language, cancellationToken).ConfigureAwait(false); + var options = await classificationOptions.GetOptionsAsync(document.Project.Services, cancellationToken).ConfigureAwait(false); var documentSpan = new DocumentSpan(document, span); var classifiedSpans = await ClassifiedSpansAndHighlightSpanFactory.ClassifyAsync( - documentSpan, classifiedSpans: null, options.ClassificationOptions, cancellationToken).ConfigureAwait(false); + documentSpan, classifiedSpans: null, options, cancellationToken).ConfigureAwait(false); await _context.OnReferenceFoundAsync( new SourceReferenceItem(_definition, documentSpan, classifiedSpans, SymbolUsageInfo.None), cancellationToken).ConfigureAwait(false); @@ -50,12 +50,8 @@ await _context.OnReferenceFoundAsync( /// Forwards IFindReferencesProgress calls to an IFindUsagesContext instance. /// private sealed class FindReferencesProgressAdapter( - Solution solution, IFindUsagesContext context, FindReferencesSearchOptions options) : IStreamingFindReferencesProgress + Solution solution, IFindUsagesContext context, FindReferencesSearchOptions searchOptions, OptionsProvider classificationOptions) : IStreamingFindReferencesProgress { - private readonly Solution _solution = solution; - private readonly IFindUsagesContext _context = context; - private readonly FindReferencesSearchOptions _options = options; - /// /// We will hear about definition symbols many times while performing FAR. We'll /// here about it first when the FAR engine discovers the symbol, and then for every @@ -71,7 +67,7 @@ private sealed class FindReferencesProgressAdapter( private readonly SemaphoreSlim _gate = new(initialCount: 1); public IStreamingProgressTracker ProgressTracker - => _context.ProgressTracker; + => context.ProgressTracker; // Do nothing functions. The streaming far service doesn't care about // any of these. @@ -91,9 +87,9 @@ private async ValueTask GetDefinitionItemAsync(SymbolGroup group if (!_definitionToItem.TryGetValue(group, out var definitionItem)) { definitionItem = await group.ToClassifiedDefinitionItemAsync( - _context, - _solution, - _options, + classificationOptions, + solution, + searchOptions, isPrimary: _definitionToItem.Count == 0, includeHiddenLocations: false, cancellationToken).ConfigureAwait(false); @@ -108,20 +104,20 @@ private async ValueTask GetDefinitionItemAsync(SymbolGroup group public async ValueTask OnDefinitionFoundAsync(SymbolGroup group, CancellationToken cancellationToken) { var definitionItem = await GetDefinitionItemAsync(group, cancellationToken).ConfigureAwait(false); - await _context.OnDefinitionFoundAsync(definitionItem, cancellationToken).ConfigureAwait(false); + await context.OnDefinitionFoundAsync(definitionItem, cancellationToken).ConfigureAwait(false); } public async ValueTask OnReferenceFoundAsync(SymbolGroup group, ISymbol definition, ReferenceLocation location, CancellationToken cancellationToken) { var definitionItem = await GetDefinitionItemAsync(group, cancellationToken).ConfigureAwait(false); var referenceItem = await location.TryCreateSourceReferenceItemAsync( - _context, + classificationOptions, definitionItem, includeHiddenLocations: false, cancellationToken).ConfigureAwait(false); if (referenceItem != null) - await _context.OnReferenceFoundAsync(referenceItem, cancellationToken).ConfigureAwait(false); + await context.OnReferenceFoundAsync(referenceItem, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindImplementations.cs b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindImplementations.cs index c11cdc7478e2a..a364da9fbb310 100644 --- a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindImplementations.cs +++ b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindImplementations.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Remote; @@ -20,7 +21,7 @@ namespace Microsoft.CodeAnalysis.FindUsages internal abstract partial class AbstractFindUsagesService { public async Task FindImplementationsAsync( - IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) { // If this is a symbol from a metadata-as-source project, then map that symbol back to a symbol in the primary workspace. var symbolAndProjectOpt = await FindUsagesHelpers.GetRelevantSymbolAndProjectAtPositionAsync( @@ -34,11 +35,11 @@ await context.ReportMessageAsync( var symbolAndProject = symbolAndProjectOpt.Value; await FindImplementationsAsync( - context, symbolAndProject.symbol, symbolAndProject.project, cancellationToken).ConfigureAwait(false); + context, symbolAndProject.symbol, symbolAndProject.project, classificationOptions, cancellationToken).ConfigureAwait(false); } public static async Task FindImplementationsAsync( - IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken) + IFindUsagesContext context, ISymbol symbol, Project project, OptionsProvider classificationOptions, CancellationToken cancellationToken) { var solution = project.Solution; var client = await RemoteHostClient.TryGetClientAsync(solution.Services, cancellationToken).ConfigureAwait(false); @@ -47,7 +48,7 @@ public static async Task FindImplementationsAsync( // Create a callback that we can pass to the server process to hear about the // results as it finds them. When we hear about results we'll forward them to // the 'progress' parameter which will then update the UI. - var serverCallback = new FindUsagesServerCallback(solution, context); + var serverCallback = new FindUsagesServerCallback(solution, context, classificationOptions); var symbolAndProjectId = SerializableSymbolAndProjectId.Create(symbol, project, cancellationToken); await client.TryInvokeAsync( @@ -60,12 +61,12 @@ await client.TryInvokeAsync( { // Couldn't effectively search in OOP. Perform the search in-process. await FindImplementationsInCurrentProcessAsync( - symbol, project, context, cancellationToken).ConfigureAwait(false); + symbol, project, context, classificationOptions, cancellationToken).ConfigureAwait(false); } } private static async Task FindImplementationsInCurrentProcessAsync( - ISymbol symbol, Project project, IFindUsagesContext context, CancellationToken cancellationToken) + ISymbol symbol, Project project, IFindUsagesContext context, OptionsProvider classificationOptions, CancellationToken cancellationToken) { await context.SetSearchTitleAsync( string.Format(FeaturesResources._0_implementations, @@ -84,7 +85,7 @@ await context.SetSearchTitleAsync( foreach (var implementation in implementations) { var definitionItem = await implementation.ToClassifiedDefinitionItemAsync( - context, solution, FindReferencesSearchOptions.Default, isPrimary: true, includeHiddenLocations: false, cancellationToken).ConfigureAwait(false); + classificationOptions, solution, FindReferencesSearchOptions.Default, isPrimary: true, includeHiddenLocations: false, cancellationToken).ConfigureAwait(false); await context.OnDefinitionFoundAsync(definitionItem, cancellationToken).ConfigureAwait(false); } diff --git a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindReferences.cs b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindReferences.cs index 8630e76ba56d0..f6fa0d0f15e1a 100644 --- a/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindReferences.cs +++ b/src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindReferences.cs @@ -22,12 +22,12 @@ namespace Microsoft.CodeAnalysis.FindUsages internal abstract partial class AbstractFindUsagesService { async Task IFindUsagesService.FindReferencesAsync( - IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) { var definitionTrackingContext = new DefinitionTrackingContext(context); await FindLiteralOrSymbolReferencesAsync( - definitionTrackingContext, document, position, cancellationToken).ConfigureAwait(false); + definitionTrackingContext, document, position, classificationOptions, cancellationToken).ConfigureAwait(false); // After the FAR engine is done call into any third party extensions to see // if they want to add results. @@ -39,23 +39,23 @@ await FindLiteralOrSymbolReferencesAsync( } Task IFindUsagesLSPService.FindReferencesAsync( - IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) { // We don't need to get third party definitions when finding references in LSP. // Currently, 3rd party definitions = XAML definitions, and XAML will provide // references via LSP instead of hooking into Roslyn. // This also means that we don't need to be on the UI thread. return FindLiteralOrSymbolReferencesAsync( - new DefinitionTrackingContext(context), document, position, cancellationToken); + new DefinitionTrackingContext(context), document, position, classificationOptions, cancellationToken); } private static async Task FindLiteralOrSymbolReferencesAsync( - IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) { // First, see if we're on a literal. If so search for literals in the solution with // the same value. var found = await TryFindLiteralReferencesAsync( - context, document, position, cancellationToken).ConfigureAwait(false); + context, document, position, classificationOptions, cancellationToken).ConfigureAwait(false); if (found) { return; @@ -63,7 +63,7 @@ private static async Task FindLiteralOrSymbolReferencesAsync( // Wasn't a literal. Try again as a symbol. await FindSymbolReferencesAsync( - context, document, position, cancellationToken).ConfigureAwait(false); + context, document, position, classificationOptions, cancellationToken).ConfigureAwait(false); } private static async Task> GetThirdPartyDefinitionsAsync( @@ -85,7 +85,7 @@ private static async Task> GetThirdPartyDefinitio } private static async Task FindSymbolReferencesAsync( - IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -101,7 +101,7 @@ private static async Task FindSymbolReferencesAsync( var (symbol, project) = symbolAndProject.Value; await FindSymbolReferencesAsync( - context, symbol, project, cancellationToken).ConfigureAwait(false); + context, symbol, project, classificationOptions, cancellationToken).ConfigureAwait(false); } /// @@ -109,27 +109,28 @@ await FindSymbolReferencesAsync( /// and want to push all the references to it into the Streaming-Find-References window. /// public static async Task FindSymbolReferencesAsync( - IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken) + IFindUsagesContext context, ISymbol symbol, Project project, OptionsProvider classificationOptions, CancellationToken cancellationToken) { await context.SetSearchTitleAsync( string.Format(FeaturesResources._0_references, FindUsagesHelpers.GetDisplayName(symbol)), cancellationToken).ConfigureAwait(false); - var options = FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol); + var searchOptions = FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol); // Now call into the underlying FAR engine to find reference. The FAR // engine will push results into the 'progress' instance passed into it. // We'll take those results, massage them, and forward them along to the // FindReferencesContext instance we were given. - await FindReferencesAsync(context, symbol, project, options, cancellationToken).ConfigureAwait(false); + await FindReferencesAsync(context, symbol, project, searchOptions, classificationOptions, cancellationToken).ConfigureAwait(false); } public static async Task FindReferencesAsync( IFindUsagesContext context, ISymbol symbol, Project project, - FindReferencesSearchOptions options, + FindReferencesSearchOptions searchOptions, + OptionsProvider classificationOptions, CancellationToken cancellationToken) { var solution = project.Solution; @@ -139,12 +140,12 @@ public static async Task FindReferencesAsync( // Create a callback that we can pass to the server process to hear about the // results as it finds them. When we hear about results we'll forward them to // the 'progress' parameter which will then update the UI. - var serverCallback = new FindUsagesServerCallback(solution, context); + var serverCallback = new FindUsagesServerCallback(solution, context, classificationOptions); var symbolAndProjectId = SerializableSymbolAndProjectId.Create(symbol, project, cancellationToken); _ = await client.TryInvokeAsync( solution, - (service, solutionInfo, callbackId, cancellationToken) => service.FindReferencesAsync(solutionInfo, callbackId, symbolAndProjectId, options, cancellationToken), + (service, solutionInfo, callbackId, cancellationToken) => service.FindReferencesAsync(solutionInfo, callbackId, symbolAndProjectId, searchOptions, cancellationToken), serverCallback, cancellationToken).ConfigureAwait(false); } @@ -152,7 +153,7 @@ public static async Task FindReferencesAsync( { // Couldn't effectively search in OOP. Perform the search in-process. await FindReferencesInCurrentProcessAsync( - context, symbol, project, options, cancellationToken).ConfigureAwait(false); + context, symbol, project, searchOptions, classificationOptions, cancellationToken).ConfigureAwait(false); } } @@ -160,16 +161,17 @@ private static Task FindReferencesInCurrentProcessAsync( IFindUsagesContext context, ISymbol symbol, Project project, - FindReferencesSearchOptions options, + FindReferencesSearchOptions searchOptions, + OptionsProvider classificationOptions, CancellationToken cancellationToken) { - var progress = new FindReferencesProgressAdapter(project.Solution, context, options); + var progress = new FindReferencesProgressAdapter(project.Solution, context, searchOptions, classificationOptions); return SymbolFinder.FindReferencesAsync( - symbol, project.Solution, progress, documents: null, options, cancellationToken); + symbol, project.Solution, progress, documents: null, searchOptions, cancellationToken); } private static async Task TryFindLiteralReferencesAsync( - IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -229,7 +231,7 @@ private static async Task TryFindLiteralReferencesAsync( await context.OnDefinitionFoundAsync(definition, cancellationToken).ConfigureAwait(false); - var progressAdapter = new FindLiteralsProgressAdapter(context, definition); + var progressAdapter = new FindLiteralsProgressAdapter(context, classificationOptions, definition); // Now call into the underlying FAR engine to find reference. The FAR // engine will push results into the 'progress' instance passed into it. diff --git a/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs b/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs index bfbff56a847b2..11d1e6ccbeed5 100644 --- a/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs +++ b/src/Features/Core/Portable/FindUsages/FindUsagesContext.cs @@ -4,11 +4,7 @@ using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Classification; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Utilities; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FindUsages { @@ -21,8 +17,6 @@ protected FindUsagesContext() ProgressTracker = new StreamingProgressTracker(ReportProgressAsync); } - public abstract ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken); - public virtual ValueTask ReportMessageAsync(string message, CancellationToken cancellationToken) => default; public virtual ValueTask ReportInformationalMessageAsync(string message, CancellationToken cancellationToken) => default; @@ -36,8 +30,5 @@ protected FindUsagesContext() public virtual ValueTask OnReferenceFoundAsync(SourceReferenceItem reference, CancellationToken cancellationToken) => default; protected virtual ValueTask ReportProgressAsync(int current, int maximum, CancellationToken cancellationToken) => default; - - async ValueTask OptionsProvider.GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices.Language, cancellationToken).ConfigureAwait(false)).ClassificationOptions; } } diff --git a/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs b/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs index 1ae28d87eb640..8617e5587f307 100644 --- a/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs +++ b/src/Features/Core/Portable/FindUsages/IFindUsagesContext.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.FindUsages { - internal interface IFindUsagesContext : OptionsProvider + internal interface IFindUsagesContext { /// /// Used for clients that are finding usages to push information about how far along they @@ -18,11 +18,6 @@ internal interface IFindUsagesContext : OptionsProvider /// IStreamingProgressTracker ProgressTracker { get; } - /// - /// Get for specified language. - /// - ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken); - /// /// Report a failure message to be displayed to the user. This will be reported if the find operation returns /// no results. diff --git a/src/Features/Core/Portable/FindUsages/IFindUsagesLSPService.cs b/src/Features/Core/Portable/FindUsages/IFindUsagesLSPService.cs index ef79deb5307fa..0b8886cc1fb46 100644 --- a/src/Features/Core/Portable/FindUsages/IFindUsagesLSPService.cs +++ b/src/Features/Core/Portable/FindUsages/IFindUsagesLSPService.cs @@ -4,7 +4,7 @@ using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.FindUsages; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.FindUsages @@ -15,12 +15,12 @@ internal interface IFindUsagesLSPService : ILanguageService /// Finds the references for the symbol at the specific position in the document, /// pushing the results into the context instance. /// - Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken); + Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken); /// /// Finds the implementations for the symbol at the specific position in the document, /// pushing the results into the context instance. /// - Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken); + Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/FindUsages/IFindUsagesService.cs b/src/Features/Core/Portable/FindUsages/IFindUsagesService.cs index 4a782b8a24378..51aa66da1960f 100644 --- a/src/Features/Core/Portable/FindUsages/IFindUsagesService.cs +++ b/src/Features/Core/Portable/FindUsages/IFindUsagesService.cs @@ -4,7 +4,7 @@ using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.FindUsages; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.FindUsages @@ -15,12 +15,12 @@ internal interface IFindUsagesService : ILanguageService /// Finds the references for the symbol at the specific position in the document, /// pushing the results into the context instance. /// - Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken); + Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken); /// /// Finds the implementations for the symbol at the specific position in the document, /// pushing the results into the context instance. /// - Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken); + Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs b/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs index eacca08705d9a..00d1d3ef62df6 100644 --- a/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs +++ b/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs @@ -14,7 +14,6 @@ using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Remote; -using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -24,7 +23,7 @@ internal interface IRemoteFindUsagesService { internal interface ICallback { - ValueTask GetOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken); + ValueTask GetClassificationOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken); ValueTask AddItemsAsync(RemoteServiceCallbackId callbackId, int count, CancellationToken cancellationToken); ValueTask ItemsCompletedAsync(RemoteServiceCallbackId callbackId, int count, CancellationToken cancellationToken); ValueTask ReportMessageAsync(RemoteServiceCallbackId callbackId, string message, CancellationToken cancellationToken); @@ -60,8 +59,8 @@ public FindUsagesServerCallbackDispatcher() private new FindUsagesServerCallback GetCallback(RemoteServiceCallbackId callbackId) => (FindUsagesServerCallback)base.GetCallback(callbackId); - public ValueTask GetOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken) - => GetCallback(callbackId).GetOptionsAsync(language, cancellationToken); + public ValueTask GetClassificationOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken) + => GetCallback(callbackId).GetClassificationOptionsAsync(language, cancellationToken); public ValueTask AddItemsAsync(RemoteServiceCallbackId callbackId, int count, CancellationToken cancellationToken) => GetCallback(callbackId).AddItemsAsync(count, cancellationToken); @@ -85,14 +84,15 @@ public ValueTask SetSearchTitleAsync(RemoteServiceCallbackId callbackId, string => GetCallback(callbackId).SetSearchTitleAsync(title, cancellationToken); } - internal sealed class FindUsagesServerCallback(Solution solution, IFindUsagesContext context) + internal sealed class FindUsagesServerCallback(Solution solution, IFindUsagesContext context, OptionsProvider classificationOptions) { private readonly Solution _solution = solution; private readonly IFindUsagesContext _context = context; private readonly Dictionary _idToDefinition = new(); + private readonly OptionsProvider _classificationOptions = classificationOptions; - public ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => _context.GetOptionsAsync(language, cancellationToken); + internal ValueTask GetClassificationOptionsAsync(string language, CancellationToken cancellationToken) + => _classificationOptions.GetOptionsAsync(_solution.Services.GetLanguageServices(language), cancellationToken); public ValueTask AddItemsAsync(int count, CancellationToken cancellationToken) => _context.ProgressTracker.AddItemsAsync(count, cancellationToken); diff --git a/src/Features/Core/Portable/GoToBase/AbstractGoToBaseService.cs b/src/Features/Core/Portable/GoToBase/AbstractGoToBaseService.cs index 2d9d85bc647c8..579b82947d614 100644 --- a/src/Features/Core/Portable/GoToBase/AbstractGoToBaseService.cs +++ b/src/Features/Core/Portable/GoToBase/AbstractGoToBaseService.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -28,7 +29,7 @@ internal abstract class AbstractGoToBaseService : IGoToBaseService baseConstructor.Parameters.All(p => p.IsOptional || p.IsParams)); } - public async Task FindBasesAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) + public async Task FindBasesAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) { var symbolAndProjectOpt = await FindUsagesHelpers.GetRelevantSymbolAndProjectAtPositionAsync( document, position, cancellationToken).ConfigureAwait(false); @@ -68,7 +69,7 @@ await context.SetSearchTitleAsync( if (sourceDefinition != null) { var definitionItem = await sourceDefinition.ToClassifiedDefinitionItemAsync( - context, solution, FindReferencesSearchOptions.Default, isPrimary: true, includeHiddenLocations: false, cancellationToken: cancellationToken).ConfigureAwait(false); + classificationOptions, solution, FindReferencesSearchOptions.Default, isPrimary: true, includeHiddenLocations: false, cancellationToken: cancellationToken).ConfigureAwait(false); await context.OnDefinitionFoundAsync(definitionItem, cancellationToken).ConfigureAwait(false); found = true; diff --git a/src/Features/Core/Portable/GoToBase/IGoToBaseService.cs b/src/Features/Core/Portable/GoToBase/IGoToBaseService.cs index 3572fea7b3ae7..4bc6915c27e3d 100644 --- a/src/Features/Core/Portable/GoToBase/IGoToBaseService.cs +++ b/src/Features/Core/Portable/GoToBase/IGoToBaseService.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Host; @@ -15,6 +16,6 @@ internal interface IGoToBaseService : ILanguageService /// Finds the base members overridden or implemented by the symbol at the specific position in the document, /// pushing the results into the context instance. /// - Task FindBasesAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken); + Task FindBasesAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken); } } diff --git a/src/Features/LanguageServer/Protocol/Features/FindUsages/SimpleFindUsagesContext.cs b/src/Features/LanguageServer/Protocol/Features/FindUsages/SimpleFindUsagesContext.cs index 7faf0cefe2be7..cfadbfe86b98d 100644 --- a/src/Features/LanguageServer/Protocol/Features/FindUsages/SimpleFindUsagesContext.cs +++ b/src/Features/LanguageServer/Protocol/Features/FindUsages/SimpleFindUsagesContext.cs @@ -19,7 +19,6 @@ namespace Microsoft.CodeAnalysis.FindUsages internal sealed class SimpleFindUsagesContext : FindUsagesContext { private readonly object _gate = new(); - private readonly IGlobalOptionService _globalOptions; private readonly ImmutableArray.Builder _definitionItems = ImmutableArray.CreateBuilder(); @@ -27,17 +26,9 @@ internal sealed class SimpleFindUsagesContext : FindUsagesContext private readonly ImmutableArray.Builder _referenceItems = ImmutableArray.CreateBuilder(); - public SimpleFindUsagesContext(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } - public string Message { get; private set; } public string SearchTitle { get; private set; } - public override ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(_globalOptions.GetFindUsagesOptions(language)); - public override ValueTask ReportMessageAsync(string message, CancellationToken cancellationToken) { Message = message; diff --git a/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs index 3be916e1e5f91..87d9faa3241fd 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Classification; internal static class ClassificationOptionsStorage { - public static ClassificationOptions GetClassificationOptions(this IGlobalOptionService globalOptions, string language) + public static ClassificationOptions GetClassificationOptions(this IOptionsReader globalOptions, string language) => new() { ClassifyReassignedVariables = globalOptions.GetOption(ClassifyReassignedVariables, language), @@ -17,6 +17,9 @@ public static ClassificationOptions GetClassificationOptions(this IGlobalOptionS // ForceFrozenPartialSemanticsForCrossProcessOperations not stored in global options }; + public static OptionsProvider GetClassificationOptionsProvider(this IOptionsReader globalOptions) + => globalOptions.GetProvider(GetClassificationOptions); + public static PerLanguageOption2 ClassifyReassignedVariables = new("dotnet_classify_reassigned_variables", ClassificationOptions.Default.ClassifyReassignedVariables); diff --git a/src/Features/LanguageServer/Protocol/Handler/References/FindAllReferencesHandler.cs b/src/Features/LanguageServer/Protocol/Handler/References/FindAllReferencesHandler.cs index ef7205e352c11..8e24d9425f109 100644 --- a/src/Features/LanguageServer/Protocol/Handler/References/FindAllReferencesHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/References/FindAllReferencesHandler.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; @@ -65,7 +66,8 @@ public FindAllReferencesHandler( progress, workspace, document, position, _metadataAsSourceFileService, _asyncListener, _globalOptions, cancellationToken); // Finds the references for the symbol at the specific position in the document, reporting them via streaming to the LSP client. - await findUsagesService.FindReferencesAsync(findUsagesContext, document, position, cancellationToken).ConfigureAwait(false); + var classificationOptions = _globalOptions.GetClassificationOptionsProvider(); + await findUsagesService.FindReferencesAsync(findUsagesContext, document, position, classificationOptions, cancellationToken).ConfigureAwait(false); await findUsagesContext.OnCompletedAsync(cancellationToken).ConfigureAwait(false); return progress.GetFlattenedValues(); diff --git a/src/Features/LanguageServer/Protocol/Handler/References/FindImplementationsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/References/FindImplementationsHandler.cs index 4217f4b9d99e4..80e447be3956f 100644 --- a/src/Features/LanguageServer/Protocol/Handler/References/FindImplementationsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/References/FindImplementationsHandler.cs @@ -5,6 +5,7 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; @@ -43,8 +44,9 @@ public FindImplementationsHandler(IGlobalOptionService globalOptions) var findUsagesService = document.GetRequiredLanguageService(); var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); - var findUsagesContext = new SimpleFindUsagesContext(_globalOptions); - await findUsagesService.FindImplementationsAsync(findUsagesContext, document, position, cancellationToken).ConfigureAwait(false); + var findUsagesContext = new SimpleFindUsagesContext(); + var classificationOptions = _globalOptions.GetClassificationOptionsProvider(); + await findUsagesService.FindImplementationsAsync(findUsagesContext, document, position, classificationOptions, cancellationToken).ConfigureAwait(false); foreach (var definition in findUsagesContext.GetDefinitions()) { diff --git a/src/Features/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs b/src/Features/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs index ec1cb44179655..d5aff6fd236fc 100644 --- a/src/Features/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs +++ b/src/Features/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs @@ -12,9 +12,7 @@ using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.FindSymbols; -using Microsoft.CodeAnalysis.FindSymbols.Finders; using Microsoft.CodeAnalysis.FindUsages; -using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.MetadataAsSource; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; @@ -22,7 +20,6 @@ using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Text; -using Roslyn.Core.Imaging; using Roslyn.LanguageServer.Protocol; using Roslyn.Text.Adornments; using Roslyn.Utilities; @@ -94,9 +91,6 @@ public FindUsagesLSPContext( DelayTimeSpan.Medium, ReportReferencesAsync, asyncListener, cancellationToken); } - public override ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(_globalOptions.GetFindUsagesOptions(language)); - // After all definitions/references have been found, wait here until all results have been reported. public override async ValueTask OnCompletedAsync(CancellationToken cancellationToken) => await _workQueue.WaitUntilCurrentBatchCompletesAsync().ConfigureAwait(false); @@ -256,10 +250,10 @@ public override async ValueTask OnReferenceFoundAsync(SourceReferenceItem refere if (documentSpan != null) { var document = documentSpan.Value.Document; - var options = await GetOptionsAsync(document.Project.Language, cancellationToken).ConfigureAwait(false); + var options = _globalOptions.GetClassificationOptions(document.Project.Language); var classifiedSpansAndHighlightSpan = await ClassifiedSpansAndHighlightSpanFactory.ClassifyAsync( - documentSpan.Value, classifiedSpans: null, options.ClassificationOptions, cancellationToken).ConfigureAwait(false); + documentSpan.Value, classifiedSpans: null, options, cancellationToken).ConfigureAwait(false); var classifiedSpans = classifiedSpansAndHighlightSpan.ClassifiedSpans; var docText = await document.GetValueTextAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj index 6b0e9a6acd8f4..77cac1bb7def4 100644 --- a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj +++ b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj @@ -68,6 +68,7 @@ + diff --git a/src/Features/TestUtilities/Options/TestOptionsProvider.cs b/src/Features/TestUtilities/Options/TestOptionsProvider.cs new file mode 100644 index 0000000000000..4f50cc6f65bf8 --- /dev/null +++ b/src/Features/TestUtilities/Options/TestOptionsProvider.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Host; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Test.Utilities; + +internal class TestOptionsProvider(TOptions options) : OptionsProvider +{ + public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(options); +} diff --git a/src/Tools/ExternalAccess/Debugger/DebuggerFindReferencesService.cs b/src/Tools/ExternalAccess/Debugger/DebuggerFindReferencesService.cs index 7dd11892a818f..4a2c3099422ee 100644 --- a/src/Tools/ExternalAccess/Debugger/DebuggerFindReferencesService.cs +++ b/src/Tools/ExternalAccess/Debugger/DebuggerFindReferencesService.cs @@ -6,28 +6,23 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Editor; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Editor.Host; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.ExternalAccess.Debugger { [Export] [Shared] - internal sealed class DebuggerFindReferencesService + [method: ImportingConstructor] + [method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + internal sealed class DebuggerFindReferencesService( + IGlobalOptionService globalOptions, + Lazy streamingPresenter) { - private readonly Lazy _streamingPresenter; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public DebuggerFindReferencesService( - IThreadingContext threadingContext, - Lazy streamingPresenter) - { - _streamingPresenter = streamingPresenter; - } + private readonly Lazy _streamingPresenter = streamingPresenter; public async Task FindSymbolReferencesAsync(ISymbol symbol, Project project, CancellationToken cancellationToken) { @@ -42,9 +37,11 @@ public async Task FindSymbolReferencesAsync(ISymbol symbol, Project project, Can // is cancelable. var (context, _) = streamingPresenter.StartSearch(EditorFeaturesResources.Find_References, supportsReferences: true); + var classificationOptions = globalOptions.GetClassificationOptionsProvider(); + try { - await AbstractFindUsagesService.FindSymbolReferencesAsync(context, symbol, project, cancellationToken).ConfigureAwait(false); + await AbstractFindUsagesService.FindSymbolReferencesAsync(context, symbol, project, classificationOptions, cancellationToken).ConfigureAwait(false); } finally { diff --git a/src/Tools/ExternalAccess/Debugger/InternalAPI.Unshipped.txt b/src/Tools/ExternalAccess/Debugger/InternalAPI.Unshipped.txt index e1864b247c42d..7340d7825d4db 100644 --- a/src/Tools/ExternalAccess/Debugger/InternalAPI.Unshipped.txt +++ b/src/Tools/ExternalAccess/Debugger/InternalAPI.Unshipped.txt @@ -1,6 +1,6 @@ #nullable enable Microsoft.CodeAnalysis.ExternalAccess.Debugger.DebuggerFindReferencesService -Microsoft.CodeAnalysis.ExternalAccess.Debugger.DebuggerFindReferencesService.DebuggerFindReferencesService(Microsoft.CodeAnalysis.Editor.Shared.Utilities.IThreadingContext! threadingContext, System.Lazy! streamingPresenter) -> void +Microsoft.CodeAnalysis.ExternalAccess.Debugger.DebuggerFindReferencesService.DebuggerFindReferencesService(Microsoft.CodeAnalysis.Options.IGlobalOptionService! globalOptions, System.Lazy! streamingPresenter) -> void Microsoft.CodeAnalysis.ExternalAccess.Debugger.DebuggerFindReferencesService.FindSymbolReferencesAsync(Microsoft.CodeAnalysis.ISymbol! symbol, Microsoft.CodeAnalysis.Project! project, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! Microsoft.CodeAnalysis.ExternalAccess.Debugger.GlassTestsHotReloadService Microsoft.CodeAnalysis.ExternalAccess.Debugger.GlassTestsHotReloadService.CommitSolutionUpdate() -> void diff --git a/src/Tools/ExternalAccess/FSharp/Internal/Editor/FindUsages/FSharpFindUsagesService.cs b/src/Tools/ExternalAccess/FSharp/Internal/Editor/FindUsages/FSharpFindUsagesService.cs index a742ec2c7facd..b65722044ce6b 100644 --- a/src/Tools/ExternalAccess/FSharp/Internal/Editor/FindUsages/FSharpFindUsagesService.cs +++ b/src/Tools/ExternalAccess/FSharp/Internal/Editor/FindUsages/FSharpFindUsagesService.cs @@ -6,6 +6,7 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.ExternalAccess.FSharp.Editor.FindUsages; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Host.Mef; @@ -14,19 +15,14 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.FSharp.Internal.Editor.FindUsage { [Shared] [ExportLanguageService(typeof(IFindUsagesService), LanguageNames.FSharp)] - internal sealed class FSharpFindUsagesService : IFindUsagesService + [method: ImportingConstructor] + [method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + internal sealed class FSharpFindUsagesService(IFSharpFindUsagesService service) : IFindUsagesService { - private readonly IFSharpFindUsagesService _service; + public Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) + => service.FindImplementationsAsync(document, position, new FSharpFindUsagesContext(context, cancellationToken)); - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public FSharpFindUsagesService(IFSharpFindUsagesService service) - => _service = service; - - public Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) - => _service.FindImplementationsAsync(document, position, new FSharpFindUsagesContext(context, cancellationToken)); - - public Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken) - => _service.FindReferencesAsync(document, position, new FSharpFindUsagesContext(context, cancellationToken)); + public Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, OptionsProvider classificationOptions, CancellationToken cancellationToken) + => service.FindReferencesAsync(document, position, new FSharpFindUsagesContext(context, cancellationToken)); } } diff --git a/src/VisualStudio/Core/Def/FindReferences/Contexts/AbstractTableDataSourceFindUsagesContext.cs b/src/VisualStudio/Core/Def/FindReferences/Contexts/AbstractTableDataSourceFindUsagesContext.cs index f389468a0c29d..3d1a389d1e44d 100644 --- a/src/VisualStudio/Core/Def/FindReferences/Contexts/AbstractTableDataSourceFindUsagesContext.cs +++ b/src/VisualStudio/Core/Def/FindReferences/Contexts/AbstractTableDataSourceFindUsagesContext.cs @@ -168,9 +168,6 @@ protected AbstractTableDataSourceFindUsagesContext( protected abstract ValueTask OnDefinitionFoundWorkerAsync(DefinitionItem definition, CancellationToken cancellationToken); protected abstract ValueTask OnReferenceFoundWorkerAsync(SourceReferenceItem reference, CancellationToken cancellationToken); - public override ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(_globalOptions.GetFindUsagesOptions(language)); - private static ImmutableArray SelectCustomColumnsToInclude(ImmutableArray customColumns, bool includeContainingTypeAndMemberColumns, bool includeKindColumn) { var customColumnsToInclude = ArrayBuilder.GetInstance(); diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs index bf2c97dfe9551..9e53c38bda7c2 100644 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs +++ b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs @@ -9,10 +9,12 @@ using System.Text; using System.Threading; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Editor; using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.FindUsages; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.ComponentModelHost; using Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser.Lists; @@ -490,9 +492,10 @@ protected override bool TryExec(Guid commandGroup, uint commandId) // immediately. var streamingPresenter = ComponentModel.GetService(); var asynchronousOperationListener = ComponentModel.GetService().GetListener(FeatureAttribute.LibraryManager); + var globalOptions = ComponentModel.GetService(); var asyncToken = asynchronousOperationListener.BeginAsyncOperation(nameof(AbstractObjectBrowserLibraryManager) + "." + nameof(TryExec)); - FindReferencesAsync(streamingPresenter, symbolListItem, project).CompletesAsyncOperation(asyncToken); + FindReferencesAsync(streamingPresenter, symbolListItem, project, globalOptions.GetClassificationOptionsProvider()).CompletesAsyncOperation(asyncToken); return true; } } @@ -505,7 +508,7 @@ protected override bool TryExec(Guid commandGroup, uint commandId) } private static async Task FindReferencesAsync( - IStreamingFindUsagesPresenter presenter, SymbolListItem symbolListItem, Project project) + IStreamingFindUsagesPresenter presenter, SymbolListItem symbolListItem, Project project, OptionsProvider classificationOptions) { try { @@ -520,7 +523,7 @@ private static async Task FindReferencesAsync( // t block the calling (UI) thread too long if we happen to do our work on this // thread. await Task.Run( - () => FindReferencesAsync(symbolListItem, project, context, cancellationToken), cancellationToken).ConfigureAwait(false); + () => FindReferencesAsync(symbolListItem, project, context, classificationOptions, cancellationToken), cancellationToken).ConfigureAwait(false); } finally { @@ -536,13 +539,16 @@ await Task.Run( } private static async Task FindReferencesAsync( - SymbolListItem symbolListItem, Project project, - FindUsagesContext context, CancellationToken cancellationToken) + SymbolListItem symbolListItem, + Project project, + FindUsagesContext context, + OptionsProvider classificationOptions, + CancellationToken cancellationToken) { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var symbol = symbolListItem.ResolveSymbol(compilation); if (symbol != null) - await AbstractFindUsagesService.FindSymbolReferencesAsync(context, symbol, project, cancellationToken).ConfigureAwait(false); + await AbstractFindUsagesService.FindSymbolReferencesAsync(context, symbol, project, classificationOptions, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/VisualStudio/Core/Test/GoToDefinition/GoToDefinitionApiTests.vb b/src/VisualStudio/Core/Test/GoToDefinition/GoToDefinitionApiTests.vb index 32554cf478854..058f6f3686833 100644 --- a/src/VisualStudio/Core/Test/GoToDefinition/GoToDefinitionApiTests.vb +++ b/src/VisualStudio/Core/Test/GoToDefinition/GoToDefinitionApiTests.vb @@ -41,7 +41,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.GoToDefinition Assert.NotNull(symbolInfo.Symbol) Dim threadingContext = workspace.ExportProvider.GetExportedValue(Of IThreadingContext)() - Dim presenter = New MockStreamingFindUsagesPresenter(workspace.GlobalOptions, Sub() Exit Sub) + Dim presenter = New MockStreamingFindUsagesPresenter(Sub() Exit Sub) WpfTestRunner.RequireWpfFact($"{NameOf(GoToDefinitionHelpers)}.{NameOf(GoToDefinitionHelpers.GetDefinitionLocationAsync)} assumes it's on the UI thread with a {NameOf(TaskExtensions.WaitAndGetResult)} call") Dim location = Await GoToDefinitionHelpers.GetDefinitionLocationAsync( diff --git a/src/VisualStudio/Core/Test/Venus/DocumentService_IntegrationTests.vb b/src/VisualStudio/Core/Test/Venus/DocumentService_IntegrationTests.vb index e0a21a08faf0a..a551ecc89bd36 100644 --- a/src/VisualStudio/Core/Test/Venus/DocumentService_IntegrationTests.vb +++ b/src/VisualStudio/Core/Test/Venus/DocumentService_IntegrationTests.vb @@ -77,8 +77,10 @@ class {|Definition:C1|} Dim startDocument = workspace.CurrentSolution.GetDocument(cursorDocument.Id) Assert.NotNull(startDocument) + Dim classificationOptions = workspace.GlobalOptions.GetClassificationOptionsProvider() + Dim findRefsService = startDocument.GetLanguageService(Of IFindUsagesService) - Await findRefsService.FindReferencesAsync(context, startDocument, cursorPosition, CancellationToken.None) + Await findRefsService.FindReferencesAsync(context, startDocument, cursorPosition, classificationOptions, CancellationToken.None) Dim definitionDocument = workspace.Documents.First(Function(d) d.AnnotatedSpans.ContainsKey("Definition")) Dim definitionText = Await workspace.CurrentSolution.GetDocument(definitionDocument.Id).GetTextAsync() diff --git a/src/Workspaces/CoreTestUtilities/Fakes/StubStreamingFindUsagesPresenter.cs b/src/Workspaces/CoreTestUtilities/Fakes/StubStreamingFindUsagesPresenter.cs index 5c06e271f96b4..2b96fc8f2e191 100644 --- a/src/Workspaces/CoreTestUtilities/Fakes/StubStreamingFindUsagesPresenter.cs +++ b/src/Workspaces/CoreTestUtilities/Fakes/StubStreamingFindUsagesPresenter.cs @@ -8,32 +8,24 @@ using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.FindUsages; using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.UnitTests.Fakes { [Export(typeof(IStreamingFindUsagesPresenter))] [Shared] [PartNotDiscoverable] - internal sealed class StubStreamingFindUsagesPresenter : IStreamingFindUsagesPresenter + [method: ImportingConstructor] + [method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + internal sealed class StubStreamingFindUsagesPresenter() : IStreamingFindUsagesPresenter { - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public StubStreamingFindUsagesPresenter(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } - public void ClearAll() { } public (FindUsagesContext, CancellationToken) StartSearch(string title, bool supportsReferences) - => (new SimpleFindUsagesContext(_globalOptions), CancellationToken.None); + => (new SimpleFindUsagesContext(), CancellationToken.None); public (FindUsagesContext, CancellationToken) StartSearchWithCustomColumns(string title, bool supportsReferences, bool includeContainingTypeAndMemberColumns, bool includeKindColumn) - => (new SimpleFindUsagesContext(_globalOptions), CancellationToken.None); + => (new SimpleFindUsagesContext(), CancellationToken.None); } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs b/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs index 12e9a5dfa15fd..66ff6b0dd4b52 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs @@ -6,59 +6,40 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; -using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Rename; -using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote; // TODO: Use generic IRemoteOptionsCallback once https://github.com/microsoft/vs-streamjsonrpc/issues/789 is fixed -internal sealed class RemoteOptionsProviderCache +internal sealed class RemoteOptionsProviderCache(Func> callback, RemoteServiceCallbackId callbackId) { - private readonly Func> _callback; - private readonly RemoteServiceCallbackId _callbackId; - private ImmutableDictionary> _cache = ImmutableDictionary>.Empty; - public RemoteOptionsProviderCache(Func> callback, RemoteServiceCallbackId callbackId) - { - _callback = callback; - _callbackId = callbackId; - } - public async ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) { var lazyOptions = ImmutableInterlocked.GetOrAdd(ref _cache, languageServices.Language, _ => AsyncLazy.Create(GetRemoteOptionsAsync)); return await lazyOptions.GetValueAsync(cancellationToken).ConfigureAwait(false); Task GetRemoteOptionsAsync(CancellationToken cancellationToken) - => _callback(_callbackId, languageServices.Language, cancellationToken).AsTask(); + => callback(callbackId, languageServices.Language, cancellationToken).AsTask(); } } -internal sealed class ClientCleanCodeGenerationOptionsProvider : AbstractCleanCodeGenerationOptionsProvider +internal sealed class ClientCleanCodeGenerationOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) : AbstractCleanCodeGenerationOptionsProvider { - private readonly RemoteOptionsProviderCache _cache; - - public ClientCleanCodeGenerationOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) - => _cache = new RemoteOptionsProviderCache(callback, callbackId); + private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); public override ValueTask GetCleanCodeGenerationOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) => _cache.GetOptionsAsync(languageServices, cancellationToken); } -internal sealed class ClientCodeCleanupOptionsProvider : AbstractCodeCleanupOptionsProvider +internal sealed class ClientCodeCleanupOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) : AbstractCodeCleanupOptionsProvider { - private readonly RemoteOptionsProviderCache _cache; - - public ClientCodeCleanupOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) - => _cache = new RemoteOptionsProviderCache(callback, callbackId); + private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); public override ValueTask GetCodeCleanupOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) => _cache.GetOptionsAsync(languageServices, cancellationToken); diff --git a/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs b/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs index 4ccb4c26982e3..e2f2f7b44131b 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.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; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -14,7 +15,8 @@ namespace Microsoft.CodeAnalysis.Remote { - internal sealed class RemoteFindUsagesService : BrokeredServiceBase, IRemoteFindUsagesService + internal sealed class RemoteFindUsagesService(in BrokeredServiceBase.ServiceConstructionArguments arguments, RemoteCallback callback) + : BrokeredServiceBase(arguments), IRemoteFindUsagesService { internal sealed class Factory : FactoryBase { @@ -22,14 +24,17 @@ protected override IRemoteFindUsagesService CreateService(in ServiceConstruction => new RemoteFindUsagesService(arguments, callback); } - private readonly RemoteCallback _callback; - - public RemoteFindUsagesService(in ServiceConstructionArguments arguments, RemoteCallback callback) - : base(arguments) + internal sealed class ClientClassificationOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) : OptionsProvider { - _callback = callback; + private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); + + public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => _cache.GetOptionsAsync(languageServices, cancellationToken); } + private ClientClassificationOptionsProvider GetClientOptionsProvider(RemoteServiceCallbackId callbackId) + => new((callbackId, language, cancellationToken) => callback.InvokeAsync((callback, cancellationToken) => callback.GetClassificationOptionsAsync(callbackId, language, cancellationToken), cancellationToken), callbackId); + public ValueTask FindReferencesAsync( Checksum solutionChecksum, RemoteServiceCallbackId callbackId, @@ -47,9 +52,9 @@ public ValueTask FindReferencesAsync( if (symbol == null) return; - var context = new RemoteFindUsageContext(_callback, callbackId); + var context = new RemoteFindUsageContext(callback, callbackId); await AbstractFindUsagesService.FindReferencesAsync( - context, symbol, project, options, cancellationToken).ConfigureAwait(false); + context, symbol, project, options, GetClientOptionsProvider(callbackId), cancellationToken).ConfigureAwait(false); }, cancellationToken); } @@ -68,9 +73,9 @@ public ValueTask FindImplementationsAsync( if (symbol == null) return; - var context = new RemoteFindUsageContext(_callback, callbackId); + var context = new RemoteFindUsageContext(callback, callbackId); await AbstractFindUsagesService.FindImplementationsAsync( - context, symbol, project, cancellationToken).ConfigureAwait(false); + context, symbol, project, GetClientOptionsProvider(callbackId), cancellationToken).ConfigureAwait(false); }, cancellationToken); } @@ -100,12 +105,6 @@ public ValueTask ItemsCompletedAsync(int count, CancellationToken cancellationTo public IStreamingProgressTracker ProgressTracker => this; - public ValueTask GetOptionsAsync(string language, CancellationToken cancellationToken) - => _callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(_callbackId, language, cancellationToken), cancellationToken); - - async ValueTask OptionsProvider.GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices.Language, cancellationToken).ConfigureAwait(false)).ClassificationOptions; - public ValueTask ReportMessageAsync(string message, CancellationToken cancellationToken) => _callback.InvokeAsync((callback, cancellationToken) => callback.ReportMessageAsync(_callbackId, message, cancellationToken), cancellationToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Options/OptionsProvider.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Options/OptionsProvider.cs index e9203392350b2..2c46e1d9eaefc 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Options/OptionsProvider.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Options/OptionsProvider.cs @@ -2,9 +2,12 @@ // 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.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis; @@ -12,3 +15,15 @@ internal interface OptionsProvider { ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken); } + +internal static class OptionsProvider +{ + private sealed class OptionsReaderProvider(IOptionsReader optionsReader, Func reader) : OptionsProvider + { + public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(reader(optionsReader, languageServices.Language)); + } + + public static OptionsProvider GetProvider(this IOptionsReader optionsReader, Func reader) + => new OptionsReaderProvider(optionsReader, reader); +} From 120c0cf5194994820371d716c2c782f6af2af454 Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 24 Jan 2024 18:38:57 -0800 Subject: [PATCH 3/4] RemoteOptionsProvider --- ...vertTupleToStructCodeRefactoringService.cs | 4 +-- .../IRemoteEncapsulateFieldService.cs | 5 +--- .../FindUsages/IRemoteFindUsagesService.cs | 5 ++-- .../Portable/Remote/IRemoteOptionsCallback.cs | 2 -- .../Portable/Rename/IRemoteRenamerService.cs | 4 +-- .../Services/BrokeredServiceBase.cs | 28 ++++++++++--------- .../FindUsages/RemoteFindUsagesService.cs | 21 ++++---------- 7 files changed, 26 insertions(+), 43 deletions(-) diff --git a/src/Features/Core/Portable/ConvertTupleToStruct/IRemoteConvertTupleToStructCodeRefactoringService.cs b/src/Features/Core/Portable/ConvertTupleToStruct/IRemoteConvertTupleToStructCodeRefactoringService.cs index 49bfc83dfedc9..ac63f41aabd3a 100644 --- a/src/Features/Core/Portable/ConvertTupleToStruct/IRemoteConvertTupleToStructCodeRefactoringService.cs +++ b/src/Features/Core/Portable/ConvertTupleToStruct/IRemoteConvertTupleToStructCodeRefactoringService.cs @@ -19,10 +19,8 @@ namespace Microsoft.CodeAnalysis.ConvertTupleToStruct { internal interface IRemoteConvertTupleToStructCodeRefactoringService { - // TODO https://github.com/microsoft/vs-streamjsonrpc/issues/789 - internal interface ICallback // : IRemoteOptionsCallback + internal interface ICallback : IRemoteOptionsCallback { - ValueTask GetOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken); } ValueTask ConvertToStructAsync( diff --git a/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs b/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs index 395aae8130d5d..394d74b8b1f07 100644 --- a/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs +++ b/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs @@ -9,7 +9,6 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Remote; @@ -19,10 +18,8 @@ namespace Microsoft.CodeAnalysis.EncapsulateField { internal interface IRemoteEncapsulateFieldService { - // TODO https://github.com/microsoft/vs-streamjsonrpc/issues/789 - internal interface ICallback // : IRemoteOptionsCallback + internal interface ICallback : IRemoteOptionsCallback { - ValueTask GetOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken); } ValueTask)>> EncapsulateFieldsAsync( diff --git a/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs b/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs index 00d1d3ef62df6..2afc6af8f1335 100644 --- a/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs +++ b/src/Features/Core/Portable/FindUsages/IRemoteFindUsagesService.cs @@ -21,9 +21,8 @@ namespace Microsoft.CodeAnalysis.FindUsages { internal interface IRemoteFindUsagesService { - internal interface ICallback + internal interface ICallback : IRemoteOptionsCallback { - ValueTask GetClassificationOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken); ValueTask AddItemsAsync(RemoteServiceCallbackId callbackId, int count, CancellationToken cancellationToken); ValueTask ItemsCompletedAsync(RemoteServiceCallbackId callbackId, int count, CancellationToken cancellationToken); ValueTask ReportMessageAsync(RemoteServiceCallbackId callbackId, string message, CancellationToken cancellationToken); @@ -59,7 +58,7 @@ public FindUsagesServerCallbackDispatcher() private new FindUsagesServerCallback GetCallback(RemoteServiceCallbackId callbackId) => (FindUsagesServerCallback)base.GetCallback(callbackId); - public ValueTask GetClassificationOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken) + public ValueTask GetOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken) => GetCallback(callbackId).GetClassificationOptionsAsync(language, cancellationToken); public ValueTask AddItemsAsync(RemoteServiceCallbackId callbackId, int count, CancellationToken cancellationToken) diff --git a/src/Workspaces/Core/Portable/Remote/IRemoteOptionsCallback.cs b/src/Workspaces/Core/Portable/Remote/IRemoteOptionsCallback.cs index a329f8d17f979..e4d612753d408 100644 --- a/src/Workspaces/Core/Portable/Remote/IRemoteOptionsCallback.cs +++ b/src/Workspaces/Core/Portable/Remote/IRemoteOptionsCallback.cs @@ -7,9 +7,7 @@ namespace Microsoft.CodeAnalysis.Remote; -#if TODO // Uncomment once https://github.com/microsoft/vs-streamjsonrpc/issues/789 is fixed internal interface IRemoteOptionsCallback { ValueTask GetOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken); } -#endif diff --git a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs index bc1b80d3f13d3..193d145f8d706 100644 --- a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs +++ b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs @@ -22,10 +22,8 @@ namespace Microsoft.CodeAnalysis.Rename { internal interface IRemoteRenamerService { - // TODO https://github.com/microsoft/vs-streamjsonrpc/issues/789 - internal interface ICallback // : IRemoteOptionsCallback + internal interface ICallback : IRemoteOptionsCallback { - ValueTask GetOptionsAsync(RemoteServiceCallbackId callbackId, string language, CancellationToken cancellationToken); } /// diff --git a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs index 7df368e7c0733..f947b17142153 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs @@ -173,22 +173,24 @@ internal static async ValueTask RunServiceImplAsync(Func GetClientOptionsAsync( - RemoteCallback callback, - RemoteServiceCallbackId callbackId, - HostLanguageServices languageServices, - CancellationToken cancellationToken) - where TCallbackInterface : class, IRemoteOptionsCallback + private sealed class ClientOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) : OptionsProvider { - var cache = ImmutableDictionary>.Empty; - var lazyOptions = ImmutableInterlocked.GetOrAdd(ref cache, languageServices.Language, _ => new AsyncLazy(GetRemoteOptions, cacheResult: true)); - return await lazyOptions.GetValueAsync(cancellationToken).ConfigureAwait(false); + private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); - Task GetRemoteOptions(CancellationToken cancellationToken) - => callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(callbackId, languageServices.Language, cancellationToken), cancellationToken).AsTask(); + public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => _cache.GetOptionsAsync(languageServices, cancellationToken); } -#endif + + /// + /// Use for on-demand retrieval of language-specific options from the client. + /// + /// If the service doesn't know up-front for which languages it will need to retrieve specific options, + /// its ICallback interface should implement and use this + /// method to create the options provider to be passed to the feature implementation. + /// + protected static OptionsProvider GetClientOptionsProvider(RemoteCallback callback, RemoteServiceCallbackId callbackId) + where TCallback : class, IRemoteOptionsCallback + => new ClientOptionsProvider((callbackId, language, cancellationToken) => callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(callbackId, language, cancellationToken), cancellationToken), callbackId); private static void SetNativeDllSearchDirectories() { diff --git a/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs b/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs index e2f2f7b44131b..6e89dc49b6087 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/FindUsages/RemoteFindUsagesService.cs @@ -2,14 +2,12 @@ // 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.Classification; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindUsages; -using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; @@ -24,17 +22,6 @@ protected override IRemoteFindUsagesService CreateService(in ServiceConstruction => new RemoteFindUsagesService(arguments, callback); } - internal sealed class ClientClassificationOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) : OptionsProvider - { - private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); - - public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => _cache.GetOptionsAsync(languageServices, cancellationToken); - } - - private ClientClassificationOptionsProvider GetClientOptionsProvider(RemoteServiceCallbackId callbackId) - => new((callbackId, language, cancellationToken) => callback.InvokeAsync((callback, cancellationToken) => callback.GetClassificationOptionsAsync(callbackId, language, cancellationToken), cancellationToken), callbackId); - public ValueTask FindReferencesAsync( Checksum solutionChecksum, RemoteServiceCallbackId callbackId, @@ -53,8 +40,10 @@ public ValueTask FindReferencesAsync( return; var context = new RemoteFindUsageContext(callback, callbackId); + var classificationOptions = GetClientOptionsProvider(callback, callbackId); + await AbstractFindUsagesService.FindReferencesAsync( - context, symbol, project, options, GetClientOptionsProvider(callbackId), cancellationToken).ConfigureAwait(false); + context, symbol, project, options, classificationOptions, cancellationToken).ConfigureAwait(false); }, cancellationToken); } @@ -74,8 +63,10 @@ public ValueTask FindImplementationsAsync( return; var context = new RemoteFindUsageContext(callback, callbackId); + var classificationOptions = GetClientOptionsProvider(callback, callbackId); + await AbstractFindUsagesService.FindImplementationsAsync( - context, symbol, project, GetClientOptionsProvider(callbackId), cancellationToken).ConfigureAwait(false); + context, symbol, project, classificationOptions, cancellationToken).ConfigureAwait(false); }, cancellationToken); } From 1636ef5c8439a8e23e7a3fa2cdbc80355bdc9d14 Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 24 Jan 2024 20:15:34 -0800 Subject: [PATCH 4/4] Cleanup --- .../Services/BrokeredServiceBase.cs | 10 +--- .../Services/ClientOptionProviders.cs | 47 ------------------- .../Services/ClientOptionsProvider.cs | 27 +++++++++++ ...vertTupleToStructCodeRefactoringService.cs | 18 ++----- .../RemoteEncapsulateFieldService.cs | 21 ++------- .../Services/Renamer/RemoteRenamerService.cs | 22 +++------ .../Core/CodeCleanup/CodeCleanupOptions.cs | 9 ++++ .../CleanCodeGenerationOptions.cs | 9 ++++ 8 files changed, 58 insertions(+), 105 deletions(-) delete mode 100644 src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs create mode 100644 src/Workspaces/Remote/ServiceHub/Services/ClientOptionsProvider.cs diff --git a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs index f947b17142153..eb639944636dc 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs @@ -173,14 +173,6 @@ internal static async ValueTask RunServiceImplAsync(Func(Func> callback, RemoteServiceCallbackId callbackId) : OptionsProvider - { - private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); - - public ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => _cache.GetOptionsAsync(languageServices, cancellationToken); - } - /// /// Use for on-demand retrieval of language-specific options from the client. /// @@ -190,7 +182,7 @@ public ValueTask GetOptionsAsync(LanguageServices languageServices, Ca /// protected static OptionsProvider GetClientOptionsProvider(RemoteCallback callback, RemoteServiceCallbackId callbackId) where TCallback : class, IRemoteOptionsCallback - => new ClientOptionsProvider((callbackId, language, cancellationToken) => callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(callbackId, language, cancellationToken), cancellationToken), callbackId); + => new ClientOptionsProvider(callback, callbackId); private static void SetNativeDllSearchDirectories() { diff --git a/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs b/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs deleted file mode 100644 index 66ff6b0dd4b52..0000000000000 --- a/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Immutable; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeCleanup; -using Microsoft.CodeAnalysis.CodeGeneration; -using Microsoft.CodeAnalysis.Host; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.Remote; - -// TODO: Use generic IRemoteOptionsCallback once https://github.com/microsoft/vs-streamjsonrpc/issues/789 is fixed - -internal sealed class RemoteOptionsProviderCache(Func> callback, RemoteServiceCallbackId callbackId) -{ - private ImmutableDictionary> _cache = ImmutableDictionary>.Empty; - - public async ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - { - var lazyOptions = ImmutableInterlocked.GetOrAdd(ref _cache, languageServices.Language, _ => AsyncLazy.Create(GetRemoteOptionsAsync)); - return await lazyOptions.GetValueAsync(cancellationToken).ConfigureAwait(false); - - Task GetRemoteOptionsAsync(CancellationToken cancellationToken) - => callback(callbackId, languageServices.Language, cancellationToken).AsTask(); - } -} - -internal sealed class ClientCleanCodeGenerationOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) : AbstractCleanCodeGenerationOptionsProvider -{ - private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); - - public override ValueTask GetCleanCodeGenerationOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => _cache.GetOptionsAsync(languageServices, cancellationToken); -} - -internal sealed class ClientCodeCleanupOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) : AbstractCodeCleanupOptionsProvider -{ - private readonly RemoteOptionsProviderCache _cache = new(callback, callbackId); - - public override ValueTask GetCodeCleanupOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) - => _cache.GetOptionsAsync(languageServices, cancellationToken); -} - diff --git a/src/Workspaces/Remote/ServiceHub/Services/ClientOptionsProvider.cs b/src/Workspaces/Remote/ServiceHub/Services/ClientOptionsProvider.cs new file mode 100644 index 0000000000000..707deb56b06a8 --- /dev/null +++ b/src/Workspaces/Remote/ServiceHub/Services/ClientOptionsProvider.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Host; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Remote; + +internal sealed class ClientOptionsProvider(RemoteCallback callback, RemoteServiceCallbackId callbackId) : OptionsProvider + where TCallback : class, IRemoteOptionsCallback +{ + private ImmutableDictionary> _cache = ImmutableDictionary>.Empty; + + public async ValueTask GetOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + { + var lazyOptions = ImmutableInterlocked.GetOrAdd(ref _cache, languageServices.Language, _ => AsyncLazy.Create(GetRemoteOptionsAsync)); + return await lazyOptions.GetValueAsync(cancellationToken).ConfigureAwait(false); + + Task GetRemoteOptionsAsync(CancellationToken cancellationToken) + => callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(callbackId, languageServices.Language, cancellationToken), cancellationToken).AsTask(); + } +} diff --git a/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs b/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs index 2e090bda6642b..d7cdc206882f5 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs @@ -17,7 +17,8 @@ namespace Microsoft.CodeAnalysis.Remote { - internal sealed class RemoteConvertTupleToStructCodeRefactoringService : BrokeredServiceBase, IRemoteConvertTupleToStructCodeRefactoringService + internal sealed class RemoteConvertTupleToStructCodeRefactoringService(in BrokeredServiceBase.ServiceConstructionArguments arguments, RemoteCallback callback) + : BrokeredServiceBase(arguments), IRemoteConvertTupleToStructCodeRefactoringService { internal sealed class Factory : FactoryBase { @@ -25,19 +26,6 @@ protected override IRemoteConvertTupleToStructCodeRefactoringService CreateServi => new RemoteConvertTupleToStructCodeRefactoringService(arguments, callback); } - private readonly RemoteCallback _callback; - - public RemoteConvertTupleToStructCodeRefactoringService(in ServiceConstructionArguments arguments, RemoteCallback callback) - : base(arguments) - { - _callback = callback; - } - - // TODO: Use generic IRemoteOptionsCallback once https://github.com/microsoft/vs-streamjsonrpc/issues/789 is fixed - private CleanCodeGenerationOptionsProvider GetClientOptionsProvider(RemoteServiceCallbackId callbackId) - => new ClientCleanCodeGenerationOptionsProvider( - (callbackId, language, cancellationToken) => _callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(callbackId, language, cancellationToken), cancellationToken), callbackId); - public ValueTask ConvertToStructAsync( Checksum solutionChecksum, RemoteServiceCallbackId callbackId, @@ -52,7 +40,7 @@ public ValueTask ConvertToStructAsync( var document = solution.GetRequiredDocument(documentId); var service = document.GetRequiredLanguageService(); - var fallbackOptions = GetClientOptionsProvider(callbackId); + var fallbackOptions = GetClientOptionsProvider(callback, callbackId).ToCleanCodeGenerationOptionsProvider(); var updatedSolution = await service.ConvertToStructAsync(document, span, scope, fallbackOptions, isRecord, cancellationToken).ConfigureAwait(false); diff --git a/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs b/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs index 63911a9e14089..0879780f6b6e8 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs @@ -2,22 +2,20 @@ // 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.Immutable; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.EncapsulateField; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote { - internal sealed class RemoteEncapsulateFieldService : BrokeredServiceBase, IRemoteEncapsulateFieldService + internal sealed class RemoteEncapsulateFieldService(in BrokeredServiceBase.ServiceConstructionArguments arguments, RemoteCallback callback) + : BrokeredServiceBase(arguments), IRemoteEncapsulateFieldService { internal sealed class Factory : FactoryBase { @@ -25,19 +23,6 @@ protected override IRemoteEncapsulateFieldService CreateService(in ServiceConstr => new RemoteEncapsulateFieldService(arguments, callback); } - private readonly RemoteCallback _callback; - - public RemoteEncapsulateFieldService(in ServiceConstructionArguments arguments, RemoteCallback callback) - : base(arguments) - { - _callback = callback; - } - - // TODO: Use generic IRemoteOptionsCallback once https://github.com/microsoft/vs-streamjsonrpc/issues/789 is fixed - private CleanCodeGenerationOptionsProvider GetClientOptionsProvider(RemoteServiceCallbackId callbackId) - => new ClientCleanCodeGenerationOptionsProvider( - (callbackId, language, cancellationToken) => _callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(callbackId, language, cancellationToken), cancellationToken), callbackId); - public ValueTask)>> EncapsulateFieldsAsync( Checksum solutionChecksum, RemoteServiceCallbackId callbackId, @@ -63,7 +48,7 @@ private CleanCodeGenerationOptionsProvider GetClientOptionsProvider(RemoteServic } var service = document.GetRequiredLanguageService(); - var fallbackOptions = GetClientOptionsProvider(callbackId); + var fallbackOptions = GetClientOptionsProvider(callback, callbackId).ToCleanCodeGenerationOptionsProvider(); var newSolution = await service.EncapsulateFieldsAsync( document, fields.ToImmutable(), fallbackOptions, updateReferences, cancellationToken).ConfigureAwait(false); diff --git a/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs b/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs index 08cbd2e50ca4f..9b875a22f48d7 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs @@ -11,7 +11,8 @@ namespace Microsoft.CodeAnalysis.Remote { - internal sealed partial class RemoteRenamerService : BrokeredServiceBase, IRemoteRenamerService + internal sealed partial class RemoteRenamerService(in BrokeredServiceBase.ServiceConstructionArguments arguments, RemoteCallback callback) + : BrokeredServiceBase(arguments), IRemoteRenamerService { internal sealed class Factory : FactoryBase { @@ -19,19 +20,6 @@ protected override IRemoteRenamerService CreateService(in ServiceConstructionArg => new RemoteRenamerService(arguments, callback); } - private readonly RemoteCallback _callback; - - public RemoteRenamerService(in ServiceConstructionArguments arguments, RemoteCallback callback) - : base(arguments) - { - _callback = callback; - } - - // TODO: Use generic IRemoteOptionsCallback once https://github.com/microsoft/vs-streamjsonrpc/issues/789 is fixed - private CodeCleanupOptionsProvider GetClientOptionsProvider(RemoteServiceCallbackId callbackId) - => new ClientCodeCleanupOptionsProvider( - (callbackId, language, cancellationToken) => _callback.InvokeAsync((callback, cancellationToken) => callback.GetOptionsAsync(callbackId, language, cancellationToken), cancellationToken), callbackId); - public ValueTask RenameSymbolAsync( Checksum solutionChecksum, RemoteServiceCallbackId callbackId, @@ -49,7 +37,7 @@ private CodeCleanupOptionsProvider GetClientOptionsProvider(RemoteServiceCallbac if (symbol == null) return null; - var fallbackOptions = GetClientOptionsProvider(callbackId); + var fallbackOptions = GetClientOptionsProvider(callback, callbackId).ToCodeCleanupOptionsProvider(); var result = await Renamer.RenameSymbolAsync( solution, symbol, newName, options, fallbackOptions, nonConflictSymbolKeys, cancellationToken).ConfigureAwait(false); @@ -103,8 +91,10 @@ private CodeCleanupOptionsProvider GetClientOptionsProvider(RemoteServiceCallbac if (locations is null) return null; + var fallbackOptions = GetClientOptionsProvider(callback, callbackId).ToCodeCleanupOptionsProvider(); + var result = await ConflictResolver.ResolveSymbolicLocationConflictsInCurrentProcessAsync( - locations, replacementText, nonConflictSymbolKeys, GetClientOptionsProvider(callbackId), cancellationToken).ConfigureAwait(false); + locations, replacementText, nonConflictSymbolKeys, fallbackOptions, cancellationToken).ConfigureAwait(false); return await result.DehydrateAsync(cancellationToken).ConfigureAwait(false); }, cancellationToken); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeCleanup/CodeCleanupOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeCleanup/CodeCleanupOptions.cs index 0ac1bc7cfbcbc..03e3542930354 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeCleanup/CodeCleanupOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeCleanup/CodeCleanupOptions.cs @@ -101,6 +101,15 @@ public static async ValueTask GetCodeCleanupOptionsAsync(thi public static async ValueTask GetCodeCleanupOptionsAsync(this Document document, CodeCleanupOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) => await document.GetCodeCleanupOptionsAsync(await ((OptionsProvider)fallbackOptionsProvider).GetOptionsAsync(document.Project.Services, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); + + private sealed class Provider(OptionsProvider provider) : AbstractCodeCleanupOptionsProvider + { + public override ValueTask GetCodeCleanupOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => provider.GetOptionsAsync(languageServices, cancellationToken); + } + + public static CodeCleanupOptionsProvider ToCodeCleanupOptionsProvider(this OptionsProvider provider) + => new Provider(provider); #endif } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CleanCodeGenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CleanCodeGenerationOptions.cs index e0cfee0b46d40..888a817226cc8 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CleanCodeGenerationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CleanCodeGenerationOptions.cs @@ -82,5 +82,14 @@ public static async ValueTask GetCleanCodeGeneration public static async ValueTask GetCleanCodeGenerationOptionsAsync(this Document document, CleanCodeGenerationOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) => await document.GetCleanCodeGenerationOptionsAsync(await ((OptionsProvider)fallbackOptionsProvider).GetOptionsAsync(document.Project.Services, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); + + private sealed class Provider(OptionsProvider provider) : AbstractCleanCodeGenerationOptionsProvider + { + public override ValueTask GetCleanCodeGenerationOptionsAsync(LanguageServices languageServices, CancellationToken cancellationToken) + => provider.GetOptionsAsync(languageServices, cancellationToken); + } + + public static CleanCodeGenerationOptionsProvider ToCleanCodeGenerationOptionsProvider(this OptionsProvider provider) + => new Provider(provider); } #endif