krasimir updated this revision to Diff 103352.
krasimir added a comment.

- Remove newline


https://reviews.llvm.org/D34441

Files:
  include/clang/Format/Format.h
  lib/Format/ContinuationIndenter.cpp
  lib/Format/Format.cpp
  lib/Format/TokenAnnotator.cpp
  lib/Format/UnwrappedLineParser.cpp
  lib/Format/UnwrappedLineParser.h
  unittests/Format/CMakeLists.txt
  unittests/Format/FormatTestTextProto.cpp

Index: unittests/Format/FormatTestTextProto.cpp
===================================================================
--- /dev/null
+++ unittests/Format/FormatTestTextProto.cpp
@@ -0,0 +1,131 @@
+//===- unittest/Format/FormatTestProto.cpp --------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FormatTestUtils.h"
+#include "clang/Format/Format.h"
+#include "llvm/Support/Debug.h"
+#include "gtest/gtest.h"
+
+#define DEBUG_TYPE "format-test"
+
+namespace clang {
+namespace format {
+
+class FormatTestTextProto : public ::testing::Test {
+protected:
+  static std::string format(llvm::StringRef Code, unsigned Offset,
+                            unsigned Length, const FormatStyle &Style) {
+    DEBUG(llvm::errs() << "---\n");
+    DEBUG(llvm::errs() << Code << "\n\n");
+    std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
+    tooling::Replacements Replaces = reformat(Style, Code, Ranges);
+    auto Result = applyAllReplacements(Code, Replaces);
+    EXPECT_TRUE(static_cast<bool>(Result));
+    DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+    return *Result;
+  }
+
+  static std::string format(llvm::StringRef Code) {
+    FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+    Style.ColumnLimit = 60; // To make writing tests easier.
+    return format(Code, 0, Code.size(), Style);
+  }
+
+  static void verifyFormat(llvm::StringRef Code) {
+    EXPECT_EQ(Code.str(), format(test::messUp(Code)));
+  }
+};
+
+TEST_F(FormatTestTextProto, KeepsTopLevelEntriesFittingALine) {
+  verifyFormat("field_a: OK field_b: OK field_c: OK field_d: OK field_e: OK");
+}
+
+TEST_F(FormatTestTextProto, SupportsMessageFields) {
+  verifyFormat("msg_field: {}");
+
+  verifyFormat("msg_field: {field_a: A}");
+
+  verifyFormat("msg_field: {field_a: \"OK\" field_b: 123}");
+
+  verifyFormat("msg_field: {\n"
+               "  field_a: 1\n"
+               "  field_b: OK\n"
+               "  field_c: \"OK\"\n"
+               "  field_d: 123\n"
+               "  field_e: 23\n"
+               "}");
+
+  verifyFormat("msg_field{}");
+
+  verifyFormat("msg_field{field_a: A}");
+
+  verifyFormat("msg_field{field_a: \"OK\" field_b: 123}");
+
+  verifyFormat("msg_field{\n"
+               "  field_a: 1\n"
+               "  field_b: OK\n"
+               "  field_c: \"OK\"\n"
+               "  field_d: 123\n"
+               "  field_e: 23.0\n"
+               "  field_f: false\n"
+               "  field_g: 'lala'\n"
+               "  field_h: 1234.567e-89\n"
+               "}");
+
+  verifyFormat("msg_field: {msg_field{field_a: 1}}");
+
+  verifyFormat("id: \"ala.bala\"\n"
+               "item{type: ITEM_A rank: 1 score: 90.0}\n"
+               "item{type: ITEM_B rank: 2 score: 70.5}\n"
+               "item{\n"
+               "  type: ITEM_A\n"
+               "  rank: 3\n"
+               "  score: 20.0\n"
+               "  description: \"the third item has a description\"\n"
+               "}");
+}
+
+TEST_F(FormatTestTextProto, AvoidsTopLevelBinPacking) {
+  verifyFormat("field_a: OK\n"
+               "field_b: OK\n"
+               "field_c: OK\n"
+               "field_d: OK\n"
+               "field_e: OK\n"
+               "field_f: OK");
+
+  verifyFormat("field_a: OK\n"
+               "field_b: \"OK\"\n"
+               "field_c: \"OK\"\n"
+               "msg_field: {field_d: 123}\n"
+               "field_e: OK\n"
+               "field_f: OK");
+
+  verifyFormat("field_a: OK\n"
+               "field_b: \"OK\"\n"
+               "field_c: \"OK\"\n"
+               "msg_field: {field_d: 123 field_e: OK}");
+}
+
+TEST_F(FormatTestTextProto, AddsNewlinesAfterTrailingComments) {
+  verifyFormat("field_a: OK  // Comment\n"
+               "field_b: 1");
+
+  verifyFormat("field_a: OK\n"
+               "msg_field: {\n"
+               "  field_b: OK  // Comment\n"
+               "}");
+
+  verifyFormat("field_a: OK\n"
+               "msg_field{\n"
+               "  field_b: OK  // Comment\n"
+               "}");
+}
+
+} // end namespace tooling
+} // end namespace clang
Index: unittests/Format/CMakeLists.txt
===================================================================
--- unittests/Format/CMakeLists.txt
+++ unittests/Format/CMakeLists.txt
@@ -11,6 +11,7 @@
   FormatTestObjC.cpp
   FormatTestProto.cpp
   FormatTestSelective.cpp
