]> granicus.if.org Git - clang/commitdiff
[clang-format] Adds space around angle brackets in text protos
authorKrasimir Georgiev <krasimir@google.com>
Tue, 6 Feb 2018 11:34:34 +0000 (11:34 +0000)
committerKrasimir Georgiev <krasimir@google.com>
Tue, 6 Feb 2018 11:34:34 +0000 (11:34 +0000)
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

lib/Format/ContinuationIndenter.cpp
lib/Format/FormatToken.h
lib/Format/TokenAnnotator.cpp
unittests/Format/FormatTestProto.cpp
unittests/Format/FormatTestRawStrings.cpp
unittests/Format/FormatTestTextProto.cpp

index db4fe8f0a3fac8f5188a63af8d86969ba12b3561..00f79ad17dbd1f93299ebf75f20f482b285616ab 100644 (file)
@@ -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)) {
index 60c11a3d0807533480fbd42ae1dcb92563bd974a..071230a52623409e62ba844f13ef56ca484449d6 100644 (file)
@@ -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);
   }
index 05629eda09b2fa6a33e3ba60b15716bf5720393d..bb7c5ada51a9228aa18e04ab35cb896ec840b53a 100644 (file)
@@ -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)))
index 4d52a61dc3fbe84b55705936773019cc1938e002..3889bc677664fb586327a277ef36b682531bd812 100644 (file)
@@ -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"
index 4d1da9775951670cd5585425d7115370eb0b7568..21bbc3fe6f6ada645862f6c7367c6978c6ceac93 100644 (file)
@@ -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",
index 65f73066fe0b1627d3df3eb1816138752858f4b3..1206a2b514ed8202dd161231c6700727932917d5 100644 (file)
@@ -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"