]> granicus.if.org Git - clang/commitdiff
clang-format: Format extern "C" blocks like namespace blocks.
authorNico Weber <nicolasweber@gmx.de>
Thu, 13 Nov 2014 16:25:37 +0000 (16:25 +0000)
committerNico Weber <nicolasweber@gmx.de>
Thu, 13 Nov 2014 16:25:37 +0000 (16:25 +0000)
namespace blocks act as if KeepEmptyLinesAtTheStartOfBlocks is always true,
and aren't collapsed to a single line even if they would fit. Do the same
for extern "C" blocks.

Before,

  extern "C" {

  void ExternCFunction();

  }

was collapsed into `extern "C" { void ExternCFunction(); }`. Now it stays like
it was.

Fixes http://crbug.com/432640 and part of PR21419.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@221897 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/Format.cpp
unittests/Format/FormatTest.cpp

index 8e4be3e053d5bfac051bb14702b944a45dd19533..74adaf76056e1ad907724ea3415d0a14ce15d464 100644 (file)
@@ -574,6 +574,13 @@ std::string configurationAsText(const FormatStyle &Style) {
 
 namespace {
 
+bool startsExternCBlock(const AnnotatedLine &Line) {
+  const FormatToken *Next = Line.First->getNextNonComment();
+  const FormatToken *NextNext = Next ? Next->getNextNonComment() : nullptr;
+  return Line.First->is(tok::kw_extern) && Next && Next->isStringLiteral() &&
+         NextNext && NextNext->is(tok::l_brace);
+}
+
 class NoColumnLimitFormatter {
 public:
   NoColumnLimitFormatter(ContinuationIndenter *Indenter) : Indenter(Indenter) {}
@@ -785,7 +792,8 @@ private:
       Tok->SpacesRequiredBefore = 0;
       Tok->CanBreakBefore = true;
       return 1;
-    } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
+    } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace) &&
+               !startsExternCBlock(Line)) {
       // We don't merge short records.
       if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct))
         return 0;
@@ -1069,7 +1077,8 @@ private:
     // Remove empty lines after "{".
     if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
         PreviousLine->Last->is(tok::l_brace) &&
-        PreviousLine->First->isNot(tok::kw_namespace))
+        PreviousLine->First->isNot(tok::kw_namespace) &&
+        !startsExternCBlock(*PreviousLine))
       Newlines = 1;
 
     // Insert extra new line before access specifiers.
index 37c3c0e7528a90bd774b7d9c4b00d6cda9005462..b8ab1df139b5e5dd562de208418046e170fb1aae 100644 (file)
@@ -187,7 +187,7 @@ TEST_F(FormatTest, RemovesEmptyLines) {
                    "\n"
                    "};"));
 
-  // Don't remove empty lines at the start of namespaces.
+  // Don't remove empty lines at the start of namespaces or extern "C" blocks.
   EXPECT_EQ("namespace N {\n"
             "\n"
             "int i;\n"
@@ -197,6 +197,29 @@ TEST_F(FormatTest, RemovesEmptyLines) {
                    "int    i;\n"
                    "}",
                    getGoogleStyle()));
+  EXPECT_EQ("extern /**/ \"C\" /**/ {\n"
+            "\n"
+            "int i;\n"
+            "}",
+            format("extern /**/ \"C\" /**/ {\n"
+                   "\n"
+                   "int    i;\n"
+                   "}",
+                   getGoogleStyle()));
+
+  // ...but do keep inlining and removing empty lines for non-block extern "C"
+  // functions.
+  verifyFormat("extern \"C\" int f() { return 42; }", getGoogleStyle());
+  EXPECT_EQ("extern \"C\" int f() {\n"
+            "  int i = 42;\n"
+            "  return i;\n"
+            "}",
+            format("extern \"C\" int f() {\n"
+                   "\n"
+                   "  int i = 42;\n"
+                   "  return i;\n"
+                   "}",
+                   getGoogleStyle()));
 
   // Remove empty lines at the beginning and end of blocks.
   EXPECT_EQ("void f() {\n"