-
Notifications
You must be signed in to change notification settings - Fork 4.3k
[Sonic] Support multiple C# documents in code actions #84203
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
Changes from all commits
af412e1
1abce2d
b2e620d
1ccc101
5a4d5fb
8acbfb4
610b163
f5b8799
898a90d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System; | ||
| using System.Collections.Frozen; | ||
| using System.Collections.Generic; | ||
| using System.Collections.Immutable; | ||
| using System.Composition; | ||
|
|
@@ -29,8 +30,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.CodeActions; | |
| [Export(typeof(ICSharpCodeActionProvider)), Shared] | ||
| internal sealed class TypeAccessibilityCodeActionProvider : ICSharpCodeActionProvider | ||
| { | ||
| private static readonly IEnumerable<string> s_supportedDiagnostics = new[] | ||
| { | ||
| private static readonly FrozenSet<string> s_supportedDiagnostics = FrozenSet.Create(StringComparer.OrdinalIgnoreCase, [ | ||
| // `The type or namespace name 'type/namespace' could not be found | ||
| // (are you missing a using directive or an assembly reference?)` | ||
| // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0246 | ||
|
|
@@ -42,7 +42,7 @@ internal sealed class TypeAccessibilityCodeActionProvider : ICSharpCodeActionPro | |
|
|
||
| // `The name 'identifier' does not exist in the current context` | ||
| "IDE1007" | ||
| }; | ||
| ]); | ||
|
|
||
| public Task<ImmutableArray<RazorVSInternalCodeAction>> ProvideAsync( | ||
| RazorCodeActionContext context, | ||
|
|
@@ -74,7 +74,7 @@ private static ImmutableArray<RazorVSInternalCodeAction> ProcessCodeActionsVSCod | |
| var diagnostics = context.Request.Context.Diagnostics.Where(diagnostic => | ||
| diagnostic is { Severity: LspDiagnosticSeverity.Error, Code: { } code } && | ||
| code.TryGetSecond(out var str) && | ||
| s_supportedDiagnostics.Any(d => str.Equals(d, StringComparison.OrdinalIgnoreCase))); | ||
| s_supportedDiagnostics.Contains(str)); | ||
|
|
||
| if (diagnostics is null || !diagnostics.Any()) | ||
| { | ||
|
|
@@ -163,50 +163,29 @@ private static ImmutableArray<RazorVSInternalCodeAction> ProcessCodeActionsVS( | |
|
|
||
| foreach (var codeAction in codeActions) | ||
| { | ||
| // For fully qualify, we just want to filter out single line expressions as the formatter doesn't support them and will | ||
| // drop the edits | ||
| if (codeAction.Name is not null && codeAction.Name.Equals(PredefinedCodeFixProviderNames.FullyQualify, StringComparison.Ordinal)) | ||
| { | ||
| string action; | ||
|
|
||
| if (!TryGetOwner(context, out var owner)) | ||
| { | ||
| // Failed to locate a valid owner for the light bulb | ||
| continue; | ||
| } | ||
| else if (IsSingleLineDirectiveNode(owner)) | ||
| { | ||
| // Don't support single line directives | ||
| continue; | ||
| } | ||
| else if (IsExplicitExpressionNode(owner)) | ||
| if (TryGetOwner(context, out var owner) && | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, this was deliberate on my part. My thinking was that previously we needed the the owner to filter out a number of scenarios because what we supported was quite narrow. Now we only care about one thing, and unless we're in that state, we let the normal system handle things, so if we can't get an owner, then we can't be in the one state we care about not offering for, so let it through. In reality I suspect owner will never be null. |
||
| IsSingleLineDirectiveNode(owner)) | ||
| { | ||
| // Don't support explicit expressions | ||
| continue; | ||
| } | ||
| else if (IsImplicitExpressionNode(owner)) | ||
| { | ||
| action = LanguageServerConstants.CodeActions.UnformattedRemap; | ||
| } | ||
| else | ||
| { | ||
| // All other scenarios we support default formatted code action behavior | ||
| action = LanguageServerConstants.CodeActions.Default; | ||
| } | ||
|
|
||
| typeAccessibilityCodeActions.Add(codeAction.WrapResolvableCodeAction(context, action)); | ||
| } | ||
| // For add using suggestions, the code action title is of the form: | ||
| // `using System.Net;` | ||
| // For add using suggestions, we make the title more Razor-idiomatic | ||
| else if (codeAction.Name is not null && codeAction.Name.Equals(PredefinedCodeFixProviderNames.AddImport, StringComparison.Ordinal) && | ||
| UsingDirectiveHelper.TryExtractNamespace(codeAction.Title, out var @namespace, out var prefix)) | ||
| { | ||
| codeAction.Title = $"{prefix}@using {@namespace}"; | ||
| typeAccessibilityCodeActions.Add(codeAction.WrapResolvableCodeAction(context, LanguageServerConstants.CodeActions.Default)); | ||
| } | ||
| // Not a type accessibility code action | ||
| else | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| // Type accessibility code actions need no special handling at edit time, so we just send them through the standard C# resolver | ||
| typeAccessibilityCodeActions.Add(codeAction.WrapResolvableCodeAction(context, LanguageServerConstants.CodeActions.Default)); | ||
| } | ||
|
|
||
| return typeAccessibilityCodeActions.ToImmutable(); | ||
|
|
@@ -229,24 +208,6 @@ static bool TryGetOwner(RazorCodeActionContext context, [NotNullWhen(true)] out | |
| return true; | ||
| } | ||
|
|
||
| static bool IsImplicitExpressionNode(SyntaxNode owner) | ||
| { | ||
| // E.g, (| is position) | ||
| // | ||
| // `@|foo` - true | ||
| // | ||
| return owner.AncestorsAndSelf().Any(n => n is CSharpImplicitExpressionSyntax); | ||
| } | ||
|
|
||
| static bool IsExplicitExpressionNode(SyntaxNode owner) | ||
| { | ||
| // E.g, (| is position) | ||
| // | ||
| // `@(|foo)` - true | ||
| // | ||
| return owner.AncestorsAndSelf().Any(n => n is CSharpExplicitExpressionBodySyntax); | ||
| } | ||
|
|
||
| static bool IsSingleLineDirectiveNode(SyntaxNode owner) | ||
| { | ||
| // E.g, (| is position) | ||
|
|
||
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.