-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add helper for common pattern of producing an array. #73336
Conversation
src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionBatchFixAllProvider.cs
Show resolved
Hide resolved
@@ -101,7 +102,7 @@ private static void ClearCachedData() | |||
ImmutableArray<DocumentKey> priorityDocumentKeys, | |||
string searchPattern, | |||
IImmutableSet<string> kinds, | |||
Func<ImmutableArray<RoslynNavigateToItem>, VoidResult, CancellationToken, Task> onItemsFound, | |||
Func<IAsyncEnumerable<RoslynNavigateToItem>, VoidResult, CancellationToken, Task> onItemsFound, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i was getting into overload explosion. So i changes a lot of hte core helpers to be all IAsyncEnumerable based
await foreach (var (docId, nodeOrText) in results) | ||
docIdToNewRootOrText[docId] = nodeOrText; | ||
|
||
return docIdToNewRootOrText; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of neeing this to be on the outsdie, captured in 'args', we now just allow consumeItems to create a final value which is the value of the entire producer/consumer operation.
@@ -82,27 +82,27 @@ public abstract class DiagnosticProvider | |||
return ImmutableDictionary.CreateRange([KeyValuePairUtil.Create(project, diagnostics)]); | |||
|
|||
case FixAllScope.Solution: | |||
var projectsAndDiagnostics = ImmutableDictionary.CreateBuilder<Project, ImmutableArray<Diagnostic>>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above, this moves into consumeItems now.
src/Workspaces/Core/Portable/CodeFixesAndRefactorings/DocumentBasedFixAllProviderHelpers.cs
Show resolved
Hide resolved
@@ -94,12 +94,10 @@ public sealed override IEnumerable<FixAllScope> GetSupportedFixAllScopes() | |||
|
|||
using var _1 = progressTracker.ItemCompletedScope(); | |||
|
|||
var docIdToNewRootOrText = new Dictionary<DocumentId, (SyntaxNode? node, SourceText? text)>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved inside consumeItems.
args: (source, produceItems, consumeItems, args), | ||
cancellationToken); | ||
// Bridge to sibling helper that operates on an IAsyncEnumerable. | ||
return RunParallelAsync(source.AsAsyncEnumerable(), produceItems, consumeItems, args, cancellationToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was able to get several overloads to be much simpler by having the iAsyncEnumerable forms be the primary ones, and the IEnumerable forms just trivially defer to that.
consumeItems: static async (items, args, cancellationToken) => | ||
{ | ||
await args.consumeItems(items, args.args, cancellationToken).ConfigureAwait(false); | ||
return default(VoidResult); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similarly, the Task based mthods work by deferring to the Task version, using VoidResult as the ignored type arg.
// Bridge to sibling helper that takes a consumeItems that returns a value. | ||
return RunAsync( | ||
options, | ||
produceItems: static (callback, args, cancellationToken) => args.produceItems(callback, args.args, cancellationToken), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. Notice the args.args
part. The two delegates have definite different shapes.
ReadFromChannelAndConsumeItemsAsync()).ConfigureAwait(false); | ||
var writeTask = ProduceItemsAndWriteToChannelAsync(); | ||
var readTask = ReadFromChannelAndConsumeItemsAsync(); | ||
await Task.WhenAll(writeTask, readTask).ConfigureAwait(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tecahnically we don't even need to await 'writeTask'. we could just return 'readTask'. but i like the clarity of this WhenAll :)
return await RunParallelAsync( | ||
source, | ||
produceItems: static (item, callback, args, cancellationToken) => args.produceItems(item, callback, args.args, cancellationToken), | ||
consumeItems: static (stream, args, cancellationToken) => stream.ToImmutableArrayAsync(cancellationToken), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasonmalinowski For review when you get back. |
No description provided.