From: Krasimir Georgiev Date: Tue, 6 Feb 2018 11:34:34 +0000 (+0000) Subject: [clang-format] Adds space around angle brackets in text protos X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a6469cd80d2064e52854093b689cbeb8bbbb76af;p=clang [clang-format] Adds space around angle brackets in text protos Summary: This patch adds spaces around angle brackets in text proto Google style. Previously these were detected as template openers and closers, which happened to have the expected effect. Now we detect them as scope openers and closers similarly to the way braces are handled in this context. Reviewers: djasper Reviewed By: djasper Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D42727 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324337 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index db4fe8f0a3..00f79ad17d 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/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/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index 60c11a3d08..071230a526 100644 --- a/lib/Format/FormatToken.h +++ b/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/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 05629eda09..bb7c5ada51 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/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 + // msg < item: data > + // msg: < item: data > + // In TT_TextProto, map 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 + // msg < item: data > + // msg: < item: data > + // In TT_TextProto, map 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/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp index 4d52a61dc3..3889bc6776 100644 --- a/unittests/Format/FormatTestProto.cpp +++ b/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: \n" + " msg_field: < field_d: 123 >\n" + " empty: <>\n" + " empty <>\n" "};"); verifyFormat("option (MyProto.options) = {\n" " field_a: OK\n" - " field_b \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: \n" + " msg_field: < field_d: 123 >\n" " field_e: OK\n" - " msg_field: \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 \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 \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 \n" + " data < key: value >\n" ">;"); verifyFormat("option (MyProto.options) = {\n" diff --git a/unittests/Format/FormatTestRawStrings.cpp b/unittests/Format/FormatTestRawStrings.cpp index 4d1da97759..21bbc3fe6f 100644 --- a/unittests/Format/FormatTestRawStrings.cpp +++ b/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/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp index 65f73066fe..1206a2b514 100644 --- a/unittests/Format/FormatTestTextProto.cpp +++ b/unittests/Format/FormatTestTextProto.cpp @@ -143,21 +143,21 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { // 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 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { 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 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { 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 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { " >\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 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { 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"