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];
   }] };
 }

llvm-svn: 189932
This commit is contained in:
Manuel Klimek 2013-09-04 13:25:30 +00:00
parent dc647a2603
commit 516e054c05
3 changed files with 42 additions and 14 deletions

View File

@ -346,6 +346,20 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel) {
Line->Level = InitialLevel; 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() { void UnwrappedLineParser::parsePPDirective() {
assert(FormatTok->Tok.is(tok::hash) && "'#' expected"); assert(FormatTok->Tok.is(tok::hash) && "'#' expected");
ScopedMacroState MacroState(*Line, Tokens, FormatTok, StructuralError); ScopedMacroState MacroState(*Line, Tokens, FormatTok, StructuralError);
@ -591,6 +605,12 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::l_paren: case tok::l_paren:
parseParens(); parseParens();
break; break;
case tok::caret:
nextToken();
if (FormatTok->is(tok::l_brace)) {
parseChildBlock();
}
break;
case tok::l_brace: case tok::l_brace:
if (!tryToParseBracedList()) { if (!tryToParseBracedList()) {
// A block outside of parentheses must be the last part of a // A block outside of parentheses must be the last part of a
@ -674,17 +694,7 @@ void UnwrappedLineParser::tryToParseLambda() {
break; break;
} }
} }
FormatTok->BlockKind = BK_Block; parseChildBlock();
nextToken();
{
ScopedLineState LineState(*this);
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
/*MustBeDeclaration=*/false);
Line->Level += 1;
parseLevel(/*HasOpeningBrace=*/true);
Line->Level -= 1;
}
nextToken();
} }
bool UnwrappedLineParser::tryToParseLambdaIntroducer() { bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
@ -741,9 +751,15 @@ void UnwrappedLineParser::parseBracedList() {
// here, otherwise our bail-out scenarios below break. The better solution // here, otherwise our bail-out scenarios below break. The better solution
// might be to just implement a more or less complete expression parser. // might be to just implement a more or less complete expression parser.
switch (FormatTok->Tok.getKind()) { switch (FormatTok->Tok.getKind()) {
case tok::l_square: case tok::caret:
tryToParseLambda(); nextToken();
break; if (FormatTok->is(tok::l_brace)) {
parseChildBlock();
}
break;
case tok::l_square:
tryToParseLambda();
break;
case tok::l_brace: case tok::l_brace:
// Assume there are no blocks inside a braced init list apart // Assume there are no blocks inside a braced init list apart
// from the ones we explicitly parse out (like lambdas). // from the ones we explicitly parse out (like lambdas).

View File

@ -66,6 +66,7 @@ private:
void parseFile(); void parseFile();
void parseLevel(bool HasOpeningBrace); void parseLevel(bool HasOpeningBrace);
void parseBlock(bool MustBeDeclaration, bool AddLevel = true); void parseBlock(bool MustBeDeclaration, bool AddLevel = true);
void parseChildBlock();
void parsePPDirective(); void parsePPDirective();
void parsePPDefine(); void parsePPDefine();
void parsePPIf(); void parsePPIf();

View File

@ -6311,5 +6311,16 @@ TEST_F(FormatTest, FormatsLambdas) {
"}\n"); "}\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 tooling
} // end namespace clang } // end namespace clang