Skip to content

Commit

Permalink
Add FindUsagesOptions and thread option getter through FAR services
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Feb 5, 2022
1 parent b6e8cae commit f2f4054
Show file tree
Hide file tree
Showing 49 changed files with 290 additions and 237 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
Expand All @@ -33,6 +34,7 @@ internal abstract class AbstractGoToCommandHandler<TLanguageService, TCommandArg
private readonly IStreamingFindUsagesPresenter _streamingPresenter;
private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor;
private readonly IAsynchronousOperationListener _listener;
private readonly IGlobalOptionService _globalOptions;

/// <summary>
/// The current go-to command that is in progress. Tracked so that if we issue multiple find-impl commands that
Expand All @@ -59,19 +61,21 @@ public AbstractGoToCommandHandler(
IThreadingContext threadingContext,
IStreamingFindUsagesPresenter streamingPresenter,
IUIThreadOperationExecutor uiThreadOperationExecutor,
IAsynchronousOperationListener listener)
IAsynchronousOperationListener listener,
IGlobalOptionService globalOptions)
{
_threadingContext = threadingContext;
_streamingPresenter = streamingPresenter;
_uiThreadOperationExecutor = uiThreadOperationExecutor;
_listener = listener;
_globalOptions = globalOptions;
}

public abstract string DisplayName { get; }
protected abstract string ScopeDescription { get; }
protected abstract FunctionId FunctionId { get; }

protected abstract Task FindActionAsync(Document document, int caretPosition, IFindUsagesContext context, CancellationToken cancellationToken);
protected abstract Task FindActionAsync(IFindUsagesContext context, Document document, int caretPosition, CancellationToken cancellationToken);

