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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits