teak-llvm/clang/unittests/Format/FormatTestRawStrings.cpp
Chandler Carruth 2946cd7010 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

987 lines
27 KiB
C++

//===- unittest/Format/FormatTestRawStrings.cpp - Formatting unit tests ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/Format/Format.h"
#include "../Tooling/ReplacementTest.h"
#include "FormatTestUtils.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
#define DEBUG_TYPE "format-test"
using clang::tooling::ReplacementTest;
using clang::tooling::toReplacements;
namespace clang {
namespace format {
namespace {
class FormatTestRawStrings : public ::testing::Test {
protected:
enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete, SC_DoNotCheck };
std::string format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(),
StatusCheck CheckComplete = SC_ExpectComplete) {
LLVM_DEBUG(llvm::errs() << "---\n");
LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
reformat(Style, Code, Ranges, "<stdin>", &Status);
if (CheckComplete != SC_DoNotCheck) {
bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
<< Code << "\n\n";
}
ReplacementCount = Replaces.size();
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
FormatStyle getStyleWithColumns(FormatStyle Style, unsigned ColumnLimit) {
Style.ColumnLimit = ColumnLimit;
return Style;
}
FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) {
return getStyleWithColumns(getLLVMStyle(), ColumnLimit);
}
int ReplacementCount;
FormatStyle getRawStringPbStyleWithColumns(unsigned ColumnLimit) {
FormatStyle Style = getLLVMStyle();
Style.ColumnLimit = ColumnLimit;
Style.RawStringFormats = {
{
/*Language=*/FormatStyle::LK_TextProto,
/*Delimiters=*/{"pb"},
/*EnclosingFunctions=*/{},
/*CanonicalDelimiter=*/"",
/*BasedOnStyle=*/"google",
},
};
return Style;
}
FormatStyle getRawStringLLVMCppStyleBasedOn(std::string BasedOnStyle) {
FormatStyle Style = getLLVMStyle();
Style.RawStringFormats = {
{
/*Language=*/FormatStyle::LK_Cpp,
/*Delimiters=*/{"cpp"},
/*EnclosingFunctions=*/{},
/*CanonicalDelimiter=*/"",
BasedOnStyle,
},
};
return Style;
}
FormatStyle getRawStringGoogleCppStyleBasedOn(std::string BasedOnStyle) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
Style.RawStringFormats = {
{
/*Language=*/FormatStyle::LK_Cpp,
/*Delimiters=*/{"cpp"},
/*EnclosingFunctions=*/{},
/*CanonicalDelimiter=*/"",
BasedOnStyle,
},
};
return Style;
}
// Gcc 4.8 doesn't support raw string literals in macros, which breaks some
// build bots. We use this function instead.
void expect_eq(const std::string Expected, const std::string Actual) {
EXPECT_EQ(Expected, Actual);
}
};
TEST_F(FormatTestRawStrings, ReformatsAccordingToBaseStyle) {
// llvm style puts '*' on the right.
// google style puts '*' on the left.
// Use the llvm style if the raw string style has no BasedOnStyle.
expect_eq(R"test(int *i = R"cpp(int *p = nullptr;)cpp")test",
format(R"test(int * i = R"cpp(int * p = nullptr;)cpp")test",
getRawStringLLVMCppStyleBasedOn("")));
// Use the google style if the raw string style has BasedOnStyle=google.
expect_eq(R"test(int *i = R"cpp(int* p = nullptr;)cpp")test",
format(R"test(int * i = R"cpp(int * p = nullptr;)cpp")test",
getRawStringLLVMCppStyleBasedOn("google")));
// Use the llvm style if the raw string style has no BasedOnStyle=llvm.
expect_eq(R"test(int* i = R"cpp(int *p = nullptr;)cpp")test",
format(R"test(int * i = R"cpp(int * p = nullptr;)cpp")test",
getRawStringGoogleCppStyleBasedOn("llvm")));
}
TEST_F(FormatTestRawStrings, UsesConfigurationOverBaseStyle) {
// llvm style puts '*' on the right.
// google style puts '*' on the left.
// Uses the configured google style inside raw strings even if BasedOnStyle in
// the raw string format is llvm.
FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
EXPECT_EQ(0, parseConfiguration("---\n"
"Language: Cpp\n"
"BasedOnStyle: Google", &Style).value());
Style.RawStringFormats = {{
FormatStyle::LK_Cpp,
{"cpp"},
{},
/*CanonicalDelimiter=*/"",
/*BasedOnStyle=*/"llvm",
}};
expect_eq(R"test(int* i = R"cpp(int* j = 0;)cpp";)test",
format(R"test(int * i = R"cpp(int * j = 0;)cpp";)test", Style));
}
TEST_F(FormatTestRawStrings, MatchesDelimitersCaseSensitively) {
// Don't touch the 'PB' raw string, format the 'pb' raw string.
expect_eq(R"test(
s = R"PB(item:1)PB";
t = R"pb(item: 1)pb";)test",
format(R"test(
s = R"PB(item:1)PB";
t = R"pb(item:1)pb";)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, RespectsClangFormatOff) {
expect_eq(R"test(
// clang-format off
s = R"pb(item: 1)pb";
// clang-format on
t = R"pb(item: 1)pb";)test",
format(R"test(
// clang-format off
s = R"pb(item: 1)pb";
// clang-format on
t = R"pb(item: 1)pb";)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) {
expect_eq(
R"test(P p = TP(R"pb()pb");)test",
format(
R"test(P p = TP(R"pb( )pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(
R"test(P p = TP(R"pb(item_1: 1)pb");)test",
format(
R"test(P p = TP(R"pb(item_1:1)pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(
R"test(P p = TP(R"pb(item_1: 1)pb");)test",
format(
R"test(P p = TP(R"pb( item_1 : 1 )pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(
R"test(P p = TP(R"pb(item_1: 1 item_2: 2)pb");)test",
format(
R"test(P p = TP(R"pb(item_1:1 item_2:2)pb");)test",
getRawStringPbStyleWithColumns(40)));
// Merge two short lines into one.
expect_eq(R"test(
std::string s = R"pb(
item_1: 1 item_2: 2
)pb";
)test",
format(R"test(
std::string s = R"pb(
item_1:1
item_2:2
)pb";
)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, BreaksShortRawStringsWhenNeeded) {
// The raw string contains multiple submessage entries, so break for
// readability.
expect_eq(R"test(
P p = TP(R"pb(item_1 < 1 >
item_2: { 2 })pb");)test",
format(
R"test(
P p = TP(R"pb(item_1<1> item_2:{2})pb");)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, BreaksRawStringsExceedingColumnLimit) {
expect_eq(R"test(
P p = TPPPPPPPPPPPPPPP(
R"pb(item_1: 1, item_2: 2)pb");)test",
format(R"test(
P p = TPPPPPPPPPPPPPPP(R"pb(item_1: 1, item_2: 2)pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
P p =
TPPPPPPPPPPPPPPP(
R"pb(item_1: 1,
item_2: 2,
item_3: 3)pb");)test",
format(R"test(
P p = TPPPPPPPPPPPPPPP(R"pb(item_1: 1, item_2: 2, item_3: 3)pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
P p = TP(R"pb(item_1 < 1 >
item_2: < 2 >
item_3 {})pb");)test",
format(R"test(
P p = TP(R"pb(item_1<1> item_2:<2> item_3{ })pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(
R"test(
P p = TP(R"pb(item_1: 1,
item_2: 2,
item_3: 3,
item_4: 4)pb");)test",
format(
R"test(
P p = TP(R"pb(item_1: 1, item_2: 2, item_3: 3, item_4: 4)pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
P p = TPPPPPPPPPPPPPPP(
R"pb(item_1 < 1 >,
item_2: { 2 },
item_3: < 3 >,
item_4: { 4 })pb");)test",
format(R"test(
P p = TPPPPPPPPPPPPPPP(R"pb(item_1<1>, item_2: {2}, item_3: <3>, item_4:{4})pb");)test",
getRawStringPbStyleWithColumns(40)));
// Breaks before a short raw string exceeding the column limit.
expect_eq(R"test(
FFFFFFFFFFFFFFFFFFFFFFFFFFF(
R"pb(key: 1)pb");
P p = TPPPPPPPPPPPPPPPPPPPP(
R"pb(key: 2)pb");
auto TPPPPPPPPPPPPPPPPPPPP =
R"pb(key: 3)pb";
P p = TPPPPPPPPPPPPPPPPPPPP(
R"pb(i: 1, j: 2)pb");
int f(string s) {
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF(
R"pb(key: 1)pb");
P p = TPPPPPPPPPPPPPPPPPPPP(
R"pb(key: 2)pb");
auto TPPPPPPPPPPPPPPPPPPPP =
R"pb(key: 3)pb";
if (s.empty())
P p = TPPPPPPPPPPPPPPPPPPPP(
R"pb(i: 1, j: 2)pb");
}
)test",
format(R"test(
FFFFFFFFFFFFFFFFFFFFFFFFFFF(R"pb(key:1)pb");
P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(key:2)pb");
auto TPPPPPPPPPPPPPPPPPPPP = R"pb(key:3)pb";
P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(i: 1, j:2)pb");
int f(string s) {
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF(R"pb(key:1)pb");
P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(key:2)pb");
auto TPPPPPPPPPPPPPPPPPPPP = R"pb(key:3)pb";
if (s.empty())
P p = TPPPPPPPPPPPPPPPPPPPP(R"pb(i: 1, j:2)pb");
}
)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, FormatsRawStringArguments) {
expect_eq(R"test(
P p = TP(R"pb(key { 1 })pb", param_2);)test",
format(R"test(
P p = TP(R"pb(key{1})pb",param_2);)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
PPPPPPPPPPPPP(R"pb(keykeyk)pb",
param_2);)test",
format(R"test(
PPPPPPPPPPPPP(R"pb(keykeyk)pb", param_2);)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
P p = TP(
R"pb(item: { i: 1, s: 's' }
item: { i: 2, s: 't' })pb");)test",
format(R"test(
P p = TP(R"pb(item: {i: 1, s: 's'} item: {i: 2, s: 't'})pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
FFFFFFFFFFFFFFFFFFF(
R"pb(key: "value")pb",
R"pb(key2: "value")pb");)test",
format(R"test(
FFFFFFFFFFFFFFFFFFF(R"pb(key: "value")pb", R"pb(key2: "value")pb");)test",
getRawStringPbStyleWithColumns(40)));
// Formats the first out of two arguments.
expect_eq(R"test(
FFFFFFFF(R"pb(key: 1)pb", argument2);
struct S {
const s =
f(R"pb(key: 1)pb", argument2);
void f() {
if (gol)
return g(R"pb(key: 1)pb",
132789237);
return g(R"pb(key: 1)pb", "172893");
}
};)test",
format(R"test(
FFFFFFFF(R"pb(key:1)pb", argument2);
struct S {
const s = f(R"pb(key:1)pb", argument2);
void f() {
if (gol)
return g(R"pb(key:1)pb", 132789237);
return g(R"pb(key:1)pb", "172893");
}
};)test",
getRawStringPbStyleWithColumns(40)));
// Formats the second out of two arguments.
expect_eq(R"test(
FFFFFFFF(argument1, R"pb(key: 2)pb");
struct S {
const s =
f(argument1, R"pb(key: 2)pb");
void f() {
if (gol)
return g(12784137,
R"pb(key: 2)pb");
return g(17283122, R"pb(key: 2)pb");
}
};)test",
format(R"test(
FFFFFFFF(argument1, R"pb(key:2)pb");
struct S {
const s = f(argument1, R"pb(key:2)pb");
void f() {
if (gol)
return g(12784137, R"pb(key:2)pb");
return g(17283122, R"pb(key:2)pb");
}
};)test",
getRawStringPbStyleWithColumns(40)));
// Formats two short raw string arguments.
expect_eq(R"test(
FFFFF(R"pb(key: 1)pb", R"pb(key: 2)pb");)test",
format(R"test(
FFFFF(R"pb(key:1)pb", R"pb(key:2)pb");)test",
getRawStringPbStyleWithColumns(40)));
// TODO(krasimir): The original source code fits on one line, so the
// non-optimizing formatter is chosen. But after the formatting in protos is
// made, the code doesn't fit on one line anymore and further formatting
// splits it.
//
// Should we disable raw string formatting for the non-optimizing formatter?
expect_eq(R"test(
FFFFFFF(R"pb(key: 1)pb", R"pb(key: 2)pb");)test",
format(R"test(
FFFFFFF(R"pb(key:1)pb", R"pb(key:2)pb");)test",
getRawStringPbStyleWithColumns(40)));
// Formats two short raw string arguments, puts second on newline.
expect_eq(R"test(
FFFFFFFF(R"pb(key: 1)pb",
R"pb(key: 2)pb");)test",
format(R"test(
FFFFFFFF(R"pb(key:1)pb", R"pb(key:2)pb");)test",
getRawStringPbStyleWithColumns(40)));
// Formats both arguments.
expect_eq(R"test(
FFFFFFFF(R"pb(key: 1)pb",
R"pb(key: 2)pb");
struct S {
const s = f(R"pb(key: 1)pb",
R"pb(key: 2)pb");
void f() {
if (gol)
return g(R"pb(key: 1)pb",
R"pb(key: 2)pb");
return g(R"pb(k1)pb", R"pb(k2)pb");
}
};)test",
format(R"test(
FFFFFFFF(R"pb(key:1)pb", R"pb(key:2)pb");
struct S {
const s = f(R"pb(key:1)pb", R"pb(key:2)pb");
void f() {
if (gol)
return g(R"pb(key:1)pb", R"pb(key:2)pb");
return g(R"pb( k1 )pb", R"pb( k2 )pb");
}
};)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, RawStringStartingWithNewlines) {
expect_eq(R"test(
std::string s = R"pb(
item_1: 1
)pb";
)test",
format(R"test(
std::string s = R"pb(
item_1:1
)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
std::string s = R"pb(
item_1: 1
)pb";
)test",
format(R"test(
std::string s = R"pb(
item_1:1
)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
std::string s = R"pb(
item_1: 1
)pb";
)test",
format(R"test(
std::string s = R"pb(
item_1:1
)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
std::string s = R"pb(
item_1: 1,
item_2: 2
)pb";
)test",
format(R"test(
std::string s = R"pb(
item_1:1, item_2:2
)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
std::string s = R"pb(
book {
title: "Alice's Adventures"
author: "Lewis Caroll"
}
book {
title: "Peter Pan"
author: "J. M. Barrie"
}
)pb";
)test",
format(R"test(
std::string s = R"pb(
book { title: "Alice's Adventures" author: "Lewis Caroll" }
book { title: "Peter Pan" author: "J. M. Barrie" }
)pb";
)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, BreaksBeforeRawStrings) {
expect_eq(R"test(
ASSERT_TRUE(
ParseFromString(R"pb(item_1: 1)pb"),
ptr);)test",
format(R"test(
ASSERT_TRUE(ParseFromString(R"pb(item_1: 1)pb"), ptr);)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
ASSERT_TRUE(toolong::ParseFromString(
R"pb(item_1: 1)pb"),
ptr);)test",
format(R"test(
ASSERT_TRUE(toolong::ParseFromString(R"pb(item_1: 1)pb"), ptr);)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
ASSERT_TRUE(ParseFromString(
R"pb(item_1: 1,
item_2: 2)pb"),
ptr);)test",
format(R"test(
ASSERT_TRUE(ParseFromString(R"pb(item_1: 1, item_2: 2)pb"), ptr);)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
ASSERT_TRUE(
ParseFromString(
R"pb(item_1: 1 item_2: 2)pb"),
ptr);)test",
format(R"test(
ASSERT_TRUE(ParseFromString(R"pb(item_1: 1 item_2: 2)pb"), ptr);)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, RawStringsInOperands) {
// Formats the raw string first operand of a binary operator expression.
expect_eq(R"test(auto S = R"pb(item_1: 1)pb" + rest;)test",
format(R"test(auto S = R"pb(item_1:1)pb" + rest;)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = R"pb(item_1: 1, item_2: 2)pb" +
rest;)test",
format(R"test(
auto S = R"pb(item_1:1,item_2:2)pb"+rest;)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S =
R"pb(item_1: 1 item_2: 2)pb" + rest;)test",
format(R"test(
auto S = R"pb(item_1:1 item_2:2)pb"+rest;)test",
getRawStringPbStyleWithColumns(40)));
// `rest` fits on the line after )pb", but forced on newline since the raw
// string literal is multiline.
expect_eq(R"test(
auto S = R"pb(item_1: 1,
item_2: 2,
item_3: 3)pb" +
rest;)test",
format(R"test(
auto S = R"pb(item_1:1,item_2:2,item_3:3)pb"+rest;)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = R"pb(item_1: 1,
item_2: 2,
item_3: 3)pb" +
longlongrest;)test",
format(R"test(
auto S = R"pb(item_1:1,item_2:2,item_3:3)pb"+longlongrest;)test",
getRawStringPbStyleWithColumns(40)));
// Formats the raw string second operand of a binary operator expression.
expect_eq(R"test(auto S = first + R"pb(item_1: 1)pb";)test",
format(R"test(auto S = first + R"pb(item_1:1)pb";)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = first + R"pb(item_1: 1,
item_2: 2)pb";)test",
format(R"test(
auto S = first+R"pb(item_1:1,item_2:2)pb";)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = first + R"pb(item_1: 1
item_2: 2)pb";)test",
format(R"test(
auto S = first+R"pb(item_1:1 item_2:2)pb";)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = R"pb(item_1: 1,
item_2: 2,
item_3: 3)pb" +
rest;)test",
format(R"test(
auto S = R"pb(item_1:1,item_2:2,item_3:3)pb"+rest;)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = R"pb(item_1: 1,
item_2: 2,
item_3: 3)pb" +
longlongrest;)test",
format(R"test(
auto S = R"pb(item_1:1,item_2:2,item_3:3)pb"+longlongrest;)test",
getRawStringPbStyleWithColumns(40)));
// Formats the raw string operands in expressions.
expect_eq(R"test(
auto S = R"pb(item_1: 1)pb" +
R"pb(item_2: 2)pb";
)test",
format(R"test(
auto S=R"pb(item_1:1)pb"+R"pb(item_2:2)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = R"pb(item_1: 1)pb" +
R"pb(item_2: 2)pb" +
R"pb(item_3: 3)pb";
)test",
format(R"test(
auto S=R"pb(item_1:1)pb"+R"pb(item_2:2)pb"+R"pb(item_3:3)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S = (count < 3)
? R"pb(item_1: 1)pb"
: R"pb(item_2: 2)pb";
)test",
format(R"test(
auto S=(count<3)?R"pb(item_1:1)pb":R"pb(item_2:2)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S =
(count < 3)
? R"pb(item_1: 1, item_2: 2)pb"
: R"pb(item_3: 3)pb";
)test",
format(R"test(
auto S=(count<3)?R"pb(item_1:1,item_2:2)pb":R"pb(item_3:3)pb";
)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
auto S =
(count < 3)
? R"pb(item_1: 1)pb"
: R"pb(item_2: 2, item_3: 3)pb";
)test",
format(R"test(
auto S=(count<3)?R"pb(item_1:1)pb":R"pb(item_2:2,item_3:3)pb";
)test",
getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, PrefixAndSuffixAlignment) {
// Keep the suffix at the end of line if not on newline.
expect_eq(R"test(
int s() {
auto S = PTP(
R"pb(
item_1: 1,
item_2: 2)pb");
})test",
format(R"test(
int s() {
auto S = PTP(
R"pb(
item_1: 1,
item_2: 2)pb");
})test",
getRawStringPbStyleWithColumns(20)));
// Align the suffix with the surrounding indent if the prefix is not on
// a line of its own.
expect_eq(R"test(
int s() {
auto S = PTP(R"pb(
item_1: 1,
item_2: 2
)pb");
})test",
format(R"test(
int s() {
auto S = PTP(R"pb(
item_1: 1,
item_2: 2
)pb");
})test",
getRawStringPbStyleWithColumns(20)));
// Align the prefix with the suffix if both the prefix and suffix are on a
// line of their own.
expect_eq(R"test(
int s() {
auto S = PTP(
R"pb(
item_1: 1,
item_2: 2,
)pb");
})test",
format(R"test(
int s() {
auto S = PTP(
R"pb(
item_1: 1,
item_2: 2,
)pb");
})test",
getRawStringPbStyleWithColumns(20)));
}
TEST_F(FormatTestRawStrings, EstimatesPenalty) {
// The penalty for characters exceeding the column limit in the raw string
// forces 'hh' to be put on a newline.
expect_eq(R"test(
ff(gggggg,
hh(R"pb(key {
i1: k1
i2: k2
})pb"));
)test",
format(R"test(
ff(gggggg, hh(R"pb(key {
i1: k1
i2: k2
})pb"));
)test",
getRawStringPbStyleWithColumns(20)));
}
TEST_F(FormatTestRawStrings, DontFormatNonRawStrings) {
expect_eq(R"test(a = R"pb(key:value)";)test",
format(R"test(a = R"pb(key:value)";)test",
getRawStringPbStyleWithColumns(20)));
}
TEST_F(FormatTestRawStrings, FormatsRawStringsWithEnclosingFunctionName) {
FormatStyle Style = getRawStringPbStyleWithColumns(40);
Style.RawStringFormats[0].EnclosingFunctions.push_back(
"PARSE_TEXT_PROTO");
Style.RawStringFormats[0].EnclosingFunctions.push_back("ParseTextProto");
expect_eq(R"test(a = PARSE_TEXT_PROTO(R"(key: value)");)test",
format(R"test(a = PARSE_TEXT_PROTO(R"(key:value)");)test", Style));
expect_eq(R"test(
a = PARSE_TEXT_PROTO /**/ (
/**/ R"(key: value)");)test",
format(R"test(
a = PARSE_TEXT_PROTO/**/(/**/R"(key:value)");)test",
Style));
expect_eq(R"test(
a = ParseTextProto<ProtoType>(
R"(key: value)");)test",
format(R"test(
a = ParseTextProto<ProtoType>(R"(key:value)");)test",
Style));
}
TEST_F(FormatTestRawStrings, UpdatesToCanonicalDelimiters) {
FormatStyle Style = getRawStringPbStyleWithColumns(25);
Style.RawStringFormats[0].CanonicalDelimiter = "proto";
expect_eq(R"test(a = R"proto(key: value)proto";)test",
format(R"test(a = R"pb(key:value)pb";)test", Style));
// Don't update to canonical delimiter if it occurs as a raw string suffix in
// the raw string content.
expect_eq(R"test(a = R"pb(key: ")proto")pb";)test",
format(R"test(a = R"pb(key:")proto")pb";)test", Style));
}
TEST_F(FormatTestRawStrings, PenalizesPrefixExcessChars) {
FormatStyle Style = getRawStringPbStyleWithColumns(60);
// The '(' in R"pb is at column 60, no break.
expect_eq(R"test(
xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
)pb"));
)test",
format(R"test(
xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
)pb"));
)test", Style));
// The '(' in R"pb is at column 61, break.
expect_eq(R"test(
xxxxxxxaaaaax wwwwwww =
_Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
)pb"));
)test",
format(R"test(
xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
)pb"));
)test", Style));
}
TEST_F(FormatTestRawStrings, KeepsRBraceFolloedByMoreLBracesOnSameLine) {
FormatStyle Style = getRawStringPbStyleWithColumns(80);
expect_eq(
R"test(
int f() {
if (1) {
TTTTTTTTTTTTTTTTTTTTT s = PARSE_TEXT_PROTO(R"pb(
ttttttttt {
ppppppppppppp {
[cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_1: "123_1" }
[cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_2: "123_2" }
}
}
)pb");
}
}
)test",
format(
R"test(
int f() {
if (1) {
TTTTTTTTTTTTTTTTTTTTT s = PARSE_TEXT_PROTO(R"pb(
ttttttttt {
ppppppppppppp {
[cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_1: "123_1" }
[cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_2: "123_2" }}}
)pb");
}
}
)test",
Style));
}
TEST_F(FormatTestRawStrings,
DoNotFormatUnrecognizedDelimitersInRecognizedFunctions) {
FormatStyle Style = getRawStringPbStyleWithColumns(60);
Style.RawStringFormats[0].EnclosingFunctions.push_back(
"EqualsProto");
// EqualsProto is a recognized function, but the Raw delimiter is
// unrecognized. Do not touch the string in this case, since it might be
// special.
expect_eq(R"test(
void f() {
aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw(
item {
key: value
}
)Raw"));
})test",
format(R"test(
void f() {
aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw(
item {
key: value
}
)Raw"));
})test",
Style));
}
TEST_F(FormatTestRawStrings,
BreaksBeforeNextParamAfterMultilineRawStringParam) {
FormatStyle Style = getRawStringPbStyleWithColumns(60);
expect_eq(R"test(
int f() {
int a = g(x, R"pb(
key: 1 #
key: 2
)pb",
3, 4);
}
)test",
format(R"test(
int f() {
int a = g(x, R"pb(
key: 1 #
key: 2
)pb", 3, 4);
}
)test",
Style));
// Breaks after a parent of a multiline param.
expect_eq(R"test(
int f() {
int a = g(x, h(R"pb(
key: 1 #
key: 2
)pb"),
3, 4);
}
)test",
format(R"test(
int f() {
int a = g(x, h(R"pb(
key: 1 #
key: 2
)pb"), 3, 4);
}
)test",
Style));
expect_eq(R"test(
int f() {
int a = g(x,
h(R"pb(
key: 1 #
key: 2
)pb",
2),
3, 4);
}
)test",
format(R"test(
int f() {
int a = g(x, h(R"pb(
key: 1 #
key: 2
)pb", 2), 3, 4);
}
)test",
Style));
// Breaks if formatting introduces a multiline raw string.
expect_eq(R"test(
int f() {
int a = g(x, R"pb(key1: value111111111
key2: value2222222222)pb",
3, 4);
}
)test",
format(R"test(
int f() {
int a = g(x, R"pb(key1: value111111111 key2: value2222222222)pb", 3, 4);
}
)test",
Style));
// Does not force a break after an original multiline param that is
// reformatterd as on single line.
expect_eq(R"test(
int f() {
int a = g(R"pb(key: 1)pb", 2);
})test",
format(R"test(
int f() {
int a = g(R"pb(key:
1)pb", 2);
})test", Style));
}
} // end namespace
} // end namespace format
} // end namespace clang