<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>