From 00934505d44e28f3c1d5739d6369648e87f10cf5 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sat, 4 Jan 2025 20:51:00 -0800 Subject: [PATCH] [clang-format] Add `TT_CompoundRequirementLBrace` for better annotation (#121539) Also, add `ST_CompoundRequirement` to help annotating */&/&& in compound requirement expressions as `TT_BinaryOperator`. Fixes #121471. --- clang/lib/Format/FormatToken.h | 1 + clang/lib/Format/TokenAnnotator.cpp | 7 ++++++- clang/lib/Format/TokenAnnotator.h | 2 ++ clang/lib/Format/UnwrappedLineFormatter.cpp | 2 +- clang/lib/Format/UnwrappedLineParser.cpp | 5 +++-- clang/unittests/Format/TokenAnnotatorTest.cpp | 12 ++++++++++++ 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 0fd3a49c71f9..d97b6522f1fe 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -45,6 +45,7 @@ namespace format { TYPE(CastRParen) \ TYPE(ClassLBrace) \ TYPE(ClassRBrace) \ + TYPE(CompoundRequirementLBrace) \ /* ternary ?: expression */ \ TYPE(ConditionalExpr) \ /* the condition in an if statement */ \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index fad375733ef8..945174ca9c58 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -143,6 +143,8 @@ private: case TT_StructLBrace: case TT_UnionLBrace: return ST_Class; + case TT_CompoundRequirementLBrace: + return ST_CompoundRequirement; default: return ST_Other; } @@ -2076,7 +2078,7 @@ private: TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause, TT_RequiresClauseInARequiresExpression, TT_RequiresExpression, TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace, - TT_BracedListLBrace)) { + TT_CompoundRequirementLBrace, TT_BracedListLBrace)) { CurrentToken->setType(TT_Unknown); } CurrentToken->Role.reset(); @@ -3100,6 +3102,9 @@ private: } } + if (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement) + return TT_BinaryOperator; + return TT_PointerOrReference; } diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 9117ca3f9fb7..1a250e94d97c 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -40,6 +40,8 @@ enum ScopeType { ST_ChildBlock, // Contained in class declaration/definition. ST_Class, + // Contained in compound requirement. + ST_CompoundRequirement, // Contained within other scope block (function, loop, if/else, etc). ST_Other, }; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 2fe4ebd4ff8e..ec65fea6ec3d 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -535,7 +535,7 @@ private: // Try to merge records. if (TheLine->Last->is(TT_EnumLBrace)) { ShouldMerge = Style.AllowShortEnumsOnASingleLine; - } else if (TheLine->Last->is(TT_RequiresExpressionLBrace)) { + } else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) { ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine; } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) { // NOTE: We use AfterClass (whereas AfterStruct exists) for both classes diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 39aa37af480c..317717241c17 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -392,7 +392,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, break; case tok::l_brace: if (InRequiresExpression) { - FormatTok->setFinalizedType(TT_RequiresExpressionLBrace); + FormatTok->setFinalizedType(TT_CompoundRequirementLBrace); } else if (FormatTok->Previous && FormatTok->Previous->ClosesRequiresClause) { // We need the 'default' case here to correctly parse a function @@ -1705,7 +1705,8 @@ void UnwrappedLineParser::parseStructuralElement( } for (const bool InRequiresExpression = - OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); + OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace, + TT_CompoundRequirementLBrace); !eof();) { if (IsCpp && FormatTok->isCppAlternativeOperatorKeyword()) { if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 875feff3d542..a5b2d09a9f70 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1456,6 +1456,18 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) { EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_RequiresExpressionLBrace); } +TEST_F(TokenAnnotatorTest, CompoundRequirement) { + auto Tokens = annotate("template \n" + "concept CheckMultiplicableBy = requires(T a, V b) {\n" + " { a * b } -> std::same_as;\n" + "};"); + ASSERT_EQ(Tokens.size(), 36u) << Tokens; + + EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_RequiresExpressionLBrace); + EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace); + EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator); +} + TEST_F(TokenAnnotatorTest, UnderstandsPragmaRegion) { // Everything after #pragma region should be ImplicitStringLiteral auto Tokens = annotate("#pragma region Foo(Bar: Hello)"); -- 2.11.4.GIT