<div dir="ltr"><span style="font-family:monospace,monospace">Hello Krasimir,<br><br>This commit broke one our builders:<br><a href="http://lab.llvm.org:8011/builders/ubuntu-gcc7.1-werror/builds/2680">http://lab.llvm.org:8011/builders/ubuntu-gcc7.1-werror/builds/2680</a><br><br>. . .<br>FAILED: /usr/local/gcc-7.1/bin/g++-7.1   -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/clang/lib/Format -I/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/tools/clang/lib/Format -I/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/tools/clang/include -Itools/clang/include -Iinclude -I/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/include -Wno-noexcept-type -fPIC -fvisibility-inlines-hidden -Werror -Werror=date-time -std=c++11 -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -fno-strict-aliasing -O3  -fPIC   -UNDEBUG  -fno-exceptions -fno-rtti -MD -MT tools/clang/lib/Format/CMakeFiles/clangFormat.dir/Format.cpp.o -MF tools/clang/lib/Format/CMakeFiles/clangFormat.dir/Format.cpp.o.d -o tools/clang/lib/Format/CMakeFiles/clangFormat.dir/Format.cpp.o -c /home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/tools/clang/lib/Format/Format.cpp<br>/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/tools/clang/lib/Format/Format.cpp:48:74: error: extra ‘;’ [-Werror=pedantic]<br> LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory);<br>                                                                          ^<br>/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/tools/clang/lib/Format/Format.cpp:49:74: error: extra ‘;’ [-Werror=pedantic]<br> LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat);<br>                                                                          ^<br>cc1plus: all warnings being treated as errors<br><br><br>Please have a look?<br><br>Thanks<br><br>Galina</span><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Oct 30, 2017 at 7:01 AM, Krasimir Georgiev via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: krasimir<br>
Date: Mon Oct 30 07:01:50 2017<br>
New Revision: 316903<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=316903&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=316903&view=rev</a><br>
Log:<br>
[clang-format] Format raw string literals<br>
<br>
Summary:<br>
This patch adds raw string literal formatting.<br>
<br>
Reviewers: djasper, klimek<br>
<br>
Reviewed By: klimek<br>
<br>
Subscribers: klimek, mgorny<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D35943" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D35943</a><br>
<br>
Added:<br>
    cfe/trunk/lib/Format/<wbr>FormatInternal.h<br>
    cfe/trunk/unittests/Format/<wbr>FormatTestRawStrings.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/<wbr>Format/Format.h<br>
    cfe/trunk/lib/Format/<wbr>ContinuationIndenter.cpp<br>
    cfe/trunk/lib/Format/<wbr>ContinuationIndenter.h<br>
    cfe/trunk/lib/Format/Format.<wbr>cpp<br>
    cfe/trunk/lib/Format/<wbr>FormatTokenLexer.cpp<br>
    cfe/trunk/lib/Format/<wbr>FormatTokenLexer.h<br>
    cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.cpp<br>
    cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.h<br>
    cfe/trunk/lib/Format/<wbr>SortJavaScriptImports.cpp<br>
    cfe/trunk/lib/Format/<wbr>TokenAnalyzer.cpp<br>
    cfe/trunk/lib/Format/<wbr>TokenAnalyzer.h<br>
    cfe/trunk/lib/Format/<wbr>TokenAnnotator.cpp<br>
    cfe/trunk/lib/Format/<wbr>TokenAnnotator.h<br>
    cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.cpp<br>
    cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.h<br>
    cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.cpp<br>
    cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.h<br>
    cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.cpp<br>
    cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.h<br>
    cfe/trunk/lib/Format/<wbr>WhitespaceManager.cpp<br>
    cfe/trunk/lib/Format/<wbr>WhitespaceManager.h<br>
    cfe/trunk/unittests/Format/<wbr>CMakeLists.txt<br>
    cfe/trunk/unittests/Format/<wbr>FormatTest.cpp<br>
<br>
Modified: cfe/trunk/include/clang/<wbr>Format/Format.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Format/Format.h?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>Format/Format.h (original)<br>
+++ cfe/trunk/include/clang/<wbr>Format/Format.h Mon Oct 30 07:01:50 2017<br>
@@ -1327,6 +1327,41 @@ struct FormatStyle {<br>
   /// \brief Pointer and reference alignment style.<br>
   PointerAlignmentStyle PointerAlignment;<br>
<br>
+  /// See documentation of ``RawStringFormats``.<br>
+  struct RawStringFormat {<br>
+    /// \brief The delimiter that this raw string format matches.<br>
+    std::string Delimiter;<br>
+    /// \brief The language of this raw string.<br>
+    LanguageKind Language;<br>
+    /// \brief The style name on which this raw string format is based on.<br>
+    /// If not specified, the raw string format is based on the style that this<br>
+    /// format is based on.<br>
+    std::string BasedOnStyle;<br>
+    bool operator==(const RawStringFormat &Other) const {<br>
+      return Delimiter == Other.Delimiter && Language == Other.Language &&<br>
+             BasedOnStyle == Other.BasedOnStyle;<br>
+    }<br>
+  };<br>
+<br>
+  /// \brief Raw string delimiters denoting that the raw string contents are<br>
+  /// code in a particular language and can be reformatted.<br>
+  ///<br>
+  /// A raw string with a matching delimiter will be reformatted assuming the<br>
+  /// specified language based on a predefined style given by 'BasedOnStyle'.<br>
+  /// If 'BasedOnStyle' is not found, the formatting is based on llvm style.<br>
+  ///<br>
+  /// To configure this in the .clang-format file, use:<br>
+  /// \code{.yaml}<br>
+  ///   RawStringFormats:<br>
+  ///     - Delimiter: 'pb'<br>
+  ///       Language:  TextProto<br>
+  ///       BasedOnStyle: llvm<br>
+  ///     - Delimiter: 'proto'<br>
+  ///       Language:  TextProto<br>
+  ///       BasedOnStyle: google<br>
+  /// \endcode<br>
+  std::vector<RawStringFormat> RawStringFormats;<br>
+<br>
   /// \brief If ``true``, clang-format will attempt to re-flow comments.<br>
   /// \code<br>
   ///    false:<br>
@@ -1592,6 +1627,7 @@ struct FormatStyle {<br>
            PenaltyExcessCharacter == R.PenaltyExcessCharacter &&<br>
            PenaltyReturnTypeOnItsOwnLine == R.<wbr>PenaltyReturnTypeOnItsOwnLine &&<br>
            PointerAlignment == R.PointerAlignment &&<br>
+           RawStringFormats == R.RawStringFormats &&<br>
            SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&<br>
            SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword &&<br>
            SpaceBeforeAssignmentOperators == R.<wbr>SpaceBeforeAssignmentOperators &&<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>ContinuationIndenter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>ContinuationIndenter.cpp?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>ContinuationIndenter.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>ContinuationIndenter.cpp Mon Oct 30 07:01:50 2017<br>
@@ -14,6 +14,7 @@<br>
<br>
 #include "ContinuationIndenter.h"<br>
 #include "BreakableToken.h"<br>
+#include "FormatInternal.h"<br>
 #include "WhitespaceManager.h"<br>
 #include "clang/Basic/<wbr>OperatorPrecedence.h"<br>
 #include "clang/Basic/SourceManager.h"<br>
@@ -76,6 +77,53 @@ static bool opensProtoMessageField(const<br>
            (LessTok.Previous && LessTok.Previous->is(tok::<wbr>equal))));<br>
 }<br>
<br>
+// Returns the delimiter of a raw string literal, or None if TokenText is not<br>
+// the text of a raw string literal. The delimiter could be the empty string.<br>
+// For example, the delimiter of R"deli(cont)deli" is deli.<br>
+static llvm::Optional<StringRef> getRawStringDelimiter(<wbr>StringRef TokenText) {<br>
+  if (TokenText.size() < 5 // The smallest raw string possible is 'R"()"'.<br>
+      || !TokenText.startswith("R\"") || !TokenText.endswith("\""))<br>
+    return None;<br>
+<br>
+  // A raw string starts with 'R"<delimiter>(' and delimiter is ascii and has<br>
+  // size at most 16 by the standard, so the first '(' must be among the first<br>
+  // 19 bytes.<br>
+  size_t LParenPos = TokenText.substr(0, 19).find_first_of('(');<br>
+  if (LParenPos == StringRef::npos)<br>
+    return None;<br>
+  StringRef Delimiter = TokenText.substr(2, LParenPos - 2);<br>
+<br>
+  // Check that the string ends in ')Delimiter"'.<br>
+  size_t RParenPos = TokenText.size() - Delimiter.size() - 2;<br>
+  if (TokenText[RParenPos] != ')')<br>
+    return None;<br>
+  if (!TokenText.substr(RParenPos + 1).startswith(Delimiter))<br>
+    return None;<br>
+  return Delimiter;<br>
+}<br>
+<br>
+RawStringFormatStyleManager::<wbr>RawStringFormatStyleManager(<br>
+    const FormatStyle &CodeStyle) {<br>
+  for (const auto &RawStringFormat : CodeStyle.RawStringFormats) {<br>
+    FormatStyle Style;<br>
+    if (!getPredefinedStyle(<wbr>RawStringFormat.BasedOnStyle,<br>
+                            RawStringFormat.Language, &Style)) {<br>
+      Style = getLLVMStyle();<br>
+      Style.Language = RawStringFormat.Language;<br>
+    }<br>
+    Style.ColumnLimit = CodeStyle.ColumnLimit;<br>
+    DelimiterStyle.insert({<wbr>RawStringFormat.Delimiter, Style});<br>
+  }<br>
+}<br>
+<br>
+llvm::Optional<FormatStyle><br>
+RawStringFormatStyleManager::<wbr>get(StringRef Delimiter) const {<br>
+  auto It = DelimiterStyle.find(Delimiter)<wbr>;<br>
+  if (It == DelimiterStyle.end())<br>
+    return None;<br>
+  return It->second;<br>
+}<br>
+<br>
 ContinuationIndenter::<wbr>ContinuationIndenter(const FormatStyle &Style,<br>
                                            const AdditionalKeywords &Keywords,<br>
                                            const SourceManager &SourceMgr,<br>
@@ -85,14 +133,18 @@ ContinuationIndenter::<wbr>ContinuationIndent<br>
     : Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),<br>
       Whitespaces(Whitespaces), Encoding(Encoding),<br>
       BinPackInconclusiveFunctions(<wbr>BinPackInconclusiveFunctions),<br>
-      CommentPragmasRegex(Style.<wbr>CommentPragmas) {}<br>
+      CommentPragmasRegex(Style.<wbr>CommentPragmas), RawStringFormats(Style) {}<br>
<br>
 LineState ContinuationIndenter::<wbr>getInitialState(unsigned FirstIndent,<br>
+                                                unsigned FirstStartColumn,<br>
                                                 const AnnotatedLine *Line,<br>
                                                 bool DryRun) {<br>
   LineState State;<br>
   State.FirstIndent = FirstIndent;<br>
-  State.Column = FirstIndent;<br>
+  if (FirstStartColumn && Line->First->NewlinesBefore == 0)<br>
+    State.Column = FirstStartColumn;<br>
+  else<br>
+    State.Column = FirstIndent;<br>
   // With preprocessor directive indentation, the line starts on column 0<br>
   // since it's indented after the hash, but FirstIndent is set to the<br>
   // preprocessor indent.<br>
@@ -1216,6 +1268,89 @@ void ContinuationIndenter::<wbr>moveStateToNe<br>
   State.Stack.back().<wbr>BreakBeforeParameter = true;<br>
 }<br>
