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

Switch to IAsyncEnumerable

上级 e2a86f0f
......@@ -238,6 +238,7 @@
<SystemCollectionsImmutableVersion>1.5.0</SystemCollectionsImmutableVersion>
<SystemReflectionMetadataVersion>1.6.0</SystemReflectionMetadataVersion>
<MicrosoftVisualStudioStaticReviewsEmbeddableVersion>0.1.99-alpha</MicrosoftVisualStudioStaticReviewsEmbeddableVersion>
<MicrosoftBclAsyncInterfacesVersion>1.1.0</MicrosoftBclAsyncInterfacesVersion>
</PropertyGroup>
<!--
The following packages are considered implementation details and will not be included
......
......@@ -36,6 +36,7 @@ internal abstract partial class AbstractFindUsagesService
var progress = new StreamingProgressTracker(context.ReportProgressAsync);
try
{
// Let the find-refs window know we have outstanding work
await progress.AddItemsAsync(1).ConfigureAwait(false);
// TODO: loc this
......@@ -48,18 +49,23 @@ internal abstract partial class AbstractFindUsagesService
originationParts: DefinitionItem.GetOriginationParts(definition));
var monikers = ImmutableArray.Create(moniker);
var currentPage = 0;
while (true)
var first = true;
await foreach (var referenceItem in monikerUsagesService.FindReferencesByMoniker(definitionItem, monikers, progress, cancellationToken))
{
var keepGoing = await FindSymbolMonikerReferencesAsync(
monikerUsagesService, monikers, context,
progress, definitionItem, currentPage, cancellationToken).ConfigureAwait(false);
if (!keepGoing)
break;
if (first)
{
// found some results. Add the definition item to the context.
first = false;
await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
}
await context.OnExternalReferenceFoundAsync(referenceItem).ConfigureAwait(false);
}
}
finally
{
// Mark that our async work is done.
await progress.ItemCompletedAsync().ConfigureAwait(false);
}
}
......@@ -80,25 +86,6 @@ internal abstract partial class AbstractFindUsagesService
{
await progress.AddItemsAsync(1).ConfigureAwait(false);
var results = await monikerUsagesService.FindReferencesByMonikerAsync(
definitionItem, monikers, page: currentPage, cancellationToken: cancellationToken).ConfigureAwait(false);
if (results.IsDefaultOrEmpty)
{
// No results, indicate that we're totally done searching for moniker items.
return false;
}
if (currentPage == 0)
{
// found some results. Add the definition item to the context.
await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
}
currentPage++;
foreach (var referenceItem in results)
await context.OnExternalReferenceFoundAsync(referenceItem).ConfigureAwait(false);
// Had a page of results. Try to get another page after we've displayed this set.
return true;
}
......
......@@ -2,6 +2,7 @@
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
......@@ -10,7 +11,7 @@
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.Shared.Utilities;
namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
......@@ -21,21 +22,21 @@ namespace Microsoft.CodeAnalysis.Editor.FindUsages
/// </summary>
internal interface IFindSymbolMonikerUsagesService : IWorkspaceService
{
Task<ImmutableArray<ExternalReferenceItem>> FindReferencesByMonikerAsync(DefinitionItem definition, ImmutableArray<SymbolMoniker> monikers, int page, CancellationToken cancellationToken);
Task<ImmutableArray<DefinitionItem>> FindDefinitionsByMonikerAsync(SymbolMoniker moniker, int page, CancellationToken cancellationToken);
Task<ImmutableArray<DefinitionItem>> FindImplementationsByMonikerAsync(SymbolMoniker moniker, int page, CancellationToken cancellationToken);
IAsyncEnumerable<ExternalReferenceItem> FindReferencesByMoniker(DefinitionItem definition, ImmutableArray<SymbolMoniker> monikers, IStreamingProgressTracker progress, CancellationToken cancellationToken);
IAsyncEnumerable<DefinitionItem> FindDefinitionsByMoniker(SymbolMoniker moniker, IStreamingProgressTracker progress, CancellationToken cancellationToken);
IAsyncEnumerable<DefinitionItem> FindImplementationsByMoniker(SymbolMoniker moniker, IStreamingProgressTracker progress, CancellationToken cancellationToken);
}
internal abstract class AbstractFindSymbolMonikerUsagesService : IFindSymbolMonikerUsagesService
{
public virtual Task<ImmutableArray<DefinitionItem>> FindDefinitionsByMonikerAsync(SymbolMoniker moniker, int page, CancellationToken cancellationToken)
=> SpecializedTasks.EmptyImmutableArray<DefinitionItem>();
public virtual IAsyncEnumerable<DefinitionItem> FindDefinitionsByMoniker(SymbolMoniker moniker, IStreamingProgressTracker progress, CancellationToken cancellationToken)
=> EmptyAsyncEnumerable<DefinitionItem>.Instance;
public virtual Task<ImmutableArray<DefinitionItem>> FindImplementationsByMonikerAsync(SymbolMoniker moniker, int page, CancellationToken cancellationToken)
=> SpecializedTasks.EmptyImmutableArray<DefinitionItem>();
public virtual IAsyncEnumerable<DefinitionItem> FindImplementationsByMoniker(SymbolMoniker moniker, IStreamingProgressTracker progress, CancellationToken cancellationToken)
=> EmptyAsyncEnumerable<DefinitionItem>.Instance;
public virtual Task<ImmutableArray<ExternalReferenceItem>> FindReferencesByMonikerAsync(DefinitionItem definition, ImmutableArray<SymbolMoniker> monikers, int page, CancellationToken cancellationToken)
=> SpecializedTasks.EmptyImmutableArray<ExternalReferenceItem>();
public virtual IAsyncEnumerable<ExternalReferenceItem> FindReferencesByMoniker(DefinitionItem definition, ImmutableArray<SymbolMoniker> monikers, IStreamingProgressTracker progress, CancellationToken cancellationToken)
=> EmptyAsyncEnumerable<ExternalReferenceItem>.Instance;
}
[ExportWorkspaceService(typeof(IFindSymbolMonikerUsagesService)), Shared]
......@@ -46,4 +47,33 @@ public DefaultFindSymbolMonikerUsagesService()
{
}
}
internal class EmptyAsyncEnumerable<T> : IAsyncEnumerable<T>
{
public static readonly IAsyncEnumerable<T> Instance = new EmptyAsyncEnumerable<T>();
private EmptyAsyncEnumerable()
{
}
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
=> EmptyAsyncEnumerator<T>.Instance;
}
internal class EmptyAsyncEnumerator<T> : IAsyncEnumerator<T>
{
public static readonly IAsyncEnumerator<T> Instance = new EmptyAsyncEnumerator<T>();
private EmptyAsyncEnumerator()
{
}
public T Current => default;
public ValueTask DisposeAsync()
=> new ValueTask();
public ValueTask<bool> MoveNextAsync()
=> new ValueTask<bool>(false);
}
}
......@@ -37,6 +37,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.Elfie" Version="$(MicrosoftCodeAnalysisElfieVersion)" />
<PackageReference Include="Microsoft.VisualStudio.SDK.EmbedInteropTypes" Version="$(MicrosoftVisualStudioSDKEmbedInteropTypesVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonVersion)" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="$(MicrosoftBclAsyncInterfacesVersion)" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.EditorFeatures" />
......
......@@ -8,8 +8,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
......@@ -18,6 +17,7 @@
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Utilities;
using VS.IntelliNav.Contracts;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.FindUsages
......@@ -34,22 +34,57 @@ internal class VisualStudioFindSymbolMonikerUsagesService : AbstractFindSymbolMo
_codeIndexProvider = codeIndexProvider;
}
public override async Task<ImmutableArray<ExternalReferenceItem>> FindReferencesByMonikerAsync(
public override async IAsyncEnumerable<ExternalReferenceItem> FindReferencesByMoniker(
DefinitionItem definition, ImmutableArray<SymbolMoniker> monikers,
int page, CancellationToken cancellationToken)
IStreamingProgressTracker progress, [EnumeratorCancellation] CancellationToken cancellationToken)
{
if (_codeIndexProvider == null)
return await base.FindReferencesByMonikerAsync(definition, monikers, page, cancellationToken).ConfigureAwait(false);
var results = await _codeIndexProvider.FindReferencesByMonikerAsync(
ConvertMonikers(monikers), includeDecleration: false, pageIndex: page, cancellationToken: cancellationToken).ConfigureAwait(false);
using var _ = ArrayBuilder<ExternalReferenceItem>.GetInstance(out var referenceItems);
foreach (var result in results)
referenceItems.Add(ConvertResult(definition, result));
yield break;
var convertedMonikers = ConvertMonikers(monikers);
var currentPage = 0;
while (true)
{
var referenceItems = await FindReferencesByMonikerAsync(
_codeIndexProvider, definition, convertedMonikers, progress, currentPage, cancellationToken).ConfigureAwait(false);
// If we got no items, we're done.
if (referenceItems.Length == 0)
break;
foreach (var item in referenceItems)
yield return item;
// Otherwise, we got some items. Return them to our caller and attempt to retrieve
// another page.
currentPage++;
}
}
return referenceItems.ToImmutable();
private async Task<ImmutableArray<ExternalReferenceItem>> FindReferencesByMonikerAsync(
ICodeIndexProvider codeIndexProvider, DefinitionItem definition, ImmutableArray<ISymbolMoniker> monikers,
IStreamingProgressTracker progress, int pageIndex, CancellationToken cancellationToken)
{
try
{
// Let the find-refs window know we have outstanding work
await progress.AddItemsAsync(1).ConfigureAwait(false);
var results = await codeIndexProvider.FindReferencesByMonikerAsync(
monikers, includeDecleration: false, pageIndex: pageIndex, cancellationToken: cancellationToken).ConfigureAwait(false);
using var _ = ArrayBuilder<ExternalReferenceItem>.GetInstance(out var referenceItems);
foreach (var result in results)
referenceItems.Add(ConvertResult(definition, result));
return referenceItems.ToImmutable();
}
finally
{
// Mark that our async work is done.
await progress.ItemCompletedAsync().ConfigureAwait(false);
}
}
private ExternalReferenceItem ConvertResult(DefinitionItem definition, string result)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册