[clang] 163c13f - [clang-format] Fix formatting of the code that follows C# Lambda Expressions
Owen Pan via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 17 10:42:49 PST 2021
Author: Peter Stys
Date: 2021-12-17T10:42:15-08:00
New Revision: 163c13fed9f68c31a14b3d2409b994909f0600bb
URL: https://github.com/llvm/llvm-project/commit/163c13fed9f68c31a14b3d2409b994909f0600bb
DIFF: https://github.com/llvm/llvm-project/commit/163c13fed9f68c31a14b3d2409b994909f0600bb.diff
LOG: [clang-format] Fix formatting of the code that follows C# Lambda Expressions
The alignment fix introduced by https://reviews.llvm.org/D104388 caused a regression whereby formatting of code that follows the lambda block is incorrect i.e. separate expressions are put on the same line.
Differential Revision: https://reviews.llvm.org/D115738
Added:
Modified:
clang/lib/Format/UnwrappedLineParser.cpp
clang/lib/Format/UnwrappedLineParser.h
clang/unittests/Format/FormatTestCSharp.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 78405f23e4003..0b1771ba7c9c9 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1941,6 +1941,22 @@ bool UnwrappedLineParser::tryToParseBracedList() {
return true;
}
+bool UnwrappedLineParser::tryToParseCSharpLambda() {
+ // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
+ // TT_FatArrow. They always start an expression or a child block if
+ // followed by a curly brace.
+ nextToken();
+ if (FormatTok->isNot(tok::l_brace))
+ return false;
+ // C# may break after => if the next character is a newline.
+ if (Style.BraceWrapping.AfterFunction) {
+ // calling `addUnwrappedLine()` here causes odd parsing errors.
+ FormatTok->MustBreakBefore = true;
+ }
+ parseChildBlock();
+ return true;
+}
+
bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
bool IsEnum,
tok::TokenKind ClosingBraceKind) {
@@ -1949,23 +1965,9 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
// FIXME: Once we have an expression parser in the UnwrappedLineParser,
// replace this by using parseAssignmentExpression() inside.
do {
- if (Style.isCSharp()) {
- // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
- // TT_FatArrow. They always start an expression or a child block if
- // followed by a curly brace.
- if (FormatTok->is(TT_FatArrow)) {
- nextToken();
- if (FormatTok->is(tok::l_brace)) {
- // C# may break after => if the next character is a newline.
- if (Style.isCSharp() && Style.BraceWrapping.AfterFunction == true) {
- // calling `addUnwrappedLine()` here causes odd parsing errors.
- FormatTok->MustBreakBefore = true;
- }
- parseChildBlock();
- continue;
- }
- }
- }
+ if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
+ if (tryToParseCSharpLambda())
+ continue;
if (Style.Language == FormatStyle::LK_JavaScript) {
if (FormatTok->is(Keywords.kw_function) ||
FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function)) {
@@ -2092,7 +2094,7 @@ void UnwrappedLineParser::parseParens() {
break;
case tok::equal:
if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
- parseStructuralElement();
+ tryToParseCSharpLambda();
else
nextToken();
break;
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index b4c0826545971..3c07fbf2e8d36 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -138,6 +138,7 @@ class UnwrappedLineParser {
// https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
void parseCSharpGenericTypeConstraint();
bool tryToParseLambda();
+ bool tryToParseCSharpLambda();
bool tryToParseLambdaIntroducer();
bool tryToParsePropertyAccessor();
void tryToParseJSFunction();
diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp
index 78547e07d2150..2cfec61d8f94b 100644
--- a/clang/unittests/Format/FormatTestCSharp.cpp
+++ b/clang/unittests/Format/FormatTestCSharp.cpp
@@ -759,6 +759,128 @@ class MyClass
GoogleStyle);
}
+TEST_F(FormatTestCSharp, CSharpLambdasDontBreakFollowingCodeAlignment) {
+ FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
+ FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
+
+ verifyFormat(R"(//
+public class Sample
+{
+ public void Test()
+ {
+ while (true)
+ {
+ preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
+ CodeThatFollowsLambda();
+ IsWellAligned();
+ }
+ }
+})",
+ MicrosoftStyle);
+
+ verifyFormat(R"(//
+public class Sample {
+ public void Test() {
+ while (true) {
+ preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
+ CodeThatFollowsLambda();
+ IsWellAligned();
+ }
+ }
+})",
+ GoogleStyle);
+}
+
+TEST_F(FormatTestCSharp, CSharpLambdasComplexLambdasDontBreakAlignment) {
+ FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
+ FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
+
+ verifyFormat(R"(//
+public class Test
+{
+ private static void ComplexLambda(BuildReport protoReport)
+ {
+ allSelectedScenes =
+ veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
+ .Select(scene => scene.path)
+ .ToArray();
+ if (allSelectedScenes.Count == 0)
+ {
+ return;
+ }
+ Functions();
+ AreWell();
+ Aligned();
+ AfterLambdaBlock();
+ }
+})",
+ MicrosoftStyle);
+
+ verifyFormat(R"(//
+public class Test {
+ private static void ComplexLambda(BuildReport protoReport) {
+ allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
+ .Where(scene => scene.enabled)
+ .Select(scene => scene.path)
+ .ToArray();
+ if (allSelectedScenes.Count == 0) {
+ return;
+ }
+ Functions();
+ AreWell();
+ Aligned();
+ AfterLambdaBlock();
+ }
+})",
+ GoogleStyle);
+}
+
+TEST_F(FormatTestCSharp, CSharpLambdasMulipleLambdasDontBreakAlignment) {
+ FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
+ FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
+
+ verifyFormat(R"(//
+public class Test
+{
+ private static void MultipleLambdas(BuildReport protoReport)
+ {
+ allSelectedScenes =
+ veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
+ .Select(scene => scene.path)
+ .ToArray();
+ preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
+ if (allSelectedScenes.Count == 0)
+ {
+ return;
+ }
+ Functions();
+ AreWell();
+ Aligned();
+ AfterLambdaBlock();
+ }
+})",
+ MicrosoftStyle);
+
+ verifyFormat(R"(//
+public class Test {
+ private static void MultipleLambdas(BuildReport protoReport) {
+ allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
+ .Where(scene => scene.enabled)
+ .Select(scene => scene.path)
+ .ToArray();
+ preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
+ if (allSelectedScenes.Count == 0) {
+ return;
+ }
+ Functions();
+ AreWell();
+ Aligned();
+ AfterLambdaBlock();
+ }
+})",
+ GoogleStyle);
+}
+
TEST_F(FormatTestCSharp, CSharpObjectInitializers) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
More information about the cfe-commits
mailing list