<br>
+static unsigned getLastLineEndColumn(StringRef Text, unsigned StartColumn,<br>
+                                     unsigned TabWidth,<br>
+                                     encoding::Encoding Encoding) {<br>
+  size_t LastNewlinePos = Text.find_last_of("\n");<br>
+  if (LastNewlinePos == StringRef::npos) {<br>
+    return StartColumn +<br>
+           encoding::columnWidthWithTabs(<wbr>Text, StartColumn, TabWidth, Encoding);<br>
+  } else {<br>
+    return encoding::columnWidthWithTabs(<wbr>Text.substr(LastNewlinePos),<br>
+                                         /*StartColumn=*/0, TabWidth, Encoding);<br>
+  }<br>
+}<br>
+<br>
+unsigned ContinuationIndenter::<wbr>reformatRawStringLiteral(<br>
+    const FormatToken &Current, unsigned StartColumn, LineState &State,<br>
+    StringRef Delimiter, const FormatStyle &RawStringStyle, bool DryRun) {<br>
+  // The text of a raw string is between the leading 'R"delimiter(' and the<br>
+  // trailing 'delimiter)"'.<br>
+  unsigned PrefixSize = 3 + Delimiter.size();<br>
+  unsigned SuffixSize = 2 + Delimiter.size();<br>
+<br>
+  // The first start column is the column the raw text starts.<br>
+  unsigned FirstStartColumn = StartColumn + PrefixSize;<br>
+<br>
+  // The next start column is the intended indentation a line break inside<br>
+  // the raw string at level 0. It is determined by the following rules:<br>
+  //   - if the content starts on newline, it is one level more than the current<br>
+  //     indent, and<br>
+  //   - if the content does not start on a newline, it is the first start<br>
+  //     column.<br>
+  // These rules have the advantage that the formatted content both does not<br>
+  // violate the rectangle rule and visually flows within the surrounding<br>
+  // source.<br>
+  bool ContentStartsOnNewline = Current.TokenText[PrefixSize] == '\n';<br>
+  unsigned NextStartColumn = ContentStartsOnNewline<br>
+                                 ? State.Stack.back().Indent + Style.IndentWidth<br>
+                                 : FirstStartColumn;<br>
+<br>
+  // The last start column is the column the raw string suffix starts if it is<br>
+  // put on a newline.<br>
+  // The last start column is the intended indentation of the raw string postfix<br>
+  // if it is put on a newline. It is determined by the following rules:<br>
+  //   - if the raw string prefix starts on a newline, it is the column where<br>
+  //     that raw string prefix starts, and<br>
+  //   - if the raw string prefix does not start on a newline, it is the current<br>
+  //     indent.<br>
+  unsigned LastStartColumn = Current.NewlinesBefore<br>
+                                 ? FirstStartColumn - PrefixSize<br>
+                                 : State.Stack.back().Indent;<br>
+<br>
+  std::string RawText =<br>
+      Current.TokenText.substr(<wbr>PrefixSize).drop_back(<wbr>SuffixSize);<br>
+<br>
+  std::pair<tooling::<wbr>Replacements, unsigned> Fixes = internal::reformat(<br>
+      RawStringStyle, RawText, {tooling::Range(0, RawText.size())},<br>
+      FirstStartColumn, NextStartColumn, LastStartColumn, "<stdin>",<br>
+      /*FormattingAttemptStatus=*/<wbr>nullptr);<br>
+<br>
+  auto NewCode = applyAllReplacements(RawText, Fixes.first);<br>
+  tooling::Replacements NoFixes;<br>
+  if (!NewCode) {<br>
+    State.Column += Current.ColumnWidth;<br>
+    return 0;<br>
+  }<br>
+  if (!DryRun) {<br>
+    SourceLocation OriginLoc =<br>
+        Current.Tok.getLocation().<wbr>getLocWithOffset(PrefixSize);<br>
+    for (const tooling::Replacement &Fix : Fixes.first) {<br>
+      auto Err = Whitespaces.addReplacement(<wbr>tooling::Replacement(<br>
+          SourceMgr, OriginLoc.getLocWithOffset(<wbr>Fix.getOffset()),<br>
+          Fix.getLength(), Fix.getReplacementText()));<br>
+      if (Err) {<br>
+        llvm::errs() << "Failed to reformat raw string: "<br>
+                     << llvm::toString(std::move(Err)) << "\n";<br>
+      }<br>
+    }<br>
+  }<br>
+  unsigned RawLastLineEndColumn = getLastLineEndColumn(<br>
+      *NewCode, FirstStartColumn, Style.TabWidth, Encoding);<br>
+  State.Column = RawLastLineEndColumn + SuffixSize;<br>
+  return Fixes.second;<br>
+}<br>
+<br>
 unsigned ContinuationIndenter::<wbr>addMultilineToken(const FormatToken &Current,<br>
                                                  LineState &State) {<br>
   if (!Current.IsMultiline)<br>
@@ -1238,9 +1373,18 @@ unsigned ContinuationIndenter::<wbr>addMultil<br>
 unsigned ContinuationIndenter::<wbr>breakProtrudingToken(const FormatToken &Current,<br>
                                                     LineState &State,<br>
                                                     bool DryRun) {<br>
-  // Don't break multi-line tokens other than block comments. Instead, just<br>
-  // update the state.<br>
-  if (Current.isNot(TT_<wbr>BlockComment) && Current.IsMultiline)<br>
+  // Compute the raw string style to use in case this is a raw string literal<br>
+  // that can be reformatted.<br>
+  llvm::Optional<StringRef> Delimiter = None;<br>
+  llvm::Optional<FormatStyle> RawStringStyle = None;<br>
+  if (Current.isStringLiteral())<br>
+    Delimiter = getRawStringDelimiter(Current.<wbr>TokenText);<br>
+  if (Delimiter)<br>
+    RawStringStyle = RawStringFormats.get(*<wbr>Delimiter);<br>
+<br>
+  // Don't break multi-line tokens other than block comments and raw string<br>
+  // literals. Instead, just update the state.<br>
+  if (Current.isNot(TT_<wbr>BlockComment) && !RawStringStyle && Current.IsMultiline)<br>
     return addMultilineToken(Current, State);<br>
<br>
   // Don't break implicit string literals or import statements.<br>
@@ -1275,6 +1419,11 @@ unsigned ContinuationIndenter::<wbr>breakProt<br>
     if (Current.<wbr>IsUnterminatedLiteral)<br>
       return 0;<br>
<br>
+    if (RawStringStyle) {<br>
+      RawStringStyle->ColumnLimit = ColumnLimit;<br>
+      return reformatRawStringLiteral(<wbr>Current, StartColumn, State, *Delimiter,<br>
+                                      *RawStringStyle, DryRun);<br>
+    }<br>
     StringRef Text = Current.TokenText;<br>
     StringRef Prefix;<br>
     StringRef Postfix;<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>ContinuationIndenter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>ContinuationIndenter.h?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>ContinuationIndenter.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>ContinuationIndenter.h Mon Oct 30 07:01:50 2017<br>
@@ -20,6 +20,8 @@<br>
 #include "FormatToken.h"<br>
 #include "clang/Format/Format.h"<br>
 #include "llvm/Support/Regex.h"<br>
+#include <map><br>
+#include <tuple><br>
<br>
 namespace clang {<br>
 class SourceManager;<br>
@@ -30,8 +32,17 @@ class AnnotatedLine;<br>
 struct FormatToken;<br>
 struct LineState;<br>
 struct ParenState;<br>
+struct RawStringFormatStyleManager;<br>
 class WhitespaceManager;<br>
<br>
+struct RawStringFormatStyleManager {<br>
+  llvm::StringMap<FormatStyle> DelimiterStyle;<br>
+<br>
+  RawStringFormatStyleManager(<wbr>const FormatStyle &CodeStyle);<br>
+<br>
+  llvm::Optional<FormatStyle> get(StringRef Delimiter) const;<br>
+};<br>
+<br>
 class ContinuationIndenter {<br>
 public:<br>
   /// \brief Constructs a \c ContinuationIndenter to format \p Line starting in<br>
@@ -44,9 +55,11 @@ public:<br>
                        bool BinPackInconclusiveFunctions);<br>
<br>
   /// \brief Get the initial state, i.e. the state after placing \p Line's<br>
-  /// first token at \p FirstIndent.<br>
-  LineState getInitialState(unsigned FirstIndent, const AnnotatedLine *Line,<br>
-                            bool DryRun);<br>
+  /// first token at \p FirstIndent. When reformatting a fragment of code, as in<br>
+  /// the case of formatting inside raw string literals, \p FirstStartColumn is<br>
+  /// the column at which the state of the parent formatter is.<br>
+  LineState getInitialState(unsigned FirstIndent, unsigned FirstStartColumn,<br>
+                            const AnnotatedLine *Line, bool DryRun);<br>
<br>
   // FIXME: canBreak and mustBreak aren't strictly indentation-related. Find a<br>
   // better home.<br>
@@ -88,15 +101,24 @@ private:<br>
   /// \brief Update 'State' with the next token opening a nested block.<br>
   void moveStateToNewBlock(LineState &State);<br>
<br>
+  /// \brief Reformats a raw string literal.<br>
+  ///<br>
+  /// \returns An extra penalty induced by reformatting the token.<br>
+  unsigned reformatRawStringLiteral(const FormatToken &Current,<br>
+                                    unsigned StartColumn, LineState &State,<br>
+                                    StringRef Delimiter,<br>
+                                    const FormatStyle &RawStringStyle,<br>
+                                    bool DryRun);<br>
+<br>
   /// \brief If the current token sticks out over the end of the line, break<br>
   /// it if possible.<br>
   ///<br>
   /// \returns An extra penalty if a token was broken, otherwise 0.<br>
   ///<br>
-  /// The returned penalty will cover the cost of the additional line breaks and<br>
-  /// column limit violation in all lines except for the last one. The penalty<br>
-  /// for the column limit violation in the last line (and in single line<br>
-  /// tokens) is handled in \c addNextStateToQueue.<br>
+  /// The returned penalty will cover the cost of the additional line breaks<br>
+  /// and column limit violation in all lines except for the last one. The<br>
+  /// penalty for the column limit violation in the last line (and in single<br>
+  /// line tokens) is handled in \c addNextStateToQueue.<br>
   unsigned breakProtrudingToken(const FormatToken &Current, LineState &State,<br>
                                 bool DryRun);<br>
<br>
@@ -143,6 +165,7 @@ private:<br>
   encoding::Encoding Encoding;<br>
   bool BinPackInconclusiveFunctions;<br>
   llvm::Regex CommentPragmasRegex;<br>
+  const RawStringFormatStyleManager RawStringFormats;<br>
 };<br>
<br>
 struct ParenState {<br>
<br>
Modified: cfe/trunk/lib/Format/Format.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>Format.cpp?rev=316903&r1=<wbr>316902&r2=316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/Format.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Format/Format.<wbr>cpp Mon Oct 30 07:01:50 2017<br>
@@ -16,6 +16,7 @@<br>
 #include "clang/Format/Format.h"<br>
 #include "AffectedRangeManager.h"<br>
 #include "ContinuationIndenter.h"<br>
+#include "FormatInternal.h"<br>
 #include "FormatTokenLexer.h"<br>
 #include "NamespaceEndCommentsFixer.h"<br>
 #include "SortJavaScriptImports.h"<br>
@@ -44,7 +45,8 @@<br>
<br>
 using clang::format::FormatStyle;<br>
<br>
-LLVM_YAML_IS_SEQUENCE_VECTOR(<wbr>clang::format::FormatStyle::<wbr>IncludeCategory)<br>
+LLVM_YAML_IS_SEQUENCE_VECTOR(<wbr>clang::format::FormatStyle::<wbr>IncludeCategory);<br>
+LLVM_YAML_IS_SEQUENCE_VECTOR(<wbr>clang::format::FormatStyle::<wbr>RawStringFormat);<br>
<br>
 namespace llvm {<br>
 namespace yaml {<br>
@@ -389,6 +391,7 @@ template <> struct MappingTraits<FormatS<br>
     IO.mapOptional("<wbr>PenaltyReturnTypeOnItsOwnLine"<wbr>,<br>
                    Style.<wbr>PenaltyReturnTypeOnItsOwnLine)<wbr>;<br>
     IO.mapOptional("<wbr>PointerAlignment", Style.PointerAlignment);<br>
+    IO.mapOptional("<wbr>RawStringFormats", Style.RawStringFormats);<br>
     IO.mapOptional("<wbr>ReflowComments", Style.ReflowComments);<br>
     IO.mapOptional("SortIncludes", Style.SortIncludes);<br>
     IO.mapOptional("<wbr>SortUsingDeclarations", Style.SortUsingDeclarations);<br>
@@ -441,6 +444,14 @@ template <> struct MappingTraits<FormatS<br>
   }<br>
 };<br>
<br>
+template <> struct MappingTraits<FormatStyle::<wbr>RawStringFormat> {<br>
+  static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {<br>
+    IO.mapOptional("Delimiter", Format.Delimiter);<br>
+    IO.mapOptional("Language", Format.Language);<br>
+    IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);<br>
+  }<br>
+};<br>
+<br>
 // Allows to read vector<FormatStyle> while keeping default values.<br>
 // IO.getContext() should contain a pointer to the FormatStyle structure, that<br>
 // will be used to get default values for missing keys.<br>
@@ -620,6 +631,7 @@ FormatStyle getLLVMStyle() {<br>
   LLVMStyle.<wbr>SpacesBeforeTrailingComments = 1;<br>
   LLVMStyle.Standard = FormatStyle::LS_Cpp11;<br>
   LLVMStyle.UseTab = FormatStyle::UT_Never;<br>
+  LLVMStyle.RawStringFormats = {{"pb", FormatStyle::LK_TextProto, "google"}};<br>
   LLVMStyle.ReflowComments = true;<br>
   LLVMStyle.SpacesInParentheses = false;<br>
   LLVMStyle.<wbr>SpacesInSquareBrackets = false;<br>
@@ -895,7 +907,7 @@ public:<br>
   JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)<br>
       : TokenAnalyzer(Env, Style) {}<br>
<br>
-  tooling::Replacements<br>
+  std::pair<tooling::<wbr>Replacements, unsigned><br>
   analyze(TokenAnnotator &Annotator,<br>
           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
           FormatTokenLexer &Tokens) override {<br>
@@ -903,7 +915,7 @@ public:<br>
                                           AnnotatedLines.end());<br>
     tooling::Replacements Result;<br>
     requoteJSStringLiteral(<wbr>AnnotatedLines, Result);<br>
-    return Result;<br>
+    return {Result, 0};<br>
   }<br>
<br>
 private:<br>
@@ -984,7 +996,7 @@ public:<br>
             FormattingAttemptStatus *Status)<br>
       : TokenAnalyzer(Env, Style), Status(Status) {}<br>
