summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Format/ContinuationIndenter.cpp5
-rw-r--r--clang/lib/Format/FormatToken.h10
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp46
-rw-r--r--clang/unittests/Format/FormatTestProto.cpp16
-rw-r--r--clang/unittests/Format/FormatTestRawStrings.cpp10
-rw-r--r--clang/unittests/Format/FormatTestTextProto.cpp86
6 files changed, 108 insertions, 65 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index db4fe8f0a3f..00f79ad17db 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -857,7 +857,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
(Current.Next->is(TT_DictLiteral) ||
((Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto) &&
- Current.Next->isOneOf(TT_TemplateOpener, tok::l_brace))))
+ Current.Next->isOneOf(tok::less, tok::l_brace))))
return State.Stack.back().Indent;
if (NextNonComment->is(TT_ObjCStringLiteral) &&
State.StartOfStringLiteral != 0)
@@ -1293,7 +1293,8 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
if (State.Stack.size() > 1 &&
(Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
(Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
- State.NextToken->is(TT_TemplateCloser)))
+ State.NextToken->is(TT_TemplateCloser) ||
+ (Current.is(tok::greater) && Current.is(TT_DictLiteral))))
State.Stack.pop_back();
if (Current.is(tok::r_square)) {
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 60c11a3d080..071230a5262 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -348,17 +348,23 @@ struct FormatToken {
Next->isObjCAtKeyword(tok::objc_private));
}
- /// \brief Returns whether \p Tok is ([{ or a template opening <.
+ /// \brief Returns whether \p Tok is ([{ or an opening < of a template or in
+ /// protos.
bool opensScope() const {
if (is(TT_TemplateString) && TokenText.endswith("${"))
return true;
+ if (is(TT_DictLiteral) && is(tok::less))
+ return true;
return isOneOf(tok::l_paren, tok::l_brace, tok::l_square,
TT_TemplateOpener);
}
- /// \brief Returns whether \p Tok is )]} or a template closing >.
+ /// \brief Returns whether \p Tok is )]} or a closing > of a template or in
+ /// protos.
bool closesScope() const {
if (is(TT_TemplateString) && TokenText.startswith("}"))
return true;
+ if (is(TT_DictLiteral) && is(tok::greater))
+ return true;
return isOneOf(tok::r_paren, tok::r_brace, tok::r_square,
TT_TemplateCloser);
}
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 05629eda09b..bb7c5ada51a 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -79,7 +79,17 @@ private:
if (CurrentToken->is(tok::greater)) {
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
- CurrentToken->Type = TT_TemplateCloser;
+ // In TT_Proto, we must distignuish between:
+ // map<key, value>
+ // msg < item: data >
+ // msg: < item: data >
+ // In TT_TextProto, map<key, value> does not occur.
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto && Left->Previous &&
+ Left->Previous->isOneOf(TT_SelectorName, TT_DictLiteral)))
+ CurrentToken->Type = TT_DictLiteral;
+ else
+ CurrentToken->Type = TT_TemplateCloser;
next();
return true;
}
@@ -670,7 +680,15 @@ private:
case tok::less:
if (parseAngle()) {
Tok->Type = TT_TemplateOpener;
- if (Style.Language == FormatStyle::LK_TextProto) {
+ // In TT_Proto, we must distignuish between:
+ // map<key, value>
+ // msg < item: data >
+ // msg: < item: data >
+ // In TT_TextProto, map<key, value> does not occur.
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto && Tok->Previous &&
+ Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {
+ Tok->Type = TT_DictLiteral;
FormatToken *Previous = Tok->getPreviousNonComment();
if (Previous && Previous->Type != TT_DictLiteral)
Previous->Type = TT_SelectorName;
@@ -691,7 +709,8 @@ private:
return false;
break;
case tok::greater:
- Tok->Type = TT_BinaryOperator;
+ if (Style.Language != FormatStyle::LK_TextProto)
+ Tok->Type = TT_BinaryOperator;
break;
case tok::kw_operator:
while (CurrentToken &&
@@ -1157,7 +1176,9 @@ private:
Current.Type = TT_ConditionalExpr;
}
} else if (Current.isBinaryOperator() &&
- (!Current.Previous || Current.Previous->isNot(tok::l_square))) {
+ (!Current.Previous || Current.Previous->isNot(tok::l_square)) &&
+ (!Current.is(tok::greater) &&
+ Style.Language != FormatStyle::LK_TextProto)) {
Current.Type = TT_BinaryOperator;
} else if (Current.is(tok::comment)) {
if (Current.TokenText.startswith("/*")) {
@@ -2226,8 +2247,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return !Left.is(TT_ObjCMethodExpr);
if (Left.is(tok::coloncolon))
return false;
- if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
+ if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto &&
+ (Left.is(TT_DictLiteral) || Right.is(TT_DictLiteral)))) {
+ // Format empty list as `<>`.
+ if (Left.is(tok::less) && Right.is(tok::greater))
+ return false;
+ return !Style.Cpp11BracedListStyle;
+ }
return false;
+ }
if (Right.is(tok::ellipsis))
return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
Left.Previous->is(tok::kw_case));
@@ -2502,9 +2532,13 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return Style.SpaceAfterCStyleCast ||
Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
- if (Left.is(tok::greater) && Right.is(tok::greater))
+ if (Left.is(tok::greater) && Right.is(tok::greater)) {
+ if (Style.Language == FormatStyle::LK_TextProto ||
+ (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
+ return !Style.Cpp11BracedListStyle;
return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
(Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
+ }
if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
(Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
diff --git a/clang/unittests/Format/FormatTestProto.cpp b/clang/unittests/Format/FormatTestProto.cpp
index 4d52a61dc3f..3889bc67766 100644
--- a/clang/unittests/Format/FormatTestProto.cpp
+++ b/clang/unittests/Format/FormatTestProto.cpp
@@ -211,12 +211,14 @@ TEST_F(FormatTestProto, FormatsOptions) {
// Support syntax with <> instead of {}.
verifyFormat("option (MyProto.options) = {\n"
" field_c: \"OK\",\n"
- " msg_field: <field_d: 123>\n"
+ " msg_field: < field_d: 123 >\n"
+ " empty: <>\n"
+ " empty <>\n"
"};");
verifyFormat("option (MyProto.options) = {\n"
" field_a: OK\n"
- " field_b <field_c: OK>\n"
+ " field_b < field_c: OK >\n"
" field_d: OKOKOK\n"
" field_e: OK\n"
"}");
@@ -224,9 +226,9 @@ TEST_F(FormatTestProto, FormatsOptions) {
verifyFormat("option (MyProto.options) = {\n"
" msg_field: <>\n"
" field_c: \"OK\",\n"
- " msg_field: <field_d: 123>\n"
+ " msg_field: < field_d: 123 >\n"
" field_e: OK\n"
- " msg_field: <field_d: 12>\n"
+ " msg_field: < field_d: 12 >\n"
"};");
verifyFormat("option (MyProto.options) = <\n"
@@ -350,7 +352,7 @@ TEST_F(FormatTestProto, FormatsOptions) {
" field_D: 4\n"
" field_E: 5\n"
" >\n"
- " msg_field <field_A: 1 field_B: 2 field_C: 3 field_D: 4>\n"
+ " msg_field < field_A: 1 field_B: 2 field_C: 3 f_D: 4 >\n"
" field_e: OK\n"
" field_f: OK\n"
" }\n"
@@ -358,14 +360,14 @@ TEST_F(FormatTestProto, FormatsOptions) {
">;");
verifyFormat("option (MyProto.options) = <\n"
- " data1 <key1: value1>\n"
+ " data1 < key1: value1 >\n"
" data2 { key2: value2 }\n"
">;");
verifyFormat("option (MyProto.options) = <\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" head_id: 1\n"
- " data <key: value>\n"
+ " data < key: value >\n"
">;");
verifyFormat("option (MyProto.options) = {\n"
diff --git a/clang/unittests/Format/FormatTestRawStrings.cpp b/clang/unittests/Format/FormatTestRawStrings.cpp
index 4d1da977595..21bbc3fe6f6 100644
--- a/clang/unittests/Format/FormatTestRawStrings.cpp
+++ b/clang/unittests/Format/FormatTestRawStrings.cpp
@@ -186,7 +186,7 @@ TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) {
R"test(P p = TP(R"pb(item_1:1 item_2:2)pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(
- R"test(P p = TP(R"pb(item_1 <1> item_2: { 2 })pb");)test",
+ 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)));
@@ -225,8 +225,8 @@ 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>
+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",
@@ -245,9 +245,9 @@ P p = TP(R"pb(item_1: 1, item_2: 2, item_3: 3, item_4: 4)pb");)test",
expect_eq(R"test(
P p = TPPPPPPPPPPPPPPP(
- R"pb(item_1 <1>,
+ R"pb(item_1 < 1 >,
item_2: { 2 },
- item_3: <3>,
+ 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",
diff --git a/clang/unittests/Format/FormatTestTextProto.cpp b/clang/unittests/Format/FormatTestTextProto.cpp
index 65f73066fe0..1206a2b514e 100644
--- a/clang/unittests/Format/FormatTestTextProto.cpp
+++ b/clang/unittests/Format/FormatTestTextProto.cpp
@@ -143,21 +143,21 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
// Single-line tests
verifyFormat("msg_field <>");
verifyFormat("msg_field: <>");
- verifyFormat("msg_field <field_a: OK>");
- verifyFormat("msg_field: <field_a: 123>");
- verifyFormat("msg_field <field_a <>>");
- verifyFormat("msg_field <field_a <field_b <>>>");
- verifyFormat("msg_field: <field_a <field_b: <>>>");
- verifyFormat("msg_field <field_a: OK, field_b: \"OK\">");
- verifyFormat("msg_field <field_a: OK field_b: <>, field_c: OK>");
- verifyFormat("msg_field <field_a { field_b: 1 }, field_c: <field_d: 2>>");
- verifyFormat("msg_field: <field_a: OK, field_b: \"OK\">");
- verifyFormat("msg_field: <field_a: OK field_b: <>, field_c: OK>");
- verifyFormat("msg_field: <field_a { field_b: 1 }, field_c: <field_d: 2>>");
- verifyFormat("field_a: \"OK\", msg_field: <field_b: 123>, field_c: {}");
- verifyFormat("field_a <field_b: 1>, msg_field: <field_b: 123>, field_c <>");
- verifyFormat("field_a <field_b: 1> msg_field: <field_b: 123> field_c <>");
- verifyFormat("field <field <field: <>>, field <>> field: <field: 1>");
+ verifyFormat("msg_field < field_a: OK >");
+ verifyFormat("msg_field: < field_a: 123 >");
+ verifyFormat("msg_field < field_a <> >");
+ verifyFormat("msg_field < field_a < field_b <> > >");
+ verifyFormat("msg_field: < field_a < field_b: <> > >");
+ verifyFormat("msg_field < field_a: OK, field_b: \"OK\" >");
+ verifyFormat("msg_field < field_a: OK field_b: <>, field_c: OK >");
+ verifyFormat("msg_field < field_a { field_b: 1 }, field_c: < f_d: 2 > >");
+ verifyFormat("msg_field: < field_a: OK, field_b: \"OK\" >");
+ verifyFormat("msg_field: < field_a: OK field_b: <>, field_c: OK >");
+ verifyFormat("msg_field: < field_a { field_b: 1 }, field_c: < fd_d: 2 > >");
+ verifyFormat("field_a: \"OK\", msg_field: < field_b: 123 >, field_c: {}");
+ verifyFormat("field_a < field_b: 1 >, msg_fid: < fiel_b: 123 >, field_c <>");
+ verifyFormat("field_a < field_b: 1 > msg_fied: < field_b: 123 > field_c <>");
+ verifyFormat("field < field < field: <> >, field <> > field: < field: 1 >");
// Multiple lines tests
verifyFormat("msg_field <\n"
@@ -170,31 +170,31 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
verifyFormat("msg_field: <>\n"
"field_c: \"OK\",\n"
- "msg_field: <field_d: 123>\n"
+ "msg_field: < field_d: 123 >\n"
"field_e: OK\n"
- "msg_field: <field_d: 12>");
+ "msg_field: < field_d: 12 >");
verifyFormat("field_a: OK,\n"
- "field_b <field_c: OK>,\n"
- "field_d: <12.5>,\n"
+ "field_b < field_c: OK >,\n"
+ "field_d: < 12.5 >,\n"
"field_e: OK");
verifyFormat("field_a: OK\n"
- "field_b <field_c: OK>\n"
- "field_d: <12.5>\n"
+ "field_b < field_c: OK >\n"
+ "field_d: < 12.5 >\n"
"field_e: OKOKOK");
verifyFormat("msg_field <\n"
" field_a: OK,\n"
- " field_b <field_c: OK>,\n"
- " field_d: <12.5>,\n"
+ " field_b < field_c: OK >,\n"
+ " field_d: < 12.5 >,\n"
" field_e: OK\n"
">");
verifyFormat("msg_field <\n"
- " field_a: <field: OK>,\n"
- " field_b <field_c: OK>,\n"
- " field_d: <12.5>,\n"
+ " field_a: < field: OK >,\n"
+ " field_b < field_c: OK >,\n"
+ " field_d: < 12.5 >,\n"
" field_e: OK,\n"
">");
@@ -208,19 +208,19 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
verifyFormat("field_a {\n"
" field_d: ok\n"
- " field_b: <field_c: 1>\n"
+ " field_b: < field_c: 1 >\n"
" field_d: ok\n"
" field_d: ok\n"
"}");
verifyFormat("field_a: {\n"
" field_d: ok\n"
- " field_b: <field_c: 1>\n"
+ " field_b: < field_c: 1 >\n"
" field_d: ok\n"
" field_d: ok\n"
"}");
- verifyFormat("field_a: <f1: 1, f2: <>>\n"
+ verifyFormat("field_a: < f1: 1, f2: <> >\n"
"field_b <\n"
" field_b1: <>\n"
" field_b2: ok,\n"
@@ -231,45 +231,45 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
" >\n"
" field {\n"
" field_x <> // Comment\n"
- " field_y: <field_z: 1>\n"
+ " field_y: < field_z: 1 >\n"
" field_w: ok\n"
" msg_field: <\n"
" field: <>\n"
- " field: <field: 1>\n"
- " field: <field: 2>\n"
- " field: <field: 3>\n"
- " field: <field: 4>\n"
+ " field: < field: 1 >\n"
+ " field: < field: 2 >\n"
+ " field: < field: 3 >\n"
+ " field: < field: 4 >\n"
" field: ok\n"
" >\n"
" }\n"
">\n"
"field: OK,\n"
- "field_c <field <field <>>>");
+ "field_c < field < field <> > >");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"head_id: 1\n"
- "data <key: value>");
+ "data < key: value >");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"head_id: 1\n"
- "data <key: value>\n"
+ "data < key: value >\n"
"tail_id: 2");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"head_id: 1\n"
- "data <key: value>\n"
+ "data < key: value >\n"
"data { key: value }");
verifyFormat("app {\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" head_id: 1\n"
- " data <key: value>\n"
+ " data < key: value >\n"
"}");
verifyFormat("app: {\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" head_id: 1\n"
- " data <key: value>\n"
+ " data < key: value >\n"
"}");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
@@ -278,16 +278,16 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"headheadheadheadheadhead_id: 1\n"
- "product_data <product { 1 }>");
+ "product_data < product { 1 } >");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"headheadheadheadheadhead_id: 1\n"
- "product_data <product <1>>");
+ "product_data < product < 1 > >");
verifyFormat("app <\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" headheadheadheadheadhead_id: 1\n"
- " product_data <product { 1 }>\n"
+ " product_data < product { 1 } >\n"
">");
verifyFormat("dcccwrnfioeruvginerurneitinfo {\n"
OpenPOWER on IntegriCloud