[clang] f993710 - [clang-format] PR50727 C# Invoke Lamda Expression indentation incorrect
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 1 03:47:11 PDT 2021
Author: mydeveloperday
Date: 2021-07-01T10:46:43+01:00
New Revision: f9937106b7171eb1f4f8914e29c2be0c36ebc46d
URL: https://github.com/llvm/llvm-project/commit/f9937106b7171eb1f4f8914e29c2be0c36ebc46d
DIFF: https://github.com/llvm/llvm-project/commit/f9937106b7171eb1f4f8914e29c2be0c36ebc46d.diff
LOG: [clang-format] PR50727 C# Invoke Lamda Expression indentation incorrect
https://bugs.llvm.org/show_bug.cgi?id=50727
When processing C# Lambda expression in the indentation can goes a little wrong,
resulting the the closing } being at the wrong indentation level and meaning the remaining part of the file is
incorrectly indented.
This can be a fairly common pattern for when C# wants to peform a UI action from a thread,
and it wants to invoke that action on the main thread
Reviewed By: exv, jbcoe
Differential Revision: https://reviews.llvm.org/D104388
Added:
Modified:
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/FormatTestCSharp.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 45ff319b5841d..f76cb4d341a22 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1482,8 +1482,8 @@ void UnwrappedLineParser::parseStructuralElement() {
}
case tok::equal:
// Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
- // TT_FatArrow. The always start an expression or a child block if
- // followed by a curly.
+ // 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)) {
@@ -1790,14 +1790,20 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
bool HasError = false;
// FIXME: Once we have an expression parser in the UnwrappedLineParser,
- // replace this by using parseAssigmentExpression() inside.
+ // 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();
- // Fat arrows can be followed by simple expressions or by child blocks
- // in curly braces.
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;
}
@@ -1927,6 +1933,12 @@ void UnwrappedLineParser::parseParens() {
parseBracedList();
}
break;
+ case tok::equal:
+ if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
+ parseStructuralElement();
+ else
+ nextToken();
+ break;
case tok::kw_class:
if (Style.Language == FormatStyle::LK_JavaScript)
parseRecord(/*ParseAsExpr=*/true);
diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp
index 651b54cd342a7..3c990339cf748 100644
--- a/clang/unittests/Format/FormatTestCSharp.cpp
+++ b/clang/unittests/Format/FormatTestCSharp.cpp
@@ -640,6 +640,122 @@ class MyClass
};
})",
MicrosoftStyle);
+
+ verifyFormat("void bar()\n"
+ "{\n"
+ " Function(Val, (Action)(() =>\n"
+ " {\n"
+ " lock (mylock)\n"
+ " {\n"
+ " if (true)\n"
+ " {\n"
+ " A.Remove(item);\n"
+ " }\n"
+ " }\n"
+ " }));\n"
+ "}",
+ MicrosoftStyle);
+
+ verifyFormat("void baz()\n"
+ "{\n"
+ " Function(Val, (Action)(() =>\n"
+ " {\n"
+ " using (var a = new Lock())\n"
+ " {\n"
+ " if (true)\n"
+ " {\n"
+ " A.Remove(item);\n"
+ " }\n"
+ " }\n"
+ " }));\n"
+ "}",
+ MicrosoftStyle);
+
+ verifyFormat("void baz()\n"
+ "{\n"
+ " Function(Val, (Action)(() =>\n"
+ " {\n"
+ " if (true)\n"
+ " {\n"
+ " A.Remove(item);\n"
+ " }\n"
+ " }));\n"
+ "}",
+ MicrosoftStyle);
+
+ verifyFormat("void baz()\n"
+ "{\n"
+ " Function(Val, (Action)(() =>\n"
+ " {\n"
+ " do\n"
+ " {\n"
+ " A.Remove(item);\n"
+ " } while (true)\n"
+ " }));\n"
+ "}",
+ MicrosoftStyle);
+
+ verifyFormat("void baz()\n"
+ "{\n"
+ " Function(Val, (Action)(() =>\n"
+ " { A.Remove(item); }));\n"
+ "}",
+ MicrosoftStyle);
+
+ verifyFormat("void bar()\n"
+ "{\n"
+ " Function(Val, (() =>\n"
+ " {\n"
+ " lock (mylock)\n"
+ " {\n"
+ " if (true)\n"
+ " {\n"
+ " A.Remove(item);\n"
+ " }\n"
+ " }\n"
+ " }));\n"
+ "}",
+ MicrosoftStyle);
+ verifyFormat("void bar()\n"
+ "{\n"
+ " Function((() =>\n"
+ " {\n"
+ " lock (mylock)\n"
+ " {\n"
+ " if (true)\n"
+ " {\n"
+ " A.Remove(item);\n"
+ " }\n"
+ " }\n"
+ " }));\n"
+ "}",
+ MicrosoftStyle);
+
+ MicrosoftStyle.IndentWidth = 2;
+ verifyFormat("void bar()\n"
+ "{\n"
+ " Function((() =>\n"
+ " {\n"
+ " lock (mylock)\n"
+ " {\n"
+ " if (true)\n"
+ " {\n"
+ " A.Remove(item);\n"
+ " }\n"
+ " }\n"
+ " }));\n"
+ "}",
+ MicrosoftStyle);
+ verifyFormat("void bar() {\n"
+ " Function((() => {\n"
+ " lock (mylock) {\n"
+ " if (true) {\n"
+ " A.Remove(item);\n"
+ " }\n"
+ " }\n"
+ " }));\n"
+ "}",
+ GoogleStyle);
}
TEST_F(FormatTestCSharp, CSharpObjectInitializers) {
More information about the cfe-commits
mailing list