<br>
-  tooling::Replacements<br>
+  std::pair<tooling::<wbr>Replacements, unsigned><br>
   analyze(TokenAnnotator &Annotator,<br>
           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
           FormatTokenLexer &Tokens) override {<br>
@@ -1003,13 +1015,20 @@ public:<br>
     ContinuationIndenter Indenter(Style, Tokens.getKeywords(),<br>
                                   Env.getSourceManager(), Whitespaces, Encoding,<br>
                                   BinPackInconclusiveFunctions);<br>
-    UnwrappedLineFormatter(&<wbr>Indenter, &Whitespaces, Style, Tokens.getKeywords(),<br>
-                           Env.getSourceManager(), Status)<br>
-        .format(AnnotatedLines);<br>
+    unsigned Penalty =<br>
+        UnwrappedLineFormatter(&<wbr>Indenter, &Whitespaces, Style,<br>
+                               Tokens.getKeywords(), Env.getSourceManager(),<br>
+                               Status)<br>
+            .format(AnnotatedLines, /*DryRun=*/false,<br>
+                    /*AdditionalIndent=*/0,<br>
+                    /*FixBadIndentation=*/false,<br>
+                    /*FirstStartColumn=*/Env.<wbr>getFirstStartColumn(),<br>
+                    /*NextStartColumn=*/Env.<wbr>getNextStartColumn(),<br>
+                    /*LastStartColumn=*/Env.<wbr>getLastStartColumn());<br>
     for (const auto &R : Whitespaces.<wbr>generateReplacements())<br>
       if (Result.add(R))<br>
-        return Result;<br>
-    return Result;<br>
+        return {Result, 0};<br>
+    return {Result, Penalty};<br>
   }<br>
<br>
 private:<br>
@@ -1097,7 +1116,7 @@ public:<br>
         DeletedTokens(FormatTokenLess(<wbr>Env.getSourceManager())) {}<br>
<br>
   // FIXME: eliminate unused parameters.<br>
-  tooling::Replacements<br>
+  std::pair<tooling::<wbr>Replacements, unsigned><br>
   analyze(TokenAnnotator &Annotator,<br>
           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
           FormatTokenLexer &Tokens) override {<br>
@@ -1125,7 +1144,7 @@ public:<br>
       }<br>
     }<br>
<br>
-    return generateFixes();<br>
+    return {generateFixes(), 0};<br>
   }<br>
<br>
 private:<br>
@@ -1906,19 +1925,22 @@ cleanupAroundReplacements(<wbr>StringRef Code<br>
   return processReplacements(Cleanup, Code, NewReplaces, Style);<br>
 }<br>
<br>
-tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,<br>
-                               ArrayRef<tooling::Range> Ranges,<br>
-                               StringRef FileName,<br>
-                               FormattingAttemptStatus *Status) {<br>
+namespace internal {<br>
+std::pair<tooling::<wbr>Replacements, unsigned><br>
+reformat(const FormatStyle &Style, StringRef Code,<br>
+         ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,<br>
+         unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,<br>
+         FormattingAttemptStatus *Status) {<br>
   FormatStyle Expanded = expandPresets(Style);<br>
   if (Expanded.DisableFormat)<br>
-    return tooling::Replacements();<br>
+    return {tooling::Replacements(), 0};<br>
   if (isLikelyXml(Code))<br>
-    return tooling::Replacements();<br>
+    return {tooling::Replacements(), 0};<br>
   if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))<br>
-    return tooling::Replacements();<br>
+    return {tooling::Replacements(), 0};<br>
<br>
-  typedef std::function<tooling::<wbr>Replacements(const Environment &)><br>
+  typedef std::function<std::pair<<wbr>tooling::Replacements, unsigned>(<br>
+      const Environment &)><br>
       AnalyzerPass;<br>
   SmallVector<AnalyzerPass, 4> Passes;<br>
<br>
@@ -1944,26 +1966,42 @@ tooling::Replacements reformat(const For<br>
     return Formatter(Env, Expanded, Status).process();<br>
   });<br>
<br>
-  std::unique_ptr<Environment> Env =<br>
-      Environment::<wbr>CreateVirtualEnvironment(Code, FileName, Ranges);<br>
+  std::unique_ptr<Environment> Env = Environment::<wbr>CreateVirtualEnvironment(<br>
+      Code, FileName, Ranges, FirstStartColumn, NextStartColumn,<br>
+      LastStartColumn);<br>
   llvm::Optional<std::string> CurrentCode = None;<br>
   tooling::Replacements Fixes;<br>
+  unsigned Penalty = 0;<br>
   for (size_t I = 0, E = Passes.size(); I < E; ++I) {<br>
-    tooling::Replacements PassFixes = Passes[I](*Env);<br>
+    std::pair<tooling::<wbr>Replacements, unsigned> PassFixes = Passes[I](*Env);<br>
     auto NewCode = applyAllReplacements(<br>
-        CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes);<br>
+        CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);<br>
     if (NewCode) {<br>
-      Fixes = Fixes.merge(PassFixes);<br>
+      Fixes = Fixes.merge(PassFixes.first);<br>
+      Penalty += PassFixes.second;<br>
       if (I + 1 < E) {<br>
         CurrentCode = std::move(*NewCode);<br>
         Env = Environment::<wbr>CreateVirtualEnvironment(<br>
             *CurrentCode, FileName,<br>
-            tooling::<wbr>calculateRangesAfterReplacemen<wbr>ts(Fixes, Ranges));<br>
+            tooling::<wbr>calculateRangesAfterReplacemen<wbr>ts(Fixes, Ranges),<br>
+            FirstStartColumn, NextStartColumn, LastStartColumn);<br>
       }<br>
     }<br>
   }<br>
<br>
-  return Fixes;<br>
+  return {Fixes, Penalty};<br>
+}<br>
+} // namespace internal<br>
+<br>
+tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,<br>
+                               ArrayRef<tooling::Range> Ranges,<br>
+                               StringRef FileName,<br>
+                               FormattingAttemptStatus *Status) {<br>
+  return internal::reformat(Style, Code, Ranges,<br>
+                            /*FirstStartColumn=*/0,<br>
+                            /*NextStartColumn=*/0,<br>
+                            /*LastStartColumn=*/0, FileName, Status)<br>
+      .first;<br>
 }<br>
<br>
 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,<br>
@@ -1975,7 +2013,7 @@ tooling::Replacements cleanup(const Form<br>
   std::unique_ptr<Environment> Env =<br>
       Environment::<wbr>CreateVirtualEnvironment(Code, FileName, Ranges);<br>
   Cleaner Clean(*Env, Style);<br>
-  return Clean.process();<br>
+  return Clean.process().first;<br>
 }<br>
<br>
 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,<br>
@@ -1995,7 +2033,7 @@ tooling::Replacements fixNamespaceEndCom<br>
   std::unique_ptr<Environment> Env =<br>
       Environment::<wbr>CreateVirtualEnvironment(Code, FileName, Ranges);<br>
   NamespaceEndCommentsFixer Fix(*Env, Style);<br>
-  return Fix.process();<br>
+  return Fix.process().first;<br>
 }<br>
<br>
 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,<br>
@@ -2005,7 +2043,7 @@ tooling::Replacements sortUsingDeclarati<br>
   std::unique_ptr<Environment> Env =<br>
       Environment::<wbr>CreateVirtualEnvironment(Code, FileName, Ranges);<br>
   UsingDeclarationsSorter Sorter(*Env, Style);<br>
-  return Sorter.process();<br>
+  return Sorter.process().first;<br>
 }<br>
<br>
 LangOptions getFormattingLangOpts(const FormatStyle &Style) {<br>
<br>
Added: cfe/trunk/lib/Format/<wbr>FormatInternal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatInternal.h?rev=316903&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>FormatInternal.h?rev=316903&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>FormatInternal.h (added)<br>
+++ cfe/trunk/lib/Format/<wbr>FormatInternal.h Mon Oct 30 07:01:50 2017<br>
@@ -0,0 +1,79 @@<br>
+//===--- FormatInternal.h - Format C++ code ---------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief This file declares Format APIs to be used internally by the<br>
+/// formatting library implementation.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_CLANG_LIB_FORMAT_<wbr>FORMATINTERNAL_H<br>
+#define LLVM_CLANG_LIB_FORMAT_<wbr>FORMATINTERNAL_H<br>
+<br>
+namespace clang {<br>
+namespace format {<br>
+namespace internal {<br>
+<br>
+/// \brief Reformats the given \p Ranges in the code fragment \p Code.<br>
+///<br>
+/// A fragment of code could conceptually be surrounded by other code that might<br>
+/// constrain how that fragment is laid out.<br>
+/// For example, consider the fragment of code between 'R"(' and ')"',<br>
+/// exclusive, in the following code:<br>
+///<br>
+/// void outer(int x) {<br>
+///   string inner = R"(name: data<br>
+///                     ^ FirstStartColumn<br>
+///     value: {<br>
+///       x: 1<br>
+///     ^ NextStartColumn<br>
+///     }<br>
+///   )";<br>
+///   ^ LastStartColumn<br>
+/// }<br>
+///<br>
+/// The outer code can influence the inner fragment as follows:<br>
+///   * \p FirstStartColumn specifies the column at which \p Code starts.<br>
+///   * \p NextStartColumn specifies the additional indent dictated by the<br>
+///     surrounding code. It is applied to the rest of the lines of \p Code.<br>
+///   * \p LastStartColumn specifies the column at which the last line of<br>
+///     \p Code should end, in case the last line is an empty line.<br>
+///<br>
+///     In the case where the last line of the fragment contains content,<br>
+///     the fragment ends at the end of that content and \p LastStartColumn is<br>
+///     not taken into account, for example in:<br>
+///<br>
+///     void block() {<br>
+///       string inner = R"(name: value)";<br>
+///     }<br>
+///<br>
+/// Each range is extended on either end to its next bigger logic unit, i.e.<br>
+/// everything that might influence its formatting or might be influenced by its<br>
+/// formatting.<br>
+///<br>
+/// Returns a pair P, where:<br>
+///   * P.first are the ``Replacements`` necessary to make all \p Ranges comply<br>
+///     with \p Style.<br>
+///   * P.second is the penalty induced by formatting the fragment \p Code.<br>
+///     If the formatting of the fragment doesn't have a notion of penalty,<br>
+///     returns 0.<br>
+///<br>
+/// If ``Status`` is non-null, its value will be populated with the status of<br>
+/// this formatting attempt. See \c FormattingAttemptStatus.<br>
+std::pair<tooling::<wbr>Replacements, unsigned><br>
+reformat(const FormatStyle &Style, StringRef Code,<br>
+         ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,<br>
+         unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,<br>
+         FormattingAttemptStatus *Status);<br>
+<br>
+} // namespace internal<br>
+} // namespace format<br>
+} // namespace clang<br>
+<br>
+#endif<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>FormatTokenLexer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>FormatTokenLexer.cpp?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>FormatTokenLexer.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>FormatTokenLexer.cpp Mon Oct 30 07:01:50 2017<br>
@@ -24,10 +24,10 @@ namespace clang {<br>
 namespace format {<br>
<br>
 FormatTokenLexer::<wbr>FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,<br>
-                                   const FormatStyle &Style,<br>
+                                   unsigned Column, const FormatStyle &Style,<br>
                                    encoding::Encoding Encoding)<br>
     : FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::<wbr>NORMAL}),<br>
-      Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),<br>
+      Column(Column), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),<br>
       Style(Style), IdentTable(<wbr>getFormattingLangOpts(Style)),<br>
       Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),<br>
       FormattingDisabled(false), MacroBlockBeginRegex(Style.<wbr>MacroBlockBegin),<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>FormatTokenLexer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>FormatTokenLexer.h?rev=316903&<wbr>r1=316902&r2=316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>FormatTokenLexer.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>FormatTokenLexer.h Mon Oct 30 07:01:50 2017<br>
