diff --git a/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs b/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs index 01abefa35ccf32a128dc8a4d4730b3ab9a33f061..8668673125c4198b1aa5147b132f49bf690d90d9 100644 --- a/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs +++ b/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs @@ -20,4 +20,17 @@ internal class CSharpFindReferencesService : AbstractFindReferencesService { } } -} + + [ExportLanguageService(typeof(IStreamingFindReferencesService), LanguageNames.CSharp), Shared] + internal class CSharpStreamingFindReferencesService : AbstractFindReferencesService + { + [ImportingConstructor] + public CSharpStreamingFindReferencesService( + [ImportMany] IEnumerable referencedSymbolsPresenters, + [ImportMany] IEnumerable navigableItemsPresenters, + [ImportMany] IEnumerable externalReferencesProviders) + : base(referencedSymbolsPresenters, navigableItemsPresenters, externalReferencesProviders) + { + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/Core/EditorFeatures.csproj b/src/EditorFeatures/Core/EditorFeatures.csproj index 5216bc75095871f5a1b10e971989fa9a2555a5e0..a5e0cfe7c77ee47cc0289fd76313a23767d81d0c 100644 --- a/src/EditorFeatures/Core/EditorFeatures.csproj +++ b/src/EditorFeatures/Core/EditorFeatures.csproj @@ -267,6 +267,7 @@ + @@ -808,4 +809,4 @@ - + \ No newline at end of file diff --git a/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.ProgressAdapter.cs b/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.ProgressAdapter.cs new file mode 100644 index 0000000000000000000000000000000000000000..21577e905a6d679d21406505db096924f2833198 --- /dev/null +++ b/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.ProgressAdapter.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Navigation; +using Microsoft.CodeAnalysis.FindSymbols; +using Microsoft.CodeAnalysis.Shared.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.Implementation.FindReferences +{ + internal abstract partial class AbstractFindReferencesService + { + /// + /// Forwards IFindReferencesProgress calls to a FindRefrencesContext instance. + /// + private class ProgressAdapter : IFindReferencesProgress + { + private readonly Solution _solution; + private readonly FindReferencesContext _context; + + private readonly ConcurrentDictionary _symbolToNavigableItem = + new ConcurrentDictionary(SymbolEquivalenceComparer.Instance); + + private readonly Func _navigableItemFactory; + + public ProgressAdapter(Solution solution, FindReferencesContext context) + { + _solution = solution; + _context = context; + _navigableItemFactory = s => NavigableItemFactory.GetItemFromSymbolLocation( + solution, s, s.Locations.First()); + } + + public void OnStarted() => _context.OnStarted(); + public void OnCompleted() => _context.OnCompleted(); + + public void ReportProgress(int current, int maximum) => _context.ReportProgress(current, maximum); + + public void OnFindInDocumentStarted(Document document) => _context.OnFindInDocumentStarted(document); + public void OnFindInDocumentCompleted(Document document) => _context.OnFindInDocumentCompleted(document); + + private INavigableItem GetNavigableItem(ISymbol symbol) + { + return _symbolToNavigableItem.GetOrAdd(symbol, _navigableItemFactory); + } + + public void OnDefinitionFound(ISymbol symbol) + { + _context.OnDefinitionFound(GetNavigableItem(symbol)); + } + + public void OnReferenceFound(ISymbol symbol, ReferenceLocation location) + { + _context.OnReferenceFound( + GetNavigableItem(symbol), + NavigableItemFactory.GetItemFromSymbolLocation(_solution, symbol, location.Location)); + } + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs b/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs index 929ead326c560e40cda85a0706357c9df071b4af..b2fdb8bd6a34f4b6be100ff55154ec3502dcb0d2 100644 --- a/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs +++ b/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs @@ -14,8 +14,8 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.FindReferences { - internal abstract class AbstractFindReferencesService : - IFindReferencesService + internal abstract partial class AbstractFindReferencesService : + IFindReferencesService, IStreamingFindReferencesService { private readonly IEnumerable _referenceSymbolPresenters; private readonly IEnumerable _navigableItemPresenters; @@ -34,6 +34,8 @@ internal abstract class AbstractFindReferencesService : private async Task> GetRelevantSymbolAndSolutionAtPositionAsync( Document document, int position, CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); + var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken: cancellationToken).ConfigureAwait(false); if (symbol != null) { @@ -118,7 +120,7 @@ public bool TryFindReferences(Document document, int position, IWaitContext wait // First see if we have any external navigable item references. // If so, we display the results as navigable items. - var succeeded = TryFindAndDisplayNavigableItemsReferencesAsync(document, position, waitContext).WaitAndGetResult(cancellationToken); + var succeeded = TryFindAndDisplayNavigableItemsReferencesAsync(document, position, waitContext).WaitAndGetResult(cancellationToken); if (succeeded) { return true; @@ -184,5 +186,25 @@ private bool TryDisplayReferences(Tuple, Solution> return false; } + + public async Task FindReferencesAsync( + Document document, int position, FindReferencesContext context) + { + var cancellationToken = context.CancellationToken; + cancellationToken.ThrowIfCancellationRequested(); + + var symbolAndSolution = await GetRelevantSymbolAndSolutionAtPositionAsync( + document, position, cancellationToken).ConfigureAwait(false); + + var symbol = symbolAndSolution.Item1; + var solution = symbolAndSolution.Item2; + + var result = await SymbolFinder.FindReferencesAsync( + symbol, + solution, + progress: new ProgressAdapter(solution, context), + documents: null, + cancellationToken: cancellationToken).ConfigureAwait(false); + } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs b/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs index 7878e3ae28c6a3de886c068898ef7bae9c86ac15..be485f04d3efdd3e890b96f13062fe6cdd6a7067 100644 --- a/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs +++ b/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs @@ -1,17 +1,17 @@ // 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.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Commands; +using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; -using Microsoft.CodeAnalysis.Editor.Navigation; using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.FindSymbols; -using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Text; -using Moq; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; @@ -29,7 +29,9 @@ public async Task TestFindReferencesSynchronousCall() var handler = new FindReferencesCommandHandler( TestWaitIndicator.Default, - SpecializedCollections.SingletonEnumerable(findReferencesPresenter)); + SpecializedCollections.SingletonEnumerable(findReferencesPresenter), + SpecializedCollections.EmptyEnumerable(), + workspace.ExportProvider.GetExports()); var textView = workspace.Documents[0].GetTextView(); textView.Caret.MoveTo(new SnapshotPoint(textView.TextSnapshot, 7)); diff --git a/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb b/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb index 5a3bff465158e5278492d9fdaa2b95548016ee6e..ad88637649c29dbb85f5d8fa0fe0dcedd3487ef6 100644 --- a/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb +++ b/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb @@ -17,4 +17,16 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.FindReferences MyBase.New(referencedSymbolsPresenters, navigableItemsPresenters, externalReferencesProviders) End Sub End Class -End Namespace + + + Friend Class VisualBasicStreamingFindReferencesService + Inherits AbstractFindReferencesService + + + Protected Sub New( referencedSymbolsPresenters As IEnumerable(Of IReferencedSymbolsPresenter), + navigableItemsPresenters As IEnumerable(Of INavigableItemsPresenter), + externalReferencesProviders As IEnumerable(Of IFindReferencesResultProvider)) + MyBase.New(referencedSymbolsPresenters, navigableItemsPresenters, externalReferencesProviders) + End Sub + End Class +End Namespace \ No newline at end of file