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

Switch to IAsyncEnumerable

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