diff options
author | Manuel Klimek <klimek@google.com> | 2013-01-10 11:52:21 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2013-01-10 11:52:21 +0000 |
commit | bb42bf1a8bfd18fa2beec7fcbcb73f738fb455ba (patch) | |
tree | 0764c85a4a442a13ef3caa2d3d3c818db37d0758 | |
parent | 5cf7cf317f684dc61b8a0e4476440b5635b80db4 (diff) |
Fix layout of blocks inside statements.
Previously, we would not indent:
SOME_MACRO({
int i;
});
correctly. This is fixed by adding the trailing }); to the unwrapped
line starting with SOME_MACRO({, so the formatter can correctly match
the braces and indent accordingly.
Also fixes incorrect parsing of initializer lists, like:
int a[] = { 1 };
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172058 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Format/Format.cpp | 4 | ||||
-rw-r--r-- | lib/Format/UnwrappedLineParser.cpp | 88 | ||||
-rw-r--r-- | lib/Format/UnwrappedLineParser.h | 3 | ||||
-rw-r--r-- | unittests/Format/FormatTest.cpp | 24 |
4 files changed, 100 insertions, 19 deletions
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index dfb43afafa..00a4b77980 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -279,7 +279,9 @@ private: if (Newline) { unsigned WhitespaceStartColumn = State.Column; - if (Previous.is(tok::l_brace)) { + if (Current.is(tok::r_brace)) { + State.Column = Line.Level * 2; + } else if (Previous.is(tok::l_brace)) { // FIXME: This does not work with nested static initializers. // Implement a better handling for static initializers and similar // constructs. diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index c09ee311d3..736178e1eb 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -76,6 +76,40 @@ private: FormatToken Token; }; +class ScopedLineState { +public: + ScopedLineState(UnwrappedLineParser &Parser) : Parser(Parser) { + PreBlockLine = Parser.Line.take(); + Parser.Line.reset(new UnwrappedLine(*PreBlockLine)); + assert(Parser.LastInCurrentLine == NULL || + Parser.LastInCurrentLine->Children.empty()); + PreBlockLastToken = Parser.LastInCurrentLine; + PreBlockRootTokenInitialized = Parser.RootTokenInitialized; + Parser.RootTokenInitialized = false; + Parser.LastInCurrentLine = NULL; + } + + ~ScopedLineState() { + if (Parser.RootTokenInitialized) { + Parser.addUnwrappedLine(); + } + assert(!Parser.RootTokenInitialized); + Parser.Line.reset(PreBlockLine); + Parser.RootTokenInitialized = PreBlockRootTokenInitialized; + Parser.LastInCurrentLine = PreBlockLastToken; + assert(Parser.LastInCurrentLine == NULL || + Parser.LastInCurrentLine->Children.empty()); + Parser.MustBreakBeforeNextToken = true; + } + +private: + UnwrappedLineParser &Parser; + + UnwrappedLine *PreBlockLine; + FormatToken* PreBlockLastToken; + bool PreBlockRootTokenInitialized; +}; + UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style, FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback) @@ -204,6 +238,7 @@ void UnwrappedLineParser::parseComments() { } void UnwrappedLineParser::parseStructuralElement() { + assert(!FormatTok.Tok.is(tok::l_brace)); parseComments(); int TokenNumber = 0; @@ -289,6 +324,10 @@ void UnwrappedLineParser::parseStructuralElement() { parseParens(); break; case tok::l_brace: + // A block outside of parentheses must be the last part of a + // structural element. + // FIXME: Figure out cases where this is not true, and add projections for + // them (the one we know is missing are lambdas). parseBlock(); addUnwrappedLine(); return; @@ -301,10 +340,28 @@ void UnwrappedLineParser::parseStructuralElement() { break; case tok::equal: nextToken(); - // Skip initializers as they will be formatted by a later step. - if (FormatTok.Tok.is(tok::l_brace)) - nextToken(); + if (FormatTok.Tok.is(tok::l_brace)) { + parseBracedList(); + } + break; + default: + nextToken(); + break; + } + } while (!eof()); +} + +void UnwrappedLineParser::parseBracedList() { + nextToken(); + + do { + switch (FormatTok.Tok.getKind()) { + case tok::l_brace: + parseBracedList(); break; + case tok::r_brace: + nextToken(); + return; default: nextToken(); break; @@ -323,6 +380,15 @@ void UnwrappedLineParser::parseParens() { case tok::r_paren: nextToken(); return; + case tok::l_brace: + { + nextToken(); + ScopedLineState LineState(*this); + Line->Level += 1; + parseLevel(/*HasOpeningBrace=*/true); + Line->Level -= 1; + } + break; default: nextToken(); break; @@ -626,22 +692,8 @@ void UnwrappedLineParser::readToken() { while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) && ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) || FormatTok.IsFirst)) { - UnwrappedLine* StoredLine = Line.take(); - Line.reset(new UnwrappedLine(*StoredLine)); - assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty()); - FormatToken *StoredLastInCurrentLine = LastInCurrentLine; - bool PreviousInitialized = RootTokenInitialized; - RootTokenInitialized = false; - LastInCurrentLine = NULL; - + ScopedLineState BlockState(*this); parsePPDirective(); - - assert(!RootTokenInitialized); - Line.reset(StoredLine); - RootTokenInitialized = PreviousInitialized; - LastInCurrentLine = StoredLastInCurrentLine; - assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty()); - MustBreakBeforeNextToken = true; } } diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index 16ad37eec6..017daf587f 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/lib/Format/UnwrappedLineParser.h @@ -131,6 +131,7 @@ private: void parsePPUnknown(); void parseComments(); void parseStructuralElement(); + void parseBracedList(); void parseParens(); void parseIfThenElse(); void parseForOrWhileLoop(); @@ -163,6 +164,8 @@ private: const FormatStyle &Style; FormatTokenSource *Tokens; UnwrappedLineConsumer &Callback; + + friend class ScopedLineState; }; } // end namespace format diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 51a0bd6488..860661b432 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -615,6 +615,30 @@ TEST_F(FormatTest, LayoutStatementsAroundPreprocessorDirectives) { " trailing);", getLLVMStyleWithColumns(69)); } +TEST_F(FormatTest, LayoutBlockInsideParens) { + EXPECT_EQ("functionCall({\n" + " int i;\n" + "});", format(" functionCall ( {int i;} );")); +} + +TEST_F(FormatTest, LayoutBlockInsideStatement) { + EXPECT_EQ("SOME_MACRO {\n" + " int i;\n" + "}\n" + "int i;", format(" SOME_MACRO {int i;} int i;")); +} + +TEST_F(FormatTest, LayoutNestedBlocks) { + verifyFormat("void AddOsStrings(unsigned bitmask) {\n" + " struct s {\n" + " int i;\n" + " };\n" + " s kBitsToOs[] = { { 10 } };\n" + " for (int i = 0; i < 10; ++i)\n" + " return;\n" + "}"); +} + //===----------------------------------------------------------------------===// // Line break tests. //===----------------------------------------------------------------------===// |