From: Alexander Kornienko Date: Mon, 14 Oct 2013 00:46:35 +0000 (+0000) Subject: Keep track of indentation levels in static initializers for correct indentation with... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f0fc89c358cdd0717c0e12eb4a90e4a6ce956e98;p=clang Keep track of indentation levels in static initializers for correct indentation with tabs. Summary: Store IndentationLevel in ParentState and use it instead of the Line::Level when indening. Also fixed incorrect indentation level calculation in formatFirstToken. Reviewers: djasper Reviewed By: djasper CC: cfe-commits, klimek Differential Revision: http://llvm-reviews.chandlerc.com/D1797 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192563 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 7444685d7a..7632058199 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -73,7 +73,7 @@ LineState ContinuationIndenter::getInitialState(unsigned FirstIndent, State.Column = FirstIndent; State.Line = Line; State.NextToken = Line->First; - State.Stack.push_back(ParenState(FirstIndent, FirstIndent, + State.Stack.push_back(ParenState(FirstIndent, Line->Level, FirstIndent, /*AvoidBinPacking=*/false, /*NoLineBreak=*/false)); State.LineContainsContinuedForLoopSection = false; @@ -404,9 +404,9 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, if (Current.is(tok::comment)) Newlines = std::max(Newlines, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1)); - Whitespaces.replaceWhitespace(Current, Newlines, State.Line->Level, - State.Column, State.Column, - State.Line->InPPDirective); + Whitespaces.replaceWhitespace(Current, Newlines, + State.Stack.back().IndentLevel, State.Column, + State.Column, State.Line->InPPDirective); } if (!Current.isTrailingComment()) @@ -532,6 +532,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, // prepare for the following tokens. if (Current.opensScope()) { unsigned NewIndent; + unsigned NewIndentLevel = State.Stack.back().IndentLevel; bool AvoidBinPacking; if (Current.is(tok::l_brace)) { if (Current.MatchingParen && Current.BlockKind == BK_Block) { @@ -553,9 +554,15 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) State.Stack.pop_back(); NewIndent = State.Stack.back().LastSpace + Style.IndentWidth; + ++NewIndentLevel; } else { - NewIndent = State.Stack.back().LastSpace + - (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth); + NewIndent = State.Stack.back().LastSpace; + if (Style.Cpp11BracedListStyle) + NewIndent += 4; + else { + NewIndent += Style.IndentWidth; + ++NewIndentLevel; + } } const FormatToken *NextNoComment = Current.getNextNonComment(); AvoidBinPacking = Current.BlockKind == BK_Block || @@ -571,9 +578,9 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, Current.PackingKind == PPK_Inconclusive))); } - State.Stack.push_back(ParenState(NewIndent, State.Stack.back().LastSpace, - AvoidBinPacking, - State.Stack.back().NoLineBreak)); + State.Stack.push_back( + ParenState(NewIndent, NewIndentLevel, State.Stack.back().LastSpace, + AvoidBinPacking, State.Stack.back().NoLineBreak)); State.Stack.back().BreakBeforeParameter = Current.BlockKind == BK_Block; ++State.ParenLevel; } diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h index 60e0027ec7..b317565833 100644 --- a/lib/Format/ContinuationIndenter.h +++ b/lib/Format/ContinuationIndenter.h @@ -125,10 +125,10 @@ private: }; struct ParenState { - ParenState(unsigned Indent, unsigned LastSpace, bool AvoidBinPacking, - bool NoLineBreak) - : Indent(Indent), LastSpace(LastSpace), FirstLessLess(0), - BreakBeforeClosingBrace(false), QuestionColumn(0), + ParenState(unsigned Indent, unsigned IndentLevel, unsigned LastSpace, + bool AvoidBinPacking, bool NoLineBreak) + : Indent(Indent), IndentLevel(IndentLevel), LastSpace(LastSpace), + FirstLessLess(0), BreakBeforeClosingBrace(false), QuestionColumn(0), AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false), NoLineBreak(NoLineBreak), ColonPos(0), StartOfFunctionCall(0), StartOfArraySubscripts(0), NestedNameSpecifierContinuation(0), @@ -139,6 +139,9 @@ struct ParenState { /// indented. unsigned Indent; + /// \brief The number of indentation levels of the block. + unsigned IndentLevel; + /// \brief The position of the last space on each level. /// /// Used e.g. to break like: diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 7e92a705ca..ff85767627 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -47,8 +47,8 @@ struct ScalarEnumerationTraits { template <> struct ScalarEnumerationTraits { - static void - enumeration(IO &IO, clang::format::FormatStyle::UseTabStyle &Value) { + static void enumeration(IO &IO, + clang::format::FormatStyle::UseTabStyle &Value) { IO.enumCase(Value, "Never", clang::format::FormatStyle::UT_Never); IO.enumCase(Value, "false", clang::format::FormatStyle::UT_Never); IO.enumCase(Value, "Always", clang::format::FormatStyle::UT_Always); @@ -577,7 +577,7 @@ private: if (!DryRun) { Whitespaces->replaceWhitespace( *LBrace.Children[0]->First, - /*Newlines=*/0, /*IndentLevel=*/1, /*Spaces=*/1, + /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1, /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective); UnwrappedLineFormatter Formatter(Indenter, Whitespaces, Style, *LBrace.Children[0]); @@ -904,8 +904,8 @@ public: bool WasMoved = PreviousLineWasTouched && FirstTok->NewlinesBefore == 0; if (TheLine.First->is(tok::eof)) { if (PreviousLineWasTouched) { - unsigned NewLines = std::min(FirstTok->NewlinesBefore, 1u); - Whitespaces.replaceWhitespace(*TheLine.First, NewLines, + unsigned Newlines = std::min(FirstTok->NewlinesBefore, 1u); + Whitespaces.replaceWhitespace(*TheLine.First, Newlines, /*IndentLevel=*/0, /*Spaces=*/0, /*TargetColumn=*/0); } @@ -916,7 +916,7 @@ public: // Insert a break even if there is a structural error in case where // we break apart a line consisting of multiple unwrapped lines. (FirstTok->NewlinesBefore == 0 || !StructuralError)) { - formatFirstToken(*TheLine.First, PreviousLine, Indent, + formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level, Indent, TheLine.InPPDirective); } else { Indent = LevelIndent = FirstTok->OriginalColumn; @@ -957,7 +957,7 @@ public: // Remove trailing whitespace of the previous line if it was // touched. if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine)) { - formatFirstToken(*Tok, PreviousLine, LevelIndent, + formatFirstToken(*Tok, PreviousLine, TheLine.Level, LevelIndent, TheLine.InPPDirective); } else { Whitespaces.addUntouchableToken(*Tok, TheLine.InPPDirective); @@ -1276,10 +1276,9 @@ private: /// \brief Add a new line and the required indent before the first Token /// of the \c UnwrappedLine if there was no structural parsing error. - /// Returns the indent level of the \c UnwrappedLine. void formatFirstToken(FormatToken &RootToken, - const AnnotatedLine *PreviousLine, unsigned Indent, - bool InPPDirective) { + const AnnotatedLine *PreviousLine, unsigned IndentLevel, + unsigned Indent, bool InPPDirective) { unsigned Newlines = std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); // Remove empty lines before "}" where applicable. @@ -1300,7 +1299,7 @@ private: Newlines = std::min(1u, Newlines); Whitespaces.replaceWhitespace( - RootToken, Newlines, Indent / Style.IndentWidth, Indent, Indent, + RootToken, Newlines, IndentLevel, Indent, Indent, InPPDirective && !RootToken.HasUnescapedNewline); } @@ -1386,8 +1385,8 @@ FormatStyle getStyle(StringRef StyleName, StringRef FileName) { if (StyleName.startswith("{")) { // Parse YAML/JSON style from the command line. if (llvm::error_code ec = parseConfiguration(StyleName, &Style)) { - llvm::errs() << "Error parsing -style: " << ec.message() - << ", using " << FallbackStyle << " style\n"; + llvm::errs() << "Error parsing -style: " << ec.message() << ", using " + << FallbackStyle << " style\n"; } return Style; } @@ -1401,8 +1400,7 @@ FormatStyle getStyle(StringRef StyleName, StringRef FileName) { SmallString<128> Path(FileName); llvm::sys::fs::make_absolute(Path); - for (StringRef Directory = Path; - !Directory.empty(); + for (StringRef Directory = Path; !Directory.empty(); Directory = llvm::sys::path::parent_path(Directory)) { if (!llvm::sys::fs::is_directory(Directory)) continue; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index afe9c8b1cc..5a8b5d6f52 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -5968,6 +5968,21 @@ TEST_F(FormatTest, ConfigurableUseOfTab) { Tab)); Tab.UseTab = FormatStyle::UT_ForIndentation; + verifyFormat("T t[] = {\n" + "\taaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + "\taaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + "\taaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + "\taaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + "\taaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + "\taaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + "};", + Tab); + verifyFormat("enum A {\n" + "\ta1,\n" + "\ta2,\n" + "\ta3\n" + "};", + Tab); EXPECT_EQ("if (aaaaaaaa && // q\n" " bb) // w\n" "\t;",