Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -857,7 +857,7 @@ (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) @@ -1282,7 +1282,8 @@ 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)) { Index: lib/Format/FormatToken.h =================================================================== --- lib/Format/FormatToken.h +++ lib/Format/FormatToken.h @@ -348,17 +348,23 @@ 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); } Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -79,7 +79,10 @@ if (CurrentToken->is(tok::greater)) { Left->MatchingParen = CurrentToken; CurrentToken->MatchingParen = Left; - CurrentToken->Type = TT_TemplateCloser; + if (Style.Language == FormatStyle::LK_TextProto) + CurrentToken->Type = TT_DictLiteral; + else + CurrentToken->Type = TT_TemplateCloser; next(); return true; } @@ -671,6 +674,7 @@ if (parseAngle()) { Tok->Type = TT_TemplateOpener; if (Style.Language == FormatStyle::LK_TextProto) { + Tok->Type = TT_DictLiteral; FormatToken *Previous = Tok->getPreviousNonComment(); if (Previous && Previous->Type != TT_DictLiteral) Previous->Type = TT_SelectorName; @@ -691,7 +695,8 @@ 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 +1162,9 @@ 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("/*")) { @@ -2223,8 +2230,15 @@ 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) { + // 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)); @@ -2499,9 +2513,13 @@ 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) { + 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))) Index: unittests/Format/FormatTestRawStrings.cpp =================================================================== --- unittests/Format/FormatTestRawStrings.cpp +++ unittests/Format/FormatTestRawStrings.cpp @@ -186,7 +186,7 @@ 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 @@ 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 @@ 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", Index: unittests/Format/FormatTestTextProto.cpp =================================================================== --- unittests/Format/FormatTestTextProto.cpp +++ unittests/Format/FormatTestTextProto.cpp @@ -143,21 +143,21 @@ // Single-line tests verifyFormat("msg_field <>"); verifyFormat("msg_field: <>"); - verifyFormat("msg_field "); - verifyFormat("msg_field: "); - verifyFormat("msg_field >"); - verifyFormat("msg_field >>"); - verifyFormat("msg_field: >>"); - verifyFormat("msg_field "); - verifyFormat("msg_field , field_c: OK>"); - verifyFormat("msg_field >"); - verifyFormat("msg_field: "); - verifyFormat("msg_field: , field_c: OK>"); - verifyFormat("msg_field: >"); - verifyFormat("field_a: \"OK\", msg_field: , field_c: {}"); - verifyFormat("field_a , msg_field: , field_c <>"); - verifyFormat("field_a msg_field: field_c <>"); - verifyFormat("field >, field <>> 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: < 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 @@ verifyFormat("msg_field: <>\n" "field_c: \"OK\",\n" - "msg_field: \n" + "msg_field: < field_d: 123 >\n" "field_e: OK\n" - "msg_field: "); + "msg_field: < field_d: 12 >"); verifyFormat("field_a: OK,\n" - "field_b ,\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 \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 ,\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: ,\n" - " field_b ,\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 @@ verifyFormat("field_a {\n" " field_d: ok\n" - " field_b: \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: \n" + " field_b: < field_c: 1 >\n" " field_d: ok\n" " field_d: ok\n" "}"); - verifyFormat("field_a: >\n" + verifyFormat("field_a: < f1: 1, f2: <> >\n" "field_b <\n" " field_b1: <>\n" " field_b2: ok,\n" @@ -231,45 +231,45 @@ " >\n" " field {\n" " field_x <> // Comment\n" - " field_y: \n" + " field_y: < field_z: 1 >\n" " field_w: ok\n" " msg_field: <\n" " field: <>\n" - " field: \n" - " field: \n" - " field: \n" - " field: \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_c < field < field <> > >"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "head_id: 1\n" - "data "); + "data < key: value >"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "head_id: 1\n" - "data \n" + "data < key: value >\n" "tail_id: 2"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "head_id: 1\n" - "data \n" + "data < key: value >\n" "data { key: value }"); verifyFormat("app {\n" " app_id: 'com.javax.swing.salsa.latino'\n" " head_id: 1\n" - " data \n" + " data < key: value >\n" "}"); verifyFormat("app: {\n" " app_id: 'com.javax.swing.salsa.latino'\n" " head_id: 1\n" - " data \n" + " data < key: value >\n" "}"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" @@ -278,16 +278,16 @@ verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "headheadheadheadheadhead_id: 1\n" - "product_data "); + "product_data < product { 1 } >"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "headheadheadheadheadhead_id: 1\n" - "product_data >"); + "product_data < product < 1 > >"); verifyFormat("app <\n" " app_id: 'com.javax.swing.salsa.latino'\n" " headheadheadheadheadhead_id: 1\n" - " product_data \n" + " product_data < product { 1 } >\n" ">"); verifyFormat("dcccwrnfioeruvginerurneitinfo {\n"