(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)
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)) {
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);
}
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;
}
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;
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 &&
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("/*")) {
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));
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)))
// 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"
"}");
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"
" 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"
">;");
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"
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)));
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",
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",
// 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"
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"
">");
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"
" >\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"
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"