@@ -36,7 +36,7 @@ enum LexerState {<br>
<br>
 class FormatTokenLexer {<br>
 public:<br>
-  FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,<br>
+  FormatTokenLexer(const SourceManager &SourceMgr, FileID ID, unsigned Column,<br>
                    const FormatStyle &Style, encoding::Encoding Encoding);<br>
<br>
   ArrayRef<FormatToken *> lex();<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/NamespaceEndCommentsFixer.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.cpp?<wbr>rev=316903&r1=316902&r2=<wbr>316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.cpp Mon Oct 30 07:01:50 2017<br>
@@ -137,7 +137,7 @@ NamespaceEndCommentsFixer::<wbr>NamespaceEndC<br>
                                                      const FormatStyle &Style)<br>
     : TokenAnalyzer(Env, Style) {}<br>
<br>
-tooling::Replacements NamespaceEndCommentsFixer::<wbr>analyze(<br>
+std::pair<tooling::<wbr>Replacements, unsigned> NamespaceEndCommentsFixer::<wbr>analyze(<br>
     TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
     FormatTokenLexer &Tokens) {<br>
   const SourceManager &SourceMgr = Env.getSourceManager();<br>
@@ -206,7 +206,7 @@ tooling::Replacements NamespaceEndCommen<br>
     }<br>
     StartLineIndex = SIZE_MAX;<br>
   }<br>
-  return Fixes;<br>
+  return {Fixes, 0};<br>
 }<br>
<br>
 } // namespace format<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/NamespaceEndCommentsFixer.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.h?<wbr>rev=316903&r1=316902&r2=<wbr>316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>NamespaceEndCommentsFixer.h Mon Oct 30 07:01:50 2017<br>
@@ -25,7 +25,7 @@ class NamespaceEndCommentsFixer : public<br>
 public:<br>
   NamespaceEndCommentsFixer(<wbr>const Environment &Env, const FormatStyle &Style);<br>
<br>
-  tooling::Replacements<br>
+  std::pair<tooling::<wbr>Replacements, unsigned><br>
   analyze(TokenAnnotator &Annotator,<br>
           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
           FormatTokenLexer &Tokens) override;<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>SortJavaScriptImports.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/SortJavaScriptImports.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>SortJavaScriptImports.cpp?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>SortJavaScriptImports.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>SortJavaScriptImports.cpp Mon Oct 30 07:01:50 2017<br>
@@ -123,7 +123,7 @@ public:<br>
       : TokenAnalyzer(Env, Style),<br>
         FileContents(Env.<wbr>getSourceManager().<wbr>getBufferData(Env.getFileID())<wbr>) {}<br>
<br>
-  tooling::Replacements<br>
+  std::pair<tooling::<wbr>Replacements, unsigned><br>
   analyze(TokenAnnotator &Annotator,<br>
           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
           FormatTokenLexer &Tokens) override {<br>
@@ -138,7 +138,7 @@ public:<br>
         parseModuleReferences(<wbr>Keywords, AnnotatedLines);<br>
<br>
     if (References.empty())<br>
-      return Result;<br>
+      return {Result, 0};<br>
<br>
     SmallVector<unsigned, 16> Indices;<br>
     for (unsigned i = 0, e = References.size(); i != e; ++i)<br>
@@ -168,7 +168,7 @@ public:<br>
     }<br>
<br>
     if (ReferencesInOrder && SymbolsInOrder)<br>
-      return Result;<br>
+      return {Result, 0};<br>
<br>
     SourceRange InsertionPoint = References[0].Range;<br>
     InsertionPoint.setEnd(<wbr>References[References.size() - 1].Range.getEnd());<br>
@@ -202,7 +202,7 @@ public:<br>
       assert(false);<br>
     }<br>
<br>
-    return Result;<br>
+    return {Result, 0};<br>
   }<br>
<br>
 private:<br>
@@ -449,7 +449,7 @@ tooling::Replacements sortJavaScriptImpo<br>
   std::unique_ptr<Environment> Env =<br>
       Environment::<wbr>CreateVirtualEnvironment(Code, FileName, Ranges);<br>
   JavaScriptImportSorter Sorter(*Env, Style);<br>
-  return Sorter.process();<br>
+  return Sorter.process().first;<br>
 }<br>
<br>
 } // end namespace format<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>TokenAnalyzer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnalyzer.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>TokenAnalyzer.cpp?rev=316903&<wbr>r1=316902&r2=316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>TokenAnalyzer.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>TokenAnalyzer.cpp Mon Oct 30 07:01:50 2017<br>
