forked from OSchip/llvm-project
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. llvm-svn: 189102
This commit is contained in:
parent
377496bbad
commit
f438cb7619
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue