diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -225,6 +225,10 @@ - Option ``EmptyLineAfterAccessModifier`` has been added to remove, force or keep new lines after access modifiers. +- Checks for newlines in option ``EmptyLineBeforeAccessModifier`` are now based + on the formatted new lines and not on the new lines in the file. (Fixes + https://llvm.org/PR41870.) + libclang -------- diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -1254,15 +1254,14 @@ if (PreviousLine && RootToken.isAccessSpecifier()) { switch (Style.EmptyLineBeforeAccessModifier) { case FormatStyle::ELBAMS_Never: - if (RootToken.NewlinesBefore > 1) + if (Newlines > 1) Newlines = 1; break; case FormatStyle::ELBAMS_Leave: Newlines = std::max(RootToken.NewlinesBefore, 1u); break; case FormatStyle::ELBAMS_LogicalBlock: - if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && - RootToken.NewlinesBefore <= 1) + if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && Newlines <= 1) Newlines = 2; if (PreviousLine->First->isAccessSpecifier()) Newlines = 1; // Previous is an access modifier remove all new lines. @@ -1273,8 +1272,7 @@ previousToken = PreviousLine->Last->getPreviousNonComment(); else previousToken = PreviousLine->Last; - if ((!previousToken || !previousToken->is(tok::l_brace)) && - RootToken.NewlinesBefore <= 1) + if ((!previousToken || !previousToken->is(tok::l_brace)) && Newlines <= 1) Newlines = 2; } break; } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -9177,6 +9177,48 @@ " int j;\n" "};\n", Style); + + FormatStyle NoEmptyLines = getLLVMStyle(); + NoEmptyLines.MaxEmptyLinesToKeep = 0; + verifyFormat("struct foo {\n" + "private:\n" + " void f() {}\n" + "\n" + "private:\n" + " int i;\n" + "\n" + "public:\n" + "protected:\n" + " int j;\n" + "};\n", + NoEmptyLines); + + NoEmptyLines.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_Never; + verifyFormat("struct foo {\n" + "private:\n" + " void f() {}\n" + "private:\n" + " int i;\n" + "public:\n" + "protected:\n" + " int j;\n" + "};\n", + NoEmptyLines); + + NoEmptyLines.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_Always; + verifyFormat("struct foo {\n" + "private:\n" + " void f() {}\n" + "\n" + "private:\n" + " int i;\n" + "\n" + "public:\n" + "\n" + "protected:\n" + " int j;\n" + "};\n", + NoEmptyLines); } TEST_F(FormatTest, FormatsAfterAccessModifiers) { @@ -9266,32 +9308,26 @@ // Leave tests rely on the code layout, test::messUp can not be used. Style.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Leave; Style.MaxEmptyLinesToKeep = 0u; - EXPECT_EQ("struct foo {\n" - "private:\n" - " void f() {}\n" - "private:\n" - " int i;\n" - "protected:\n" - " int j;\n" - "};\n", - format("struct foo {\n" - "private:\n" - " void f() {}\n" - "\n" - "private:\n" - " int i;\n" - "\n" - "protected:\n" - " int j;\n" - "};\n", - Style)); + verifyFormat("struct foo {\n" + "private:\n" + " void f() {}\n" + "\n" + "private:\n" + " int i;\n" + "\n" + "protected:\n" + " int j;\n" + "};\n", + Style); // Check if MaxEmptyLinesToKeep is respected. EXPECT_EQ("struct foo {\n" "private:\n" " void f() {}\n" + "\n" "private:\n" " int i;\n" + "\n" "protected:\n" " int j;\n" "};\n",