public CommandState GetCommandState(TCommandArgs args)
{
Expand Down Expand Up @@ -161,11 +165,11 @@ 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();
var findContext = new BufferedFindUsagesContext(_globalOptions);

var cancellationToken = cancellationTokenSource.Token;
var delayTask = Task.Delay(TaggerDelay.OnIdle.ComputeTimeDelay(), cancellationToken);
var findTask = Task.Run(() => FindResultsAsync(document, position, findContext, cancellationToken), cancellationToken);
var findTask = Task.Run(() => FindResultsAsync(findContext, document, position, cancellationToken), cancellationToken);

var firstFinishedTask = await Task.WhenAny(delayTask, findTask).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
Expand Down Expand Up @@ -206,7 +210,7 @@ private async Task PresentResultsInStreamingPresenterAsync(
{
var cancellationToken = cancellationTokenSource.Token;
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
var (presenterContext, presenterCancellationToken) = _streamingPresenter.StartSearch(this.DisplayName, supportsReferences: false);
var (presenterContext, presenterCancellationToken) = _streamingPresenter.StartSearch(DisplayName, supportsReferences: false);

try
{
Expand Down Expand Up @@ -235,7 +239,7 @@ private async Task PresentResultsInStreamingPresenterAsync(
}

private async Task FindResultsAsync(
Document document, int position, IFindUsagesContext findContext, CancellationToken cancellationToken)
IFindUsagesContext findContext, Document document, int position, CancellationToken cancellationToken)
{
using (Logger.LogBlock(FunctionId, KeyValueLogMessage.Create(LogType.UserAction), cancellationToken))
{
Expand All @@ -253,7 +257,7 @@ await findContext.ReportInformationalMessageAsync(

// We were able to find the doc prior to loading the workspace (or else we would not have the service).
// So we better be able to find it afterwards.
await FindActionAsync(document, position, findContext, cancellationToken).ConfigureAwait(false);
await FindActionAsync(findContext, document, position, cancellationToken).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Roslyn.Utilities;

Expand All @@ -29,6 +30,8 @@ private class State
public ImmutableArray<DefinitionItem>.Builder Definitions = ImmutableArray.CreateBuilder<DefinitionItem>();
}

private readonly IGlobalOptionService _globalOptions;

/// <summary>
/// Lock which controls access to all members below.
/// </summary>
Expand All @@ -46,8 +49,9 @@ private class State
/// </summary>
private State? _state = new();

public BufferedFindUsagesContext()
public BufferedFindUsagesContext(IGlobalOptionService globalOptions)
{
_globalOptions = globalOptions;
}

[MemberNotNullWhen(true, nameof(_streamingPresenterContext))]
Expand Down Expand Up @@ -150,6 +154,9 @@ async ValueTask IStreamingProgressTracker.ItemsCompletedAsync(int count, Cancell

#region IFindUsagesContext

ValueTask<FindUsagesOptions> IFindUsagesContext.GetOptionsAsync(string language, CancellationToken cancellationToken)
=> ValueTaskFactory.FromResult(_globalOptions.GetFindUsagesOptions(language));

async ValueTask IFindUsagesContext.ReportMessageAsync(string message, CancellationToken cancellationToken)
{
using var _ = await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ public VSTypeScriptFindUsagesService(IVSTypeScriptFindUsagesService underlyingSe
_underlyingService = underlyingService;
}

public Task FindReferencesAsync(Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
public Task FindReferencesAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken)
=> _underlyingService.FindReferencesAsync(document, position, new Context(context), cancellationToken);

public Task FindImplementationsAsync(Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
public Task FindImplementationsAsync(IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken)
=> _underlyingService.FindImplementationsAsync(document, position, new Context(context), cancellationToken);

private sealed class Context : IVSTypeScriptFindUsagesContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
Expand All @@ -30,7 +32,7 @@ namespace Microsoft.CodeAnalysis.Editor.FindReferences
internal class FindReferencesCommandHandler : ICommandHandler<FindReferencesCommandArgs>
{
private readonly IStreamingFindUsagesPresenter _streamingPresenter;

private readonly IGlobalOptionService _globalOptions;
private readonly IAsynchronousOperationListener _asyncListener;

public string DisplayName => EditorFeaturesResources.Find_References;
Expand All @@ -39,11 +41,13 @@ internal class FindReferencesCommandHandler : ICommandHandler<FindReferencesComm
[SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")]
public FindReferencesCommandHandler(
IStreamingFindUsagesPresenter streamingPresenter,
IGlobalOptionService globalOptions,
IAsynchronousOperationListenerProvider listenerProvider)
{
Contract.ThrowIfNull(listenerProvider);

_streamingPresenter = streamingPresenter;
_globalOptions = globalOptions;
_asyncListener = listenerProvider.GetListener(FeatureAttribute.FindReferences);
}

Expand Down Expand Up @@ -133,7 +137,7 @@ private async Task StreamingFindReferencesAsync(
{
try
{
await findUsagesService.FindReferencesAsync(document, caretPosition, context, cancellationToken).ConfigureAwait(false);
await findUsagesService.FindReferencesAsync(context, document, caretPosition, cancellationToken).ConfigureAwait(false);
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal abstract partial class AbstractFindUsagesService
/// definitions found to third parties in case they want to add any additional definitions
/// to the results we present.
/// </summary>
private class DefinitionTrackingContext : IFindUsagesContext
private sealed class DefinitionTrackingContext : IFindUsagesContext
{
private readonly IFindUsagesContext _underlyingContext;
private readonly object _gate = new();
Expand All @@ -30,6 +30,9 @@ private class DefinitionTrackingContext : IFindUsagesContext
public DefinitionTrackingContext(IFindUsagesContext underlyingContext)
=> _underlyingContext = underlyingContext;

public ValueTask<FindUsagesOptions> GetOptionsAsync(string language, CancellationToken cancellationToken)
=> _underlyingContext.GetOptionsAsync(language, cancellationToken);

public IStreamingProgressTracker ProgressTracker
=> _underlyingContext.ProgressTracker;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Navigation;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
Expand All @@ -23,27 +24,30 @@ internal abstract partial class AbstractFindUsagesService
/// Forwards <see cref="IStreamingFindLiteralReferencesProgress"/> calls to an
/// <see cref="IFindUsagesContext"/> instance.
/// </summary>
private class FindLiteralsProgressAdapter : IStreamingFindLiteralReferencesProgress
private sealed class FindLiteralsProgressAdapter : IStreamingFindLiteralReferencesProgress
{
private readonly IFindUsagesContext _context;
private readonly DefinitionItem _definition;
private readonly ClassificationOptions _classificationOptions;

public IStreamingProgressTracker ProgressTracker
=> _context.ProgressTracker;

public FindLiteralsProgressAdapter(
IFindUsagesContext context, DefinitionItem definition, ClassificationOptions classificationOptions)
IFindUsagesContext context, DefinitionItem definition)
{
_context = context;
_definition = definition;
_classificationOptions = classificationOptions;
}

public async ValueTask OnReferenceFoundAsync(Document document, TextSpan span, CancellationToken cancellationToken)
{
// TODO:
// var options = await _context.GetOptionsAsync(document.Project.Language, cancellationToken).ConfigureAwait(false);
var classificationOptions = ClassificationOptions.From(document.Project);

var documentSpan = await ClassifiedSpansAndHighlightSpanFactory.GetClassifiedDocumentSpanAsync(
document, span, _classificationOptions, cancellationToken).ConfigureAwait(false);
document, span, classificationOptions, cancellationToken).ConfigureAwait(false);

await _context.OnReferenceFoundAsync(
new SourceReferenceItem(_definition, documentSpan, SymbolUsageInfo.None), cancellationToken).ConfigureAwait(false);
}
Expand All @@ -52,7 +56,7 @@ await _context.OnReferenceFoundAsync(
/// <summary>
/// Forwards IFindReferencesProgress calls to an IFindUsagesContext instance.
/// </summary>
private class FindReferencesProgressAdapter : IStreamingFindReferencesProgress
private sealed class FindReferencesProgressAdapter : IStreamingFindReferencesProgress
{
private readonly Solution _solution;
private readonly IFindUsagesContext _context;
Expand Down Expand Up @@ -124,7 +128,9 @@ public async ValueTask OnReferenceFoundAsync(SymbolGroup group, ISymbol definiti
{
var definitionItem = await GetDefinitionItemAsync(group, cancellationToken).ConfigureAwait(false);
var referenceItem = await location.TryCreateSourceReferenceItemAsync(
definitionItem, includeHiddenLocations: false,
_context,
definitionItem,
includeHiddenLocations: false,
cancellationToken).ConfigureAwait(false);

if (referenceItem != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.Editor.FindUsages
internal abstract partial class AbstractFindUsagesService
{
public async Task FindImplementationsAsync(
Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
IFindUsagesContext context, Document document, int position, 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(
Expand All @@ -34,11 +34,11 @@ await context.ReportMessageAsync(

var symbolAndProject = symbolAndProjectOpt.Value;
await FindImplementationsAsync(
symbolAndProject.symbol, symbolAndProject.project, context, cancellationToken).ConfigureAwait(false);
context, symbolAndProject.symbol, symbolAndProject.project, cancellationToken).ConfigureAwait(false);
}

public static async Task FindImplementationsAsync(
ISymbol symbol, Project project, IFindUsagesContext context, CancellationToken cancellationToken)
IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken)
{
var solution = project.Solution;
var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Shared.Extensions;
Expand All @@ -21,12 +22,12 @@ namespace Microsoft.CodeAnalysis.Editor.FindUsages
internal abstract partial class AbstractFindUsagesService
{
async Task IFindUsagesService.FindReferencesAsync(
Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken)
{
var definitionTrackingContext = new DefinitionTrackingContext(context);

await FindLiteralOrSymbolReferencesAsync(
document, position, definitionTrackingContext, cancellationToken).ConfigureAwait(false);
definitionTrackingContext, document, position, cancellationToken).ConfigureAwait(false);

// After the FAR engine is done call into any third party extensions to see
// if they want to add results.
Expand All @@ -38,31 +39,31 @@ await FindLiteralOrSymbolReferencesAsync(
}

Task IFindUsagesLSPService.FindReferencesAsync(
Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
IFindUsagesContext context, Document document, int position, 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(
document, position, new DefinitionTrackingContext(context), cancellationToken);
new DefinitionTrackingContext(context), document, position, cancellationToken);
}

private static async Task FindLiteralOrSymbolReferencesAsync(
Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
IFindUsagesContext context, Document document, int position, 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(
document, position, context, cancellationToken).ConfigureAwait(false);
context, document, position, cancellationToken).ConfigureAwait(false);
if (found)
{
return;
}

// Wasn't a literal. Try again as a symbol.
await FindSymbolReferencesAsync(
document, position, context, cancellationToken).ConfigureAwait(false);
context, document, position, cancellationToken).ConfigureAwait(false);
}

private static async Task<ImmutableArray<DefinitionItem>> GetThirdPartyDefinitionsAsync(
Expand All @@ -84,7 +85,7 @@ private static async Task<ImmutableArray<DefinitionItem>> GetThirdPartyDefinitio
}

private static async Task FindSymbolReferencesAsync(
Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

Expand Down Expand Up @@ -165,7 +166,7 @@ private static Task FindReferencesInCurrentProcessAsync(
}

private static async Task<bool> TryFindLiteralReferencesAsync(
Document document, int position, IFindUsagesContext context, CancellationToken cancellationToken)
IFindUsagesContext context, Document document, int position, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

Expand Down Expand Up @@ -225,8 +226,7 @@ private static async Task<bool> TryFindLiteralReferencesAsync(

await context.OnDefinitionFoundAsync(definition, cancellationToken).ConfigureAwait(false);

var classificationOptions = ClassificationOptions.From(document.Project);
var progressAdapter = new FindLiteralsProgressAdapter(context, definition, classificationOptions);
var progressAdapter = new FindLiteralsProgressAdapter(context, definition);

// Now call into the underlying FAR engine to find reference. The FAR
// engine will push results into the 'progress' instance passed into it.
Expand Down
Loading

0 comments on commit f2f4054

Please sign in to comment.