Skip to content

Commit 0256cd5

Browse files
committed
merge master
2 parents e66df50 + 4b6dcf5 commit 0256cd5

File tree

13 files changed

+625
-107
lines changed

13 files changed

+625
-107
lines changed

ChangeLog.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Fix analyzer [RCS1229](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1229) ([PR](https://github.com/dotnet/roslynator/pull/1618))
1313

14-
### Changed
14+
### Added
1515

16-
- Move analyzer [RCS1036](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1036) to Formatting.Analyzers as [RCS0063](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0063) ([PR](https://github.com/dotnet/roslynator/pull/1600))
17-
- Old analyzer still works but is marked as obsolete.
16+
- Add analyzer "Put expression body on its own line" [RCS0062](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0062) ([PR](https://github.com/dotnet/roslynator/pull/1593) by @cbersch)
17+
- Affects analyzer [RCS1016](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1016)
18+
- Affects refacoring [RR0169](https://josefpihrt.github.io/docs/roslynator/refactorings/RR0169)
1819

1920
## [4.12.11] - 2025-01-28
2021

src/Analyzers.xml

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,40 +1630,20 @@ public class C
16301630
</Samples>
16311631
</Analyzer>
16321632
<Analyzer>
1633-
<Id>RCS0063</Id>
1634-
<Identifier>RemoveUnnecessaryBlankLine</Identifier>
1635-
<Title>Remove unnecessary blank line</Title>
1633+
<Id>RCS0062</Id>
1634+
<Identifier>PutExpressionBodyOnItsOwnLine</Identifier>
1635+
<Title>Put expression body on its own line</Title>
16361636
<DefaultSeverity>Info</DefaultSeverity>
16371637
<IsEnabledByDefault>false</IsEnabledByDefault>
16381638
<Samples>
16391639
<Sample>
1640-
<Before><![CDATA[public class Foo
1641-
{
1642-
1643-
private string _f;
1644-
1645-
1646-
public bool Bar()
1647-
{
1648-
1649-
return false;
1650-
1651-
}
1652-
1653-
}]]></Before>
1654-
<After><![CDATA[public class Foo
1655-
{
1656-
private string _f;
1657-
1658-
public bool Bar()
1659-
{
1660-
return false;
1661-
}
1662-
}]]></After>
1640+
<Before><![CDATA[object Foo() => null;]]></Before>
1641+
<After><![CDATA[object Foo()
1642+
=> null;]]></After>
16631643
</Sample>
16641644
</Samples>
16651645
<ConfigOptions>
1666-
<Option Key="blank_line_between_closing_brace_and_switch_section" />
1646+
<Option Key="arrow_token_new_line" IsRequired="false" />
16671647
</ConfigOptions>
16681648
</Analyzer>
16691649
<Analyzer>
@@ -2015,6 +1995,7 @@ foreach (var item in items)
20151995
<Option Key="body_style" IsRequired="true" />
20161996
<Option Key="use_block_body_when_declaration_spans_over_multiple_lines" IsRequired="true" />
20171997
<Option Key="use_block_body_when_expression_spans_over_multiple_lines" IsRequired="true" />
1998+
<Option Key="arrow_token_new_line" IsRequired="false" />
20181999
</ConfigOptions>
20192000
<Options>
20202001
<Option Identifier="ConvertExpressionBodyToBlockBodyWhenExpressionIsMultiLine">
@@ -2507,10 +2488,8 @@ if (f)
25072488
</Analyzer>
25082489
<Analyzer>
25092490
<Id>RCS1036</Id>
2510-
<Identifier>Obsolete_RemoveUnnecessaryBlankLine</Identifier>
2491+
<Identifier>RemoveUnnecessaryBlankLine</Identifier>
25112492
<Title>Remove unnecessary blank line</Title>
2512-
<Status>Obsolete</Status>
2513-
<ObsoleteMessage>Use RCS0063 instead</ObsoleteMessage>
25142493
<DefaultSeverity>Info</DefaultSeverity>
25152494
<IsEnabledByDefault>true</IsEnabledByDefault>
25162495
<Samples>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Microsoft.CodeAnalysis.CSharp;
2+
3+
namespace Roslynator.CSharp.Analysis;
4+
5+
internal static class ConvertExpressionBodyAnalysis
6+
{
7+
public static bool AllowPutExpressionBodyOnItsOwnLine(SyntaxKind syntaxKind)
8+
{
9+
// allow putting expression on new line for all method-like declarations, except for accessors.
10+
switch (syntaxKind)
11+
{
12+
case SyntaxKind.MethodDeclaration:
13+
case SyntaxKind.ConstructorDeclaration:
14+
case SyntaxKind.DestructorDeclaration:
15+
case SyntaxKind.PropertyDeclaration:
16+
case SyntaxKind.IndexerDeclaration:
17+
case SyntaxKind.OperatorDeclaration:
18+
case SyntaxKind.ConversionOperatorDeclaration:
19+
return true;
20+
default:
21+
return false;
22+
}
23+
}
24+
}

src/Common/DiagnosticIdentifiers.Generated.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static partial class DiagnosticIdentifiers
6161
public const string PlaceNewLineAfterOrBeforeNullConditionalOperator = "RCS0059";
6262
public const string BlankLineAfterFileScopedNamespaceDeclaration = "RCS0060";
6363
public const string BlankLineBetweenSwitchSections = "RCS0061";
64-
public const string RemoveUnnecessaryBlankLine = "RCS0063";
64+
public const string PutExpressionBodyOnItsOwnLine = "RCS0062";
6565
public const string AddBracesWhenExpressionSpansOverMultipleLines = "RCS1001";
6666
public const string RemoveBraces = "RCS1002";
6767
public const string AddBracesToIfElseWhenExpressionSpansOverMultipleLines = "RCS1003";
@@ -86,7 +86,7 @@ public static partial class DiagnosticIdentifiers
8686
public const string RemoveRedundantBooleanLiteral = "RCS1033";
8787
public const string RemoveRedundantSealedModifier = "RCS1034";
8888
public const string RemoveRedundantCommaInInitializer = "RCS1035";
89-
public const string Obsolete_RemoveUnnecessaryBlankLine = "RCS1036";
89+
public const string RemoveUnnecessaryBlankLine = "RCS1036";
9090
public const string RemoveTrailingWhitespace = "RCS1037";
9191
public const string RemoveEmptyStatement = "RCS1038";
9292
public const string RemoveArgumentListFromAttribute = "RCS1039";

src/Common/DiagnosticRules.Generated.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -645,16 +645,16 @@ public static partial class DiagnosticRules
645645
helpLinkUri: DiagnosticIdentifiers.BlankLineBetweenSwitchSections,
646646
customTags: []);
647647

648-
/// <summary>RCS0063</summary>
649-
public static readonly DiagnosticDescriptor RemoveUnnecessaryBlankLine = DiagnosticDescriptorFactory.Create(
650-
id: DiagnosticIdentifiers.RemoveUnnecessaryBlankLine,
651-
title: "Remove unnecessary blank line",
652-
messageFormat: "Remove unnecessary blank line",
648+
/// <summary>RCS0062</summary>
649+
public static readonly DiagnosticDescriptor PutExpressionBodyOnItsOwnLine = DiagnosticDescriptorFactory.Create(
650+
id: DiagnosticIdentifiers.PutExpressionBodyOnItsOwnLine,
651+
title: "Put expression body on its own line",
652+
messageFormat: "Put expression body on its own line",
653653
category: DiagnosticCategories.Roslynator,
654654
defaultSeverity: DiagnosticSeverity.Info,
655655
isEnabledByDefault: false,
656656
description: null,
657-
helpLinkUri: DiagnosticIdentifiers.RemoveUnnecessaryBlankLine,
657+
helpLinkUri: DiagnosticIdentifiers.PutExpressionBodyOnItsOwnLine,
658658
customTags: []);
659659

660660
/// <summary>RCS1001</summary>
@@ -962,15 +962,15 @@ public static partial class DiagnosticRules
962962
customTags: WellKnownDiagnosticTags.Unnecessary);
963963

964964
/// <summary>RCS1036</summary>
965-
public static readonly DiagnosticDescriptor Obsolete_RemoveUnnecessaryBlankLine = DiagnosticDescriptorFactory.Create(
966-
id: DiagnosticIdentifiers.Obsolete_RemoveUnnecessaryBlankLine,
967-
title: "[deprecated] Remove unnecessary blank line",
968-
messageFormat: "([deprecated] Use RCS0063 instead) Remove unnecessary blank line",
965+
public static readonly DiagnosticDescriptor RemoveUnnecessaryBlankLine = DiagnosticDescriptorFactory.Create(
966+
id: DiagnosticIdentifiers.RemoveUnnecessaryBlankLine,
967+
title: "Remove unnecessary blank line",
968+
messageFormat: "Remove unnecessary blank line",
969969
category: DiagnosticCategories.Roslynator,
970970
defaultSeverity: DiagnosticSeverity.Info,
971971
isEnabledByDefault: true,
972972
description: null,
973-
helpLinkUri: DiagnosticIdentifiers.Obsolete_RemoveUnnecessaryBlankLine,
973+
helpLinkUri: DiagnosticIdentifiers.RemoveUnnecessaryBlankLine,
974974
customTags: []);
975975

976976
/// <summary>RCS1037</summary>

src/Formatting.Analyzers.CodeFixes/CSharp/SyntaxTokenCodeFixProvider.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public override ImmutableArray<string> FixableDiagnosticIds
2424
DiagnosticIdentifiers.PlaceNewLineAfterOrBeforeArrowToken,
2525
DiagnosticIdentifiers.PlaceNewLineAfterOrBeforeEqualsToken,
2626
DiagnosticIdentifiers.PutAttributeListOnItsOwnLine,
27-
DiagnosticIdentifiers.AddOrRemoveNewLineBeforeWhileInDoStatement);
27+
DiagnosticIdentifiers.AddOrRemoveNewLineBeforeWhileInDoStatement,
28+
DiagnosticIdentifiers.PutExpressionBodyOnItsOwnLine);
2829
}
2930
}
3031

@@ -60,6 +61,11 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
6061
await CodeActionFactory.RegisterCodeActionForNewLineAsync(context).ConfigureAwait(false);
6162
break;
6263
}
64+
case DiagnosticIdentifiers.PutExpressionBodyOnItsOwnLine:
65+
{
66+
await CodeActionFactory.RegisterCodeActionForNewLineAsync(context, increaseIndentation: true).ConfigureAwait(false);
67+
break;
68+
}
6369
}
6470
}
6571
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) .NET Foundation and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using System.Collections.Immutable;
4+
using Microsoft.CodeAnalysis;
5+
using Microsoft.CodeAnalysis.CSharp;
6+
using Microsoft.CodeAnalysis.CSharp.Syntax;
7+
using Microsoft.CodeAnalysis.Diagnostics;
8+
using Roslynator.CSharp;
9+
using Roslynator.CSharp.Analysis;
10+
using Roslynator.CSharp.CodeStyle;
11+
12+
namespace Roslynator.Formatting.CSharp;
13+
14+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
15+
public sealed class PutExpressionBodyOnItsOwnLineAnalyzer : BaseDiagnosticAnalyzer
16+
{
17+
private static ImmutableArray<DiagnosticDescriptor> _supportedDiagnostics;
18+
19+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
20+
{
21+
get
22+
{
23+
if (_supportedDiagnostics.IsDefault)
24+
Immutable.InterlockedInitialize(ref _supportedDiagnostics, DiagnosticRules.PutExpressionBodyOnItsOwnLine);
25+
26+
return _supportedDiagnostics;
27+
}
28+
}
29+
30+
public override void Initialize(AnalysisContext context)
31+
{
32+
base.Initialize(context);
33+
34+
context.RegisterSyntaxNodeAction(f => AnalyzeArrowExpressionClause(f), SyntaxKind.ArrowExpressionClause);
35+
}
36+
37+
private static void AnalyzeArrowExpressionClause(SyntaxNodeAnalysisContext context)
38+
{
39+
var arrowExpressionClause = (ArrowExpressionClauseSyntax)context.Node;
40+
41+
if (ConvertExpressionBodyAnalysis.AllowPutExpressionBodyOnItsOwnLine(arrowExpressionClause.Parent.Kind()))
42+
{
43+
AnalyzeArrowExpressionClause(arrowExpressionClause.ArrowToken, context);
44+
}
45+
}
46+
47+
private static void AnalyzeArrowExpressionClause(SyntaxToken arrowToken, SyntaxNodeAnalysisContext context)
48+
{
49+
NewLinePosition newLinePosition = context.GetArrowTokenNewLinePosition();
50+
51+
SyntaxToken first;
52+
SyntaxToken second;
53+
if (newLinePosition == NewLinePosition.After)
54+
{
55+
first = arrowToken;
56+
second = arrowToken.GetNextToken();
57+
}
58+
else
59+
{
60+
first = arrowToken.GetPreviousToken();
61+
second = arrowToken;
62+
}
63+
64+
TriviaBlock block = TriviaBlock.FromBetween(first, second);
65+
66+
if (block.Kind == TriviaBlockKind.NoNewLine)
67+
{
68+
DiagnosticHelpers.ReportDiagnostic(
69+
context,
70+
DiagnosticRules.PutExpressionBodyOnItsOwnLine,
71+
block.GetLocation());
72+
}
73+
}
74+
}

src/Refactorings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,9 @@ i--;]]></After>
16061606
<Syntax>operator</Syntax>
16071607
</Syntaxes>
16081608
<Span>body or accessor list</Span>
1609+
<ConfigOptions>
1610+
<Option Key="arrow_token_new_line" IsRequired="false" />
1611+
</ConfigOptions>
16091612
</Refactoring>
16101613
<Refactoring Id="RR0170" Identifier="UseLambdaInsteadOfAnonymousMethod" Title="Use lambda instead of anonymous method">
16111614
<OptionKey>use_lambda_instead_of_anonymous_method</OptionKey>

0 commit comments

Comments
 (0)