[clang] a70549a - [clang-format] Fix DefSeparator empty line issues
via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 7 06:23:26 PST 2022
Author: ksyx
Date: 2022-02-07T14:23:21Z
New Revision: a70549ae43dfa551f3eacdfa7a7f2c0df073be8e
URL: https://github.com/llvm/llvm-project/commit/a70549ae43dfa551f3eacdfa7a7f2c0df073be8e
DIFF: https://github.com/llvm/llvm-project/commit/a70549ae43dfa551f3eacdfa7a7f2c0df073be8e.diff
LOG: [clang-format] Fix DefSeparator empty line issues
- Add or remove empty lines surrounding union blocks.
- Fixes https://github.com/llvm/llvm-project/issues/53229, in which
keywords like class and struct in a line ending with left brace or
whose next line is left brace only, will be falsely recognized as
definition line, causing extra empty lines inserted surrounding blocks
with no need to be formatted.
Reviewed By: MyDeveloperDay, curdeius, HazardyKnusperkeks, owenpan
Differential Revision: https://reviews.llvm.org/D119067
Added:
Modified:
clang/lib/Format/DefinitionBlockSeparator.cpp
clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/DefinitionBlockSeparator.cpp b/clang/lib/Format/DefinitionBlockSeparator.cpp
index b7fca864efc6..b7b1123773ce 100644
--- a/clang/lib/Format/DefinitionBlockSeparator.cpp
+++ b/clang/lib/Format/DefinitionBlockSeparator.cpp
@@ -35,19 +35,31 @@ void DefinitionBlockSeparator::separateBlocks(
const bool IsNeverStyle =
Style.SeparateDefinitionBlocks == FormatStyle::SDS_Never;
const AdditionalKeywords &ExtraKeywords = Tokens.getKeywords();
- auto LikelyDefinition = [this, ExtraKeywords](const AnnotatedLine *Line,
- bool ExcludeEnum = false) {
+ auto GetBracketLevelChange = [](const FormatToken *Tok) {
+ if (Tok->isOneOf(tok::l_brace, tok::l_paren, tok::l_square))
+ return 1;
+ if (Tok->isOneOf(tok::r_brace, tok::r_paren, tok::r_square))
+ return -1;
+ return 0;
+ };
+ auto LikelyDefinition = [&](const AnnotatedLine *Line,
+ bool ExcludeEnum = false) {
if ((Line->MightBeFunctionDecl && Line->mightBeFunctionDefinition()) ||
Line->startsWithNamespace())
return true;
- FormatToken *CurrentToken = Line->First;
- while (CurrentToken) {
- if (CurrentToken->isOneOf(tok::kw_class, tok::kw_struct) ||
- (Style.isJavaScript() && CurrentToken->is(ExtraKeywords.kw_function)))
- return true;
- if (!ExcludeEnum && CurrentToken->is(tok::kw_enum))
- return true;
- CurrentToken = CurrentToken->Next;
+ int BracketLevel = 0;
+ for (const FormatToken *CurrentToken = Line->First; CurrentToken;
+ CurrentToken = CurrentToken->Next) {
+ if (BracketLevel == 0) {
+ if ((CurrentToken->isOneOf(tok::kw_class, tok::kw_struct,
+ tok::kw_union) ||
+ (Style.isJavaScript() &&
+ CurrentToken->is(ExtraKeywords.kw_function))))
+ return true;
+ if (!ExcludeEnum && CurrentToken->is(tok::kw_enum))
+ return true;
+ }
+ BracketLevel += GetBracketLevelChange(CurrentToken);
}
return false;
};
@@ -102,14 +114,17 @@ void DefinitionBlockSeparator::separateBlocks(
IsPPConditional(OpeningLineIndex - 1);
};
const auto HasEnumOnLine = [&]() {
- FormatToken *CurrentToken = CurrentLine->First;
bool FoundEnumKeyword = false;
- while (CurrentToken) {
- if (CurrentToken->is(tok::kw_enum))
- FoundEnumKeyword = true;
- else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace))
- return true;
- CurrentToken = CurrentToken->Next;
+ int BracketLevel = 0;
+ for (const FormatToken *CurrentToken = CurrentLine->First; CurrentToken;
+ CurrentToken = CurrentToken->Next) {
+ if (BracketLevel == 0) {
+ if (CurrentToken->is(tok::kw_enum))
+ FoundEnumKeyword = true;
+ else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace))
+ return true;
+ }
+ BracketLevel += GetBracketLevelChange(CurrentToken);
}
return FoundEnumKeyword && I + 1 < Lines.size() &&
Lines[I + 1]->First->is(tok::l_brace);
diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
index 4cbae0f55b03..582b62e445df 100644
--- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
+++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
@@ -109,6 +109,15 @@ TEST_F(DefinitionBlockSeparatorTest, Basic) {
"};",
Style);
+ verifyFormat("union foo {\n"
+ " int i, j;\n"
+ "};\n"
+ "\n"
+ "union bar {\n"
+ " int j, k;\n"
+ "};",
+ Style);
+
verifyFormat("class foo {\n"
" int i, j;\n"
"};\n"
@@ -311,6 +320,9 @@ TEST_F(DefinitionBlockSeparatorTest, Always) {
"int bar3(int j, int k, const enum Bar b) {\n"
" // A comment\n"
" int r = j % k;\n"
+ " if (struct S = getS()) {\n"
+ " // if condition\n"
+ " }\n"
" return r;\n"
"}\n";
std::string Postfix = "\n"
@@ -364,6 +376,9 @@ TEST_F(DefinitionBlockSeparatorTest, Never) {
"int bar3(int j, int k, const enum Bar b) {\n"
" // A comment\n"
" int r = j % k;\n"
+ " if (struct S = getS()) {\n"
+ " // if condition\n"
+ " }\n"
" return r;\n"
"}\n"
"} // namespace";
@@ -425,6 +440,10 @@ TEST_F(DefinitionBlockSeparatorTest, OpeningBracketOwnsLine) {
"{\n"
" // A comment\n"
" int r = j % k;\n"
+ " if (struct S = getS())\n"
+ " {\n"
+ " // if condition\n"
+ " }\n"
" return r;\n"
"}\n"
"} // namespace NS",
@@ -473,6 +492,9 @@ TEST_F(DefinitionBlockSeparatorTest, Leave) {
"int bar3(int j, int k, const enum Bar b) {\n"
" // A comment\n"
" int r = j % k;\n"
+ " if (struct S = getS()) {\n"
+ " // if condition\n"
+ " }\n"
" return r;\n"
"}\n"
"} // namespace";
More information about the cfe-commits
mailing list