diff --git a/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs b/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs
index 382406b5cd96ce04f682c85226bbe23e5d58bdf6..fafe045f07ce0c04a5b2a149cdda2699d9360133 100644
--- a/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs
+++ b/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.ProgressAdapter.cs
@@ -38,7 +38,7 @@ public Task ReportProgressAsync(int current, int maximum)
///
/// Forwards IFindReferencesProgress calls to an IFindUsagesContext instance.
///
- private class FindReferencesProgressAdapter : ForegroundThreadAffinitizedObject, IStreamingFindReferencesProgress
+ internal class FindReferencesProgressAdapter : ForegroundThreadAffinitizedObject, IStreamingFindReferencesProgress
{
private readonly Solution _solution;
private readonly IFindUsagesContext _context;
diff --git a/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs b/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
index 3b5f5877f5192a7c3f0362f028ee45cef166002f..3f38e7adea255bbc61927073c1b54dc92dd5fa7c 100644
--- a/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
+++ b/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
@@ -1,6 +1,7 @@
// 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 FindSymbolReferencesAsync(
+ IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken)
+ {
context.SetSearchTitle(string.Format(EditorFeaturesResources._0_references,
FindUsagesHelpers.GetDisplayName(symbol)));
diff --git a/src/VisualStudio/Core/Def/Implementation/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs b/src/VisualStudio/Core/Def/Implementation/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs
index a5a42da3000ceeb391d65aedd30e5531c23bce5b..0bd8ba4eec26adf88f498b35e5f1e54d34ade1c9 100644
--- a/src/VisualStudio/Core/Def/Implementation/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs
+++ b/src/VisualStudio/Core/Def/Implementation/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs
@@ -1,10 +1,15 @@
// 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> _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();
this.LibraryService = this.Workspace.Services.GetLanguageServices(languageName).GetService();
this.Workspace.WorkspaceChanged += OnWorkspaceChanged;
+
+ this._streamingPresenters = componentModel.DefaultExportProvider.GetExports();
}
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
diff --git a/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs b/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs
index 1c800c54b925b4bbe88a06a6ca6d06bbeda9d334..671b0ff846c71dfb32d1d410c8bb723524c2042a 100644
--- a/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs
+++ b/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs
@@ -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> _streamingPresenters;
- private readonly IEnumerable> _referencedSymbolsPresenters;
[ImportingConstructor]
private RoslynVisualStudioWorkspace(
ExportProvider exportProvider,
[ImportMany] IEnumerable> streamingPresenters,
- [ImportMany] IEnumerable> referencedSymbolsPresenters,
[ImportMany] IEnumerable 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 referencedSymbols)
+ public override void DisplayReferencedSymbols(Solution solution, IEnumerable referencedSymbols)
{
- var service = this.Services.GetService();
- 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)