Skip to content

Commit

Permalink
Simplify logic for lightbulb priority classes
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi committed Mar 29, 2023
1 parent 7033bb2 commit 415d510
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,29 @@ private static void RegisterCodeFixes(
var secondMiddlePos = secondMiddleLine.Start;
var endPos = endLine.Start;

#if !CODE_STYLE

context.RegisterCodeFix(
CodeAction.DocumentChangeAction.Create(takeTopText,
c => TakeTopAsync(document, startPos, firstMiddlePos, secondMiddlePos, endPos, c),
TakeTopEquivalenceKey,
CodeActionPriority.High),
context.Diagnostics);
context.RegisterCodeFix(
CodeAction.DocumentChangeAction.Create(takeBottomText,
c => TakeBottomAsync(document, startPos, firstMiddlePos, secondMiddlePos, endPos, c),
TakeBottomEquivalenceKey,
CodeActionPriority.High),
context.Diagnostics);
context.RegisterCodeFix(
CodeAction.DocumentChangeAction.Create(CodeFixesResources.Take_both,
c => TakeBothAsync(document, startPos, firstMiddlePos, secondMiddlePos, endPos, c),
TakeBothEquivalenceKey,
CodeActionPriority.High),
context.Diagnostics);

#else

context.RegisterCodeFix(
CodeAction.Create(takeTopText,
c => TakeTopAsync(document, startPos, firstMiddlePos, secondMiddlePos, endPos, c),
Expand All @@ -295,6 +318,8 @@ private static void RegisterCodeFixes(
c => TakeBothAsync(document, startPos, firstMiddlePos, secondMiddlePos, endPos, c),
TakeBothEquivalenceKey),
context.Diagnostics);

#endif
}

private static async Task<Document> AddEditsAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions
[DeferCreation(OptionName = EditorOption.OptionName)]
[Name("Roslyn Code Fix")]
[Order]
[SuggestedActionPriority(DefaultOrderings.Highest)]
[SuggestedActionPriority(DefaultOrderings.Default)]
[SuggestedActionPriority(DefaultOrderings.Lowest)]
[SuggestedActionPriority(DefaultOrderings.Highest)] // for providers *and* items explicitly marked as high pri.
[SuggestedActionPriority(DefaultOrderings.Default)] // for any provider/item that is neither high or low pri and is not suppressions.
[SuggestedActionPriority(DefaultOrderings.Low)] // for providers or items explicitly marked as low pri
[SuggestedActionPriority(DefaultOrderings.Lowest)] // Only for suppressions
internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceProvider
{
public static readonly ImmutableArray<string> Orderings = ImmutableArray.Create(
DefaultOrderings.Highest,
DefaultOrderings.Default,
DefaultOrderings.Low,
DefaultOrderings.Lowest);

private static readonly Guid s_CSharpSourceGuid = new Guid("b967fea8-e2c3-4984-87d4-71a38f49e16a");
Expand Down Expand Up @@ -104,8 +106,9 @@ public SuggestedActionsSourceProvider(
{
DefaultOrderings.Highest => CodeActionRequestPriority.High,
DefaultOrderings.Default => CodeActionRequestPriority.Normal,
DefaultOrderings.Low => CodeActionRequestPriority.Low,
DefaultOrderings.Lowest => CodeActionRequestPriority.Lowest,
_ => (CodeActionRequestPriority?)null,
_ => null,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,29 +96,25 @@ private async Task GetSuggestedActionsWorkerAsync(
// items should be pushed higher up, and less important items shouldn't take up that much space.
var currentActionCount = 0;

using var _2 = ArrayBuilder<SuggestedActionSet>.GetInstance(out var lowPrioritySets);
var pendingActionSets = new MultiDictionary<CodeActionRequestPriority, SuggestedActionSet>();

// Collectors are in priority order. So just walk them from highest to lowest.
foreach (var collector in collectors)
{
var priority = TryGetPriority(collector.Priority);

if (priority != null)
if (TryGetPriority(collector.Priority) is CodeActionRequestPriority priority)
{
var allSets = GetCodeFixesAndRefactoringsAsync(
state, requestedActionCategories, document,
range, selection,
addOperationScope: _ => null,
priority.Value,
priority,
currentActionCount, cancellationToken).WithCancellation(cancellationToken).ConfigureAwait(false);

await foreach (var set in allSets)
{
if (priority == CodeActionRequestPriority.High && set.Priority == SuggestedActionSetPriority.Low)
if (ShouldPendActionSet(priority, set.Priority, out var pendTo))
{
// if we're processing the high pri bucket, but we get action sets for lower pri
// groups, then keep track of them and add them in later when we get to that group.
lowPrioritySets.Add(set);
pendingActionSets.Add(pendTo, set);
}
else
{
Expand All @@ -127,14 +123,10 @@ private async Task GetSuggestedActionsWorkerAsync(
}
}

if (priority == CodeActionRequestPriority.Normal)
foreach (var set in pendingActionSets[priority])
{
// now, add any low pri items we've been waiting on to the final group.
foreach (var set in lowPrioritySets)
{
currentActionCount += set.Actions.Count();
collector.Add(set);
}
currentActionCount += set.Actions.Count();
collector.Add(set);
}
}

Expand All @@ -145,6 +137,36 @@ private async Task GetSuggestedActionsWorkerAsync(
completedCollectors.Add(collector);
}
}

return;

static bool ShouldPendActionSet(
CodeActionRequestPriority requestPriority,
SuggestedActionSetPriority setPriority,
out CodeActionRequestPriority pendTo)
{
var actualPriorityDeterminedBySet = setPriority switch
{
SuggestedActionSetPriority.None => CodeActionRequestPriority.Lowest,
SuggestedActionSetPriority.Low => CodeActionRequestPriority.Low,
SuggestedActionSetPriority.Medium => CodeActionRequestPriority.Normal,
SuggestedActionSetPriority.High => CodeActionRequestPriority.High,
_ => throw ExceptionUtilities.UnexpectedValue(setPriority),
};

if (actualPriorityDeterminedBySet < requestPriority)
{
// We got a result that is lower pri than what we asked for. This should go in a later bucket
// when the lightbulb gets around to it.
pendTo = actualPriorityDeterminedBySet;
return true;
}

// We got a result that either goes with our current priority class, or is even higher than what
// we asked for. We def want to add this now.
pendTo = default;
return false;
}
}

private async IAsyncEnumerable<SuggestedActionSet> GetCodeFixesAndRefactoringsAsync(
Expand Down

0 comments on commit 415d510

Please sign in to comment.