This revision was automatically updated to reflect the committed changes.
Closed by commit rL306406: [clang-format] Support <>-style proto message fields 
(authored by krasimir).

Repository:
  rL LLVM

https://reviews.llvm.org/D34621

Files:
  cfe/trunk/lib/Format/ContinuationIndenter.cpp
  cfe/trunk/lib/Format/FormatToken.h
  cfe/trunk/lib/Format/TokenAnnotator.cpp
  cfe/trunk/lib/Format/UnwrappedLineParser.cpp
  cfe/trunk/lib/Format/UnwrappedLineParser.h
  cfe/trunk/unittests/Format/FormatTestProto.cpp

Index: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp
@@ -1176,9 +1176,11 @@
       }
 
       nextToken();
-      if (FormatTok->Tok.is(tok::l_brace)) {
+      if (FormatTok->Tok.is(tok::l_brace))
         parseBracedList();
-      }
+      else if (Style.Language == FormatStyle::LK_Proto &&
+               FormatTok->Tok.is(tok::less))
+        parseBracedList(/*ClosingBraceKind=*/tok::greater);
       break;
     case tok::l_square:
       parseSquare();
@@ -1346,7 +1348,8 @@
   return true;
 }
 
-bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
+bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
+                                          tok::TokenKind ClosingBraceKind) {
   bool HasError = false;
   nextToken();
 
@@ -1375,6 +1378,10 @@
         parseChildBlock();
       }
     }
+    if (FormatTok->Tok.getKind() == ClosingBraceKind) {
+      nextToken();
+      return !HasError;
+    }
     switch (FormatTok->Tok.getKind()) {
     case tok::caret:
       nextToken();
@@ -1401,9 +1408,6 @@
       FormatTok->BlockKind = BK_BracedInit;
       parseBracedList();
       break;
-    case tok::r_brace:
-      nextToken();
-      return !HasError;
     case tok::semi:
       // JavaScript (or more precisely TypeScript) can have semicolons in braced
       // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -89,7 +89,8 @@
         continue;
       }
       if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
-          (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext))
+          (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext &&
+           Style.Language != FormatStyle::LK_Proto))
         return false;
       // If a && or || is found and interpreted as a binary operator, this set
       // of angles is likely part of something like "a < b && c > d". If the
@@ -103,6 +104,14 @@
           !Line.startsWith(tok::kw_template))
         return false;
       updateParameterCount(Left, CurrentToken);
+      if (Style.Language == FormatStyle::LK_Proto) {
+        if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) {
+          if (CurrentToken->is(tok::colon) ||
+              (CurrentToken->isOneOf(tok::l_brace, tok::less) &&
+               Previous->isNot(tok::colon)))
+            Previous->Type = TT_SelectorName;
+        }
+      }
       if (!consumeToken())
         return false;
     }
@@ -440,7 +449,7 @@
         if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
           return false;
         updateParameterCount(Left, CurrentToken);
