Allow to apply code fix in top-level statements

This commit is contained in:
Gérald Barré 2023-02-19 15:03:45 -05:00 committed by Phil Scott
parent 819b948e78
commit 955fe07bac
4 changed files with 45 additions and 10 deletions

View File

@ -69,8 +69,8 @@ public class SwitchToAnsiConsoleAction : CodeAction
{
return _originalInvocation
.Ancestors().OfType<MethodDeclarationSyntax>()
.First()
.ParameterList.Parameters
.FirstOrDefault()
?.ParameterList.Parameters
.FirstOrDefault(i => i.Type?.NormalizeWhitespace()?.ToString() == "IAnsiConsole")
?.Identifier.Text;
}
@ -79,12 +79,19 @@ public class SwitchToAnsiConsoleAction : CodeAction
{
// let's look to see if our call is in a static method.
// if so we'll only want to look for static IAnsiConsoles
// and vice-versa if we aren't.
// and vice-versa if we aren't.
// If there is no parent method, the SyntaxNode should be in
// a top-level statement, so there is no field anyway.
var isStatic = _originalInvocation
.Ancestors()
.OfType<MethodDeclarationSyntax>()
.First()
.Modifiers.Any(i => i.IsKind(SyntaxKind.StaticKeyword));
.FirstOrDefault()
?.Modifiers.Any(i => i.IsKind(SyntaxKind.StaticKeyword));
if (isStatic == null)
{
return null;
}
return _originalInvocation
.Ancestors().OfType<ClassDeclarationSyntax>()
@ -93,7 +100,7 @@ public class SwitchToAnsiConsoleAction : CodeAction
.OfType<FieldDeclarationSyntax>()
.FirstOrDefault(i =>
i.Declaration.Type.NormalizeWhitespace().ToString() == "IAnsiConsole" &&
(!isStatic ^ i.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.StaticKeyword))))
(!isStatic.GetValueOrDefault() ^ i.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.StaticKeyword))))
?.Declaration.Variables.First().Identifier.Text;
}

View File

@ -20,7 +20,7 @@ public class StaticAnsiConsoleToInstanceFix : CodeFixProvider
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
if (root != null)
{
var methodDeclaration = root.FindNode(context.Span).FirstAncestorOrSelf<InvocationExpressionSyntax>();
var methodDeclaration = root.FindNode(context.Span, getInnermostNodeForTie: true).FirstAncestorOrSelf<InvocationExpressionSyntax>();
if (methodDeclaration != null)
{
context.RegisterCodeFix(

View File

@ -4,13 +4,20 @@ public static class SpectreAnalyzerVerifier<TAnalyzer>
where TAnalyzer : DiagnosticAnalyzer, new()
{
public static Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource)
=> VerifyCodeFixAsync(source, new[] { expected }, fixedSource);
=> VerifyCodeFixAsync(source, OutputKind.DynamicallyLinkedLibrary, new[] { expected }, fixedSource);
public static Task VerifyCodeFixAsync(string source, OutputKind outputKind, DiagnosticResult expected, string fixedSource)
=> VerifyCodeFixAsync(source, outputKind, new[] { expected }, fixedSource);
private static Task VerifyCodeFixAsync(string source, IEnumerable<DiagnosticResult> expected, string fixedSource)
private static Task VerifyCodeFixAsync(string source, OutputKind outputKind, IEnumerable<DiagnosticResult> expected, string fixedSource)
{
var test = new Test
{
TestCode = source,
TestCode = source,
TestState =
{
OutputKind = outputKind,
},
FixedCode = fixedSource,
};

View File

@ -139,4 +139,25 @@ class TestClass
.VerifyCodeFixAsync(Source, _expectedDiagnostic.WithLocation(11, 9), FixedSource)
.ConfigureAwait(false);
}
[Fact]
public async Task SystemConsole_replaced_with_AnsiConsole_in_top_level_statements()
{
const string Source = @"
using System;
Console.WriteLine(""Hello, World"");
";
const string FixedSource = @"
using System;
using Spectre.Console;
AnsiConsole.WriteLine(""Hello, World"");
";
await SpectreAnalyzerVerifier<UseSpectreInsteadOfSystemConsoleAnalyzer>
.VerifyCodeFixAsync(Source, OutputKind.ConsoleApplication, _expectedDiagnostic.WithLocation(4, 1), FixedSource)
.ConfigureAwait(false);
}
}