提交 b94c6fb8 编写于 作者: C Cyrus Najmabadi

Add the external reference concept

上级 0a220a62
......@@ -2,11 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Composition;
using Microsoft.CodeAnalysis.Editor.FindUsages;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using VS.IntelliNav.Contracts;
namespace Microsoft.CodeAnalysis.Editor.CSharp.FindUsages
{
......@@ -15,8 +18,10 @@ internal class CSharpFindUsagesService : AbstractFindUsagesService
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpFindUsagesService(IThreadingContext threadingContext)
: base(threadingContext)
public CSharpFindUsagesService(
IThreadingContext threadingContext,
[Import(AllowDefault = true)] ICodeIndexProvider? codeIndexProvider)
: base(threadingContext, codeIndexProvider)
{
}
}
......
// 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.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.SymbolMonikers;
using Roslyn.Utilities;
using VS.IntelliNav.Contracts;
namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
using static FindUsagesHelpers;
internal abstract partial class AbstractFindUsagesService
{
private static async Task FindCodeIndexReferencesAsync(
ICodeIndexProvider? codeIndexProvider,
ISymbol definition,
IFindUsagesContext context,
CancellationToken cancellationToken)
{
if (codeIndexProvider == null)
return;
var moniker = SymbolMoniker.TryCreate(definition);
if (moniker == null)
return;
var progress = new StreamingProgressTracker(context.ReportProgressAsync);
try
{
await progress.AddItemsAsync(1).ConfigureAwait(false);
// TODO: loc this
var displayParts = GetDisplayParts(definition).Add(
new TaggedText(TextTags.Text, " - (external)"));
var definitionItem = DefinitionItem.CreateNonNavigableItem(
GlyphTags.GetTags(definition.GetGlyph()),
displayParts,
originationParts: ImmutableArray.Create(new TaggedText(TextTags.Text, "external")));
var monikers = SpecializedCollections.SingletonEnumerable(moniker);
var currentPage = 0;
while (true)
{
var keepGoing = await FindCodeIndexReferencesAsync(
codeIndexProvider, monikers, context,
progress, definitionItem, currentPage, cancellationToken).ConfigureAwait(false);
if (!keepGoing)
break;
}
}
finally
{
await progress.ItemCompletedAsync().ConfigureAwait(false);
}
}
/// <summary>
/// Returns <c>false</c> when it's time to stop searching.
/// </summary>
private static async Task<bool> FindCodeIndexReferencesAsync(
ICodeIndexProvider codeIndexProvider,
IEnumerable<ISymbolMoniker> monikers,
IFindUsagesContext context,
IStreamingProgressTracker progress,
DefinitionItem definitionItem,
int currentPage,
CancellationToken cancellationToken)
{
try
{
await progress.AddItemsAsync(1).ConfigureAwait(false);
var results = await codeIndexProvider.FindReferencesByMonikerAsync(
monikers, includeDecleration: true, pageIndex: currentPage, cancellationToken: cancellationToken).ConfigureAwait(false);
if (results == null || results.Count == 0)
return false;
if (currentPage == 0)
{
// found some results. Add the definition item to the context.
await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
}
currentPage++;
await ProcessCodeIndexResultsAsync(
codeIndexProvider, context, definitionItem, results, cancellationToken).ConfigureAwait(false);
return true;
}
finally
{
await progress.ItemCompletedAsync().ConfigureAwait(false);
}
}
private static async Task ProcessCodeIndexResultsAsync(
ICodeIndexProvider codeIndexProvider,
IFindUsagesContext context,
DefinitionItem definitionItem,
ICollection<string> results,
CancellationToken cancellationToken)
{
foreach (var result in results)
{
var referenceItem = new ExternalReferenceItem(
definitionItem, null, null, null, null);
await context.OnExternalReferenceFoundAsync(referenceItem).ConfigureAwait(false);
}
}
}
}
......@@ -43,6 +43,9 @@ public Task SetSearchTitleAsync(string title)
public Task OnReferenceFoundAsync(SourceReferenceItem reference)
=> _underlyingContext.OnReferenceFoundAsync(reference);
public Task OnExternalReferenceFoundAsync(ExternalReferenceItem reference)
=> _underlyingContext.OnExternalReferenceFoundAsync(reference);
public Task ReportProgressAsync(int current, int maximum)
=> _underlyingContext.ReportProgressAsync(current, maximum);
......
......@@ -14,6 +14,7 @@
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.SymbolMonikers;
using Roslyn.Utilities;
using VS.IntelliNav.Contracts;
......@@ -153,7 +154,14 @@ internal abstract partial class AbstractFindUsagesService : IFindUsagesService
FindUsagesHelpers.GetDisplayName(symbol))).ConfigureAwait(false);
var options = FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol);
var progressAdapter = new FindReferencesProgressAdapter(threadingContext, project.Solution, context, options);
// We're doing to kick off two find-references here. One that roslyn performs, and one
// that goes through rich-nav. In order for things like progress to work, we have each
// subsystem call into their context object. These then get aggregated and passed along
// to the real context object.
var aggregator = new FindUsagesContextAggregator(context);
var roslynFindUsagesContext = aggregator.CreateForwardingContext();
var codeIndexFindUsagesContext = aggregator.CreateForwardingContext();
// Now call into the underlying FAR engine to find reference. The FAR
// engine will push results into the 'progress' instance passed into it.
......@@ -162,7 +170,7 @@ internal abstract partial class AbstractFindUsagesService : IFindUsagesService
var normalFindReferencesTask = SymbolFinder.FindReferencesAsync(
SymbolAndProjectId.Create(symbol, project.Id),
project.Solution,
progressAdapter,
new FindReferencesProgressAdapter(threadingContext, project.Solution, roslynFindUsagesContext, options),
documents: null,
options,
cancellationToken);
......@@ -171,43 +179,12 @@ internal abstract partial class AbstractFindUsagesService : IFindUsagesService
var codeIndexReferencesTask = FindCodeIndexReferencesAsync(
codeIndexProvider,
symbol,
project.Solution,
progressAdapter,
options,
codeIndexFindUsagesContext,
cancellationToken);
await Task.WhenAll(normalFindReferencesTask, codeIndexReferencesTask).ConfigureAwait(false);
}
private async Task FindCodeIndexReferencesAsync(
ICodeIndexProvider? codeIndexProvider,
ISymbol symbol, Solution solution,
FindReferencesProgressAdapter progressAdapter,
FindReferencesSearchOptions options,
CancellationToken cancellationToken)
{
if (codeIndexProvider == null)
return;
var moniker = SymbolMoniker.TryCreate(symbol);
if (moniker == null)
return;
var monikers = SpecializedCollections.SingletonEnumerable(moniker);
var currentPage = 0;
while (true)
{
var results = await codeIndexProvider.FindReferencesByMonikerAsync(
monikers, includeDecleration: true, pageIndex: currentPage, cancellationToken: cancellationToken).ConfigureAwait(false);
if (results == null || results.Count == 0)
break;
currentPage++;
await ProcessCodeIndexResultsAsync(
codeIndexProvider, results, cancellationToken).ConfigureAwait(false);
}
}
private async Task<bool> TryFindLiteralReferencesAsync(
Document document, int position, IFindUsagesContext context)
{
......
// 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.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindUsages;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
/// <summary>
/// Helper class that allows us to provide a unified Find-Usages progress over multiple
/// subroutines computing different types of usages.
/// </summary>
internal class FindUsagesContextAggregator
{
/// <summary>
/// Real context object we'll forward messages to.
/// </summary>
private readonly IFindUsagesContext _context;
/// <summary>
/// Underlying context objects that we'll receive messages from and forward to <see cref="_context"/>
/// </summary>
private readonly List<ForwardingFindUsagesContext> _underlyingContexts = new List<ForwardingFindUsagesContext>();
private readonly object _gate = new object();
private readonly Dictionary<ForwardingFindUsagesContext, (int current, int maxium)> _underlyingContextToProgress =
new Dictionary<ForwardingFindUsagesContext, (int current, int maxium)>();
public FindUsagesContextAggregator(IFindUsagesContext context)
{
_context = context;
}
public IFindUsagesContext CreateForwardingContext()
{
var result = new ForwardingFindUsagesContext(this);
lock (_gate)
{
_underlyingContexts.Add(result);
}
return result;
}
private Task ReportProgressAsync(ForwardingFindUsagesContext context, int current, int maximum)
{
int combinedCurrent = 0, combinedMaximum = 0;
lock (_gate)
{
_underlyingContextToProgress[context] = (current, maximum);
foreach (var (_, (singleCurrent, singleMaximum)) in _underlyingContextToProgress)
{
combinedCurrent += singleCurrent;
combinedMaximum += singleMaximum;
}
}
return _context.ReportProgressAsync(combinedCurrent, combinedMaximum);
}
#region Simple forwarding calls
private CancellationToken CancellationToken
=> _context.CancellationToken;
private Task OnDefinitionFoundAsync(DefinitionItem definition)
=> _context.OnDefinitionFoundAsync(definition);
private Task OnReferenceFoundAsync(SourceReferenceItem reference)
=> _context.OnReferenceFoundAsync(reference);
private Task OnExternalReferenceFoundAsync(ExternalReferenceItem reference)
=> _context.OnExternalReferenceFoundAsync(reference);
private Task ReportMessageAsync(string message)
=> _context.ReportMessageAsync(message);
private Task SetSearchTitleAsync(string title)
=> _context.ReportMessageAsync(title);
#endregion
private class ForwardingFindUsagesContext : IFindUsagesContext
{
private readonly FindUsagesContextAggregator _aggregator;
public ForwardingFindUsagesContext(FindUsagesContextAggregator aggregateFindUsagesContext)
{
_aggregator = aggregateFindUsagesContext;
}
// We pass ourselves along to the aggregator so it can keep track of the current/max
// *per* underlying context.
public Task ReportProgressAsync(int current, int maximum)
=> _aggregator.ReportProgressAsync(this, current, maximum);
#region Simple forwarding calls
public CancellationToken CancellationToken
=> _aggregator.CancellationToken;
public Task OnDefinitionFoundAsync(DefinitionItem definition)
=> _aggregator.OnDefinitionFoundAsync(definition);
public Task OnReferenceFoundAsync(SourceReferenceItem reference)
=> _aggregator.OnReferenceFoundAsync(reference);
public Task OnExternalReferenceFoundAsync(ExternalReferenceItem reference)
=> _aggregator.OnExternalReferenceFoundAsync(reference);
public Task ReportMessageAsync(string message)
=> _aggregator.ReportMessageAsync(message);
public Task SetSearchTitleAsync(string title)
=> _aggregator.ReportMessageAsync(title);
#endregion
}
}
}
......@@ -2,10 +2,8 @@
// 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 Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FindUsages
{
......@@ -27,6 +25,8 @@ protected FindUsagesContext()
public virtual Task OnReferenceFoundAsync(SourceReferenceItem reference) => Task.CompletedTask;
public virtual Task OnExternalReferenceFoundAsync(ExternalReferenceItem reference) => Task.CompletedTask;
public virtual Task ReportProgressAsync(int current, int maximum) => Task.CompletedTask;
}
}
......@@ -138,5 +138,43 @@ public static async Task<(ISymbol symbol, Project project, ImmutableArray<ISymbo
return ImmutableArray.Create(symbol);
}
}
private static SymbolDisplayFormat GetFormat(ISymbol definition)
{
return definition.Kind == SymbolKind.Parameter
? s_parameterDefinitionFormat
: s_definitionFormat;
}
private static readonly SymbolDisplayFormat s_namePartsFormat = new SymbolDisplayFormat(
memberOptions: SymbolDisplayMemberOptions.IncludeContainingType);
private static readonly SymbolDisplayFormat s_definitionFormat =
new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
parameterOptions: SymbolDisplayParameterOptions.IncludeType,
propertyStyle: SymbolDisplayPropertyStyle.ShowReadWriteDescriptor,
delegateStyle: SymbolDisplayDelegateStyle.NameAndSignature,
kindOptions: SymbolDisplayKindOptions.IncludeMemberKeyword | SymbolDisplayKindOptions.IncludeNamespaceKeyword | SymbolDisplayKindOptions.IncludeTypeKeyword,
localOptions: SymbolDisplayLocalOptions.IncludeType,
memberOptions:
SymbolDisplayMemberOptions.IncludeContainingType |
SymbolDisplayMemberOptions.IncludeExplicitInterface |
SymbolDisplayMemberOptions.IncludeModifiers |
SymbolDisplayMemberOptions.IncludeParameters |
SymbolDisplayMemberOptions.IncludeType,
miscellaneousOptions:
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
private static readonly SymbolDisplayFormat s_parameterDefinitionFormat = s_definitionFormat
.AddParameterOptions(SymbolDisplayParameterOptions.IncludeName);
public static ImmutableArray<TaggedText> GetDisplayParts(ISymbol definition)
=> definition.ToDisplayParts(GetFormat(definition)).ToTaggedText();
public static ImmutableArray<TaggedText> GetNameDisplayParts(ISymbol definition)
=> definition.ToDisplayParts(s_namePartsFormat).ToTaggedText();
}
}
......@@ -20,6 +20,8 @@
namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
using static FindUsagesHelpers;
internal interface IDefinitionsAndReferencesFactory : IWorkspaceService
{
DefinitionItem GetThirdPartyDefinitionItem(
......@@ -94,8 +96,8 @@ internal static class DefinitionItemExtensions
definition = definition.OriginalDefinition;
}
var displayParts = definition.ToDisplayParts(GetFormat(definition)).ToTaggedText();
var nameDisplayParts = definition.ToDisplayParts(s_namePartsFormat).ToTaggedText();
var displayParts = GetDisplayParts(definition);
var nameDisplayParts = GetNameDisplayParts(definition);
var tags = GlyphTags.GetTags(definition.GetGlyph());
var displayIfNoReferences = definition.ShouldShowWithNoReferenceLocations(
......@@ -204,37 +206,5 @@ internal static class DefinitionItemExtensions
return new SourceReferenceItem(definitionItem, documentSpan, referenceLocation.SymbolUsageInfo, referenceLocation.AdditionalProperties);
}
private static SymbolDisplayFormat GetFormat(ISymbol definition)
{
return definition.Kind == SymbolKind.Parameter
? s_parameterDefinitionFormat
: s_definitionFormat;
}
private static readonly SymbolDisplayFormat s_namePartsFormat = new SymbolDisplayFormat(
memberOptions: SymbolDisplayMemberOptions.IncludeContainingType);
private static readonly SymbolDisplayFormat s_definitionFormat =
new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
parameterOptions: SymbolDisplayParameterOptions.IncludeType,
propertyStyle: SymbolDisplayPropertyStyle.ShowReadWriteDescriptor,
delegateStyle: SymbolDisplayDelegateStyle.NameAndSignature,
kindOptions: SymbolDisplayKindOptions.IncludeMemberKeyword | SymbolDisplayKindOptions.IncludeNamespaceKeyword | SymbolDisplayKindOptions.IncludeTypeKeyword,
localOptions: SymbolDisplayLocalOptions.IncludeType,
memberOptions:
SymbolDisplayMemberOptions.IncludeContainingType |
SymbolDisplayMemberOptions.IncludeExplicitInterface |
SymbolDisplayMemberOptions.IncludeModifiers |
SymbolDisplayMemberOptions.IncludeParameters |
SymbolDisplayMemberOptions.IncludeType,
miscellaneousOptions:
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
private static readonly SymbolDisplayFormat s_parameterDefinitionFormat = s_definitionFormat
.AddParameterOptions(SymbolDisplayParameterOptions.IncludeName);
}
}
......@@ -23,6 +23,7 @@ internal interface IFindUsagesContext
Task OnDefinitionFoundAsync(DefinitionItem definition);
Task OnReferenceFoundAsync(SourceReferenceItem reference);
Task OnExternalReferenceFoundAsync(ExternalReferenceItem reference);
Task ReportProgressAsync(int current, int maximum);
}
......
......@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindUsages;
......
......@@ -6,6 +6,7 @@ Imports System.Composition
Imports Microsoft.CodeAnalysis.Editor.FindUsages
Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities
Imports Microsoft.CodeAnalysis.Host.Mef
Imports VS.IntelliNav.Contracts
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.FindUsages
<ExportLanguageService(GetType(IFindUsagesService), LanguageNames.VisualBasic), [Shared]>
......@@ -14,8 +15,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.FindUsages
<ImportingConstructor>
<Obsolete(MefConstruction.ImportingConstructorMessage, True)>
Public Sub New(threadingContext As IThreadingContext)
MyBase.New(threadingContext)
Public Sub New(threadingContext As IThreadingContext,
<Import(AllowDefault:=True)> codeIndexProvider As ICodeIndexProvider)
MyBase.New(threadingContext, codeIndexProvider)
End Sub
End Class
End Namespace
// 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.
namespace Microsoft.CodeAnalysis.FindUsages
{
/// <summary>
/// Information about a symbol's reference that can be used for display and navigation in an
/// editor. These generally reference items outside of the Roslyn <see cref="Solution"/> model
/// provided by external sources (for example: RichNav).
/// </summary>
internal sealed class ExternalReferenceItem
{
/// <summary>
/// The definition this reference corresponds to.
/// </summary>
public DefinitionItem Definition { get; }
public ExternalReferenceItem(
DefinitionItem definition,
string documentName,
string projectName,
object text,
string displayPath)
{
Definition = definition;
DocumentName = documentName;
ProjectName = projectName;
Text = text;
DisplayPath = displayPath;
}
public string DocumentName { get; }
public string ProjectName { get; }
/// <remarks>
/// Must be of type Microsoft.VisualStudio.Text.Adornments.ImageElement or
/// Microsoft.VisualStudio.Text.Adornments.ContainerElement or
/// Microsoft.VisualStudio.Text.Adornments.ClassifiedTextElement or System.String
/// </remarks>
public object Text { get; }
public string DisplayPath { get; }
}
}
......@@ -39,7 +39,9 @@ public async Task FindSymbolReferencesAsync(ISymbol symbol, Project project, Can
// the context object that the FAR service will push results into.
var context = streamingPresenter.StartSearch(EditorFeaturesResources.Find_References, supportsReferences: true);
await AbstractFindUsagesService.FindSymbolReferencesAsync(_threadingContext, context, symbol, project, cancellationToken).ConfigureAwait(false);
await AbstractFindUsagesService.FindSymbolReferencesAsync(
_threadingContext, codeIndexProvider: null,
context, symbol, project, cancellationToken).ConfigureAwait(false);
// Note: we don't need to put this in a finally. The only time we might not hit
// this is if cancellation or another error gets thrown. In the former case,
......
......@@ -6,23 +6,19 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.DocumentHighlighting;
using Microsoft.CodeAnalysis.FindSymbols.Finders;
using Microsoft.CodeAnalysis.FindSymbols.FindReferences;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Implementation.FindReferences;
using Microsoft.VisualStudio.Shell.FindAllReferences;
using Microsoft.VisualStudio.Shell.TableControl;
using Microsoft.VisualStudio.Shell.TableManager;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{
......@@ -259,7 +255,7 @@ public IDisposable Subscribe(ITableDataSink sink)
#endregion
#region FindUsagesContext overrides.
#region IFindUsagesContext implementation.
public sealed override Task SetSearchTitleAsync(string title)
{
......@@ -268,7 +264,7 @@ public sealed override Task SetSearchTitleAsync(string title)
return Task.CompletedTask;
}
public sealed override async Task OnCompletedAsync()
public async sealed override Task OnCompletedAsync()
{
await OnCompletedAsyncWorkerAsync().ConfigureAwait(false);
......@@ -355,12 +351,15 @@ private async Task<(ExcerptResult, SourceText)> ExcerptAsync(SourceText sourceTe
}
public sealed override Task OnReferenceFoundAsync(SourceReferenceItem reference)
{
return OnReferenceFoundWorkerAsync(reference);
}
=> OnReferenceFoundWorkerAsync(reference);
protected abstract Task OnReferenceFoundWorkerAsync(SourceReferenceItem reference);
public sealed override Task OnExternalReferenceFoundAsync(ExternalReferenceItem reference)
=> OnExternalReferenceFoundWorkerAsync(reference);
protected abstract Task OnExternalReferenceFoundWorkerAsync(ExternalReferenceItem reference);
protected RoslynDefinitionBucket GetOrCreateDefinitionBucket(DefinitionItem definition)
{
lock (Gate)
......@@ -375,6 +374,9 @@ protected RoslynDefinitionBucket GetOrCreateDefinitionBucket(DefinitionItem defi
}
}
public sealed override Task ReportMessageAsync(string message)
=> throw new InvalidOperationException("This should never be called in the streaming case.");
public sealed override Task ReportProgressAsync(int current, int maximum)
{
// https://devdiv.visualstudio.com/web/wi.aspx?pcguid=011b8bdf-6d56-4f87-be0d-0092136884d9&id=359162
......
......@@ -117,6 +117,21 @@ protected override Task OnReferenceFoundWorkerAsync(SourceReferenceItem referenc
addToEntriesWhenNotGroupingByDefinition: true);
}
protected override Task OnExternalReferenceFoundWorkerAsync(ExternalReferenceItem reference)
{
// Normal references go into both sets of entries.
return OnEntryFoundAsync(
reference.Definition,
bucket => TryCreateExternalItemEntryAsync(reference),
addToEntriesWhenGroupingByDefinition: true,
addToEntriesWhenNotGroupingByDefinition: true);
}
private Task<Entry> TryCreateExternalItemEntryAsync(ExternalReferenceItem reference)
{
throw new NotImplementedException();
}
protected async Task OnEntryFoundAsync(
DefinitionItem definition,
Func<RoslynDefinitionBucket, Task<Entry>> createEntryAsync,
......
......@@ -37,6 +37,10 @@ private class WithoutReferencesFindUsagesContext : AbstractTableDataSourceFindUs
protected override Task OnReferenceFoundWorkerAsync(SourceReferenceItem reference)
=> throw new InvalidOperationException();
// We should never be called in a context where we get references.
protected override Task OnExternalReferenceFoundWorkerAsync(ExternalReferenceItem reference)
=> throw new InvalidOperationException();
// Nothing to do on completion.
protected override Task OnCompletedAsyncWorkerAsync()
=> Task.CompletedTask;
......
......@@ -17,6 +17,7 @@
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using VS.IntelliNav.Contracts;
using IServiceProvider = System.IServiceProvider;
using Task = System.Threading.Tasks.Task;
......@@ -44,6 +45,7 @@ internal abstract partial class AbstractObjectBrowserLibraryManager : AbstractLi
private readonly IStreamingFindUsagesPresenter _streamingPresenter;
private readonly IThreadingContext _threadingContext;
private readonly ICodeIndexProvider _codeIndexProvider;
protected AbstractObjectBrowserLibraryManager(
string languageName,
......@@ -64,6 +66,7 @@ internal abstract partial class AbstractObjectBrowserLibraryManager : AbstractLi
_libraryService = new Lazy<ILibraryService>(() => Workspace.Services.GetLanguageServices(_languageName).GetService<ILibraryService>());
_streamingPresenter = componentModel.DefaultExportProvider.GetExportedValue<IStreamingFindUsagesPresenter>();
_threadingContext = componentModel.DefaultExportProvider.GetExportedValue<IThreadingContext>();
_codeIndexProvider = componentModel.DefaultExportProvider.GetExportedValue<ICodeIndexProvider>();
}
internal abstract AbstractDescriptionBuilder CreateDescriptionBuilder(
......@@ -542,7 +545,7 @@ protected override bool TryExec(Guid commandGroup, uint commandId)
// thread.
await Task.Run(async () =>
{
await FindReferencesAsync(_threadingContext, symbolListItem, project, context, cancellationToken).ConfigureAwait(false);
await FindReferencesAsync(_threadingContext, _codeIndexProvider, symbolListItem, project, context, cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false);
// Note: we don't need to put this in a finally. The only time we might not hit
......@@ -560,14 +563,16 @@ protected override bool TryExec(Guid commandGroup, uint commandId)
}
}
private static async Task FindReferencesAsync(IThreadingContext threadingContext, SymbolListItem symbolListItem, Project project, CodeAnalysis.FindUsages.FindUsagesContext context, CancellationToken cancellationToken)
private static async Task FindReferencesAsync(
IThreadingContext threadingContext, ICodeIndexProvider codeIndexProvider,
SymbolListItem symbolListItem, Project project, CodeAnalysis.FindUsages.FindUsagesContext context, CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var symbol = symbolListItem.ResolveSymbol(compilation);
if (symbol != null)
{
await AbstractFindUsagesService.FindSymbolReferencesAsync(
threadingContext,
threadingContext, codeIndexProvider,
context, symbol, project, cancellationToken).ConfigureAwait(false);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册