-
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 support for async lightbulb model. #53117
Merged
CyrusNajmabadi
merged 68 commits into
dotnet:main-vs-deps
from
CyrusNajmabadi:asyncLightbulb
Jun 29, 2021
Merged
Changes from all commits
Commits
Show all changes
68 commits
Select commit
Hold shift + click to select a range
bd67d0b
Initial stubs for async lightbulbs
CyrusNajmabadi 25b6bba
Add parameter
CyrusNajmabadi 5e4b103
Thread through priority information
CyrusNajmabadi b5ad99f
Thread through value.
CyrusNajmabadi 60b9671
Fallout
CyrusNajmabadi 183333d
Add docs
CyrusNajmabadi 4d32a88
Add flag
CyrusNajmabadi e1b9a30
warning
CyrusNajmabadi 1122406
Simplify logic
CyrusNajmabadi df499e8
use a different code
CyrusNajmabadi 187ae22
Move down into the executor
CyrusNajmabadi a0e9b9f
Run high and low priority each after the other.
CyrusNajmabadi 6003f2c
move down
CyrusNajmabadi ed9bf08
Push down
CyrusNajmabadi 8477a12
temp
CyrusNajmabadi cb1a318
Simplify suggested action computation.
CyrusNajmabadi a2ba308
Simplify
CyrusNajmabadi 34642f4
PRoduce results as soon as we have them
CyrusNajmabadi c0b4244
Switch to valuetask
CyrusNajmabadi b4834c9
fallout
CyrusNajmabadi ea93f62
restore
CyrusNajmabadi 79765d6
Remove
CyrusNajmabadi f95e48b
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 57765be
Merge branch 'main-vs-deps' into asyncLightbulb
CyrusNajmabadi 56d51e0
Roll back to the previous model
CyrusNajmabadi 89f3187
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi c10ab09
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 4b735b5
Update version
CyrusNajmabadi ad1c39a
Merge remote-tracking branch 'upstream/main' into asyncLightbulb
CyrusNajmabadi 5651d97
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 397154a
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 505c91f
Update version
CyrusNajmabadi 27a15e6
Update version
CyrusNajmabadi 0825ee7
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 6403b5e
Update version
CyrusNajmabadi 3f5d239
Fix
CyrusNajmabadi 5ff2685
Move to an enum
CyrusNajmabadi 188be8f
Add docs
CyrusNajmabadi 4aa0237
Move new code into new files
CyrusNajmabadi 677099f
Wrap
CyrusNajmabadi 1d8249a
REvert
CyrusNajmabadi 6475254
Make sync
CyrusNajmabadi dd8e145
Fix
CyrusNajmabadi 63320d4
Revert
CyrusNajmabadi 726bec2
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 3062206
No alloc
CyrusNajmabadi 00ea3f0
Simplify
CyrusNajmabadi 4e3524b
Update src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixP…
CyrusNajmabadi fe96d77
Update src/Workspaces/Core/Portable/CodeActions/CodeActionPriority.cs
CyrusNajmabadi 3423ad9
Update src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionSource_…
CyrusNajmabadi 8ab7971
Update src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionSource_…
CyrusNajmabadi c2b1f61
Simplify
CyrusNajmabadi ddcf0b0
Simplify
CyrusNajmabadi cb1d5bd
Merge branch 'asyncLightbulb' of https://github.com/CyrusNajmabadi/ro…
CyrusNajmabadi 1d59ca0
Simplify
CyrusNajmabadi 8a7679f
Simplify
CyrusNajmabadi e626d4b
Rename type
CyrusNajmabadi e0ca75c
Move away from a bool
CyrusNajmabadi c81e9d6
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi adfeb29
SImplify
CyrusNajmabadi 2afda3c
Comments
CyrusNajmabadi 249c808
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 58df3bc
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi 7011bab
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi ffe832e
Add option
CyrusNajmabadi 75b96cb
Update version
CyrusNajmabadi d3a74c3
Rename string
CyrusNajmabadi b7359c6
Merge remote-tracking branch 'upstream/main-vs-deps' into asyncLightbulb
CyrusNajmabadi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// 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; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.CodeActions; | ||
using Microsoft.CodeAnalysis.Editor.Shared; | ||
using Microsoft.CodeAnalysis.Editor.Shared.Utilities; | ||
using Microsoft.CodeAnalysis.Host; | ||
using Microsoft.CodeAnalysis.Internal.Log; | ||
using Microsoft.CodeAnalysis.Text; | ||
using Microsoft.CodeAnalysis.UnifiedSuggestions; | ||
using Microsoft.VisualStudio.Language.Intellisense; | ||
using Microsoft.VisualStudio.Text; | ||
using Microsoft.VisualStudio.Text.Editor; | ||
using Roslyn.Utilities; | ||
|
||
namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions | ||
{ | ||
internal partial class SuggestedActionsSourceProvider | ||
{ | ||
private partial class AsyncSuggestedActionsSource : SuggestedActionsSource, ISuggestedActionsSourceExperimental | ||
{ | ||
public AsyncSuggestedActionsSource( | ||
IThreadingContext threadingContext, | ||
SuggestedActionsSourceProvider owner, | ||
ITextView textView, | ||
ITextBuffer textBuffer, | ||
ISuggestedActionCategoryRegistryService suggestedActionCategoryRegistry) | ||
: base(threadingContext, owner, textView, textBuffer, suggestedActionCategoryRegistry) | ||
{ | ||
} | ||
|
||
public async IAsyncEnumerable<SuggestedActionSet> GetSuggestedActionsAsync( | ||
ISuggestedActionCategorySet requestedActionCategories, | ||
SnapshotSpan range, | ||
[EnumeratorCancellation] CancellationToken cancellationToken) | ||
{ | ||
AssertIsForeground(); | ||
|
||
using var state = SourceState.TryAddReference(); | ||
if (state is null) | ||
yield break; | ||
|
||
var workspace = state.Target.Workspace; | ||
if (workspace is null) | ||
yield break; | ||
|
||
var selection = TryGetCodeRefactoringSelection(state, range); | ||
await workspace.Services.GetRequiredService<IWorkspaceStatusService>().WaitUntilFullyLoadedAsync(cancellationToken).ConfigureAwait(false); | ||
|
||
using (Logger.LogBlock(FunctionId.SuggestedActions_GetSuggestedActionsAsync, cancellationToken)) | ||
{ | ||
var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); | ||
if (document is null) | ||
yield break; | ||
|
||
// Compute and return the high pri set of fixes and refactorings first so the user | ||
// can act on them immediately without waiting on the regular set. | ||
var highPriSet = GetCodeFixesAndRefactoringsAsync( | ||
state, requestedActionCategories, document, range, selection, _ => null, | ||
CodeActionRequestPriority.High, cancellationToken).WithCancellation(cancellationToken).ConfigureAwait(false); | ||
await foreach (var set in highPriSet) | ||
yield return set; | ||
|
||
var lowPriSet = GetCodeFixesAndRefactoringsAsync( | ||
state, requestedActionCategories, document, range, selection, _ => null, | ||
CodeActionRequestPriority.Normal, cancellationToken).WithCancellation(cancellationToken).ConfigureAwait(false); | ||
await foreach (var set in lowPriSet) | ||
yield return set; | ||
} | ||
} | ||
|
||
private async IAsyncEnumerable<SuggestedActionSet> GetCodeFixesAndRefactoringsAsync( | ||
ReferenceCountedDisposable<State> state, | ||
ISuggestedActionCategorySet requestedActionCategories, | ||
Document document, | ||
SnapshotSpan range, | ||
TextSpan? selection, | ||
Func<string, IDisposable?> addOperationScope, | ||
CodeActionRequestPriority priority, | ||
[EnumeratorCancellation] CancellationToken cancellationToken) | ||
{ | ||
var workspace = document.Project.Solution.Workspace; | ||
var supportsFeatureService = workspace.Services.GetRequiredService<ITextBufferSupportsFeatureService>(); | ||
|
||
var fixesTask = GetCodeFixesAsync( | ||
state, supportsFeatureService, requestedActionCategories, workspace, document, range, | ||
addOperationScope, priority, isBlocking: false, cancellationToken); | ||
var refactoringsTask = GetRefactoringsAsync( | ||
state, supportsFeatureService, requestedActionCategories, workspace, document, selection, | ||
addOperationScope, priority, isBlocking: false, cancellationToken); | ||
|
||
if (priority == CodeActionRequestPriority.High) | ||
{ | ||
// in a high pri scenario, return data as soon as possible so that the user can interact with them. | ||
// this is especially important for state-machine oriented refactorings (like rename) where the user | ||
// should always have access to them effectively synchronously. | ||
var firstTask = await Task.WhenAny(fixesTask, refactoringsTask).ConfigureAwait(false); | ||
var secondTask = firstTask == fixesTask ? refactoringsTask : fixesTask; | ||
|
||
var orderedTasks = new[] { firstTask, secondTask }; | ||
foreach (var task in orderedTasks) | ||
{ | ||
if (task == fixesTask) | ||
{ | ||
var fixes = await fixesTask.ConfigureAwait(false); | ||
foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes, ImmutableArray<UnifiedSuggestedActionSet>.Empty)) | ||
yield return set; | ||
} | ||
else | ||
{ | ||
Contract.ThrowIfFalse(task == refactoringsTask); | ||
|
||
var refactorings = await refactoringsTask.ConfigureAwait(false); | ||
foreach (var set in ConvertToSuggestedActionSets(state, selection, ImmutableArray<UnifiedSuggestedActionSet>.Empty, refactorings)) | ||
yield return set; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
var actionsArray = await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false); | ||
foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: actionsArray[0], refactorings: actionsArray[1])) | ||
yield return set; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Not to get into a bikeshedding argument here, but whats the thinking around whether there are high or normal? For example "Remove unused usings" only triggers from one spot in a document so would seem to me to be a decent candidate for high priority.
Perhaps its worth documenting some guidelines on the enum (if they're not already there.. haven't got that far yet)
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.
Effectively, everything that previously produced a 'high pri code action' is in the 'high pri request' category. Anything that produces a normal/low pri code action is in the normal request category. I didn't want to change anything in that regard here. Right now we've had a long historical precedent of recognizing two code actions (one analzyer, one refactoring) that are so important that they should beat out everything else. This PR codifies things so that not only do those come first, they are computed first so we can display them asap for the user.