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.

llvm-svn: 221897
This commit is contained in:
Nico Weber 2014-11-13 16:25:37 +00:00
parent 17072ef348
commit 34272657de
2 changed files with 35 additions and 3 deletions

View 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.

View 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"