[clang-format] Link the braces of a block in UnwrappedLineParser

This includes TT_MacroBlockBegin and TT_MacroBlockEnd as well.

We can no longer use MatchingParen of FormatToken as an indicator
to mark optional braces. Instead, we directly set Optional of an
l_brace first and reset it later if it turns out that the braces
are not optional.

Also added a test case for deeply nested loops.

Differential Revision: https://reviews.llvm.org/D139257
This commit is contained in:
Owen Pan 2022-12-03 07:16:32 -08:00
parent 4f33339fb4
commit e33243c950
2 changed files with 39 additions and 20 deletions

View File

@ -934,6 +934,9 @@ FormatToken *UnwrappedLineParser::parseBlock(
return IfLBrace; return IfLBrace;
} }
Tok->MatchingParen = FormatTok;
FormatTok->MatchingParen = Tok;
const bool IsFunctionRBrace = const bool IsFunctionRBrace =
FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace); FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
@ -967,10 +970,7 @@ FormatToken *UnwrappedLineParser::parseBlock(
} }
return mightFitOnOneLine((*CurrentLines)[Index], Tok); return mightFitOnOneLine((*CurrentLines)[Index], Tok);
}; };
if (RemoveBraces()) { Tok->Optional = RemoveBraces();
Tok->MatchingParen = FormatTok;
FormatTok->MatchingParen = Tok;
}
size_t PPEndHash = computePPHash(); size_t PPEndHash = computePPHash();
@ -2707,10 +2707,20 @@ static void markOptionalBraces(FormatToken *LeftBrace) {
assert(RightBrace->is(tok::r_brace)); assert(RightBrace->is(tok::r_brace));
assert(RightBrace->MatchingParen == LeftBrace); assert(RightBrace->MatchingParen == LeftBrace);
assert(LeftBrace->Optional == RightBrace->Optional);
LeftBrace->Optional = true; RightBrace->Optional = LeftBrace->Optional;
RightBrace->Optional = true; }
static void resetOptional(FormatToken *LeftBrace) {
if (!LeftBrace)
return;
const auto *RightBrace = LeftBrace->MatchingParen;
const bool IsOptionalRightBrace = RightBrace && RightBrace->Optional;
assert(LeftBrace->Optional || !IsOptionalRightBrace);
if (!IsOptionalRightBrace)
LeftBrace->Optional = false;
} }
void UnwrappedLineParser::handleAttributes() { void UnwrappedLineParser::handleAttributes() {
@ -2770,8 +2780,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
if (Style.RemoveBracesLLVM) { if (Style.RemoveBracesLLVM) {
assert(!NestedTooDeep.empty()); assert(!NestedTooDeep.empty());
KeepIfBraces = KeepIfBraces || KeepIfBraces = KeepIfBraces || (IfLeftBrace && !IfLeftBrace->Optional) ||
(IfLeftBrace && !IfLeftBrace->MatchingParen) ||
NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly || NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
IfBlockKind == IfStmtKind::IfElseIf; IfBlockKind == IfStmtKind::IfElseIf;
} }
@ -2802,8 +2811,9 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
ElseBlockKind == IfStmtKind::IfElseIf; ElseBlockKind == IfStmtKind::IfElseIf;
} else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) { } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
KeepElseBraces = true; KeepElseBraces = true;
assert(ElseLeftBrace->Optional);
assert(ElseLeftBrace->MatchingParen); assert(ElseLeftBrace->MatchingParen);
markOptionalBraces(ElseLeftBrace); ElseLeftBrace->MatchingParen->Optional = true;
} }
addUnwrappedLine(); addUnwrappedLine();
} else if (FormatTok->is(tok::kw_if)) { } else if (FormatTok->is(tok::kw_if)) {
@ -2838,7 +2848,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
assert(!NestedTooDeep.empty()); assert(!NestedTooDeep.empty());
KeepElseBraces = KeepElseBraces || KeepElseBraces = KeepElseBraces ||
(ElseLeftBrace && !ElseLeftBrace->MatchingParen) || (ElseLeftBrace && !ElseLeftBrace->Optional) ||
NestedTooDeep.back(); NestedTooDeep.back();
NestedTooDeep.pop_back(); NestedTooDeep.pop_back();
@ -2846,17 +2856,11 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
if (!KeepIfBraces && !KeepElseBraces) { if (!KeepIfBraces && !KeepElseBraces) {
markOptionalBraces(IfLeftBrace); markOptionalBraces(IfLeftBrace);
markOptionalBraces(ElseLeftBrace); markOptionalBraces(ElseLeftBrace);
} else if (IfLeftBrace) {
FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
if (IfRightBrace) {
assert(IfRightBrace->MatchingParen == IfLeftBrace);
assert(!IfLeftBrace->Optional);
assert(!IfRightBrace->Optional);
IfLeftBrace->MatchingParen = nullptr;
IfRightBrace->MatchingParen = nullptr;
}
} }
resetOptional(IfLeftBrace);
resetOptional(ElseLeftBrace);
if (IfKind) if (IfKind)
*IfKind = Kind; *IfKind = Kind;
@ -3071,6 +3075,7 @@ void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {
if (!NestedTooDeep.back()) if (!NestedTooDeep.back())
markOptionalBraces(LeftBrace); markOptionalBraces(LeftBrace);
} }
resetOptional(LeftBrace);
if (WrapRightBrace) if (WrapRightBrace)
addUnwrappedLine(); addUnwrappedLine();
} else { } else {

View File

@ -204,6 +204,20 @@ TEST_F(BracesRemoverTest, RemoveBraces) {
"while (j < 0) { ++j; }", "while (j < 0) { ++j; }",
Style); Style);
verifyFormat("for (;;) {\n"
" for (;;)\n"
" for (;;)\n"
" a;\n"
"}",
"for (;;) {\n"
" for (;;) {\n"
" for (;;) {\n"
" a;\n"
" }\n"
" }\n"
"}",
Style);
verifyFormat("if (a)\n" verifyFormat("if (a)\n"
" b; // comment\n" " b; // comment\n"
"else if (c)\n" "else if (c)\n"