提交 0cfdfb8a 编写于 作者: C CyrusNajmabadi

Merge branch 'findRefsRQNames1' into findRefsOOPWork

......@@ -106,6 +106,7 @@
<ItemGroup>
<Compile Include="FindUsages\AbstractFindUsagesService.cs" />
<Compile Include="FindUsages\ClassifiedSpansAndHighlightSpan.cs" />
<Compile Include="FindUsages\AbstractFindUsagesService.DefinitionTrackingContext.cs" />
<Compile Include="FindUsages\FindUsagesHelpers.cs" />
<Compile Include="FindUsages\FindUsagesContext.cs" />
<Compile Include="FindUsages\IDefinitionsAndReferencesFactory.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindUsages;
namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
internal abstract partial class AbstractFindUsagesService
{
/// <summary>
/// Forwards <see cref="IFindUsagesContext"/> notifications to an underlying <see cref="IFindUsagesContext"/>
/// while also keeping track of the <see cref="DefinitionItem"/> definitions reported.
///
/// These can then be used by <see cref="CallThirdPartyExtensionsAsync"/> to report the
/// 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 readonly IFindUsagesContext _underlyingContext;
private readonly object _gate = new object();
private readonly List<DefinitionItem> _definitions = new List<DefinitionItem>();
public DefinitionTrackingContext(IFindUsagesContext underlyingContext)
{
_underlyingContext = underlyingContext;
}
public CancellationToken CancellationToken
=> _underlyingContext.CancellationToken;
public void ReportMessage(string message)
=> _underlyingContext.ReportMessage(message);
public void SetSearchTitle(string title)
=> _underlyingContext.SetSearchTitle(title);
public Task OnReferenceFoundAsync(SourceReferenceItem reference)
=> _underlyingContext.OnReferenceFoundAsync(reference);
public Task ReportProgressAsync(int current, int maximum)
=> _underlyingContext.ReportProgressAsync(current, maximum);
public Task OnDefinitionFoundAsync(DefinitionItem definition)
{
lock (_gate)
{
_definitions.Add(definition);
}
return _underlyingContext.OnDefinitionFoundAsync(definition);
}
public ImmutableArray<DefinitionItem> GetDefinitions()
{
lock (_gate)
{
return _definitions.ToImmutableArray();
}
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
......@@ -16,6 +14,10 @@ namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
internal abstract partial class AbstractFindUsagesService
{
/// <summary>
/// Forwards <see cref="IStreamingFindLiteralReferencesProgress"/> calls to an
/// <see cref="IFindUsagesContext"/> instance.
/// </summary>
private class FindLiteralsProgressAdapter : IStreamingFindLiteralReferencesProgress
{
private readonly IFindUsagesContext _context;
......@@ -124,22 +126,6 @@ public async Task OnReferenceFoundAsync(SymbolAndProjectId definition, Reference
await _context.OnReferenceFoundAsync(referenceItem).ConfigureAwait(false);
}
}
public async Task CallThirdPartyExtensionsAsync(CancellationToken cancellationToken)
{
var factory = _solution.Workspace.Services.GetService<IDefinitionsAndReferencesFactory>();
foreach (var definition in _definitionToItem.Values)
{
var item = factory.GetThirdPartyDefinitionItem(
_solution, definition, cancellationToken);
if (item != null)
{
// ConfigureAwait(true) because we want to come back on the
// same thread after calling into extensions.
await _context.OnDefinitionFoundAsync(item).ConfigureAwait(true);
}
}
}
}
}
}
\ No newline at end of file
......@@ -48,36 +48,60 @@ internal abstract partial class AbstractFindUsagesService : IFindUsagesService
public async Task FindReferencesAsync(
Document document, int position, IFindUsagesContext context)
{
var definitionTrackingContext = new DefinitionTrackingContext(context);
// NOTE: All ConFigureAwaits in this method need to pass 'true' so that
// we return to the caller's context. that's so the call to
// CallThirdPartyExtensionsAsync will happen on the UI thread. We need
// this to maintain the threading guarantee we had around that method
// from pre-Roslyn days.
var cancellationToken = context.CancellationToken;
cancellationToken.ThrowIfCancellationRequested();
await FindLiteralOrSymbolReferencesAsync(
document, position, definitionTrackingContext).ConfigureAwait(true);
// After the FAR engine is done call into any third party extensions to see
// if they want to add results.
await CallThirdPartyExtensionsAsync(
document.Project.Solution, definitionTrackingContext, context).ConfigureAwait(true);
}
private async Task FindLiteralOrSymbolReferencesAsync(
Document document, int position, IFindUsagesContext context)
{
// 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).ConfigureAwait(true);
var found = await TryFindLiteralReferencesAsync(
document, position, context).ConfigureAwait(false);
if (found)
{
return;
}
var findReferencesProgress = await FindSymbolReferencesAsync(
document, position, context).ConfigureAwait(true);
if (findReferencesProgress == null)
// Wasn't a literal. Try again as a symbol.
await FindSymbolReferencesAsync(
document, position, context).ConfigureAwait(false);
}
private async Task CallThirdPartyExtensionsAsync(
Solution solution,
DefinitionTrackingContext definitionTrackingContext,
IFindUsagesContext underlyingContext)
{
var cancellationToken = definitionTrackingContext.CancellationToken;
var factory = solution.Workspace.Services.GetService<IDefinitionsAndReferencesFactory>();
foreach (var definition in definitionTrackingContext.GetDefinitions())
{
return;
var item = factory.GetThirdPartyDefinitionItem(solution, definition, cancellationToken);
if (item != null)
{
// ConfigureAwait(true) because we want to come back on the
// same thread after calling into extensions.
await underlyingContext.OnDefinitionFoundAsync(item).ConfigureAwait(true);
}
}
// After the FAR engine is done call into any third party extensions to see
// if they want to add results.
await findReferencesProgress.CallThirdPartyExtensionsAsync(
context.CancellationToken).ConfigureAwait(true);
}
private async Task<FindReferencesProgressAdapter> FindSymbolReferencesAsync(
private async Task FindSymbolReferencesAsync(
Document document, int position, IFindUsagesContext context)
{
var cancellationToken = context.CancellationToken;
......@@ -88,10 +112,10 @@ internal abstract partial class AbstractFindUsagesService : IFindUsagesService
document, position, cancellationToken).ConfigureAwait(false);
if (symbolAndProject == null)
{
return null;
return;
}
return await FindSymbolReferencesWorkerAsync(
await FindSymbolReferencesAsync(
context, symbolAndProject?.symbol, symbolAndProject?.project, cancellationToken).ConfigureAwait(false);
}
......@@ -99,13 +123,7 @@ internal abstract partial class AbstractFindUsagesService : IFindUsagesService
/// Public helper that we use from features like ObjectBrowser which start with a symbol
/// and want to push all the references to it into the Streaming-Find-References window.
/// </summary>
public static Task FindSymbolReferencesAsync(
IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken)
{
return FindSymbolReferencesWorkerAsync(context, symbol, project, cancellationToken);
}
private static async Task<FindReferencesProgressAdapter> FindSymbolReferencesWorkerAsync(
public static async Task FindSymbolReferencesAsync(
IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken)
{
context.SetSearchTitle(string.Format(EditorFeaturesResources._0_references,
......@@ -123,8 +141,6 @@ internal abstract partial class AbstractFindUsagesService : IFindUsagesService
progressAdapter,
documents: null,
cancellationToken: cancellationToken).ConfigureAwait(false);
return progressAdapter;
}
private async Task<bool> TryFindLiteralReferencesAsync(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册