@@ -38,7 +38,10 @@ namespace format {<br>
 // Code.<br>
 std::unique_ptr<Environment><br>
 Environment::<wbr>CreateVirtualEnvironment(<wbr>StringRef Code, StringRef FileName,<br>
-                                      ArrayRef<tooling::Range> Ranges) {<br>
+                                      ArrayRef<tooling::Range> Ranges,<br>
+                                      unsigned FirstStartColumn,<br>
+                                      unsigned NextStartColumn,<br>
+                                      unsigned LastStartColumn) {<br>
   // This is referenced by `FileMgr` and will be released by `FileMgr` when it<br>
   // is deleted.<br>
   IntrusiveRefCntPtr<vfs::<wbr>InMemoryFileSystem> InMemoryFileSystem(<br>
@@ -70,9 +73,9 @@ Environment::<wbr>CreateVirtualEnvironment(St<br>
     SourceLocation End = Start.getLocWithOffset(Range.<wbr>getLength());<br>
     CharRanges.push_back(<wbr>CharSourceRange::getCharRange(<wbr>Start, End));<br>
   }<br>
-  return llvm::make_unique<Environment><wbr>(ID, std::move(FileMgr),<br>
-                                        std::move(VirtualSM),<br>
-                                        std::move(Diagnostics), CharRanges);<br>
+  return llvm::make_unique<Environment><wbr>(<br>
+      ID, std::move(FileMgr), std::move(VirtualSM), std::move(Diagnostics),<br>
+      CharRanges, FirstStartColumn, NextStartColumn, LastStartColumn);<br>
 }<br>
<br>
 TokenAnalyzer::TokenAnalyzer(<wbr>const Environment &Env, const FormatStyle &Style)<br>
@@ -89,14 +92,16 @@ TokenAnalyzer::TokenAnalyzer(<wbr>const Envir<br>
                      << "\n");<br>
 }<br>
<br>
-tooling::Replacements TokenAnalyzer::process() {<br>
+std::pair<tooling::<wbr>Replacements, unsigned> TokenAnalyzer::process() {<br>
   tooling::Replacements Result;<br>
-  FormatTokenLexer Tokens(Env.getSourceManager(), Env.getFileID(), Style,<br>
-                          Encoding);<br>
+  FormatTokenLexer Tokens(Env.getSourceManager(), Env.getFileID(),<br>
+                          Env.getFirstStartColumn(), Style, Encoding);<br>
<br>
-  UnwrappedLineParser Parser(Style, Tokens.getKeywords(), Tokens.lex(), *this);<br>
+  UnwrappedLineParser Parser(Style, Tokens.getKeywords(),<br>
+                             Env.getFirstStartColumn(), Tokens.lex(), *this);<br>
   Parser.parse();<br>
   assert(UnwrappedLines.rbegin()<wbr>->empty());<br>
+  unsigned Penalty = 0;<br>
   for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE; ++Run) {<br>
     DEBUG(llvm::dbgs() << "Run " << Run << "...\n");<br>
     SmallVector<AnnotatedLine *, 16> AnnotatedLines;<br>
@@ -107,13 +112,13 @@ tooling::Replacements TokenAnalyzer::pro<br>
       Annotator.annotate(*<wbr>AnnotatedLines.back());<br>
     }<br>
<br>
-    tooling::Replacements RunResult =<br>
+    std::pair<tooling::<wbr>Replacements, unsigned> RunResult =<br>
         analyze(Annotator, AnnotatedLines, Tokens);<br>
<br>
     DEBUG({<br>
       llvm::dbgs() << "Replacements for run " << Run << ":\n";<br>
-      for (tooling::Replacements::const_<wbr>iterator I = RunResult.begin(),<br>
-                                                 E = RunResult.end();<br>
+      for (tooling::Replacements::const_<wbr>iterator I = RunResult.first.begin(),<br>
+                                                 E = RunResult.first.end();<br>
            I != E; ++I) {<br>
         llvm::dbgs() << I->toString() << "\n";<br>
       }<br>
@@ -121,17 +126,19 @@ tooling::Replacements TokenAnalyzer::pro<br>
     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>
       delete AnnotatedLines[i];<br>
     }<br>
-    for (const auto &R : RunResult) {<br>
+<br>
+    Penalty += RunResult.second;<br>
+    for (const auto &R : RunResult.first) {<br>
       auto Err = Result.add(R);<br>
       // FIXME: better error handling here. For now, simply return an empty<br>
       // Replacements to indicate failure.<br>
       if (Err) {<br>
         llvm::errs() << llvm::toString(std::move(Err)) << "\n";<br>
-        return tooling::Replacements();<br>
+        return {tooling::Replacements(), 0};<br>
       }<br>
     }<br>
   }<br>
-  return Result;<br>
+  return {Result, Penalty};<br>
 }<br>
<br>
 void TokenAnalyzer::<wbr>consumeUnwrappedLine(const UnwrappedLine &TheLine) {<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>TokenAnalyzer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnalyzer.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>TokenAnalyzer.h?rev=316903&r1=<wbr>316902&r2=316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>TokenAnalyzer.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>TokenAnalyzer.h Mon Oct 30 07:01:50 2017<br>
@@ -37,21 +37,37 @@ namespace format {<br>
 class Environment {<br>
 public:<br>
   Environment(SourceManager &SM, FileID ID, ArrayRef<CharSourceRange> Ranges)<br>
-      : ID(ID), CharRanges(Ranges.begin(), Ranges.end()), SM(SM) {}<br>
+      : ID(ID), CharRanges(Ranges.begin(), Ranges.end()), SM(SM),<br>
+      FirstStartColumn(0),<br>
+      NextStartColumn(0),<br>
+      LastStartColumn(0) {}<br>
<br>
   Environment(FileID ID, std::unique_ptr<FileManager> FileMgr,<br>
               std::unique_ptr<SourceManager> VirtualSM,<br>
               std::unique_ptr<<wbr>DiagnosticsEngine> Diagnostics,<br>
-              const std::vector<CharSourceRange> &CharRanges)<br>
+              const std::vector<CharSourceRange> &CharRanges,<br>
+              unsigned FirstStartColumn,<br>
+              unsigned NextStartColumn,<br>
+              unsigned LastStartColumn)<br>
       : ID(ID), CharRanges(CharRanges.begin(), CharRanges.end()),<br>
-        SM(*VirtualSM), FileMgr(std::move(FileMgr)),<br>
+        SM(*VirtualSM),<br>
+        FirstStartColumn(<wbr>FirstStartColumn),<br>
+        NextStartColumn(<wbr>NextStartColumn),<br>
+        LastStartColumn(<wbr>LastStartColumn),<br>
+        FileMgr(std::move(FileMgr)),<br>
         VirtualSM(std::move(VirtualSM)<wbr>), Diagnostics(std::move(<wbr>Diagnostics)) {}<br>
<br>
-  // This sets up an virtual file system with file \p FileName containing \p<br>
-  // Code.<br>
+  // This sets up an virtual file system with file \p FileName containing the<br>
+  // fragment \p Code. Assumes that \p Code starts at \p FirstStartColumn,<br>
+  // that the next lines of \p Code should start at \p NextStartColumn, and<br>
+  // that \p Code should end at \p LastStartColumn if it ends in newline.<br>
+  // See also the documentation of clang::format::internal::<wbr>reformat.<br>
   static std::unique_ptr<Environment><br>
   CreateVirtualEnvironment(<wbr>StringRef Code, StringRef FileName,<br>
-                           ArrayRef<tooling::Range> Ranges);<br>
+                           ArrayRef<tooling::Range> Ranges,<br>
+                           unsigned FirstStartColumn = 0,<br>
+                           unsigned NextStartColumn = 0,<br>
+                           unsigned LastStartColumn = 0);<br>
<br>
   FileID getFileID() const { return ID; }<br>
<br>
@@ -59,10 +75,25 @@ public:<br>
<br>
   const SourceManager &getSourceManager() const { return SM; }<br>
<br>
+  // Returns the column at which the fragment of code managed by this<br>
+  // environment starts.<br>
+  unsigned getFirstStartColumn() const { return FirstStartColumn; }<br>
+<br>
+  // Returns the column at which subsequent lines of the fragment of code<br>
+  // managed by this environment should start.<br>
+  unsigned getNextStartColumn() const { return NextStartColumn; }<br>
+<br>
+  // Returns the column at which the fragment of code managed by this<br>
+  // environment should end if it ends in a newline.<br>
+  unsigned getLastStartColumn() const { return LastStartColumn; }<br>
+<br>
 private:<br>
   FileID ID;<br>
   SmallVector<CharSourceRange, 8> CharRanges;<br>
   SourceManager &SM;<br>
+  unsigned FirstStartColumn;<br>
+  unsigned NextStartColumn;<br>
+  unsigned LastStartColumn;<br>
<br>
   // The order of these fields are important - they should be in the same order<br>
   // as they are created in `CreateVirtualEnvironment` so that they can be<br>
@@ -76,10 +107,10 @@ class TokenAnalyzer : public UnwrappedLi<br>
 public:<br>
   TokenAnalyzer(const Environment &Env, const FormatStyle &Style);<br>
<br>
-  tooling::Replacements process();<br>
+  std::pair<tooling::<wbr>Replacements, unsigned> process();<br>
<br>
 protected:<br>
-  virtual tooling::Replacements<br>
+  virtual std::pair<tooling::<wbr>Replacements, unsigned><br>
   analyze(TokenAnnotator &Annotator,<br>
           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
           FormatTokenLexer &Tokens) = 0;<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>TokenAnnotator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>TokenAnnotator.cpp?rev=316903&<wbr>r1=316902&r2=316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>TokenAnnotator.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>TokenAnnotator.cpp Mon Oct 30 07:01:50 2017<br>
@@ -1891,7 +1891,8 @@ void TokenAnnotator::<wbr>calculateFormatting<br>
   }<br>
<br>
   Line.First->TotalLength =<br>
-      Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth;<br>
+      Line.First->IsMultiline ? Style.ColumnLimit<br>
+                              : Line.FirstStartColumn + Line.First->ColumnWidth;<br>
   FormatToken *Current = Line.First->Next;<br>
   bool InFunctionDecl = Line.MightBeFunctionDecl;<br>
   while (Current) {<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>TokenAnnotator.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>TokenAnnotator.h?rev=316903&<wbr>r1=316902&r2=316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>TokenAnnotator.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>TokenAnnotator.h Mon Oct 30 07:01:50 2017<br>
@@ -43,7 +43,8 @@ public:<br>
         InPPDirective(Line.<wbr>InPPDirective),<br>
         MustBeDeclaration(Line.<wbr>MustBeDeclaration), MightBeFunctionDecl(false),<br>
         IsMultiVariableDeclStmt(false)<wbr>, Affected(false),<br>
-        LeadingEmptyLinesAffected(<wbr>false), ChildrenAffected(false) {<br>
+        LeadingEmptyLinesAffected(<wbr>false), ChildrenAffected(false),<br>
+        FirstStartColumn(Line.<wbr>FirstStartColumn) {<br>
     assert(!Line.Tokens.empty());<br>
<br>
     // Calculate Next and Previous for all tokens. Note that we must overwrite<br>
@@ -127,6 +128,8 @@ public:<br>
   /// \c True if one of this line's children intersects with an input range.<br>
   bool ChildrenAffected;<br>
<br>
+  unsigned FirstStartColumn;<br>
+<br>
 private:<br>
   // Disallow copying.<br>
   AnnotatedLine(const AnnotatedLine &) = delete;<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.cpp?<wbr>rev=316903&r1=316902&r2=<wbr>316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.cpp Mon Oct 30 07:01:50 2017<br>
@@ -659,7 +659,9 @@ public:<br>
   /// \brief Formats an \c AnnotatedLine and returns the penalty.<br>
   ///<br>
   /// If \p DryRun is \c false, directly applies the changes.<br>
-  virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
+  virtual unsigned formatLine(const AnnotatedLine &Line,<br>
+                              unsigned FirstIndent,<br>
+                              unsigned FirstStartColumn,<br>
                               bool DryRun) = 0;<br>
<br>
 protected:<br>
@@ -730,7 +732,8 @@ protected:<br>
           *Child->First, /*Newlines=*/0, /*Spaces=*/1,<br>
           /*StartOfTokenColumn=*/State.<wbr>Column, State.Line->InPPDirective);<br>
     }<br>
-    Penalty += formatLine(*Child, State.Column + 1, DryRun);<br>
+    Penalty +=<br>
+        formatLine(*Child, State.Column + 1, /*FirstStartColumn=*/0, DryRun);<br>
<br>
     State.Column += 1 + Child->Last->TotalLength;<br>
     return true;<br>
@@ -756,10 +759,10 @@ public:<br>
   /// \brief Formats the line, simply keeping all of the input's line breaking<br>
   /// decisions.<br>
   unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
-                      bool DryRun) override {<br>
+                      unsigned FirstStartColumn, bool DryRun) override {<br>
     assert(!DryRun);<br>
-    LineState State =<br>
-        Indenter->getInitialState(<wbr>FirstIndent, &Line, /*DryRun=*/false);<br>
+    LineState State = Indenter->getInitialState(<wbr>FirstIndent, FirstStartColumn,<br>
+                                                &Line, /*DryRun=*/false);<br>
     while (State.NextToken) {<br>
       bool Newline =<br>
           Indenter->mustBreak(State) ||<br>
@@ -782,9 +785,10 @@ public:<br>
<br>
   /// \brief Puts all tokens into a single line.<br>
   unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
-                      bool DryRun) override {<br>
+                      unsigned FirstStartColumn, bool DryRun) override {<br>
     unsigned Penalty = 0;<br>
-    LineState State = Indenter->getInitialState(<wbr>FirstIndent, &Line, DryRun);<br>
+    LineState State =<br>
+        Indenter->getInitialState(<wbr>FirstIndent, FirstStartColumn, &Line, DryRun);<br>
     while (State.NextToken) {<br>
       formatChildren(State, /*Newline=*/false, DryRun, Penalty);<br>
       Indenter->addTokenToState(<br>
@@ -806,8 +810,9 @@ public:<br>
   /// \brief Formats the line by finding the best line breaks with line lengths<br>
   /// below the column limit.<br>
   unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
-                      bool DryRun) override {<br>
-    LineState State = Indenter->getInitialState(<wbr>FirstIndent, &Line, DryRun);<br>
+                      unsigned FirstStartColumn, bool DryRun) override {<br>
+    LineState State =<br>
+        Indenter->getInitialState(<wbr>FirstIndent, FirstStartColumn, &Line, DryRun);<br>
<br>
     // If the ObjC method declaration does not fit on a line, we should format<br>
     // it with one arg per line.<br>
@@ -974,7 +979,10 @@ private:<br>
 unsigned<br>
 UnwrappedLineFormatter::<wbr>format(const SmallVectorImpl<AnnotatedLine *> &Lines,<br>
                                bool DryRun, int AdditionalIndent,<br>
-                               bool FixBadIndentation) {<br>
+                               bool FixBadIndentation,<br>
+                               unsigned FirstStartColumn,<br>
+                               unsigned NextStartColumn,<br>
+                               unsigned LastStartColumn) {<br>
   LineJoiner Joiner(Style, Keywords, Lines);<br>
<br>
   // Try to look up already computed penalty in DryRun-mode.<br>
@@ -994,9 +1002,10 @@ UnwrappedLineFormatter::<wbr>format(const Sma<br>
   // The minimum level of consecutive lines that have been formatted.<br>
   unsigned RangeMinLevel = UINT_MAX;<br>
<br>
+  bool FirstLine = true;<br>
   for (const AnnotatedLine *Line =<br>
            Joiner.getNextMergedLine(<wbr>DryRun, IndentTracker);<br>
-       Line; Line = NextLine) {<br>
+       Line; Line = NextLine, FirstLine = false) {<br>
     const AnnotatedLine &TheLine = *Line;<br>
     unsigned Indent = IndentTracker.getIndent();<br>
<br>
@@ -1020,8 +1029,12 @@ UnwrappedLineFormatter::<wbr>format(const Sma<br>
     }<br>
<br>
     if (ShouldFormat && TheLine.Type != LT_Invalid) {<br>
-      if (!DryRun)<br>
-        formatFirstToken(TheLine, PreviousLine, Indent);<br>
+      if (!DryRun) {<br>
+        bool LastLine = Line->First->is(tok::eof);<br>
+        formatFirstToken(TheLine, PreviousLine,<br>
+                         Indent,<br>
+                         LastLine ? LastStartColumn : NextStartColumn + Indent);<br>
+      }<br>
<br>
       NextLine = Joiner.getNextMergedLine(<wbr>DryRun, IndentTracker);<br>
       unsigned ColumnLimit = getColumnLimit(TheLine.<wbr>InPPDirective, NextLine);<br>
@@ -1030,16 +1043,18 @@ UnwrappedLineFormatter::<wbr>format(const Sma<br>
           (TheLine.Type == LT_ImportStatement &&<br>
            (Style.Language != FormatStyle::LK_JavaScript ||<br>
             !Style.JavaScriptWrapImports))<wbr>;<br>
-<br>
       if (Style.ColumnLimit == 0)<br>
         NoColumnLimitLineFormatter(<wbr>Indenter, Whitespaces, Style, this)<br>
-            .formatLine(TheLine, Indent, DryRun);<br>
+            .formatLine(TheLine, NextStartColumn + Indent,<br>
+                        FirstLine ? FirstStartColumn : 0, DryRun);<br>
       else if (FitsIntoOneLine)<br>
         Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this)<br>
-                       .formatLine(TheLine, Indent, DryRun);<br>
+                       .formatLine(TheLine, NextStartColumn + Indent,<br>
+                                   FirstLine ? FirstStartColumn : 0, DryRun);<br>
       else<br>
         Penalty += OptimizingLineFormatter(<wbr>Indenter, Whitespaces, Style, this)<br>
-                       .formatLine(TheLine, Indent, DryRun);<br>
+                       .formatLine(TheLine, NextStartColumn + Indent,<br>
+                                   FirstLine ? FirstStartColumn : 0, DryRun);<br>
       RangeMinLevel = std::min(RangeMinLevel, TheLine.Level);<br>
     } else {<br>
       // If no token in the current line is affected, we still need to format<br>
@@ -1062,6 +1077,7 @@ UnwrappedLineFormatter::<wbr>format(const Sma<br>
         // Format the first token.<br>
         if (ReformatLeadingWhitespace)<br>
           formatFirstToken(TheLine, PreviousLine,<br>
+                           TheLine.First->OriginalColumn,<br>
                            TheLine.First->OriginalColumn)<wbr>;<br>
         else<br>
           Whitespaces-><wbr>addUntouchableToken(*TheLine.<wbr>First,<br>
@@ -1084,12 +1100,14 @@ UnwrappedLineFormatter::<wbr>format(const Sma<br>
<br>
 void UnwrappedLineFormatter::<wbr>formatFirstToken(const AnnotatedLine &Line,<br>
                                               const AnnotatedLine *PreviousLine,<br>
-                                              unsigned Indent) {<br>
+                                              unsigned Indent,<br>
+                                              unsigned NewlineIndent) {<br>
   FormatToken &RootToken = *Line.First;<br>
   if (RootToken.is(tok::eof)) {<br>
     unsigned Newlines = std::min(RootToken.<wbr>NewlinesBefore, 1u);<br>
-    Whitespaces-><wbr>replaceWhitespace(RootToken, Newlines, /*Spaces=*/0,<br>
-                                   /*StartOfTokenColumn=*/0);<br>
+    unsigned TokenIndent = Newlines ? NewlineIndent : 0;<br>
+    Whitespaces-><wbr>replaceWhitespace(RootToken, Newlines, TokenIndent,<br>
+                                   TokenIndent);<br>
     return;<br>
   }<br>
   unsigned Newlines =<br>
@@ -1104,10 +1122,6 @@ void UnwrappedLineFormatter::<wbr>formatFirst<br>
   if (RootToken.IsFirst && !RootToken.<wbr>HasUnescapedNewline)<br>
     Newlines = 0;<br>
<br>
-  // Preprocessor directives get indented after the hash, if indented.<br>
-  if (Line.Type == LT_PreprocessorDirective || Line.Type == LT_ImportStatement)<br>
-    Indent = 0;<br>
-<br>
   // Remove empty lines after "{".<br>
   if (!Style.<wbr>KeepEmptyLinesAtTheStartOfBloc<wbr>ks && PreviousLine &&<br>
       PreviousLine->Last->is(tok::l_<wbr>brace) &&<br>
@@ -1125,6 +1139,13 @@ void UnwrappedLineFormatter::<wbr>formatFirst<br>
       (!PreviousLine->InPPDirective || !RootToken.<wbr>HasUnescapedNewline))<br>
     Newlines = std::min(1u, Newlines);<br>
<br>
+  if (Newlines)<br>
+    Indent = NewlineIndent;<br>
+<br>
+  // Preprocessor directives get indented after the hash, if indented.<br>
+  if (Line.Type == LT_PreprocessorDirective || Line.Type == LT_ImportStatement)<br>
+    Indent = 0;<br>
+<br>
   Whitespaces-><wbr>replaceWhitespace(RootToken, Newlines, Indent, Indent,<br>
                                  Line.InPPDirective &&<br>
                                      !RootToken.<wbr>HasUnescapedNewline);<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.h?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>UnwrappedLineFormatter.h Mon Oct 30 07:01:50 2017<br>
@@ -40,13 +40,17 @@ public:<br>
   /// \brief Format the current block and return the penalty.<br>
   unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,<br>
                   bool DryRun = false, int AdditionalIndent = 0,<br>
-                  bool FixBadIndentation = false);<br>
+                  bool FixBadIndentation = false,<br>
+                  unsigned FirstStartColumn = 0,<br>
+                  unsigned NextStartColumn = 0,<br>
+                  unsigned LastStartColumn = 0);<br>
<br>
 private:<br>
   /// \brief Add a new line and the required indent before the first Token<br>
   /// of the \c UnwrappedLine if there was no structural parsing error.<br>
   void formatFirstToken(const AnnotatedLine &Line,<br>
-                        const AnnotatedLine *PreviousLine, unsigned Indent);<br>
+                        const AnnotatedLine *PreviousLine, unsigned Indent,<br>
+                        unsigned NewlineIndent);<br>
<br>
   /// \brief Returns the column limit for a line, taking into account whether we<br>
   /// need an escaped newline due to a continued preprocessor directive.<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.cpp?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.cpp Mon Oct 30 07:01:50 2017<br>
@@ -225,6 +225,7 @@ private:<br>
<br>
 UnwrappedLineParser::<wbr>UnwrappedLineParser(const FormatStyle &Style,<br>
                                          const AdditionalKeywords &Keywords,<br>
+                                         unsigned FirstStartColumn,<br>
                                          ArrayRef<FormatToken *> Tokens,<br>
                                          UnwrappedLineConsumer &Callback)<br>
     : Line(new UnwrappedLine), MustBreakBeforeNextToken(<wbr>false),<br>
@@ -232,7 +233,7 @@ UnwrappedLineParser::<wbr>UnwrappedLineParser<br>
       CommentPragmasRegex(Style.<wbr>CommentPragmas), Tokens(nullptr),<br>
       Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),<br>
       IfNdefCondition(nullptr), FoundIncludeGuardStart(false),<br>
-      IncludeGuardRejected(false) {}<br>
+      IncludeGuardRejected(false), FirstStartColumn(<wbr>FirstStartColumn) {}<br>
<br>
 void UnwrappedLineParser::reset() {<br>
   PPBranchLevel = -1;<br>
@@ -247,10 +248,12 @@ void UnwrappedLineParser::reset() {<br>
   CurrentLines = &Lines;<br>
   DeclarationScopeStack.clear();<br>
   PPStack.clear();<br>
+  Line->FirstStartColumn = FirstStartColumn;<br>
 }<br>
<br>
 void UnwrappedLineParser::parse() {<br>
   IndexedTokenSource TokenSource(AllTokens);<br>
+  Line->FirstStartColumn = FirstStartColumn;<br>
   do {<br>
     DEBUG(llvm::dbgs() << "----\n");<br>
     reset();<br>
@@ -2193,7 +2196,8 @@ void UnwrappedLineParser::<wbr>parseJavaScrip<br>
<br>
 LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,<br>
                                                  StringRef Prefix = "") {<br>
-  llvm::dbgs() << Prefix << "Line(" << Line.Level << ")"<br>
+  llvm::dbgs() << Prefix << "Line(" << Line.Level<br>
+               << ", FSC=" << Line.FirstStartColumn << ")"<br>
                << (Line.InPPDirective ? " MACRO" : "") << ": ";<br>
   for (std::list<UnwrappedLineNode>:<wbr>:const_iterator I = Line.Tokens.begin(),<br>
                                                     E = Line.Tokens.end();<br>
@@ -2226,6 +2230,7 @@ void UnwrappedLineParser::<wbr>addUnwrappedLi<br>
   CurrentLines->push_back(std::<wbr>move(*Line));<br>
   Line->Tokens.clear();<br>
   Line-><wbr>MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;<br>
+  Line->FirstStartColumn = 0;<br>
   if (CurrentLines == &Lines && !PreprocessorDirectives.empty(<wbr>)) {<br>
     CurrentLines->append(<br>
         std::make_move_iterator(<wbr>PreprocessorDirectives.begin()<wbr>),<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.h?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>UnwrappedLineParser.h Mon Oct 30 07:01:50 2017<br>
@@ -56,6 +56,8 @@ struct UnwrappedLine {<br>
   size_t MatchingOpeningBlockLineIndex;<br>
<br>
   static const size_t kInvalidIndex = -1;<br>
+<br>
+  unsigned FirstStartColumn = 0;<br>
 };<br>
<br>
 class UnwrappedLineConsumer {<br>
@@ -71,6 +73,7 @@ class UnwrappedLineParser {<br>
 public:<br>
   UnwrappedLineParser(const FormatStyle &Style,<br>
                       const AdditionalKeywords &Keywords,<br>
+                      unsigned FirstStartColumn,<br>
                       ArrayRef<FormatToken *> Tokens,<br>
                       UnwrappedLineConsumer &Callback);<br>
<br>
@@ -249,6 +252,10 @@ private:<br>
   FormatToken *IfNdefCondition;<br>
   bool FoundIncludeGuardStart;<br>
   bool IncludeGuardRejected;<br>
+  // Contains the first start column where the source begins. This is zero for<br>
+  // normal source code and may be nonzero when formatting a code fragment that<br>
+  // does not start at the beginning of the file.<br>
+  unsigned FirstStartColumn;<br>
<br>
   friend class ScopedLineState;<br>
   friend class CompoundStatementIndenter;<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UsingDeclarationsSorter.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.cpp?<wbr>rev=316903&r1=316902&r2=<wbr>316903&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.cpp Mon Oct 30 07:01:50 2017<br>
@@ -124,7 +124,7 @@ UsingDeclarationsSorter::<wbr>UsingDeclaratio<br>
                                                  const FormatStyle &Style)<br>
     : TokenAnalyzer(Env, Style) {}<br>
<br>
-tooling::Replacements UsingDeclarationsSorter::<wbr>analyze(<br>
+std::pair<tooling::<wbr>Replacements, unsigned> UsingDeclarationsSorter::<wbr>analyze(<br>
     TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
     FormatTokenLexer &Tokens) {<br>
   const SourceManager &SourceMgr = Env.getSourceManager();<br>
@@ -149,7 +149,7 @@ tooling::Replacements UsingDeclarationsS<br>
     UsingDeclarations.push_back(<wbr>UsingDeclaration(<wbr>AnnotatedLines[I], Label));<br>
   }<br>
   endUsingDeclarationBlock(&<wbr>UsingDeclarations, SourceMgr, &Fixes);<br>
-  return Fixes;<br>
+  return {Fixes, 0};<br>
 }<br>
<br>
 } // namespace format<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UsingDeclarationsSorter.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.h?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>UsingDeclarationsSorter.h Mon Oct 30 07:01:50 2017<br>
@@ -25,7 +25,7 @@ class UsingDeclarationsSorter : public T<br>
 public:<br>
   UsingDeclarationsSorter(const Environment &Env, const FormatStyle &Style);<br>
<br>
-  tooling::Replacements<br>
+  std::pair<tooling::<wbr>Replacements, unsigned><br>
   analyze(TokenAnnotator &Annotator,<br>
           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br>
           FormatTokenLexer &Tokens) override;<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>WhitespaceManager.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/WhitespaceManager.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>WhitespaceManager.cpp?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>WhitespaceManager.cpp (original)<br>
+++ cfe/trunk/lib/Format/<wbr>WhitespaceManager.cpp Mon Oct 30 07:01:50 2017<br>
@@ -67,6 +67,11 @@ void WhitespaceManager::<wbr>addUntouchableTo<br>
                            /*IsInsideToken=*/false));<br>
 }<br>
<br>
+llvm::Error<br>
+WhitespaceManager::<wbr>addReplacement(const tooling::Replacement &Replacement) {<br>
+  return Replaces.add(Replacement);<br>
+}<br>
+<br>
 void WhitespaceManager::<wbr>replaceWhitespaceInToken(<br>
     const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,<br>
     StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,<br>
<br>
Modified: cfe/trunk/lib/Format/<wbr>WhitespaceManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/WhitespaceManager.h?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Format/<wbr>WhitespaceManager.h?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Format/<wbr>WhitespaceManager.h (original)<br>
+++ cfe/trunk/lib/Format/<wbr>WhitespaceManager.h Mon Oct 30 07:01:50 2017<br>
@@ -57,6 +57,8 @@ public:<br>
   /// was not called.<br>
   void addUntouchableToken(const FormatToken &Tok, bool InPPDirective);<br>
<br>
+  llvm::Error addReplacement(const tooling::Replacement &Replacement);<br>
+<br>
   /// \brief Inserts or replaces whitespace in the middle of a token.<br>
   ///<br>
   /// Inserts \p PreviousPostfix, \p Newlines, \p Spaces and \p CurrentPrefix<br>
<br>
Modified: cfe/trunk/unittests/Format/<wbr>CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/CMakeLists.txt?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/unittests/<wbr>Format/CMakeLists.txt?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/Format/<wbr>CMakeLists.txt (original)<br>
+++ cfe/trunk/unittests/Format/<wbr>CMakeLists.txt Mon Oct 30 07:01:50 2017<br>
@@ -10,6 +10,7 @@ add_clang_unittest(FormatTests<br>
   FormatTestJava.cpp<br>
   FormatTestObjC.cpp<br>
   FormatTestProto.cpp<br>
+  FormatTestRawStrings.cpp<br>
   FormatTestSelective.cpp<br>
   FormatTestTextProto.cpp<br>
   NamespaceEndCommentsFixerTest.<wbr>cpp<br>
<br>
Modified: cfe/trunk/unittests/Format/<wbr>FormatTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=316903&r1=316902&r2=316903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/unittests/<wbr>Format/FormatTest.cpp?rev=<wbr>316903&r1=316902&r2=316903&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/Format/<wbr>FormatTest.cpp (original)<br>
+++ cfe/trunk/unittests/Format/<wbr>FormatTest.cpp Mon Oct 30 07:01:50 2017<br>
@@ -10254,6 +10254,20 @@ TEST_F(FormatTest, ParsesConfiguration)<br>
               "    Priority: 1",<br>
               IncludeCategories, ExpectedCategories);<br>
   CHECK_PARSE("<wbr>IncludeIsMainRegex: 'abc$'", IncludeIsMainRegex, "abc$");<br>
+<br>
+  Style.RawStringFormats.clear()<wbr>;<br>
+  std::vector<FormatStyle::<wbr>RawStringFormat> ExpectedRawStringFormats = {<br>
+      {"pb", FormatStyle::LK_TextProto, "llvm"},<br>
+      {"cpp", FormatStyle::LK_Cpp, "google"}};<br>
+<br>
+  CHECK_PARSE("RawStringFormats:<wbr>\n"<br>
+              "  - Delimiter: 'pb'\n"<br>
+              "    Language: TextProto\n"<br>
+              "    BasedOnStyle: llvm\n"<br>
+              "  - Delimiter: 'cpp'\n"<br>
+              "    Language: Cpp\n"<br>
+              "    BasedOnStyle: google",<br>
+              RawStringFormats, ExpectedRawStringFormats);<br>
 }<br>
<br>
 TEST_F(FormatTest, ParsesConfigurationWithLanguag<wbr>es) {<br>
<br>
Added: cfe/trunk/unittests/Format/<wbr>FormatTestRawStrings.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestRawStrings.cpp?rev=316903&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/unittests/<wbr>Format/FormatTestRawStrings.<wbr>cpp?rev=316903&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/Format/<wbr>FormatTestRawStrings.cpp (added)<br>
+++ cfe/trunk/unittests/Format/<wbr>FormatTestRawStrings.cpp Mon Oct 30 07:01:50 2017<br>
@@ -0,0 +1,733 @@<br>
+//===- unittest/Format/<wbr>FormatTestRawStrings.cpp - Formatting unit tests ---===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "clang/Format/Format.h"<br>
+<br>
+#include "../Tooling/ReplacementTest.h"<br>
+#include "FormatTestUtils.h"<br>
+<br>
+#include "clang/Frontend/<wbr>TextDiagnosticPrinter.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/MemoryBuffer.h"<br>
+#include "gtest/gtest.h"<br>
+<br>
+#define DEBUG_TYPE "format-test"<br>
+<br>
+using clang::tooling::<wbr>ReplacementTest;<br>
+using clang::tooling::<wbr>toReplacements;<br>
+<br>
+namespace clang {<br>
+namespace format {<br>
+namespace {<br>
+<br>
+class FormatTestRawStrings : public ::testing::Test {<br>
+protected:<br>
+  enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete, SC_DoNotCheck };<br>
+<br>
+  std::string format(llvm::StringRef Code,<br>
+                     const FormatStyle &Style = getLLVMStyle(),<br>
+                     StatusCheck CheckComplete = SC_ExpectComplete) {<br>
+    DEBUG(llvm::errs() << "---\n");<br>
+    DEBUG(llvm::errs() << Code << "\n\n");<br>
+    std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));<br>
+    FormattingAttemptStatus Status;<br>
+    tooling::Replacements Replaces =<br>
+        reformat(Style, Code, Ranges, "<stdin>", &Status);<br>
+    if (CheckComplete != SC_DoNotCheck) {<br>
+      bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;<br>
+      EXPECT_EQ(<wbr>ExpectedCompleteFormat, Status.FormatComplete)<br>
+          << Code << "\n\n";<br>
+    }<br>
+    ReplacementCount = Replaces.size();<br>
+    auto Result = applyAllReplacements(Code, Replaces);<br>
+    EXPECT_TRUE(static_cast<bool>(<wbr>Result));<br>
+    DEBUG(llvm::errs() << "\n" << *Result << "\n\n");<br>
+    return *Result;<br>
+  }<br>
+<br>
+  FormatStyle getStyleWithColumns(<wbr>FormatStyle Style, unsigned ColumnLimit) {<br>
+    Style.ColumnLimit = ColumnLimit;<br>
+    return Style;<br>
+  }<br>
+<br>
+  FormatStyle getLLVMStyleWithColumns(<wbr>unsigned ColumnLimit) {<br>
+    return getStyleWithColumns(<wbr>getLLVMStyle(), ColumnLimit);<br>
+  }<br>
+<br>
+  int ReplacementCount;<br>
+<br>
+  FormatStyle getRawStringPbStyleWithColumns<wbr>(unsigned ColumnLimit) {<br>
+    FormatStyle Style = getLLVMStyle();<br>
+    Style.ColumnLimit = ColumnLimit;<br>
+    Style.RawStringFormats = {{/*Delimiter=*/"pb",<br>
+                               /*Kind=*/FormatStyle::LK_<wbr>TextProto,<br>
+                               /*BasedOnStyle=*/"google"}};<br>
+    return Style;<br>
+  }<br>
+<br>
+  FormatStyle getRawStringLLVMCppStyleBasedO<wbr>n(std::string BasedOnStyle) {<br>
+    FormatStyle Style = getLLVMStyle();<br>
+    Style.RawStringFormats = {{/*Delimiter=*/"cpp",<br>
+                               /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}};<br>
+    return Style;<br>
+  }<br>
+<br>
+  FormatStyle getRawStringGoogleCppStyleBase<wbr>dOn(std::string BasedOnStyle) {<br>
+    FormatStyle Style = getGoogleStyle(FormatStyle::<wbr>LK_Cpp);<br>
+    Style.RawStringFormats = {{/*Delimiter=*/"cpp",<br>
+                               /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}};<br>
+    return Style;<br>
+  }<br>
+<br>
+  // Gcc 4.8 doesn't support raw string literals in macros, which breaks some<br>
+  // build bots. We use this function instead.<br>
+  void expect_eq(const std::string Expected, const std::string Actual) {<br>
+    EXPECT_EQ(Expected, Actual);<br>
+  }<br>
+};<br>
+<br>
+TEST_F(FormatTestRawStrings, ReformatsAccordingToBaseStyle) {<br>
+  // llvm style puts '*' on the right.<br>
+  // google style puts '*' on the left.<br>
+<br>
+  // Use the llvm style if the raw string style has no BasedOnStyle.<br>
+  expect_eq(R"test(int *i = R"cpp(int *p = nullptr;)cpp")test",<br>
+            format(R"test(int * i = R"cpp(int * p = nullptr;)cpp")test",<br>
+                   getRawStringLLVMCppStyleBasedO<wbr>n("")));<br>
+<br>
+  // Use the google style if the raw string style has BasedOnStyle=google.<br>
+  expect_eq(R"test(int *i = R"cpp(int* p = nullptr;)cpp")test",<br>
+            format(R"test(int * i = R"cpp(int * p = nullptr;)cpp")test",<br>
+                   getRawStringLLVMCppStyleBasedO<wbr>n("google")));<br>
+<br>
+  // Use the llvm style if the raw string style has no BasedOnStyle=llvm.<br>
+  expect_eq(R"test(int* i = R"cpp(int *p = nullptr;)cpp")test",<br>
+            format(R"test(int * i = R"cpp(int * p = nullptr;)cpp")test",<br>
+                   getRawStringGoogleCppStyleBase<wbr>dOn("llvm")));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, MatchesDelimitersCaseSensitive<wbr>ly) {<br>
+  // Don't touch the 'PB' raw string, format the 'pb' raw string.<br>
+  expect_eq(R"test(<br>
+s = R"PB(item:1)PB";<br>
+t = R"pb(item: 1)pb";)test",<br>
+            format(R"test(<br>
+s = R"PB(item:1)PB";<br>
+t = R"pb(item:1)pb";)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  FormatStyle MixedStyle = getLLVMStyle();<br>
+  MixedStyle.RawStringFormats = {<br>
+      {/*Delimiter=*/"cpp", /*Kind=*/FormatStyle::LK_Cpp,<br>
+       /*BasedOnStyle=*/"llvm"},<br>
+      {/*Delimiter=*/"CPP", /*Kind=*/FormatStyle::LK_Cpp,<br>
+       /*BasedOnStyle=*/"google"}};<br>
+<br>
+  // Format the 'cpp' raw string with '*' on the right.<br>
+  // Format the 'CPP' raw string with '*' on the left.<br>
+  // Do not format the 'Cpp' raw string.<br>
+  // Do not format non-raw strings.<br>
+  expect_eq(R"test(<br>
+a = R"cpp(int *i = 0;)cpp";<br>
+b = R"CPP(int* j = 0;)CPP";<br>
+c = R"Cpp(int * k = 0;)Cpp";<br>
+d = R"cpp(int * k = 0;)Cpp";)test",<br>
+            format(R"test(<br>
+a = R"cpp(int * i = 0;)cpp";<br>
+b = R"CPP(int * j = 0;)CPP";<br>
+c = R"Cpp(int * k = 0;)Cpp";<br>
+d = R"cpp(int * k = 0;)Cpp";)test",<br>
+                   MixedStyle));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSing<wbr>leLine) {<br>
+  expect_eq(<br>
+      R"test(P p = TP(R"pb()pb");)test",<br>
+      format(<br>
+          R"test(P p = TP(R"pb( )pb");)test",<br>
+          getRawStringPbStyleWithColumns<wbr>(40)));<br>
+  expect_eq(<br>
+      R"test(P p = TP(R"pb(item_1: 1)pb");)test",<br>
+      format(<br>
+          R"test(P p = TP(R"pb(item_1:1)pb");)test",<br>
+          getRawStringPbStyleWithColumns<wbr>(40)));<br>
+  expect_eq(<br>
+      R"test(P p = TP(R"pb(item_1: 1)pb");)test",<br>
+      format(<br>
+          R"test(P p = TP(R"pb(  item_1 :  1   )pb");)test",<br>
+          getRawStringPbStyleWithColumns<wbr>(40)));<br>
+  expect_eq(<br>
+      R"test(P p = TP(R"pb(item_1: 1 item_2: 2)pb");)test",<br>
+      format(<br>
+          R"test(P p = TP(R"pb(item_1:1 item_2:2)pb");)test",<br>
+          getRawStringPbStyleWithColumns<wbr>(40)));<br>
+  expect_eq(<br>
+      R"test(P p = TP(R"pb(item_1 <1> item_2: {2})pb");)test",<br>
+      format(<br>
+          R"test(P p = TP(R"pb(item_1<1> item_2:{2})pb");)test",<br>
+          getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Merge two short lines into one.<br>
+  expect_eq(R"test(<br>
+std::string s = R"pb(<br>
+  item_1: 1 item_2: 2<br>
+)pb";<br>
+)test",<br>
+            format(R"test(<br>
+std::string s = R"pb(<br>
+  item_1:1<br>
+  item_2:2<br>
+)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, BreaksRawStringsExceedingColum<wbr>nLimit) {<br>
+  expect_eq(R"test(<br>
+P p = TPPPPPPPPPPPPPPP(<br>
+    R"pb(item_1: 1, item_2: 2)pb");)test",<br>
+            format(R"test(<br>
+P p = TPPPPPPPPPPPPPPP(R"pb(item_1: 1, item_2: 2)pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+P p =<br>
+    TPPPPPPPPPPPPPPP(<br>
+        R"pb(item_1: 1,<br>
+             item_2: 2,<br>
+             item_3: 3)pb");)test",<br>
+            format(R"test(<br>
+P p = TPPPPPPPPPPPPPPP(R"pb(item_1: 1, item_2: 2, item_3: 3)pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+P p = TP(R"pb(item_1 <1><br>
+              item_2: <2><br>
+              item_3 {})pb");)test",<br>
+      format(R"test(<br>
+P p = TP(R"pb(item_1<1> item_2:<2> item_3{ })pb");)test",<br>
+          getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(<br>
+      R"test(<br>
+P p = TP(R"pb(item_1: 1,<br>
+              item_2: 2,<br>
+              item_3: 3,<br>
+              item_4: 4)pb");)test",<br>
+      format(<br>
+          R"test(<br>
+P p = TP(R"pb(item_1: 1, item_2: 2, item_3: 3, item_4: 4)pb");)test",<br>
+          getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+P p = TPPPPPPPPPPPPPPP(<br>
+    R"pb(item_1 <1>,<br>
+         item_2: {2},<br>
+         item_3: <3>,<br>
+         item_4: {4})pb");)test",<br>
+            format(R"test(<br>
+P p = TPPPPPPPPPPPPPPP(R"pb(item_1<<wbr>1>, item_2: {2}, item_3: <3>, item_4:{4})pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Breaks before a short raw string exceeding the column limit.<br>
+  expect_eq(R"test(<br>
+FFFFFFFFFFFFFFFFFFFFFFFFFFF(<br>
+    R"pb(key: 1)pb");<br>
+P p = TPPPPPPPPPPPPPPPPPPPP(<br>
+    R"pb(key: 2)pb");<br>
+auto TPPPPPPPPPPPPPPPPPPPP =<br>
+    R"pb(key: 3)pb";<br>
+P p = TPPPPPPPPPPPPPPPPPPPP(<br>
+    R"pb(i: 1, j: 2)pb");<br>
+<br>
+int f(string s) {<br>
+  FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF<wbr>(<br>
+      R"pb(key: 1)pb");<br>
+  P p = TPPPPPPPPPPPPPPPPPPPP(<br>
+      R"pb(key: 2)pb");<br>
+  auto TPPPPPPPPPPPPPPPPPPPP =<br>
+      R"pb(key: 3)pb";<br>
+  if (s.empty())<br>
+    P p = TPPPPPPPPPPPPPPPPPPPP(<br>
+        R"pb(i: 1, j: 2)pb");<br>
+}<br>
+)test",<br>
+            format(R"test(<br>
+FFFFFFFFFFFFFFFFFFFFFFFFFFF(<wbr>R"pb(key:1)pb");<br>
+P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(<wbr>key:2)pb");<br>
+auto TPPPPPPPPPPPPPPPPPPPP = R"pb(key:3)pb";<br>
+P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(i: 1, j:2)pb");<br>
+<br>
+int f(string s) {<br>
+  FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF<wbr>(R"pb(key:1)pb");<br>
+  P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(<wbr>key:2)pb");<br>
+  auto TPPPPPPPPPPPPPPPPPPPP = R"pb(key:3)pb";<br>
+  if (s.empty())<br>
+    P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(i: 1, j:2)pb");<br>
+}<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, FormatsRawStringArguments) {<br>
+  expect_eq(R"test(<br>
+P p = TP(R"pb(key {1})pb", param_2);)test",<br>
+            format(R"test(<br>
+P p = TP(R"pb(key{1})pb",param_2);)<wbr>test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+PPPPPPPPPPPPP(R"pb(keykeyk)<wbr>pb",<br>
+              param_2);)test",<br>
+            format(R"test(<br>
+PPPPPPPPPPPPP(R"pb(keykeyk)<wbr>pb", param_2);)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+P p =<br>
+    TP(R"pb(item: {i: 1, s: 's'}<br>
+            item: {i: 2, s: 't'})pb");)test",<br>
+            format(R"test(<br>
+P p = TP(R"pb(item: {i: 1, s: 's'} item: {i: 2, s: 't'})pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+  expect_eq(R"test(<br>
+FFFFFFFFFFFFFFFFFFF(<br>
+    R"pb(key: "value")pb",<br>
+    R"pb(key2: "value")pb");)test",<br>
+            format(R"test(<br>
+FFFFFFFFFFFFFFFFFFF(R"pb(key: "value")pb", R"pb(key2: "value")pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Formats the first out of two arguments.<br>
+  expect_eq(R"test(<br>
+FFFFFFFF(R"pb(key: 1)pb", argument2);<br>
+struct S {<br>
+  const s =<br>
+      f(R"pb(key: 1)pb", argument2);<br>
+  void f() {<br>
+    if (gol)<br>
+      return g(R"pb(key: 1)pb",<br>
+               132789237);<br>
+    return g(R"pb(key: 1)pb", "172893");<br>
+  }<br>
+};)test",<br>
+            format(R"test(<br>
+FFFFFFFF(R"pb(key:1)pb", argument2);<br>
+struct S {<br>
+const s = f(R"pb(key:1)pb", argument2);<br>
+void f() {<br>
+  if (gol)<br>
+    return g(R"pb(key:1)pb", 132789237);<br>
+  return g(R"pb(key:1)pb", "172893");<br>
+}<br>
+};)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Formats the second out of two arguments.<br>
+  expect_eq(R"test(<br>
+FFFFFFFF(argument1, R"pb(key: 2)pb");<br>
+struct S {<br>
+  const s =<br>
+      f(argument1, R"pb(key: 2)pb");<br>
+  void f() {<br>
+    if (gol)<br>
+      return g(12784137,<br>
+               R"pb(key: 2)pb");<br>
+    return g(17283122, R"pb(key: 2)pb");<br>
+  }<br>
+};)test",<br>
+            format(R"test(<br>
+FFFFFFFF(argument1, R"pb(key:2)pb");<br>
+struct S {<br>
+const s = f(argument1, R"pb(key:2)pb");<br>
+void f() {<br>
+  if (gol)<br>
+    return g(12784137, R"pb(key:2)pb");<br>
+  return g(17283122, R"pb(key:2)pb");<br>
+}<br>
+};)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Formats two short raw string arguments.<br>
+  expect_eq(R"test(<br>
+FFFFF(R"pb(key: 1)pb", R"pb(key: 2)pb");)test",<br>
+            format(R"test(<br>
+FFFFF(R"pb(key:1)pb", R"pb(key:2)pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+  // TODO(krasimir): The original source code fits on one line, so the<br>
+  // non-optimizing formatter is chosen. But after the formatting in protos is<br>
+  // made, the code doesn't fit on one line anymore and further formatting<br>
+  // splits it.<br>
+  //<br>
+  // Should we disable raw string formatting for the non-optimizing formatter?<br>
+  expect_eq(R"test(<br>
+FFFFFFF(R"pb(key: 1)pb", R"pb(key: 2)pb");)test",<br>
+            format(R"test(<br>
+FFFFFFF(R"pb(key:1)pb", R"pb(key:2)pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Formats two short raw string arguments, puts second on newline.<br>
+  expect_eq(R"test(<br>
+FFFFFFFF(R"pb(key: 1)pb",<br>
+         R"pb(key: 2)pb");)test",<br>
+            format(R"test(<br>
+FFFFFFFF(R"pb(key:1)pb", R"pb(key:2)pb");)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Formats both arguments.<br>
+  expect_eq(R"test(<br>
+FFFFFFFF(R"pb(key: 1)pb",<br>
+         R"pb(key: 2)pb");<br>
+struct S {<br>
+  const s = f(R"pb(key: 1)pb",<br>
+              R"pb(key: 2)pb");<br>
+  void f() {<br>
+    if (gol)<br>
+      return g(R"pb(key: 1)pb",<br>
+               R"pb(key: 2)pb");<br>
+    return g(R"pb(k1)pb", R"pb(k2)pb");<br>
+  }<br>
+};)test",<br>
+            format(R"test(<br>
+FFFFFFFF(R"pb(key:1)pb", R"pb(key:2)pb");<br>
+struct S {<br>
+const s = f(R"pb(key:1)pb", R"pb(key:2)pb");<br>
+void f() {<br>
+  if (gol)<br>
+    return g(R"pb(key:1)pb", R"pb(key:2)pb");<br>
+  return g(R"pb( k1 )pb", R"pb( k2 )pb");<br>
+}<br>
+};)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, RawStringStartingWithNewlines) {<br>
+  expect_eq(R"test(<br>
+std::string s = R"pb(<br>
+  item_1: 1<br>
+)pb";<br>
+)test",<br>
+            format(R"test(<br>
+std::string s = R"pb(<br>
+    item_1:1<br>
+)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+std::string s = R"pb(<br>
+<br>
+  item_1: 1<br>
+)pb";<br>
+)test",<br>
+            format(R"test(<br>
+std::string s = R"pb(<br>
+<br>
+    item_1:1<br>
+)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+std::string s = R"pb(<br>
+  item_1: 1<br>
+)pb";<br>
+)test",<br>
+            format(R"test(<br>
+std::string s = R"pb(<br>
+    item_1:1<br>
+<br>
+)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+std::string s = R"pb(<br>
+  item_1: 1,<br>
+  item_2: 2<br>
+)pb";<br>
+)test",<br>
+            format(R"test(<br>
+std::string s = R"pb(<br>
+  item_1:1, item_2:2<br>
+)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+std::string s = R"pb(<br>
+  book {<br>
+    title: "Alice's Adventures"<br>
+    author: "Lewis Caroll"<br>
+  }<br>
+  book {<br>
+    title: "Peter Pan"<br>
+    author: "J. M. Barrie"<br>
+  }<br>
+)pb";<br>
+)test",<br>
+            format(R"test(<br>
+std::string s = R"pb(<br>
+    book { title: "Alice's Adventures" author: "Lewis Caroll" }<br>
+    book { title: "Peter Pan" author: "J. M. Barrie" }<br>
+)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, BreaksBeforeRawStrings) {<br>
+  expect_eq(R"test(<br>
+ASSERT_TRUE(<br>
+    ParseFromString(R"pb(item_1: 1)pb"),<br>
+    ptr);)test",<br>
+            format(R"test(<br>
+ASSERT_TRUE(ParseFromString(<wbr>R"pb(item_1: 1)pb"), ptr);)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+ASSERT_TRUE(toolong::<wbr>ParseFromString(<br>
+                R"pb(item_1: 1)pb"),<br>
+            ptr);)test",<br>
+            format(R"test(<br>
+ASSERT_TRUE(toolong::<wbr>ParseFromString(R"pb(item_1: 1)pb"), ptr);)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+ASSERT_TRUE(ParseFromString(<br>
+                R"pb(item_1: 1,<br>
+                     item_2: 2)pb"),<br>
+            ptr);)test",<br>
+            format(R"test(<br>
+ASSERT_TRUE(ParseFromString(<wbr>R"pb(item_1: 1, item_2: 2)pb"), ptr);)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+ASSERT_TRUE(<br>
+    ParseFromString(<br>
+        R"pb(item_1: 1 item_2: 2)pb"),<br>
+    ptr);)test",<br>
+            format(R"test(<br>
+ASSERT_TRUE(ParseFromString(<wbr>R"pb(item_1: 1 item_2: 2)pb"), ptr);)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, RawStringsInOperands) {<br>
+  // Formats the raw string first operand of a binary operator expression.<br>
+  expect_eq(R"test(auto S = R"pb(item_1: 1)pb" + rest;)test",<br>
+            format(R"test(auto S = R"pb(item_1:1)pb" + rest;)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = R"pb(item_1: 1, item_2: 2)pb" +<br>
+         rest;)test",<br>
+            format(R"test(<br>
+auto S = R"pb(item_1:1,item_2:2)pb"+<wbr>rest;)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S =<br>
+    R"pb(item_1: 1 item_2: 2)pb" + rest;)test",<br>
+            format(R"test(<br>
+auto S = R"pb(item_1:1 item_2:2)pb"+rest;)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = R"pb(item_1: 1,<br>
+              item_2: 2,<br>
+              item_3: 3)pb" + rest;)test",<br>
+            format(R"test(<br>
+auto S = R"pb(item_1:1,item_2:2,item_3:<wbr>3)pb"+rest;)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = R"pb(item_1: 1,<br>
+              item_2: 2,<br>
+              item_3: 3)pb" +<br>
+         longlongrest;)test",<br>
+            format(R"test(<br>
+auto S = R"pb(item_1:1,item_2:2,item_3:<wbr>3)pb"+longlongrest;)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Formats the raw string second operand of a binary operator expression.<br>
+  expect_eq(R"test(auto S = first + R"pb(item_1: 1)pb";)test",<br>
+            format(R"test(auto S = first + R"pb(item_1:1)pb";)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = first + R"pb(item_1: 1,<br>
+                      item_2: 2)pb";)test",<br>
+            format(R"test(<br>
+auto S = first+R"pb(item_1:1,item_2:2)<wbr>pb";)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = first + R"pb(item_1: 1<br>
+                      item_2: 2)pb";)test",<br>
+            format(R"test(<br>
+auto S = first+R"pb(item_1:1 item_2:2)pb";)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = R"pb(item_1: 1,<br>
+              item_2: 2,<br>
+              item_3: 3)pb" + rest;)test",<br>
+            format(R"test(<br>
+auto S = R"pb(item_1:1,item_2:2,item_3:<wbr>3)pb"+rest;)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = R"pb(item_1: 1,<br>
+              item_2: 2,<br>
+              item_3: 3)pb" +<br>
+         longlongrest;)test",<br>
+            format(R"test(<br>
+auto S = R"pb(item_1:1,item_2:2,item_3:<wbr>3)pb"+longlongrest;)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  // Formats the raw string operands in expressions.<br>
+  expect_eq(R"test(<br>
+auto S = R"pb(item_1: 1)pb" +<br>
+         R"pb(item_2: 2)pb";<br>
+)test",<br>
+            format(R"test(<br>
+auto S=R"pb(item_1:1)pb"+R"pb(item_<wbr>2:2)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = R"pb(item_1: 1)pb" +<br>
+         R"pb(item_2: 2)pb" +<br>
+         R"pb(item_3: 3)pb";<br>
+)test",<br>
+            format(R"test(<br>
+auto S=R"pb(item_1:1)pb"+R"pb(item_<wbr>2:2)pb"+R"pb(item_3:3)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S = (count < 3)<br>
+             ? R"pb(item_1: 1)pb"<br>
+             : R"pb(item_2: 2)pb";<br>
+)test",<br>
+            format(R"test(<br>
+auto S=(count<3)?R"pb(item_1:1)pb":<wbr>R"pb(item_2:2)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S =<br>
+    (count < 3)<br>
+        ? R"pb(item_1: 1, item_2: 2)pb"<br>
+        : R"pb(item_3: 3)pb";<br>
+)test",<br>
+            format(R"test(<br>
+auto S=(count<3)?R"pb(item_1:1,<wbr>item_2:2)pb":R"pb(item_3:3)pb"<wbr>;<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+  expect_eq(R"test(<br>
+auto S =<br>
+    (count < 3)<br>
+        ? R"pb(item_1: 1)pb"<br>
+        : R"pb(item_2: 2, item_3: 3)pb";<br>
+)test",<br>
+            format(R"test(<br>
+auto S=(count<3)?R"pb(item_1:1)pb":<wbr>R"pb(item_2:2,item_3:3)pb";<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(40)));<br>
+<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, PrefixAndSuffixAlignment) {<br>
+  // Keep the suffix at the end of line if not on newline.<br>
+  expect_eq(R"test(<br>
+int s() {<br>
+  auto S = PTP(<br>
+      R"pb(<br>
+        item_1: 1,<br>
+        item_2: 2)pb");<br>
+})test",<br>
+            format(R"test(<br>
+int s() {<br>
+  auto S = PTP(<br>
+      R"pb(<br>
+      item_1: 1,<br>
+      item_2: 2)pb");<br>
+})test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(20)));<br>
+<br>
+  // Align the suffix with the surrounding FirstIndent if the prefix is not on<br>
+  // a line of its own.<br>
+  expect_eq(R"test(<br>
+int s() {<br>
+  auto S = PTP(<br>
+      R"pb(<br>
+        item_1: 1,<br>
+        item_2: 2<br>
+      )pb");<br>
+})test",<br>
+            format(R"test(<br>
+int s() {<br>
+  auto S = PTP(R"pb(<br>
+      item_1: 1,<br>
+      item_2: 2<br>
+      )pb");<br>
+})test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(20)));<br>
+<br>
+  // Align the prefix with the suffix if both the prefix and suffix are on a<br>
+  // line of their own.<br>
+  expect_eq(R"test(<br>
+int s() {<br>
+  auto S = PTP(<br>
+      R"pb(<br>
+        item_1: 1,<br>
+        item_2: 2,<br>
+      )pb");<br>
+})test",<br>
+            format(R"test(<br>
+int s() {<br>
+  auto S = PTP(<br>
+      R"pb(<br>
+      item_1: 1,<br>
+      item_2: 2,<br>
+      )pb");<br>
+})test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(20)));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, EstimatesPenalty) {<br>
+  // The penalty for characters exceeding the column limit in the raw string<br>
+  // forces 'hh' to be put on a newline.<br>
+  expect_eq(R"test(<br>
+ff(gggggg,<br>
+   hh(R"pb(key {<br>
+             i1: k1<br>
+             i2: k2<br>
+           })pb"));<br>
+)test",<br>
+            format(R"test(<br>
+ff(gggggg, hh(R"pb(key {<br>
+    i1: k1<br>
+    i2: k2<br>
+    })pb"));<br>
+)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(20)));<br>
+}<br>
+<br>
+TEST_F(FormatTestRawStrings, DontFormatNonRawStrings) {<br>
+  expect_eq(R"test(a = R"pb(key:value)";)test",<br>
+            format(R"test(a = R"pb(key:value)";)test",<br>
+                   getRawStringPbStyleWithColumns<wbr>(20)));<br>
+}<br>
+<br>
+} // end namespace<br>
+} // end namespace format<br>
+} // end namespace clang<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>