From: Daniel Jasper Date: Fri, 23 Aug 2013 11:57:34 +0000 (+0000) Subject: clang-format: Fix corner case for string splitting .. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4df1ff96262b8bde75c6801ef42659f352aa2422;p=clang clang-format: Fix corner case for string splitting .. .. in conjunction with Style.AlwaysBreakBeforeMultilineStrings. Also, simplify the implementation by handling newly split strings and already split strings by the same code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189102 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 005eec82b7..4f6fca9a2b 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -116,12 +116,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { !Current.isOneOf(tok::r_paren, tok::r_brace)) return true; if (Style.AlwaysBreakBeforeMultilineStrings && - State.Column > State.Stack.back().Indent && - Current.is(tok::string_literal) && Previous.isNot(tok::lessless) && - Previous.Type != TT_InlineASMColon && - ((Current.getNextNonComment() && - Current.getNextNonComment()->is(tok::string_literal)) || - (Current.TokenText.find("\\\n") != StringRef::npos))) + State.Column > State.Stack.back().Indent && // Breaking saves columns. + Previous.isNot(tok::lessless) && Previous.Type != TT_InlineASMColon && + NextIsMultilineString(State)) return true; if (!Style.BreakBeforeBinaryOperators) { @@ -547,13 +544,8 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, } State.Column += Current.CodePointCount; - State.NextToken = State.NextToken->Next; - - unsigned Penalty = 0; - if (Newline || !Style.AlwaysBreakBeforeMultilineStrings || - Current.isNot(tok::string_literal) || !Current.CanBreakBefore) - Penalty += breakProtrudingToken(Current, State, DryRun); + unsigned Penalty = breakProtrudingToken(Current, State, DryRun); // If the previous has a special role, let it consume tokens as appropriate. // It is necessary to start at the previous token for the only implemented @@ -688,5 +680,19 @@ unsigned ContinuationIndenter::getColumnLimit() const { return Style.ColumnLimit - (Line.InPPDirective ? 2 : 0); } +bool ContinuationIndenter::NextIsMultilineString(const LineState &State) { + const FormatToken &Current = *State.NextToken; + if (!Current.is(tok::string_literal)) + return false; + if (Current.getNextNonComment() && + Current.getNextNonComment()->is(tok::string_literal)) + return true; // Implicit concatenation. + if (State.Column + Current.CodePointCount + Current.UnbreakableTailLength > + Style.ColumnLimit) + return true; // String will be split. + // String literal might have escaped newlines. + return Current.TokenText.find("\\\n") != StringRef::npos; +} + } // namespace format } // namespace clang diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h index 470d07a22f..e234c3e7ef 100644 --- a/lib/Format/ContinuationIndenter.h +++ b/lib/Format/ContinuationIndenter.h @@ -84,6 +84,13 @@ private: unsigned breakProtrudingToken(const FormatToken &Current, LineState &State, bool DryRun); + /// \brief Returns \c true if the next token starts a multiline string + /// literal. + /// + /// This includes implicitly concatenated strings, strings that will be broken + /// by clang-format and string literals with escaped newlines. + bool NextIsMultilineString(const LineState &State); + FormatStyle Style; SourceManager &SourceMgr; const AnnotatedLine &Line; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 94d7b34632..aec93bb4cf 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -5265,6 +5265,12 @@ TEST_F(FormatTest, BreakStringLiterals) { format("llvm::outs() << " "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaa\";")); + EXPECT_EQ("ffff(\n" + " {\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \"\n" + " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"});", + format("ffff({\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"});", + getGoogleStyle())); FormatStyle AlignLeft = getLLVMStyleWithColumns(12); AlignLeft.AlignEscapedNewlinesLeft = true;