clang-format: Improve handling of raw string literals.

Especially try to keep existing line breaks before raw string literals,
as the code author might have aligned content to it.

Thereby, clang-format now keeps things like:

  parseStyle(R"(
      BasedOnStyle: Google,
      ColumnLimit: 100)");
  parseStyle(
      R"(BasedOnStyle: Google,
         ColumnLimit: 100)");

llvm-svn: 197368
This commit is contained in:
Daniel Jasper 2013-12-16 07:23:08 +00:00
parent 69b899a127
commit c39b56fe14
4 changed files with 22 additions and 5 deletions

View File

@ -136,7 +136,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (Style.AlwaysBreakBeforeMultilineStrings &&
State.Column > State.Stack.back().Indent && // Breaking saves columns.
!Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) &&
Previous.Type != TT_InlineASMColon && NextIsMultilineString(State))
Previous.Type != TT_InlineASMColon && nextIsMultilineString(State))
return true;
if (((Previous.Type == TT_DictLiteral && Previous.is(tok::l_brace)) ||
Previous.Type == TT_ArrayInitializerLSquare) &&
@ -865,12 +865,13 @@ unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {
return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
}
bool ContinuationIndenter::NextIsMultilineString(const LineState &State) {
bool ContinuationIndenter::nextIsMultilineString(const LineState &State) {
const FormatToken &Current = *State.NextToken;
if (!Current.is(tok::string_literal))
return false;
// We never consider raw string literals "multiline" for the purpose of
// AlwaysBreakBeforeMultilineStrings implementation.
// AlwaysBreakBeforeMultilineStrings implementation as they are special-cased
// (see TokenAnnotator::mustBreakBefore().
if (Current.TokenText.startswith("R\""))
return false;
if (Current.IsMultiline)

View File

@ -115,7 +115,7 @@ private:
///
/// This includes implicitly concatenated strings, strings that will be broken
/// by clang-format and string literals with escaped newlines.
bool NextIsMultilineString(const LineState &State);
bool nextIsMultilineString(const LineState &State);
FormatStyle Style;
SourceManager &SourceMgr;

View File

@ -1412,6 +1412,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
} else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) {
return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU;
} else if (Right.is(tok::string_literal) &&
Right.TokenText.startswith("R\"")) {
// Raw string literals are special wrt. line breaks. The author has made a
// deliberate choice and might have aligned the contents of the string
// literal accordingly. Thus, we try keep existing line breaks.
return Right.NewlinesBefore > 0;
}
return false;
}

View File

@ -6187,7 +6187,7 @@ TEST_F(FormatTest, DontSplitStringLiteralsWithEscapedNewlines) {
TEST_F(FormatTest, CountsCharactersInMultilineRawStringLiterals) {
EXPECT_EQ("f(g(R\"x(raw literal)x\", a), b);",
format("f(g(R\"x(raw literal)x\", a), b);", getGoogleStyle()));
format("f(g(R\"x(raw literal)x\", a), b);", getGoogleStyle()));
EXPECT_EQ("fffffffffff(g(R\"x(\n"
"multiline raw string literal xxxxxxxxxxxxxx\n"
")x\",\n"
@ -6223,6 +6223,16 @@ TEST_F(FormatTest, CountsCharactersInMultilineRawStringLiterals) {
"multiline raw string literal xxxxxxxxxxxxxx\n"
")x\" + bbbbbb);",
getGoogleStyleWithColumns(20)));
EXPECT_EQ("fffffffffff(\n"
" R\"x(\n"
"multiline raw string literal xxxxxxxxxxxxxx\n"
")x\" +\n"
" bbbbbb);",
format("fffffffffff(\n"
" R\"x(\n"
"multiline raw string literal xxxxxxxxxxxxxx\n"
")x\" + bbbbbb);",
getGoogleStyleWithColumns(20)));
}
TEST_F(FormatTest, SkipsUnknownStringLiterals) {