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"; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits