From f9a84b5f577dda8468f471ba2e2e5791f9962ce1 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Fri, 1 Mar 2013 16:48:32 +0000 Subject: [PATCH] Normal indent for last element of builder-type call. In builder type call, we indent to the laster function calls. However, for the last element of such a call, we don't need to do so, as that normally just wastes space and does not increase readability. Before: aaaaaa->aaaaaa->aaaaaa( // break aaaaaa); aaaaaaaaaaaaaaaaaaaaa->aaaaaaaaaaaaaaaaaaaaaa ->aaaaaaaaaaaaaaaaaaaaaaaaaa( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); After: aaaaaa->aaaaaa->aaaaaa( // break aaaaaa); aaaaaaaaaaaaaaaaaaaaa->aaaaaaaaaaaaaaaaaaaaaa->aaaaaaaaaaaaaaaaaaaaaaaaaa( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); llvm-svn: 176352 --- clang/lib/Format/Format.cpp | 18 +++++++++++++----- clang/lib/Format/TokenAnnotator.cpp | 11 ++++++++--- clang/lib/Format/TokenAnnotator.h | 5 ++++- clang/unittests/Format/FormatTest.cpp | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 5fd4915..bb7e0fa 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -339,7 +339,8 @@ private: : Indent(Indent), LastSpace(LastSpace), FirstLessLess(0), BreakBeforeClosingBrace(false), QuestionColumn(0), AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false), - HasMultiParameterLine(HasMultiParameterLine), ColonPos(0) {} + HasMultiParameterLine(HasMultiParameterLine), ColonPos(0), + StartOfFunctionCall(0) {} /// \brief The position to which a specific parenthesis level needs to be /// indented. @@ -382,6 +383,9 @@ private: /// \brief The position of the colon in an ObjC method declaration/call. unsigned ColonPos; + /// \brief The start of the most recent function in a builder-type call. + unsigned StartOfFunctionCall; + bool operator<(const ParenState &Other) const { if (Indent != Other.Indent) return Indent < Other.Indent; @@ -401,6 +405,8 @@ private: return HasMultiParameterLine; if (ColonPos != Other.ColonPos) return ColonPos < Other.ColonPos; + if (StartOfFunctionCall != Other.StartOfFunctionCall) + return StartOfFunctionCall < Other.StartOfFunctionCall; return false; } }; @@ -622,9 +628,6 @@ private: // If this function has multiple parameters, indent nested calls from // the start of the first parameter. State.Stack.back().LastSpace = State.Column; - else if ((Current.is(tok::period) || Current.is(tok::arrow)) && - Line.Type == LT_BuilderTypeCall && State.ParenLevel == 0) - State.Stack.back().LastSpace = State.Column; } return moveStateToNextToken(State, DryRun); @@ -642,6 +645,10 @@ private: State.Stack.back().FirstLessLess = State.Column; if (Current.is(tok::question)) State.Stack.back().QuestionColumn = State.Column; + if ((Current.is(tok::period) || Current.is(tok::arrow)) && + Line.Type == LT_BuilderTypeCall && State.ParenLevel == 0) + State.Stack.back().StartOfFunctionCall = + Current.LastInChainOfCalls ? 0 : State.Column; if (Current.Type == TT_CtorInitializerColon) { if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) State.Stack.back().AvoidBinPacking = true; @@ -667,7 +674,8 @@ private: NewIndent = 2 + State.Stack.back().LastSpace; AvoidBinPacking = false; } else { - NewIndent = 4 + State.Stack.back().LastSpace; + NewIndent = 4 + std::max(State.Stack.back().LastSpace, + State.Stack.back().StartOfFunctionCall); AvoidBinPacking = !Style.BinPackParameters || State.Stack.back().AvoidBinPacking; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index b9e35126..125619c 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -464,6 +464,7 @@ private: public: LineType parseLine() { int PeriodsAndArrows = 0; + AnnotatedToken *LastPeriodOrArrow = NULL; bool CanBeBuilderTypeStmt = true; if (CurrentToken->is(tok::hash)) { parsePreprocessorDirective(); @@ -472,8 +473,10 @@ public: while (CurrentToken != NULL) { if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; - if (CurrentToken->is(tok::period) || CurrentToken->is(tok::arrow)) + if (CurrentToken->is(tok::period) || CurrentToken->is(tok::arrow)) { ++PeriodsAndArrows; + LastPeriodOrArrow = CurrentToken; + } AnnotatedToken *TheToken = CurrentToken; if (!consumeToken()) return LT_Invalid; @@ -485,8 +488,10 @@ public: return LT_VirtualFunctionDecl; // Assume a builder-type call if there are 2 or more "." and "->". - if (PeriodsAndArrows >= 2 && CanBeBuilderTypeStmt) + if (PeriodsAndArrows >= 2 && CanBeBuilderTypeStmt) { + LastPeriodOrArrow->LastInChainOfCalls = true; return LT_BuilderTypeCall; + } if (Line.First.Type == TT_ObjCMethodSpecifier) { if (Contexts.back().FirstObjCSelectorName != NULL) @@ -934,7 +939,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, if (Level != prec::Unknown) return Level; - + return 3; } diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index aa78779..b79ee97 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -75,7 +75,7 @@ public: ClosesTemplateDeclaration(false), MatchingParen(NULL), ParameterCount(0), BindingStrength(0), SplitPenalty(0), LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0), - FakeRParens(0) { + FakeRParens(0), LastInChainOfCalls(false) { } bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); } @@ -127,6 +127,9 @@ public: /// \brief Insert this many fake ) after this token for correct indentation. unsigned FakeRParens; + /// \brief Is this the last "." or "->" in a builder-type call? + bool LastInChainOfCalls; + const AnnotatedToken *getPreviousNoneComment() const { AnnotatedToken *Tok = Parent; while (Tok != NULL && Tok->is(tok::comment)) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 052c852..9b640cb 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -1331,7 +1331,7 @@ TEST_F(FormatTest, FormatsBuilderPattern) { " ->aaaaaaaa(aaaaaaaaaaaaaaa);"); verifyFormat( "aaaaaaaaaaaaaaaaaaa()->aaaaaa(bbbbb)->aaaaaaaaaaaaaaaaaaa( // break\n" - " aaaaaaaaaaaaaa);"); + " aaaaaaaaaaaaaa);"); verifyFormat( "aaaaaaaaaaaaaaaaaaaaaaa *aaaaaaaaa = aaaaaa->aaaaaaaaaaaa()\n" " ->aaaaaaaaaaaaaaaa(\n" -- 2.7.4