From 1262b16f593352ef82f5d085e788cebf24bfbcb7 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Sat, 6 Nov 2021 09:27:19 +1100 Subject: [PATCH] Don't crash Use ExpressionBody on local functions in top level statements (#57571) --- .../UseExpressionBodyCodeFixProvider.cs | 3 +- ...ssionBodyForLocalFunctionsAnalyzerTests.cs | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/Analyzers/CSharp/CodeFixes/UseExpressionBody/UseExpressionBodyCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseExpressionBody/UseExpressionBodyCodeFixProvider.cs index 10f7e8738ac58..eee0034fba488 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseExpressionBody/UseExpressionBodyCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseExpressionBody/UseExpressionBodyCodeFixProvider.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -90,7 +89,7 @@ private static void AddEdits( { var declarationLocation = diagnostic.AdditionalLocations[0]; var helper = _helpers.Single(h => h.DiagnosticId == diagnostic.Id); - var declaration = declarationLocation.FindNode(cancellationToken); + var declaration = declarationLocation.FindNode(getInnermostNodeForTie: true, cancellationToken); var useExpressionBody = diagnostic.Properties.ContainsKey(nameof(UseExpressionBody)); var updatedDeclaration = helper.Update(semanticModel, declaration, useExpressionBody) diff --git a/src/Analyzers/CSharp/Tests/UseExpressionBody/UseExpressionBodyForLocalFunctionsAnalyzerTests.cs b/src/Analyzers/CSharp/Tests/UseExpressionBody/UseExpressionBodyForLocalFunctionsAnalyzerTests.cs index 2ae402fdc5b2e..f0667646dd8fb 100644 --- a/src/Analyzers/CSharp/Tests/UseExpressionBody/UseExpressionBodyForLocalFunctionsAnalyzerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseExpressionBody/UseExpressionBodyForLocalFunctionsAnalyzerTests.cs @@ -4,11 +4,13 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Testing; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody @@ -829,5 +831,70 @@ void Bar() }"; await TestWithUseExpressionBody(code, fixedCode); } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + [WorkItem(57570, "https://github.com/dotnet/roslyn/issues/57570")] + public async Task TestUseExpressionBodyTopLevelStatment() + { + await new VerifyCS.Test + { + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + Sources = + { + @" +{|IDE0061:int Bar(int x) +{ + return x; +}|} +" + }, + }, + FixedState = + { + Sources = + { + @" +int Bar(int x) => x; +" + }, + }, + LanguageVersion = LanguageVersion.CSharp9, + Options = { { CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, ExpressionBodyPreference.WhenPossible } }, + }.RunAsync(); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + [WorkItem(57570, "https://github.com/dotnet/roslyn/issues/57570")] + public async Task TestUseBlockBodyTopLevelStatment() + { + await new VerifyCS.Test + { + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + Sources = + { + @" +{|IDE0061:int Bar(int x) => x;|} +" + }, + }, + FixedState = + { + Sources = + { + @" +int Bar(int x) +{ + return x; +}" + }, + }, + LanguageVersion = LanguageVersion.CSharp9, + Options = { { CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, ExpressionBodyPreference.Never } }, + }.RunAsync(); + } } }