-        if (CurrentToken->isOneOf(tok::colon, tok::l_brace)) {
+        if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
           FormatToken *Previous = CurrentToken->getPreviousNonComment();
           if (((CurrentToken->is(tok::colon) &&
                 (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
@@ -2549,10 +2558,16 @@
     // deliberate choice and might have aligned the contents of the string
     // literal accordingly. Thus, we try keep existing line breaks.
     return Right.NewlinesBefore > 0;
-  if (Right.Previous->is(tok::l_brace) && Right.NestingLevel == 1 &&
-      Style.Language == FormatStyle::LK_Proto)
-    // Don't put enums onto single lines in protocol buffers.
+  if ((Right.Previous->is(tok::l_brace) ||
+       (Right.Previous->is(tok::less) &&
+        Right.Previous->Previous &&
+        Right.Previous->Previous->is(tok::equal))
+        ) &&
+      Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {
+    // Don't put enums or option definitions onto single lines in protocol
+    // buffers.
     return true;
+  }
   if (Right.is(TT_InlineASMBrace))
     return Right.HasUnescapedNewline;
   if (isAllmanBrace(Left) || isAllmanBrace(Right))
Index: cfe/trunk/lib/Format/ContinuationIndenter.cpp
===================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp
@@ -56,6 +56,8 @@
   if (Current.is(TT_CtorInitializerComma) &&
       Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
     return true;
+  if (Style.Language == FormatStyle::LK_Proto && Current.is(TT_SelectorName))
+    return true;
   return Previous.is(tok::comma) && !Current.isTrailingComment() &&
          ((Previous.isNot(TT_CtorInitializerComma) ||
            Style.BreakConstructorInitializers !=
@@ -499,6 +501,13 @@
   }
 }
 
+static bool lessOpensProtoMessageField(const FormatToken &LessTok,
+                                       const LineState &State) {
+  assert(LessTok.is(tok::less));
+  return LessTok.NestingLevel > 0 ||
+         (LessTok.Previous && LessTok.Previous->is(tok::equal));
+}
+
 unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
                                                  bool DryRun) {
   FormatToken &Current = *State.NextToken;
@@ -641,6 +650,9 @@
   // before the corresponding } or ].
   if (PreviousNonComment &&
       (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
+      (Style.Language == FormatStyle::LK_Proto &&
+       PreviousNonComment->is(tok::less) &&
+       lessOpensProtoMessageField(*PreviousNonComment, State)) ||
        (PreviousNonComment->is(TT_TemplateString) &&
         PreviousNonComment->opensScope())))
     State.Stack.back().BreakBeforeClosingBrace = true;
@@ -682,7 +694,9 @@
   if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block)
     return Current.NestingLevel == 0 ? State.FirstIndent
                                      : State.Stack.back().Indent;
-  if (Current.isOneOf(tok::r_brace, tok::r_square) && State.Stack.size() > 1) {
+  if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
+       (Current.is(tok::greater) && Style.Language == FormatStyle::LK_Proto)) &&
+      State.Stack.size() > 1) {
     if (Current.closesBlockOrBlockTypeList(Style))
       return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
     if (Current.MatchingParen &&
@@ -1035,7 +1049,9 @@
   bool BreakBeforeParameter = false;
   unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall,
                                         State.Stack.back().NestedBlockIndent);
-  if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) {
+  if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
+      (Style.Language == FormatStyle::LK_Proto && Current.is(tok::less) &&
+       lessOpensProtoMessageField(Current, State))) {
     if (Current.opensBlockOrBlockTypeList(Style)) {
       NewIndent = Style.IndentWidth +
                   std::min(State.Column, State.Stack.back().NestedBlockIndent);
Index: cfe/trunk/lib/Format/UnwrappedLineParser.h
===================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h
@@ -93,7 +93,8 @@
   void readTokenWithJavaScriptASI();
   void parseStructuralElement();
   bool tryToParseBracedList();
-  bool parseBracedList(bool ContinueOnSemicolons = false);
+  bool parseBracedList(bool ContinueOnSemicolons = false,
+                       tok::TokenKind ClosingBraceKind = tok::r_brace);
   void parseParens();
   void parseSquare();
   void parseIfThenElse();
Index: cfe/trunk/lib/Format/FormatToken.h
===================================================================
--- cfe/trunk/lib/Format/FormatToken.h
+++ cfe/trunk/lib/Format/FormatToken.h
@@ -465,7 +465,8 @@
     return is(TT_ArrayInitializerLSquare) ||
            (is(tok::l_brace) &&
             (BlockKind == BK_Block || is(TT_DictLiteral) ||
-             (!Style.Cpp11BracedListStyle && NestingLevel == 0)));
+             (!Style.Cpp11BracedListStyle && NestingLevel == 0))) ||
+           (is(tok::less) && Style.Language == FormatStyle::LK_Proto);
   }
 
   /// \brief Same as opensBlockOrBlockTypeList, but for the closing token.
Index: cfe/trunk/unittests/Format/FormatTestProto.cpp
===================================================================
--- cfe/trunk/unittests/Format/FormatTestProto.cpp
+++ cfe/trunk/unittests/Format/FormatTestProto.cpp
@@ -207,6 +207,142 @@
                "  field_c: \"OK\",\n"
                "  msg_field: <field_d: 123>\n"
                "};");
+
+  verifyFormat("option (MyProto.options) = {\n"
+               "  msg_field: <>\n"
+               "  field_c: \"OK\",\n"
+               "  msg_field: <field_d: 123>\n"
+               "  field_e: OK\n"
+               "  msg_field: <field_d: 12>\n"
+               "};");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: OK\n"
+               "  field_b: \"OK\"\n"
+               "  field_c: 1\n"
+               "  field_d: 12.5\n"
+               "  field_e: OK\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: OK,\n"
+               "  field_b: \"OK\",\n"
+               "  field_c: 1,\n"
+               "  field_d: 12.5,\n"
+               "  field_e: OK,\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field: {field_b: OK}\n"
+               "  field_g: OK\n"
+               "  field_g: OK\n"
+               "  field_g: OK\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field<\n"
+               "    field_b: OK\n"
+               "    field_c: OK\n"
+               "    field_d: OK\n"
+               "    field_e: OK\n"
+               "    field_f: OK\n"
+               "  >\n"
+               "  field_g: OK\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field<\n"
+               "    field_b: OK,\n"
+               "    field_c: OK,\n"
+               "    field_d: OK,\n"
+               "    field_e: OK,\n"
+               "    field_f: OK\n"
+               "  >\n"
+               "  field_g: OK\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field: <\n"
+               "    field_b: OK\n"
+               "    field_c: OK\n"
+               "    field_d: OK\n"
+               "    field_e: OK\n"
+               "    field_f: OK\n"
+               "  >\n"
+               "  field_g: OK\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field: {\n"
+               "    field_b: OK\n"
+               "    field_c: OK\n"
+               "    field_d: OK\n"
+               "    field_e: OK\n"
+               "    field_f: OK\n"
+               "  }\n"
+               "  field_g: OK\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field{\n"
+               "    field_b: OK\n"
+               "    field_c: OK\n"
+               "    field_d: OK\n"
+               "    field_e: OK\n"
+               "    field_f: OK\n"
+               "  }\n"
+               "  field_g: OK\n"
+               ">;");
+
+  verifyFormat("option (MyProto.options) = {\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field<\n"
+               "    field_b: OK\n"
+               "    field_c: OK\n"
+               "    field_d: OK\n"
+               "    field_e: OK\n"
+               "    field_f: OK\n"
+               "  >\n"
+               "  field_g: OK\n"
+               "};");
+
+  verifyFormat("option (MyProto.options) = {\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field: <\n"
+               "    field_b: OK\n"
+               "    field_c: OK\n"
+               "    field_d: OK\n"
+               "    field_e: OK\n"
+               "    field_f: OK\n"
+               "  >\n"
+               "  field_g: OK\n"
+               "};");
+
+  verifyFormat("option (MyProto.options) = <\n"
+               "  field_a: \"OK\"\n"
+               "  msg_field{\n"
+               "    field_b: OK\n"
+               "    field_c: OK\n"
+               "    field_d: OK\n"
+               "    msg_field<\n"
+               "      field_A: 1\n"
+               "      field_B: 2\n"
+               "      field_C: 3\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"
+               "    field_e: OK\n"
+               "    field_f: OK\n"
+               "  }\n"
+               "  field_g: OK\n"
+               ">;");
 }
 
 TEST_F(FormatTestProto, FormatsService) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to