+  FormatTestTextProto.cpp
   NamespaceEndCommentsFixerTest.cpp
   SortImportsTestJS.cpp
   SortIncludesTest.cpp
Index: lib/Format/UnwrappedLineParser.h
===================================================================
--- lib/Format/UnwrappedLineParser.h
+++ lib/Format/UnwrappedLineParser.h
@@ -93,7 +93,7 @@
   void readTokenWithJavaScriptASI();
   void parseStructuralElement();
   bool tryToParseBracedList();
-  bool parseBracedList(bool ContinueOnSemicolons = false);
+  bool parseBracedList(bool ContinueOnSemicolons = false, bool StartInside = false);
   void parseParens();
   void parseSquare();
   void parseIfThenElse();
Index: lib/Format/UnwrappedLineParser.cpp
===================================================================
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -286,7 +286,10 @@
       !Line->InPPDirective && Style.Language != FormatStyle::LK_JavaScript;
   ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
                                           MustBeDeclaration);
-  parseLevel(/*HasOpeningBrace=*/false);
+  if (Style.Language == FormatStyle::LK_TextProto)
+    parseBracedList(/*ContinueOnSemicolon=*/false, /*StartInside=*/true);
+  else
+    parseLevel(/*HasOpeningBrace=*/false);
   // Make sure to format the remaining tokens.
   flushComments(true);
   addUnwrappedLine();
@@ -1346,9 +1349,10 @@
   return true;
 }
 
-bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
+bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
+                                          bool StartInside) {
   bool HasError = false;
-  nextToken();
+  if (!StartInside) nextToken();
 
   // FIXME: Once we have an expression parser in the UnwrappedLineParser,
   // replace this by using parseAssigmentExpression() inside.
Index: lib/Format/TokenAnnotator.cpp
===================================================================
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -444,7 +444,8 @@
           FormatToken *Previous = CurrentToken->getPreviousNonComment();
           if (((CurrentToken->is(tok::colon) &&
                 (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
-               Style.Language == FormatStyle::LK_Proto) &&
+               Style.Language == FormatStyle::LK_Proto ||
+               Style.Language == FormatStyle::LK_TextProto) &&
               (Previous->Tok.getIdentifierInfo() ||
                Previous->is(tok::string_literal)))
             Previous->Type = TT_SelectorName;
@@ -527,8 +528,13 @@
         }
       }
       if (Contexts.back().ColonIsDictLiteral ||
-          Style.Language == FormatStyle::LK_Proto) {
+          Style.Language == FormatStyle::LK_Proto ||
+          Style.Language == FormatStyle::LK_TextProto) {
         Tok->Type = TT_DictLiteral;
+        if (Style.Language == FormatStyle::LK_TextProto) {
+          if (FormatToken *Previous = Tok->getPreviousNonComment())
+            Previous->Type = TT_SelectorName;
+        }
       } else if (Contexts.back().ColonIsObjCMethodExpr ||
                  Line.startsWith(TT_ObjCMethodSpecifier)) {
         Tok->Type = TT_ObjCMethodExpr;
@@ -626,6 +632,11 @@
         return false;
       break;
     case tok::l_brace:
+      if (Style.Language == FormatStyle::LK_TextProto) {
+        FormatToken *Previous =Tok->getPreviousNonComment();
+        if (Previous && Previous->Type != TT_DictLiteral)
+          Previous->Type = TT_SelectorName;
+      }
       if (!parseBrace())
         return false;
       break;
@@ -2263,7 +2274,8 @@
   if (Style.isCpp()) {
     if (Left.is(tok::kw_operator))
       return Right.is(tok::coloncolon);
-  } else if (Style.Language == FormatStyle::LK_Proto) {
+  } else if (Style.Language == FormatStyle::LK_Proto ||
+             Style.Language == FormatStyle::LK_TextProto) {
     if (Right.is(tok::period) &&
         Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
                      Keywords.kw_repeated, Keywords.kw_extend))
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -56,6 +56,7 @@
     IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
     IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
+    IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
   }
 };
 
@@ -622,6 +623,12 @@
 }
 
 FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
+  if (Language == FormatStyle::LK_TextProto) {
+    FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
+    GoogleStyle.Language = FormatStyle::LK_TextProto;
+    return GoogleStyle;
+  }
+
   FormatStyle GoogleStyle = getLLVMStyle();
   GoogleStyle.Language = Language;
 
Index: lib/Format/ContinuationIndenter.cpp
===================================================================
--- lib/Format/ContinuationIndenter.cpp
+++ lib/Format/ContinuationIndenter.cpp
@@ -92,6 +92,11 @@
   State.LowestLevelOnLine = 0;
   State.IgnoreStackForComparison = false;
 
+  if (Style.Language == FormatStyle::LK_TextProto) {
+    State.Stack.back().AvoidBinPacking = true;
+    State.Stack.back().BreakBeforeParameter = true;
+  }
+
   // The first token has already been indented and thus consumed.
   moveStateToNextToken(State, DryRun, /*Newline=*/false);
   return State;
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -1081,7 +1081,10 @@
     /// (https://developers.google.com/protocol-buffers/).
     LK_Proto,
     /// Should be used for TableGen code.
-    LK_TableGen
+    LK_TableGen,
+    /// Should be used for Protocol Buffer messages in text format
+    /// (https://developers.google.com/protocol-buffers/).
+    LK_TextProto
   };
   bool isCpp() const { return Language == LK_Cpp || Language == LK_ObjC; }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to