]> granicus.if.org Git - clang/commitdiff
clang-format: Fix corner case for string splitting ..
authorDaniel Jasper <djasper@google.com>
Fri, 23 Aug 2013 11:57:34 +0000 (11:57 +0000)
committerDaniel Jasper <djasper@google.com>
Fri, 23 Aug 2013 11:57:34 +0000 (11:57 +0000)
.. 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

lib/Format/ContinuationIndenter.cpp
lib/Format/ContinuationIndenter.h
unittests/Format/FormatTest.cpp

index 005eec82b7bb0237b05a31632fcb86ad1fdcf028..4f6fca9a2b83dd4e29aa00416640b45d8648cd08 100644 (file)
@@ -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
index 470d07a22f979fd0609cf7c5c4a556c04f94ff4d..e234c3e7efd0ab5ddc48452ab65f2b8ebd54056c 100644 (file)
@@ -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;
index 94d7b34632afebe92e22c945a67c7cf2169e65e4..aec93bb4cf460d2b09d49281b6d8cb0a18aed722 100644 (file)
@@ -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;