提交 5213112a 编写于 作者: C CyrusNajmabadi

HAve 'ObjectBrowser-FindRefs' go through the new streaming FindReferences codepath.

上级 559b64b3
......@@ -38,7 +38,7 @@ public Task ReportProgressAsync(int current, int maximum)
/// <summary>
/// Forwards IFindReferencesProgress calls to an IFindUsagesContext instance.
/// </summary>
private class FindReferencesProgressAdapter : ForegroundThreadAffinitizedObject, IStreamingFindReferencesProgress
internal class FindReferencesProgressAdapter : ForegroundThreadAffinitizedObject, IStreamingFindReferencesProgress
{
private readonly Solution _solution;
private readonly IFindUsagesContext _context;
......
// 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.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindUsages;
......@@ -87,9 +88,13 @@ public async Task FindImplementationsAsync(Document document, int position, IFin
return null;
}
var symbol = symbolAndProject?.symbol;
var project = symbolAndProject?.project;
return await FindSymbolReferencesAsync(
context, symbolAndProject?.symbol, symbolAndProject?.project, cancellationToken).ConfigureAwait(false);
}
public static async Task<FindReferencesProgressAdapter> FindSymbolReferencesAsync(
IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken)
{
context.SetSearchTitle(string.Format(EditorFeaturesResources._0_references,
FindUsagesHelpers.GetDisplayName(symbol)));
......
// 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.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Editor.FindUsages;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser.Lists;
......@@ -33,7 +38,13 @@ internal abstract partial class AbstractObjectBrowserLibraryManager : AbstractLi
private AbstractListItemFactory _listItemFactory;
private object _classMemberGate = new object();
protected AbstractObjectBrowserLibraryManager(string languageName, Guid libraryGuid, __SymbolToolLanguage preferredLanguage, IServiceProvider serviceProvider)
private readonly IEnumerable<Lazy<IStreamingFindUsagesPresenter>> _streamingPresenters;
protected AbstractObjectBrowserLibraryManager(
string languageName,
Guid libraryGuid,
__SymbolToolLanguage preferredLanguage,
IServiceProvider serviceProvider)
: base(libraryGuid, serviceProvider)
{
_languageName = languageName;
......@@ -43,6 +54,8 @@ protected AbstractObjectBrowserLibraryManager(string languageName, Guid libraryG
this.Workspace = componentModel.GetService<VisualStudioWorkspace>();
this.LibraryService = this.Workspace.Services.GetLanguageServices(languageName).GetService<ILibraryService>();
this.Workspace.WorkspaceChanged += OnWorkspaceChanged;
this._streamingPresenters = componentModel.DefaultExportProvider.GetExports<IStreamingFindUsagesPresenter>();
}
internal abstract AbstractDescriptionBuilder CreateDescriptionBuilder(
......@@ -481,24 +494,15 @@ protected override bool TryExec(Guid commandGroup, uint commandId)
switch (commandId)
{
case (uint)VSConstants.VSStd97CmdID.FindReferences:
var streamingPresenter = GetStreamingPresenter();
var symbolListItem = _activeListItem as SymbolListItem;
if (symbolListItem != null)
if (streamingPresenter != null && symbolListItem?.ProjectId != null)
{
var projectId = symbolListItem.ProjectId;
if (projectId != null)
var project = this.Workspace.CurrentSolution.GetProject(symbolListItem.ProjectId);
if (project != null)
{
var project = this.Workspace.CurrentSolution.GetProject(projectId);
if (project != null)
{
var compilation = project
.GetCompilationAsync(CancellationToken.None)
.WaitAndGetResult(CancellationToken.None);
var symbol = symbolListItem.ResolveSymbol(compilation);
this.Workspace.TryFindAllReferences(symbol, project, CancellationToken.None);
return true;
}
FindReferences(streamingPresenter, symbolListItem, project);
return true;
}
}
......@@ -508,5 +512,51 @@ protected override bool TryExec(Guid commandGroup, uint commandId)
return false;
}
private IStreamingFindUsagesPresenter GetStreamingPresenter()
{
try
{
return _streamingPresenters.FirstOrDefault()?.Value;
}
catch
{
return null;
}
}
private async void FindReferences(
IStreamingFindUsagesPresenter presenter, SymbolListItem symbolListItem, Project project)
{
try
{
// 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.
var context = presenter.StartSearch(
EditorFeaturesResources.Find_References, supportsReferences: true);
var cancellationToken = context.CancellationToken;
// Fire and forget the work to go get references.
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var symbol = symbolListItem.ResolveSymbol(compilation);
await AbstractFindUsagesService.FindSymbolReferencesAsync(
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,
// that means that a new search has started. We don't care about telling the
// context it has completed. In the latter case something wrong has happened
// and we don't want to run any more code in this particular context.
await context.OnCompletedAsync().ConfigureAwait(false);
}
catch (OperationCanceledException)
{
}
catch (Exception e) when (FatalError.ReportWithoutCrash(e))
{
}
}
}
}
}
\ No newline at end of file
......@@ -6,23 +6,17 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.FindUsages;
using Microsoft.CodeAnalysis.Editor.GoToDefinition;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Undo;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.GeneratedCodeRecognition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudio.LanguageServices.Implementation;
using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel;
using Microsoft.VisualStudio.LanguageServices.Implementation.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser.Lists;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.Shell;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices
......@@ -32,18 +26,15 @@ namespace Microsoft.VisualStudio.LanguageServices
internal class RoslynVisualStudioWorkspace : VisualStudioWorkspaceImpl
{
private readonly IEnumerable<Lazy<IStreamingFindUsagesPresenter>> _streamingPresenters;
private readonly IEnumerable<Lazy<IDefinitionsAndReferencesPresenter>> _referencedSymbolsPresenters;
[ImportingConstructor]
private RoslynVisualStudioWorkspace(
ExportProvider exportProvider,
[ImportMany] IEnumerable<Lazy<IStreamingFindUsagesPresenter>> streamingPresenters,
[ImportMany] IEnumerable<Lazy<IDefinitionsAndReferencesPresenter>> referencedSymbolsPresenters,
[ImportMany] IEnumerable<IDocumentOptionsProviderFactory> documentOptionsProviderFactories)
: base(exportProvider.AsExportProvider())
{
_streamingPresenters = streamingPresenters;
_referencedSymbolsPresenters = referencedSymbolsPresenters;
foreach (var providerFactory in documentOptionsProviderFactories)
{
......@@ -203,44 +194,15 @@ private static bool TryResolveSymbol(ISymbol symbol, Project project, Cancellati
public override bool TryFindAllReferences(ISymbol symbol, Project project, CancellationToken cancellationToken)
{
if (!_referencedSymbolsPresenters.Any())
{
return false;
}
if (!TryResolveSymbol(symbol, project, cancellationToken, out var searchSymbol, out var searchProject))
{
return false;
}
var searchSolution = searchProject.Solution;
var result = SymbolFinder
.FindReferencesAsync(searchSymbol, searchSolution, cancellationToken)
.WaitAndGetResult(cancellationToken).ToList();
if (result != null)
{
DisplayReferencedSymbols(searchSolution, result);
return true;
}
// Legacy API. Previously used by ObjectBrowser to support 'FindRefs' off of an
// object browser item. Now ObjectBrowser goes through the streaming-FindRefs system.
return false;
}
public override void DisplayReferencedSymbols(
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols)
public override void DisplayReferencedSymbols(Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols)
{
var service = this.Services.GetService<IDefinitionsAndReferencesFactory>();
var definitionsAndReferences = service.CreateDefinitionsAndReferences(
solution, referencedSymbols,
includeHiddenLocations: false, cancellationToken: CancellationToken.None);
foreach (var presenter in _referencedSymbolsPresenters)
{
presenter.Value.DisplayResult(definitionsAndReferences);
return;
}
// Legacy API. Previously used by ObjectBrowser to support 'FindRefs' off of an
// object browser item. Now ObjectBrowser goes through the streaming-FindRefs system.
}
internal override object GetBrowseObject(SymbolListItem symbolListItem)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册