From: Nico Weber Date: Thu, 13 Nov 2014 16:25:37 +0000 (+0000) Subject: clang-format: Format extern "C" blocks like namespace blocks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8be48bc867e110050254253eb86fc53494620321;p=clang clang-format: Format extern "C" blocks like namespace blocks. 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 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 8e4be3e053..74adaf7605 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -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. diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 37c3c0e752..b8ab1df139 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -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"