From 753a5114f9076c545c33cf3ced0d76e27bc0a2d5 Mon Sep 17 00:00:00 2001 From: Manuel Klimek <klimek@google.com> Date: Wed, 4 Sep 2013 13:25:30 +0000 Subject: [PATCH] Implement parsing of blocks (^{ ... }) in the unwrapped line parser. This patch makes sure we produce the right number of unwrapped lines, a follow-up patch will make the whitespace formatting consistent. Before: void f() { int i = {[operation setCompletionBlock : ^{ [self onOperationDone]; }] } ; } After: void f() { int i = {[operation setCompletionBlock : ^{ [self onOperationDone]; }] }; } git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189932 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/UnwrappedLineParser.cpp | 44 ++++++++++++++++++++---------- lib/Format/UnwrappedLineParser.h | 1 + unittests/Format/FormatTest.cpp | 11 ++++++++ 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index f58ee82303..c780fdb566 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -346,6 +346,20 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel) { Line->Level = InitialLevel; } +void UnwrappedLineParser::parseChildBlock() { + FormatTok->BlockKind = BK_Block; + nextToken(); + { + ScopedLineState LineState(*this); + ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, + /*MustBeDeclaration=*/false); + Line->Level += 1; + parseLevel(/*HasOpeningBrace=*/true); + Line->Level -= 1; + } + nextToken(); +} + void UnwrappedLineParser::parsePPDirective() { assert(FormatTok->Tok.is(tok::hash) && "'#' expected"); ScopedMacroState MacroState(*Line, Tokens, FormatTok, StructuralError); @@ -591,6 +605,12 @@ void UnwrappedLineParser::parseStructuralElement() { case tok::l_paren: parseParens(); break; + case tok::caret: + nextToken(); + if (FormatTok->is(tok::l_brace)) { + parseChildBlock(); + } + break; case tok::l_brace: if (!tryToParseBracedList()) { // A block outside of parentheses must be the last part of a @@ -674,17 +694,7 @@ void UnwrappedLineParser::tryToParseLambda() { break; } } - FormatTok->BlockKind = BK_Block; - nextToken(); - { - ScopedLineState LineState(*this); - ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, - /*MustBeDeclaration=*/false); - Line->Level += 1; - parseLevel(/*HasOpeningBrace=*/true); - Line->Level -= 1; - } - nextToken(); + parseChildBlock(); } bool UnwrappedLineParser::tryToParseLambdaIntroducer() { @@ -741,9 +751,15 @@ void UnwrappedLineParser::parseBracedList() { // here, otherwise our bail-out scenarios below break. The better solution // might be to just implement a more or less complete expression parser. switch (FormatTok->Tok.getKind()) { - case tok::l_square: - tryToParseLambda(); - break; + case tok::caret: + nextToken(); + if (FormatTok->is(tok::l_brace)) { + parseChildBlock(); + } + break; + case tok::l_square: + tryToParseLambda(); + break; case tok::l_brace: // Assume there are no blocks inside a braced init list apart // from the ones we explicitly parse out (like lambdas). diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index 4660b1dbac..5c59da3beb 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/lib/Format/UnwrappedLineParser.h @@ -66,6 +66,7 @@ private: void parseFile(); void parseLevel(bool HasOpeningBrace); void parseBlock(bool MustBeDeclaration, bool AddLevel = true); + void parseChildBlock(); void parsePPDirective(); void parsePPDefine(); void parsePPIf(); diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index d2b2dfd99b..32226fc501 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -6311,5 +6311,16 @@ TEST_F(FormatTest, FormatsLambdas) { "}\n"); } +TEST_F(FormatTest, FormatsBlocks) { + // FIXME: Make whitespace formatting consistent. Ask a ObjC dev how + // it would ideally look. + verifyFormat("[operation setCompletionBlock:^{\n" + " [self onOperationDone];\n" + "}];\n"); + verifyFormat("int i = {[operation setCompletionBlock : ^{\n" + " [self onOperationDone];\n" + "}] };\n"); +} + } // end namespace tooling } // end namespace clang -- 2.40.0