diff --git a/src/Common/CSharp/Analysis/ConvertExpressionBodyAnalysis.cs b/src/Common/CSharp/Analysis/ConvertExpressionBodyAnalysis.cs new file mode 100644 index 0000000000..933a419c3f --- /dev/null +++ b/src/Common/CSharp/Analysis/ConvertExpressionBodyAnalysis.cs @@ -0,0 +1,24 @@ +using Microsoft.CodeAnalysis.CSharp; + +namespace Roslynator.CSharp.Analysis; + +internal static class ConvertExpressionBodyAnalysis +{ + public static bool AllowPutExpressionBodyOnItsOwnLine(SyntaxKind syntaxKind) + { + // allow putting expression on new line for all method-like declarations, except for accessors. + switch (syntaxKind) + { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.DestructorDeclaration: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.IndexerDeclaration: + case SyntaxKind.OperatorDeclaration: + case SyntaxKind.ConversionOperatorDeclaration: + return true; + default: + return false; + } + } +} diff --git a/src/Formatting.Analyzers/CSharp/PutExpressionBodyOnItsOwnLineAnalyzer.cs b/src/Formatting.Analyzers/CSharp/PutExpressionBodyOnItsOwnLineAnalyzer.cs index 2ccb453d5c..1ed6c9a7ec 100644 --- a/src/Formatting.Analyzers/CSharp/PutExpressionBodyOnItsOwnLineAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/PutExpressionBodyOnItsOwnLineAnalyzer.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Roslynator.CSharp; +using Roslynator.CSharp.Analysis; using Roslynator.CSharp.CodeStyle; namespace Roslynator.Formatting.CSharp; @@ -37,17 +38,9 @@ private static void AnalyzeArrowExpressionClause(SyntaxNodeAnalysisContext conte { var arrowExpressionClause = (ArrowExpressionClauseSyntax)context.Node; - switch (arrowExpressionClause.Parent.Kind()) + if (ConvertExpressionBodyAnalysis.AllowPutExpressionBodyOnItsOwnLine(arrowExpressionClause.Parent.Kind())) { - case SyntaxKind.MethodDeclaration: - case SyntaxKind.ConstructorDeclaration: - case SyntaxKind.DestructorDeclaration: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.IndexerDeclaration: - case SyntaxKind.OperatorDeclaration: - case SyntaxKind.ConversionOperatorDeclaration: - AnalyzeArrowExpressionClause(arrowExpressionClause.ArrowToken, context); - break; + AnalyzeArrowExpressionClause(arrowExpressionClause.ArrowToken, context); } } diff --git a/src/Tests/Analyzers.Tests/RCS1016UseExpressionBodyTests.cs b/src/Tests/Analyzers.Tests/RCS1016UseExpressionBodyTests.cs index 74d2071d90..50d044f657 100644 --- a/src/Tests/Analyzers.Tests/RCS1016UseExpressionBodyTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1016UseExpressionBodyTests.cs @@ -12,6 +12,11 @@ public class RCS1016UseExpressionBodyTests : AbstractCSharpDiagnosticVerifier M(); + + void M() { } +} +", + options: Options.AddConfigOption(ConfigOptionKeys.ArrowTokenNewLine, ConfigOptionValues.ArrowTokenNewLine_Before), + additionalDiagnostics: new DiagnosticDescriptor[] { DiagnosticRules.PutExpressionBodyOnItsOwnLine }); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -55,7 +86,7 @@ class C void M() { } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -74,7 +105,7 @@ class C { string M() => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -97,7 +128,7 @@ string M(object x, object y) => M( x, y); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -122,7 +153,7 @@ string M(object x, object y, object z) => M( y, z); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -141,7 +172,7 @@ class C { void M() => M(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -166,7 +197,7 @@ void M() string LF() => null; } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -199,7 +230,7 @@ string LF() => M( y); } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -224,7 +255,7 @@ void M() void LF() => M(); } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -243,7 +274,7 @@ class C { string P => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -273,7 +304,7 @@ class C string M(string x, string y) => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -314,7 +345,7 @@ public string P string M(string x, string y) => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -355,7 +386,7 @@ public string P string M(string x, string y) => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression).AddAllowedCompilerDiagnosticId("CS0518")); +", options: Options.AddAllowedCompilerDiagnosticId("CS0518")); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -374,7 +405,7 @@ class C { string this[int index] => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -402,7 +433,7 @@ string this[int index] set => _f = value; } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -421,7 +452,7 @@ class C { public static C operator !(C value) => value; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -440,7 +471,7 @@ class C { public static explicit operator C(string value) => new C(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -463,7 +494,7 @@ class C void M() { } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -482,7 +513,7 @@ class C { ~C() => throw new System.NotImplementedException(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -501,7 +532,7 @@ class C { string M() => throw new System.NotImplementedException(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -520,7 +551,7 @@ class C { void M() => throw new System.NotImplementedException(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -545,7 +576,7 @@ void M() string LF() => throw new System.NotImplementedException(); } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -570,7 +601,7 @@ void M() void LF() => throw new System.NotImplementedException(); } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -589,7 +620,7 @@ class C { string P => throw new System.NotImplementedException(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -617,7 +648,7 @@ public string P set => throw new System.NotImplementedException(); } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -636,7 +667,7 @@ class C { string this[int index] => throw new System.NotImplementedException(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -664,7 +695,7 @@ string this[int index] set => throw new System.NotImplementedException(); } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -683,7 +714,7 @@ class C { public static C operator !(C value) => throw new System.NotImplementedException(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -702,7 +733,7 @@ class C { public static explicit operator C(string value) => throw new System.NotImplementedException(); } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -717,7 +748,7 @@ string M() return null; } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -731,7 +762,7 @@ void M() void LF() { } } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -744,7 +775,7 @@ void M() { } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -759,7 +790,7 @@ void M() M(); } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -794,7 +825,7 @@ string P string M() => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -830,7 +861,7 @@ string P } } } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -852,7 +883,7 @@ string this[int index] string M() => null; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] @@ -901,7 +932,7 @@ public string P2 string _f; } -", options: Options.AddConfigOption(ConfigOptionKeys.BodyStyle, ConfigOptionValues.BodyStyle_Expression)); +", options: Options); } [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseBlockBodyOrExpressionBody)] diff --git a/src/Tests/Refactorings.Tests/RR0169ConvertBlockBodyToExpressionBodyTests.cs b/src/Tests/Refactorings.Tests/RR0169ConvertBlockBodyToExpressionBodyTests.cs index 1801375586..7bbadb17b5 100644 --- a/src/Tests/Refactorings.Tests/RR0169ConvertBlockBodyToExpressionBodyTests.cs +++ b/src/Tests/Refactorings.Tests/RR0169ConvertBlockBodyToExpressionBodyTests.cs @@ -18,7 +18,7 @@ class C { public C() [|{ -[||] M(); +[||] M(); }|] void M() { } @@ -33,6 +33,60 @@ void M() { } ", equivalenceKey: EquivalenceKey.Create(RefactoringId)); } + [Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.ConvertBlockBodyToExpressionBody)] + public async Task Test_Constructor_BreakBeforeArrow() + { + await VerifyRefactoringAsync(@" +class C +{ + public C() + [|{ +[||] M(); + }|] + + void M() { } +} +", @" +class C +{ + public C() + => M(); + + void M() { } +} +", + equivalenceKey: EquivalenceKey.Create(RefactoringId), + options: Options.EnableDiagnostic(DiagnosticRules.PutExpressionBodyOnItsOwnLine) + .AddConfigOption(ConfigOptionKeys.ArrowTokenNewLine, ConfigOptionValues.ArrowTokenNewLine_Before)); + } + + [Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.ConvertBlockBodyToExpressionBody)] + public async Task Test_Constructor_BreakAfterArrow() + { + await VerifyRefactoringAsync(@" +class C +{ + public C() + [|{ +[||] M(); + }|] + + void M() { } +} +", @" +class C +{ + public C() => + M(); + + void M() { } +} +", + equivalenceKey: EquivalenceKey.Create(RefactoringId), + options: Options.EnableDiagnostic(DiagnosticRules.PutExpressionBodyOnItsOwnLine) + .AddConfigOption(ConfigOptionKeys.ArrowTokenNewLine, ConfigOptionValues.ArrowTokenNewLine_After)); + } + [Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.ConvertBlockBodyToExpressionBody)] public async Task Test_Destructor() { diff --git a/src/Workspaces.Common/CSharp/Refactorings/ConvertBlockBodyToExpressionBodyRefactoring.cs b/src/Workspaces.Common/CSharp/Refactorings/ConvertBlockBodyToExpressionBodyRefactoring.cs index 1f96f8c38f..86c93487b5 100644 --- a/src/Workspaces.Common/CSharp/Refactorings/ConvertBlockBodyToExpressionBodyRefactoring.cs +++ b/src/Workspaces.Common/CSharp/Refactorings/ConvertBlockBodyToExpressionBodyRefactoring.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; using Roslynator.CSharp.Analysis; +using Roslynator.CSharp.CodeStyle; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Roslynator.CSharp.Refactorings; @@ -165,8 +166,9 @@ public static Task RefactorAsync( if (CanRefactor(member)) { AnalyzerConfigOptions configOptions = document.GetConfigOptions(selectedMembers.Parent.SyntaxTree); + bool wrapLineBeforeArrowToken = DiagnosticRules.PutExpressionBodyOnItsOwnLine.IsEffective(member.SyntaxTree, document.Project.CompilationOptions); - var newMember = (MemberDeclarationSyntax)Refactor(member, configOptions); + var newMember = (MemberDeclarationSyntax)Refactor(member, configOptions, wrapLineBeforeArrowToken); return newMember .WithTrailingTrivia(member.GetTrailingTrivia()) @@ -185,13 +187,14 @@ public static Task RefactorAsync( CancellationToken cancellationToken = default) { AnalyzerConfigOptions configOptions = document.GetConfigOptions(node.SyntaxTree); + bool wrapLineBeforeArrowToken = DiagnosticRules.PutExpressionBodyOnItsOwnLine.IsEffective(node.SyntaxTree, document.Project.CompilationOptions, cancellationToken); - SyntaxNode newNode = Refactor(node, configOptions).WithFormatterAnnotation(); + SyntaxNode newNode = Refactor(node, configOptions, wrapLineBeforeArrowToken).WithFormatterAnnotation(); return document.ReplaceNodeAsync(node, newNode, cancellationToken); } - private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions configOptions) + private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions configOptions, bool wrapLineBeforeArrowToken) { switch (node.Kind()) { @@ -201,7 +204,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(methodDeclaration.Body); return methodDeclaration - .WithExpressionBody(CreateExpressionBody(analysis, methodDeclaration, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, methodDeclaration, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(methodDeclaration.Body, analysis)) .WithBody(null); } @@ -211,7 +214,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(constructorDeclaration.Body); return constructorDeclaration - .WithExpressionBody(CreateExpressionBody(analysis, constructorDeclaration, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, constructorDeclaration, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(constructorDeclaration.Body, analysis)) .WithBody(null); } @@ -221,7 +224,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(destructorDeclaration.Body); return destructorDeclaration - .WithExpressionBody(CreateExpressionBody(analysis, destructorDeclaration, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, destructorDeclaration, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(destructorDeclaration.Body, analysis)) .WithBody(null); } @@ -231,7 +234,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(localFunction.Body); return localFunction - .WithExpressionBody(CreateExpressionBody(analysis, localFunction, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, localFunction, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(localFunction.Body, analysis)) .WithBody(null); } @@ -241,7 +244,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body); return operatorDeclaration - .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis)) .WithBody(null); } @@ -251,7 +254,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body); return operatorDeclaration - .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis)) .WithBody(null); } @@ -261,7 +264,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(propertyDeclaration.AccessorList); return propertyDeclaration - .WithExpressionBody(CreateExpressionBody(analysis, propertyDeclaration, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, propertyDeclaration, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis)) .WithAccessorList(null); } @@ -271,7 +274,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(indexerDeclaration.AccessorList); return indexerDeclaration - .WithExpressionBody(CreateExpressionBody(analysis, indexerDeclaration, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, indexerDeclaration, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis)) .WithAccessorList(null); } @@ -285,7 +288,7 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(accessor); return accessor - .WithExpressionBody(CreateExpressionBody(analysis, accessor, configOptions)) + .WithExpressionBody(CreateExpressionBody(analysis, accessor, configOptions, wrapLineBeforeArrowToken)) .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis)) .WithBody(null); } @@ -300,7 +303,8 @@ private static SyntaxNode Refactor(SyntaxNode node, AnalyzerConfigOptions config private static ArrowExpressionClauseSyntax CreateExpressionBody( BlockExpressionAnalysis analysis, SyntaxNode declaration, - AnalyzerConfigOptions configOptions) + AnalyzerConfigOptions configOptions, + bool wrapLineBeforeArrowToken) { SyntaxToken arrowToken = Token(SyntaxKind.EqualsGreaterThanToken); @@ -333,6 +337,40 @@ private static ArrowExpressionClauseSyntax CreateExpressionBody( expression = SyntaxTriviaAnalysis.SetIndentation(expression, declaration, configOptions); + if (wrapLineBeforeArrowToken) + { + NewLinePosition newLinePosition = GetArrowNewLinePosition(declaration.Kind(), configOptions); + return CreateArrayExpression(arrowToken, expression, newLinePosition); + } + else + { + return ArrowExpressionClause(arrowToken, expression); + } + } + + private static NewLinePosition GetArrowNewLinePosition(SyntaxKind syntaxKind, AnalyzerConfigOptions configOptions) + { + if (ConvertExpressionBodyAnalysis.AllowPutExpressionBodyOnItsOwnLine(syntaxKind)) + { + return configOptions.GetArrowTokenNewLinePosition(); + } + else + { + return NewLinePosition.None; + } + } + + private static ArrowExpressionClauseSyntax CreateArrayExpression(SyntaxToken arrowToken, ExpressionSyntax expression, NewLinePosition newLinePosition) + { + switch (newLinePosition) + { + case NewLinePosition.After: + arrowToken = arrowToken.AppendToTrailingTrivia(CSharpFactory.NewLine()); + break; + case NewLinePosition.Before: + arrowToken = arrowToken.PrependToLeadingTrivia(CSharpFactory.NewLine()); + break; + } return ArrowExpressionClause(arrowToken, expression); }