From: Daniel Jasper Date: Mon, 17 Dec 2012 14:34:14 +0000 (+0000) Subject: Add basic support for splitting before function calls if it can't be X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9a0b494f999dfd47152565f7bbeaa69b3fef8feb;p=clang Add basic support for splitting before function calls if it can't be avoided. This required a minor modification of the memoization as now the "CurrentPenalty" depends on whether or not we break before the current token. Therefore, the CurrentPenalty should not be memoized but added after retrieving a value from memory. This should not affect the runtime behavior. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170337 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index eb077d39e5..46af06fb41 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -198,7 +198,9 @@ private: else if (Current.Tok.is(tok::lessless) && State.FirstLessLess[ParenLevel] != 0) State.Column = State.FirstLessLess[ParenLevel]; - else if (Previous.Tok.is(tok::equal) && ParenLevel != 0) + else if (ParenLevel != 0 && + (Previous.Tok.is(tok::equal) || Current.Tok.is(tok::arrow) || + Current.Tok.is(tok::period))) // Indent and extra 4 spaces after '=' as it continues an expression. // Don't do that on the top level, as we already indent 4 there. State.Column = State.Indent[ParenLevel] + 4; @@ -271,14 +273,23 @@ private: ++State.ConsumedTokens; } - unsigned splitPenalty(const FormatToken &Token) { - if (Token.Tok.is(tok::semi)) + /// \brief Calculate the panelty for splitting after the token at \p Index. + unsigned splitPenalty(unsigned Index) { + assert(Index < Line.Tokens.size() && + "Tried to calculate penalty for splitting after the last token"); + const FormatToken &Left = Line.Tokens[Index]; + const FormatToken &Right = Line.Tokens[Index + 1]; + if (Left.Tok.is(tok::semi)) return 0; - if (Token.Tok.is(tok::comma)) + if (Left.Tok.is(tok::comma)) return 1; - if (Token.Tok.is(tok::equal) || Token.Tok.is(tok::l_paren) || - Token.Tok.is(tok::pipepipe) || Token.Tok.is(tok::ampamp)) + if (Left.Tok.is(tok::equal) || Left.Tok.is(tok::l_paren) || + Left.Tok.is(tok::pipepipe) || Left.Tok.is(tok::ampamp)) return 2; + + if (Right.Tok.is(tok::arrow) || Right.Tok.is(tok::period)) + return 200; + return 3; } @@ -313,8 +324,7 @@ private: unsigned CurrentPenalty = 0; if (NewLine) { CurrentPenalty += Parameters.PenaltyIndentLevel * State.Indent.size() + - Parameters.PenaltyExtraLine + - splitPenalty(Line.Tokens[State.ConsumedTokens - 1]); + Parameters.PenaltyExtraLine + splitPenalty(State.ConsumedTokens - 1); } addTokenToState(NewLine, true, State); @@ -335,17 +345,21 @@ private: // - are now computing for a smaller or equal StopAt. unsigned SavedResult = I->second.first; unsigned SavedStopAt = I->second.second; - if (SavedResult != UINT_MAX || StopAt <= SavedStopAt) - return SavedResult; + if (SavedResult != UINT_MAX) + return SavedResult + CurrentPenalty; + else if (StopAt <= SavedStopAt) + return UINT_MAX; } unsigned NoBreak = calcPenalty(State, false, StopAt); unsigned WithBreak = calcPenalty(State, true, std::min(StopAt, NoBreak)); unsigned Result = std::min(NoBreak, WithBreak); - if (Result != UINT_MAX) - Result += CurrentPenalty; + + // We have to store 'Result' without adding 'CurrentPenalty' as the latter + // can depend on 'NewLine'. Memory[State] = std::pair(Result, StopAt); - return Result; + + return Result == UINT_MAX ? UINT_MAX : Result + CurrentPenalty; } /// \brief Replaces the whitespace in front of \p Tok. Only call once for @@ -737,9 +751,8 @@ private: if (Right.Tok.is(tok::r_paren) || Right.Tok.is(tok::l_brace) || Right.Tok.is(tok::comment) || Right.Tok.is(tok::greater)) return false; - if (isBinaryOperator(Left)) - return true; - if (Right.Tok.is(tok::lessless)) + if (isBinaryOperator(Left) || Right.Tok.is(tok::lessless) || + Right.Tok.is(tok::arrow) || Right.Tok.is(tok::period)) return true; return Right.Tok.is(tok::colon) || Left.Tok.is(tok::comma) || Left.Tok.is( tok::semi) || Left.Tok.is(tok::equal) || Left.Tok.is(tok::ampamp) || diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 5ce1022d86..bcac37c007 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -444,6 +444,37 @@ TEST_F(FormatTest, UnderstandsEquals) { " 100000000 + 100000000) {\n}"); } +TEST_F(FormatTest, WrapsAtFunctionCallsIfNecessary) { + verifyFormat( + "LoooooooooooooooooooooooooooooooooooooongObject\n" + " .looooooooooooooooooooooooooooooooooooooongFunction();"); + + verifyFormat( + "LoooooooooooooooooooooooooooooooooooooongObject\n" + " ->looooooooooooooooooooooooooooooooooooooongFunction();"); + + verifyFormat( + "LooooooooooooooooooooooooooooooooongObject->shortFunction(Parameter1,\n" + " Parameter2);"); + + verifyFormat( + "ShortObject->shortFunction(\n" + " LooooooooooooooooooooooooooooooooooooooooooooooongParameter1,\n" + " LooooooooooooooooooooooooooooooooooooooooooooooongParameter2);"); + + verifyFormat("loooooooooooooongFunction(\n" + " LoooooooooooooongObject->looooooooooooooooongFunction());"); + + verifyFormat( + "function(LoooooooooooooooooooooooooooooooooooongObject\n" + " ->loooooooooooooooooooooooooooooooooooooooongFunction());"); + + verifyFormat( + "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaa) ||\n" + " aaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n" + "}"); +} + TEST_F(FormatTest, UnderstandsTemplateParameters) { verifyFormat("A a;"); verifyFormat("A > > a;");