From 76d240a62496e432e0b127d039f4383c333a68e0 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 01:01:28 +0200 Subject: [PATCH 1/8] update --- .../CSharp/CodeFixHelpers.cs | 8 +- .../CSharp/FixFormattingOfListAnalyzer.cs | 174 ++++++++++++------ .../RCS0053FixFormattingOfListTests.cs | 51 +++++ 3 files changed, 176 insertions(+), 57 deletions(-) diff --git a/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs b/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs index 49f51ca947..17fa176da5 100644 --- a/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs +++ b/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs @@ -749,9 +749,9 @@ internal static List GetFixListChanges( if (nodes.Count == 1 && node is ArgumentSyntax argument) { - LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= argument.SyntaxTree.GetText(cancellationToken).Lines); + BracesBlock bracesBlock = GetBracesBlock(argument, lines ??= argument.SyntaxTree.GetText(cancellationToken).Lines); - if (lambdaBlock.Block is not null) + if (!bracesBlock.Token.IsKind(SyntaxKind.None)) increasedIndentation = indentationAnalysis.Indentation.ToString(); } @@ -775,9 +775,9 @@ internal static List GetFixListChanges( if (!indentations.Any()) continue; - LambdaBlock lambdaBlock2 = GetLambdaBlock(node, lines ??= node.SyntaxTree.GetText(cancellationToken).Lines); + BracesBlock bracesBlock2 = GetBracesBlock(node, lines ??= node.SyntaxTree.GetText(cancellationToken).Lines); - bool isLambdaBlockWithOpenBraceAtEndOfLine = lambdaBlock2.Token == indentations.Last().Token; + bool isLambdaBlockWithOpenBraceAtEndOfLine = bracesBlock2.Token == indentations.Last().Token; int baseIndentationLength = (isLambdaBlockWithOpenBraceAtEndOfLine) ? indentations.Last().Span.Length diff --git a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs index 218b6e8fff..a4727b9500 100644 --- a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs @@ -184,6 +184,19 @@ private static void Analyze( if (TriviaBlock.FromTrailing(nodeOrToken).IsWrapped) { + if (i == 0 + && nodes.Count == 1 + && first.IsKind(SyntaxKind.Argument)) + { + BracesBlock bracesBlock = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); + + if (bracesBlock.Token.IsKind(SyntaxKind.CloseBracketToken)) + { + AnalyzeBlock(indentationAnalysis, bracesBlock); + return; + } + } + if (ShouldFixIndentation(nodes[i].GetLeadingTrivia(), indentationLength)) { ReportDiagnostic(); @@ -202,33 +215,11 @@ private static void Analyze( if (nodes.Count == 1 && first.IsKind(SyntaxKind.Argument)) { - var argument = (ArgumentSyntax)(SyntaxNode)first; + BracesBlock bracesBlock = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); - LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= first.SyntaxTree.GetText().Lines); - - if (lambdaBlock.Block is not null) + if (bracesBlock.Token.IsKind(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) { - SyntaxToken token = lambdaBlock.Token; - SyntaxTriviaList leading = token.LeadingTrivia; - - if (leading.Any()) - { - SyntaxTrivia trivia = leading.Last(); - - if (trivia.IsWhitespaceTrivia() - && trivia.SpanStart == lambdaBlock.LineStartIndex - && trivia.Span.Length != indentationAnalysis.IndentationLength) - { - ReportDiagnostic(); - break; - } - } - else if (lambdaBlock.LineStartIndex == token.SpanStart) - { - ReportDiagnostic(); - break; - } - + AnalyzeBlock(indentationAnalysis, bracesBlock); return; } } @@ -345,9 +336,33 @@ string GetTitle() throw new InvalidOperationException(); } } + + void AnalyzeBlock(IndentationAnalysis indentationAnalysis, BracesBlock bracesBlock) + { + SyntaxToken token = bracesBlock.Token; + SyntaxTriviaList leading = token.LeadingTrivia; + + if (leading.Any()) + { + SyntaxTrivia trivia = leading.Last(); + + if (trivia.IsWhitespaceTrivia() + && trivia.SpanStart == bracesBlock.LineStartIndex + && trivia.Span.Length != indentationAnalysis.IndentationLength) + { + ReportDiagnostic(); + return; + } + } + else if (bracesBlock.LineStartIndex == token.SpanStart) + { + ReportDiagnostic(); + return; + } + } } - internal static LambdaBlock GetLambdaBlock(SyntaxNode node, TextLineCollection lines) + internal static BracesBlock GetBracesBlock(SyntaxNode node, TextLineCollection lines) { TextLine line = lines.GetLineFromPosition(node.SpanStart); @@ -356,18 +371,18 @@ internal static LambdaBlock GetLambdaBlock(SyntaxNode node, TextLineCollection l if (!node.FullSpan.Contains(startIndex)) return default; - SyntaxToken openBrace = node.FindToken(startIndex); - BlockSyntax block = null; + SyntaxToken openToken = node.FindToken(startIndex); + SyntaxNode block = null; var isOpenBraceAtEndOfLine = false; - if (IsBraceToken(openBrace, SyntaxKind.OpenBraceToken)) + if (IsOpenToken(openToken)) { - SyntaxTriviaList trailing = openBrace.TrailingTrivia; + SyntaxTriviaList trailing = openToken.TrailingTrivia; if (trailing.Any() && trailing.Span.Contains(startIndex)) { - block = (BlockSyntax)openBrace.Parent; + block = openToken.Parent; isOpenBraceAtEndOfLine = true; } } @@ -375,16 +390,16 @@ internal static LambdaBlock GetLambdaBlock(SyntaxNode node, TextLineCollection l if (block is null) { startIndex = line.EndIncludingLineBreak; - openBrace = node.FindToken(startIndex); + openToken = node.FindToken(startIndex); - if (IsBraceToken(openBrace, SyntaxKind.OpenBraceToken)) + if (IsOpenToken(openToken)) { - SyntaxTriviaList leading = openBrace.LeadingTrivia; + SyntaxTriviaList leading = openToken.LeadingTrivia; if ((leading.Any() && leading.Span.Contains(startIndex)) - || (!leading.Any() && openBrace.SpanStart == startIndex)) + || (!leading.Any() && openToken.SpanStart == startIndex)) { - block = (BlockSyntax)openBrace.Parent; + block = openToken.Parent; } } } @@ -392,19 +407,18 @@ internal static LambdaBlock GetLambdaBlock(SyntaxNode node, TextLineCollection l if (block is not null) { int endIndex = lines.GetLineFromPosition(node.Span.End).Start; - SyntaxToken closeBrace = node.FindToken(endIndex); + SyntaxToken closeToken = node.FindToken(endIndex); - if (IsBraceToken(closeBrace, SyntaxKind.CloseBraceToken) - && object.ReferenceEquals(block, closeBrace.Parent)) + if (IsCloseToken(closeToken) + && object.ReferenceEquals(block, closeToken.Parent)) { - SyntaxTriviaList leading = closeBrace.LeadingTrivia; + SyntaxTriviaList leading = closeToken.LeadingTrivia; if ((leading.Any() && leading.Span.Contains(endIndex)) - || (!leading.Any() && closeBrace.SpanStart == endIndex)) + || (!leading.Any() && closeToken.SpanStart == endIndex)) { - return new LambdaBlock( - block, - (isOpenBraceAtEndOfLine) ? closeBrace : openBrace, + return new BracesBlock( + (isOpenBraceAtEndOfLine) ? closeToken : openToken, (isOpenBraceAtEndOfLine) ? endIndex : startIndex); } } @@ -412,11 +426,68 @@ internal static LambdaBlock GetLambdaBlock(SyntaxNode node, TextLineCollection l return default; - static bool IsBraceToken(SyntaxToken token, SyntaxKind kind) + static bool IsOpenToken(SyntaxToken token) { - return token.IsKind(kind) - && token.IsParentKind(SyntaxKind.Block) - && CSharpFacts.IsAnonymousFunctionExpression(token.Parent.Parent.Kind()); + if (token.IsKind(SyntaxKind.OpenBraceToken)) + { + if (token.IsParentKind(SyntaxKind.Block) + && (CSharpFacts.IsAnonymousFunctionExpression(token.Parent.Parent.Kind()))) + { + return true; + } + + if (token.IsParentKind(SyntaxKind.ObjectInitializerExpression) + && token.Parent.Parent.IsKind( + SyntaxKind.ObjectCreationExpression, + SyntaxKind.AnonymousObjectCreationExpression, + SyntaxKind.ImplicitObjectCreationExpression)) + { + return true; + } + + if (token.IsParentKind(SyntaxKind.ArrayInitializerExpression) + && token.Parent.Parent.IsKind( + SyntaxKind.ArrayCreationExpression, + SyntaxKind.ImplicitArrayCreationExpression)) + { + return true; + } + } + + return token.IsKind(SyntaxKind.OpenBracketToken) + && token.IsParentKind(SyntaxKind.CollectionExpression); + } + + static bool IsCloseToken(SyntaxToken token) + { + if (token.IsKind(SyntaxKind.CloseBraceToken)) + { + if (token.IsParentKind(SyntaxKind.Block) + && (CSharpFacts.IsAnonymousFunctionExpression(token.Parent.Parent.Kind()))) + { + return true; + } + + if (token.IsParentKind(SyntaxKind.ObjectInitializerExpression) + && token.Parent.Parent.IsKind( + SyntaxKind.ObjectCreationExpression, + SyntaxKind.AnonymousObjectCreationExpression, + SyntaxKind.ImplicitObjectCreationExpression)) + { + return true; + } + + if (token.IsParentKind(SyntaxKind.ArrayInitializerExpression) + && token.Parent.Parent.IsKind( + SyntaxKind.ArrayCreationExpression, + SyntaxKind.ImplicitArrayCreationExpression)) + { + return true; + } + } + + return token.IsKind(SyntaxKind.CloseBracketToken) + && token.IsParentKind(SyntaxKind.CollectionExpression); } } @@ -439,17 +510,14 @@ internal static bool ShouldWrapAndIndent(SyntaxNode node, int index) return true; } - internal readonly struct LambdaBlock + internal readonly struct BracesBlock { - public LambdaBlock(BlockSyntax block, SyntaxToken token, int lineStartIndex) + public BracesBlock(SyntaxToken token, int lineStartIndex) { - Block = block; Token = token; LineStartIndex = lineStartIndex; } - public BlockSyntax Block { get; } - public SyntaxToken Token { get; } public int LineStartIndex { get; } diff --git a/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs b/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs index ae95f80e74..74186bfa83 100644 --- a/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs +++ b/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs @@ -1296,4 +1296,55 @@ internal static void Method(Foo[] foo) } ", }, options: Options.WithCompilationOptions(Options.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication))); } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfList)] + public async Task TestNoDiagnostic_Multiline_ObjectInitializer() + { + await VerifyNoDiagnosticAsync(""" +class C +{ + public C() { } + + public C(C value) { } + + public string P1 { get; set; } + + C M() + { + return new C(new C + { + P1 = "a" + }); + } +} +"""); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfList)] + public async Task TestNoDiagnostic_Multiline_CollectionExpression() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + public C P { get; set; } + + public string M(string[] values) + { + return null; + } + + public void M2() + { + object x = + P + .M( + [ + // some comment + null, + ]) + .ToString(); + } +} +"); + } } From acede17cea0ee63c3c8b78a9881a6947fde97849 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 01:03:24 +0200 Subject: [PATCH 2/8] changelog --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index 67b36e9f96..8491d31b0d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix analyzer [RCS1214](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1214) ([PR](https://github.com/dotnet/roslynator/pull/1500)) - Fix analyzer [RCS1018](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1018) ([PR](https://github.com/dotnet/roslynator/pull/1510)) - Fix analyzer [RCS1264](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1264) ([PR](https://github.com/dotnet/roslynator/pull/1511)) +- Fix analyzer [RCS0053](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0053) ([PR](https://github.com/dotnet/roslynator/pull/1512)) ### Changed From 5dc8c22979b134fa6f2602ba45ca155f8aef9fa6 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 01:24:10 +0200 Subject: [PATCH 3/8] fix --- src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs index a4727b9500..aef601bd0b 100644 --- a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs @@ -351,13 +351,11 @@ void AnalyzeBlock(IndentationAnalysis indentationAnalysis, BracesBlock bracesBlo && trivia.Span.Length != indentationAnalysis.IndentationLength) { ReportDiagnostic(); - return; } } else if (bracesBlock.LineStartIndex == token.SpanStart) { ReportDiagnostic(); - return; } } } From fddaebaad8552ebfe64226e8a6ac0c59256564e1 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 01:27:51 +0200 Subject: [PATCH 4/8] update --- .../CSharp/FixFormattingOfListAnalyzer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs index aef601bd0b..eda0f3d88d 100644 --- a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs @@ -370,7 +370,7 @@ internal static BracesBlock GetBracesBlock(SyntaxNode node, TextLineCollection l return default; SyntaxToken openToken = node.FindToken(startIndex); - SyntaxNode block = null; + SyntaxNode enclosedNode = null; var isOpenBraceAtEndOfLine = false; if (IsOpenToken(openToken)) @@ -380,12 +380,12 @@ internal static BracesBlock GetBracesBlock(SyntaxNode node, TextLineCollection l if (trailing.Any() && trailing.Span.Contains(startIndex)) { - block = openToken.Parent; + enclosedNode = openToken.Parent; isOpenBraceAtEndOfLine = true; } } - if (block is null) + if (enclosedNode is null) { startIndex = line.EndIncludingLineBreak; openToken = node.FindToken(startIndex); @@ -397,18 +397,18 @@ internal static BracesBlock GetBracesBlock(SyntaxNode node, TextLineCollection l if ((leading.Any() && leading.Span.Contains(startIndex)) || (!leading.Any() && openToken.SpanStart == startIndex)) { - block = openToken.Parent; + enclosedNode = openToken.Parent; } } } - if (block is not null) + if (enclosedNode is not null) { int endIndex = lines.GetLineFromPosition(node.Span.End).Start; SyntaxToken closeToken = node.FindToken(endIndex); if (IsCloseToken(closeToken) - && object.ReferenceEquals(block, closeToken.Parent)) + && object.ReferenceEquals(enclosedNode, closeToken.Parent)) { SyntaxTriviaList leading = closeToken.LeadingTrivia; From 77e0304e8b21bf532c69390fd5cec070b687a0fc Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 01:49:21 +0200 Subject: [PATCH 5/8] update --- .../CSharp/FixFormattingOfListAnalyzer.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs index eda0f3d88d..d8c5939aca 100644 --- a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs @@ -451,9 +451,12 @@ static bool IsOpenToken(SyntaxToken token) return true; } } - +#if ROSLYN_4_7 return token.IsKind(SyntaxKind.OpenBracketToken) - && token.IsParentKind(SyntaxKind.CollectionExpression); + && token.IsParentKind(SyntaxKind.CollectionExpression); +#else + return false; +#endif } static bool IsCloseToken(SyntaxToken token) @@ -483,9 +486,12 @@ static bool IsCloseToken(SyntaxToken token) return true; } } - +#if ROSLYN_4_7 return token.IsKind(SyntaxKind.CloseBracketToken) - && token.IsParentKind(SyntaxKind.CollectionExpression); + && token.IsParentKind(SyntaxKind.CollectionExpression); +#else + return false; +#endif } } From def2c5d35bda963878d2e492c61f8b61083d78d5 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 01:55:12 +0200 Subject: [PATCH 6/8] update --- .../CSharp/FixFormattingOfListAnalyzer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs index d8c5939aca..a42b366931 100644 --- a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs @@ -453,7 +453,7 @@ static bool IsOpenToken(SyntaxToken token) } #if ROSLYN_4_7 return token.IsKind(SyntaxKind.OpenBracketToken) - && token.IsParentKind(SyntaxKind.CollectionExpression); + && token.IsParentKind(SyntaxKind.CollectionExpression); #else return false; #endif @@ -488,7 +488,7 @@ static bool IsCloseToken(SyntaxToken token) } #if ROSLYN_4_7 return token.IsKind(SyntaxKind.CloseBracketToken) - && token.IsParentKind(SyntaxKind.CollectionExpression); + && token.IsParentKind(SyntaxKind.CollectionExpression); #else return false; #endif From 97ef53edc685cf0dadf0f5f7b8827f6f52d80d32 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 09:48:22 +0200 Subject: [PATCH 7/8] update --- .../CSharp/FixFormattingOfListAnalyzer.cs | 82 ++++++------------- .../RCS0053FixFormattingOfListTests.cs | 40 ++++++--- 2 files changed, 50 insertions(+), 72 deletions(-) diff --git a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs index a42b366931..2657375a8b 100644 --- a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs @@ -184,15 +184,14 @@ private static void Analyze( if (TriviaBlock.FromTrailing(nodeOrToken).IsWrapped) { - if (i == 0 - && nodes.Count == 1 + if (nodes.Count == 1 && first.IsKind(SyntaxKind.Argument)) { - BracesBlock bracesBlock = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); + BracesBlock block = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); - if (bracesBlock.Token.IsKind(SyntaxKind.CloseBracketToken)) + if (block.Token.IsKind(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken)) { - AnalyzeBlock(indentationAnalysis, bracesBlock); + AnalyzeBlock(block, indentationAnalysis); return; } } @@ -215,11 +214,11 @@ private static void Analyze( if (nodes.Count == 1 && first.IsKind(SyntaxKind.Argument)) { - BracesBlock bracesBlock = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); + BracesBlock block = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); - if (bracesBlock.Token.IsKind(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) + if (block.Token.IsKind(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) { - AnalyzeBlock(indentationAnalysis, bracesBlock); + AnalyzeBlock(block, indentationAnalysis); return; } } @@ -337,9 +336,9 @@ string GetTitle() } } - void AnalyzeBlock(IndentationAnalysis indentationAnalysis, BracesBlock bracesBlock) + void AnalyzeBlock(BracesBlock block, IndentationAnalysis indentationAnalysis) { - SyntaxToken token = bracesBlock.Token; + SyntaxToken token = block.Token; SyntaxTriviaList leading = token.LeadingTrivia; if (leading.Any()) @@ -347,13 +346,13 @@ void AnalyzeBlock(IndentationAnalysis indentationAnalysis, BracesBlock bracesBlo SyntaxTrivia trivia = leading.Last(); if (trivia.IsWhitespaceTrivia() - && trivia.SpanStart == bracesBlock.LineStartIndex + && trivia.SpanStart == block.LineStartIndex && trivia.Span.Length != indentationAnalysis.IndentationLength) { ReportDiagnostic(); } } - else if (bracesBlock.LineStartIndex == token.SpanStart) + else if (block.LineStartIndex == token.SpanStart) { ReportDiagnostic(); } @@ -370,45 +369,45 @@ internal static BracesBlock GetBracesBlock(SyntaxNode node, TextLineCollection l return default; SyntaxToken openToken = node.FindToken(startIndex); - SyntaxNode enclosedNode = null; + SyntaxNode block = null; var isOpenBraceAtEndOfLine = false; - if (IsOpenToken(openToken)) + if (AnalyzeToken(openToken, isOpen: true)) { SyntaxTriviaList trailing = openToken.TrailingTrivia; if (trailing.Any() && trailing.Span.Contains(startIndex)) { - enclosedNode = openToken.Parent; + block = openToken.Parent; isOpenBraceAtEndOfLine = true; } } - if (enclosedNode is null) + if (block is null) { startIndex = line.EndIncludingLineBreak; openToken = node.FindToken(startIndex); - if (IsOpenToken(openToken)) + if (AnalyzeToken(openToken, isOpen: true)) { SyntaxTriviaList leading = openToken.LeadingTrivia; if ((leading.Any() && leading.Span.Contains(startIndex)) || (!leading.Any() && openToken.SpanStart == startIndex)) { - enclosedNode = openToken.Parent; + block = openToken.Parent; } } } - if (enclosedNode is not null) + if (block is not null) { int endIndex = lines.GetLineFromPosition(node.Span.End).Start; SyntaxToken closeToken = node.FindToken(endIndex); - if (IsCloseToken(closeToken) - && object.ReferenceEquals(enclosedNode, closeToken.Parent)) + if (AnalyzeToken(closeToken, isOpen: false) + && object.ReferenceEquals(block, closeToken.Parent)) { SyntaxTriviaList leading = closeToken.LeadingTrivia; @@ -424,44 +423,9 @@ internal static BracesBlock GetBracesBlock(SyntaxNode node, TextLineCollection l return default; - static bool IsOpenToken(SyntaxToken token) - { - if (token.IsKind(SyntaxKind.OpenBraceToken)) - { - if (token.IsParentKind(SyntaxKind.Block) - && (CSharpFacts.IsAnonymousFunctionExpression(token.Parent.Parent.Kind()))) - { - return true; - } - - if (token.IsParentKind(SyntaxKind.ObjectInitializerExpression) - && token.Parent.Parent.IsKind( - SyntaxKind.ObjectCreationExpression, - SyntaxKind.AnonymousObjectCreationExpression, - SyntaxKind.ImplicitObjectCreationExpression)) - { - return true; - } - - if (token.IsParentKind(SyntaxKind.ArrayInitializerExpression) - && token.Parent.Parent.IsKind( - SyntaxKind.ArrayCreationExpression, - SyntaxKind.ImplicitArrayCreationExpression)) - { - return true; - } - } -#if ROSLYN_4_7 - return token.IsKind(SyntaxKind.OpenBracketToken) - && token.IsParentKind(SyntaxKind.CollectionExpression); -#else - return false; -#endif - } - - static bool IsCloseToken(SyntaxToken token) + static bool AnalyzeToken(SyntaxToken token, bool isOpen) { - if (token.IsKind(SyntaxKind.CloseBraceToken)) + if (token.IsKind((isOpen) ? SyntaxKind.OpenBraceToken : SyntaxKind.CloseBraceToken)) { if (token.IsParentKind(SyntaxKind.Block) && (CSharpFacts.IsAnonymousFunctionExpression(token.Parent.Parent.Kind()))) @@ -487,7 +451,7 @@ static bool IsCloseToken(SyntaxToken token) } } #if ROSLYN_4_7 - return token.IsKind(SyntaxKind.CloseBracketToken) + return token.IsKind((isOpen) ? SyntaxKind.OpenBracketToken : SyntaxKind.CloseBracketToken) && token.IsParentKind(SyntaxKind.CollectionExpression); #else return false; diff --git a/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs b/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs index 74186bfa83..047f4ff7be 100644 --- a/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs +++ b/src/Tests/Formatting.Analyzers.Tests/RCS0053FixFormattingOfListTests.cs @@ -1307,13 +1307,13 @@ public C() { } public C(C value) { } - public string P1 { get; set; } + public string P { get; set; } C M() { return new C(new C { - P1 = "a" + P = "" }); } } @@ -1323,28 +1323,42 @@ C M() [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfList)] public async Task TestNoDiagnostic_Multiline_CollectionExpression() { - await VerifyNoDiagnosticAsync(@" + await VerifyNoDiagnosticAsync(""" + class C { public C P { get; set; } - public string M(string[] values) - { - return null; - } - - public void M2() + public string M1(string[] values) { - object x = + string x = P - .M( + .M1( [ - // some comment + // x null, ]) .ToString(); + + return x; + } + + public string M2(string value, string[] values) + { + string x = + P + .M2( + "", + [ + // x + null, + ]) + .ToString(); + + return x; } } -"); + +"""); } } From 265515527ef326ed6d31b5b7e705ec5e5b24925b Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 13 Sep 2024 10:48:57 +0200 Subject: [PATCH 8/8] update --- .../CSharp/CodeFixHelpers.cs | 5 +- .../CSharp/FixFormattingOfListAnalyzer.cs | 87 +++++++++---------- 2 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs b/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs index 17fa176da5..a6b3c741a3 100644 --- a/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs +++ b/src/Formatting.Analyzers.CodeFixes/CSharp/CodeFixHelpers.cs @@ -703,7 +703,6 @@ internal static List GetFixListChanges( } var textChanges = new List(); - TextLineCollection lines = null; string endOfLine = DetermineEndOfLine(containingNode).ToString(); for (int i = 0; i < nodes.Count; i++) @@ -749,7 +748,7 @@ internal static List GetFixListChanges( if (nodes.Count == 1 && node is ArgumentSyntax argument) { - BracesBlock bracesBlock = GetBracesBlock(argument, lines ??= argument.SyntaxTree.GetText(cancellationToken).Lines); + BracesBlock bracesBlock = GetBracesBlock(argument); if (!bracesBlock.Token.IsKind(SyntaxKind.None)) increasedIndentation = indentationAnalysis.Indentation.ToString(); @@ -775,7 +774,7 @@ internal static List GetFixListChanges( if (!indentations.Any()) continue; - BracesBlock bracesBlock2 = GetBracesBlock(node, lines ??= node.SyntaxTree.GetText(cancellationToken).Lines); + BracesBlock bracesBlock2 = GetBracesBlock(node); bool isLambdaBlockWithOpenBraceAtEndOfLine = bracesBlock2.Token == indentations.Last().Token; diff --git a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs index 2657375a8b..15e9cfcb08 100644 --- a/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs +++ b/src/Formatting.Analyzers/CSharp/FixFormattingOfListAnalyzer.cs @@ -8,7 +8,6 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; using Roslynator.CSharp; -using static Roslynator.CSharp.SyntaxTriviaAnalysis; namespace Roslynator.Formatting.CSharp; @@ -166,9 +165,7 @@ private static void Analyze( else { TextLineCollection lines = null; - IndentationAnalysis indentationAnalysis = IndentationAnalysis.Create(openNodeOrToken.Parent, context.GetConfigOptions()); - int indentationLength = indentationAnalysis.IncreasedIndentationLength; if (indentationLength == 0) @@ -184,22 +181,13 @@ private static void Analyze( if (TriviaBlock.FromTrailing(nodeOrToken).IsWrapped) { - if (nodes.Count == 1 - && first.IsKind(SyntaxKind.Argument)) - { - BracesBlock block = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); - - if (block.Token.IsKind(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken)) - { - AnalyzeBlock(block, indentationAnalysis); - return; - } - } + if (AnalyzeBlock(nodes, indentationAnalysis, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken)) + return; if (ShouldFixIndentation(nodes[i].GetLeadingTrivia(), indentationLength)) { ReportDiagnostic(); - break; + return; } } else @@ -208,23 +196,13 @@ private static void Analyze( && ShouldWrapAndIndent(context.Node, i)) { ReportDiagnostic(); - break; + return; } - if (nodes.Count == 1 - && first.IsKind(SyntaxKind.Argument)) - { - BracesBlock block = GetBracesBlock(first, lines ??= first.SyntaxTree.GetText().Lines); + if (AnalyzeBlock(nodes, indentationAnalysis, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) + return; - if (block.Token.IsKind(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) - { - AnalyzeBlock(block, indentationAnalysis); - return; - } - } - - if (lines is null) - lines = first.SyntaxTree.GetText().Lines; + lines ??= first.SyntaxTree.GetText().Lines; int lineIndex = lines.IndexOf(span.Start); if (lineIndex < lines.Count - 1) @@ -250,14 +228,14 @@ private static void Analyze( && trivia.Span.Length != indentationLength) { ReportDiagnostic(); - break; + return; } } } else if (lineStartIndex == token.SpanStart) { ReportDiagnostic(); - break; + return; } } } @@ -336,31 +314,48 @@ string GetTitle() } } - void AnalyzeBlock(BracesBlock block, IndentationAnalysis indentationAnalysis) + bool AnalyzeBlock( + SeparatedSyntaxList nodes, + IndentationAnalysis indentationAnalysis, + SyntaxKind kind1, + SyntaxKind kind2) { - SyntaxToken token = block.Token; - SyntaxTriviaList leading = token.LeadingTrivia; - - if (leading.Any()) + if (nodes.Count == 1 + && nodes[0].IsKind(SyntaxKind.Argument)) { - SyntaxTrivia trivia = leading.Last(); + BracesBlock block = GetBracesBlock(nodes[0]); - if (trivia.IsWhitespaceTrivia() - && trivia.SpanStart == block.LineStartIndex - && trivia.Span.Length != indentationAnalysis.IndentationLength) + if (block.Token.IsKind(kind1, kind2)) { - ReportDiagnostic(); + SyntaxToken token = block.Token; + SyntaxTriviaList leading = token.LeadingTrivia; + + if (leading.Any()) + { + SyntaxTrivia trivia = leading.Last(); + + if (trivia.IsWhitespaceTrivia() + && trivia.SpanStart == block.LineStartIndex + && trivia.Span.Length != indentationAnalysis.IndentationLength) + { + ReportDiagnostic(); + } + } + else if (block.LineStartIndex == token.SpanStart) + { + ReportDiagnostic(); + } + return true; } } - else if (block.LineStartIndex == token.SpanStart) - { - ReportDiagnostic(); - } + + return false; } } - internal static BracesBlock GetBracesBlock(SyntaxNode node, TextLineCollection lines) + internal static BracesBlock GetBracesBlock(SyntaxNode node) { + TextLineCollection lines = node.SyntaxTree.GetText().Lines; TextLine line = lines.GetLineFromPosition(node.SpanStart); int startIndex = line.End;