Skip to content

Commit

Permalink
[clang-format] Add ClassHeadName to help annotating StartOfName (llvm…
Browse files Browse the repository at this point in the history
  • Loading branch information
owenca authored Jan 31, 2025
1 parent 45f538e commit 1a25bea
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 6 deletions.
2 changes: 2 additions & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ namespace format {
TYPE(CaseLabelColon) \
TYPE(CastRParen) \
TYPE(ClassLBrace) \
/* Name of class/struct/union/interface definition. */ \
TYPE(ClassHeadName) \
TYPE(ClassRBrace) \
TYPE(CompoundRequirementLBrace) \
/* ternary ?: expression */ \
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2581,7 +2581,7 @@ class AnnotatingParser {
if (Style.isVerilog())
return false;

if (Tok.isNot(tok::identifier) || !Tok.Previous)
if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
return false;

if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) &&
Expand Down
15 changes: 10 additions & 5 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4029,7 +4029,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
const FormatToken &InitialToken = *FormatTok;
nextToken();

const FormatToken *ClassName = nullptr;
FormatToken *ClassName = nullptr;
bool IsDerived = false;
auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();
Expand Down Expand Up @@ -4059,7 +4059,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
}
if (FormatTok->is(tok::l_square) && handleCppAttributes())
continue;
const auto *Previous = FormatTok;
auto *Previous = FormatTok;
nextToken();
switch (FormatTok->Tok.getKind()) {
case tok::l_paren:
Expand All @@ -4074,9 +4074,12 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
case tok::hashhash:
break;
default:
if (!JSPastExtendsOrImplements && !ClassName &&
Previous->is(tok::identifier) && Previous->isNot(TT_AttributeMacro) &&
Previous->TokenText != Previous->TokenText.upper()) {
if (JSPastExtendsOrImplements || ClassName ||
Previous->isNot(tok::identifier) || Previous->is(TT_AttributeMacro)) {
break;
}
if (const auto Text = Previous->TokenText;
Text.size() == 1 || Text != Text.upper()) {
ClassName = Previous;
}
}
Expand Down Expand Up @@ -4160,6 +4163,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
if (FormatTok->is(tok::l_brace)) {
if (IsListInitialization())
return;
if (ClassName)
ClassName->setFinalizedType(TT_ClassHeadName);
auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
FormatTok->setFinalizedType(OpenBraceType);
if (ParseAsExpr) {
Expand Down
53 changes: 53 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,11 +479,13 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {
TEST_F(TokenAnnotatorTest, UnderstandsClasses) {
auto Tokens = annotate("class C {};");
ASSERT_EQ(Tokens.size(), 6u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_ClassLBrace);
EXPECT_TOKEN(Tokens[3], tok::r_brace, TT_ClassRBrace);

Tokens = annotate("const class C {} c;");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
EXPECT_TOKEN(Tokens[2], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[3], tok::l_brace, TT_ClassLBrace);
EXPECT_TOKEN(Tokens[4], tok::r_brace, TT_ClassRBrace);

Expand All @@ -494,41 +496,48 @@ TEST_F(TokenAnnotatorTest, UnderstandsClasses) {

Tokens = annotate("class [[deprecated(\"\")]] C { int i; };");
ASSERT_EQ(Tokens.size(), 17u) << Tokens;
EXPECT_TOKEN(Tokens[9], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[10], tok::l_brace, TT_ClassLBrace);
EXPECT_TOKEN(Tokens[14], tok::r_brace, TT_ClassRBrace);
}

TEST_F(TokenAnnotatorTest, UnderstandsStructs) {
auto Tokens = annotate("struct S {};");
ASSERT_EQ(Tokens.size(), 6u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[3], tok::r_brace, TT_StructRBrace);

Tokens = annotate("struct macro(a) S {};");
ASSERT_EQ(Tokens.size(), 10u) << Tokens;
EXPECT_TOKEN(Tokens[5], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[7], tok::r_brace, TT_StructRBrace);

Tokens = annotate("struct EXPORT_MACRO [[nodiscard]] C { int i; };");
ASSERT_EQ(Tokens.size(), 15u) << Tokens;
EXPECT_TOKEN(Tokens[7], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[12], tok::r_brace, TT_StructRBrace);

Tokens = annotate("struct [[deprecated]] [[nodiscard]] C { int i; };");
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
EXPECT_TOKEN(Tokens[11], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[16], tok::r_brace, TT_StructRBrace);

Tokens = annotate("struct macro(a) S {\n"
" void f(T &t);\n"
"};");
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
EXPECT_TOKEN(Tokens[5], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[15], tok::r_brace, TT_StructRBrace);

Tokens = annotate("template <typename T> struct S<const T[N]> {};");
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
EXPECT_TOKEN(Tokens[6], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[7], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare);
EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser);
Expand All @@ -537,6 +546,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) {

Tokens = annotate("template <typename T> struct S<T const[N]> {};");
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
EXPECT_TOKEN(Tokens[6], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[7], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare);
EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser);
Expand All @@ -547,6 +557,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) {
" void f(T const (&a)[n]);\n"
"};");
ASSERT_EQ(Tokens.size(), 35u) << Tokens;
EXPECT_TOKEN(Tokens[9], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[10], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[13], tok::l_square, TT_ArraySubscriptLSquare);
EXPECT_TOKEN(Tokens[16], tok::greater, TT_TemplateCloser);
Expand All @@ -558,12 +569,24 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) {

Tokens = annotate("template <typename T, enum E e> struct S {};");
ASSERT_EQ(Tokens.size(), 15u) << Tokens;
EXPECT_TOKEN(Tokens[10], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[11], tok::l_brace, TT_StructLBrace);

Tokens = annotate(
"template <> struct __declspec(foo) Op<Bar *> : OpImpl<Bar *> {};");
ASSERT_EQ(Tokens.size(), 23u) << Tokens;
EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_AttributeLParen);
EXPECT_TOKEN(Tokens[7], tok::r_paren, TT_AttributeRParen);
EXPECT_TOKEN(Tokens[8], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[13], tok::colon, TT_InheritanceColon);
EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[20], tok::r_brace, TT_StructRBrace);

constexpr StringRef Code{"struct EXPORT StructName {};"};

Tokens = annotate(Code);
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
EXPECT_TOKEN(Tokens[2], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[3], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[4], tok::r_brace, TT_StructRBrace);

Expand All @@ -572,18 +595,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) {
Tokens = annotate(Code, Style);
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_AttributeMacro);
EXPECT_TOKEN(Tokens[2], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[3], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[4], tok::r_brace, TT_StructRBrace);
}

TEST_F(TokenAnnotatorTest, UnderstandsUnions) {
auto Tokens = annotate("union U {};");
ASSERT_EQ(Tokens.size(), 6u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_UnionLBrace);
EXPECT_TOKEN(Tokens[3], tok::r_brace, TT_UnionRBrace);

Tokens = annotate("union U { void f() { return; } };");
ASSERT_EQ(Tokens.size(), 14u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_UnionLBrace);
EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_FunctionLBrace);
EXPECT_TOKEN(Tokens[11], tok::r_brace, TT_UnionRBrace);
Expand Down Expand Up @@ -716,8 +742,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsTemplateTemplateParameters) {
EXPECT_TOKEN(Tokens[11], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[14], tok::greater, TT_TemplateCloser);
EXPECT_FALSE(Tokens[14]->ClosesTemplateDeclaration);
EXPECT_TOKEN(Tokens[16], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[21], tok::greater, TT_TemplateCloser);
EXPECT_TRUE(Tokens[21]->ClosesTemplateDeclaration);
EXPECT_TOKEN(Tokens[23], tok::identifier, TT_ClassHeadName);
}

TEST_F(TokenAnnotatorTest, UnderstandsWhitespaceSensitiveMacros) {
Expand Down Expand Up @@ -800,6 +828,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) {

Tokens = annotate("return (struct foo){};");
ASSERT_EQ(Tokens.size(), 9u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[4], tok::r_paren, TT_CastRParen);

Tokens = annotate("#define FOO(bar) foo((uint64_t)&bar)");
Expand Down Expand Up @@ -1167,6 +1196,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) {
EXPECT_EQ(Tokens[32]->FakeRParens, 1u);
EXPECT_TOKEN(Tokens[33], tok::r_paren, TT_Unknown);
EXPECT_TRUE(Tokens[33]->ClosesRequiresClause);
EXPECT_TOKEN(Tokens[35], tok::identifier, TT_Unknown);

Tokens = annotate("template <typename T>\n"
"void foo(T) noexcept requires Bar<T>;");
Expand Down Expand Up @@ -1248,6 +1278,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) {
"return number_zero_v<T>; }\n"
"};");
ASSERT_EQ(Tokens.size(), 44u) << Tokens;
EXPECT_TOKEN(Tokens[6], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[11], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[13], tok::kw_requires, TT_RequiresClause);
EXPECT_TOKEN(Tokens[14], tok::kw_requires, TT_RequiresExpression);
EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_RequiresExpressionLBrace);
Expand All @@ -1259,6 +1291,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) {
annotate("template <class A, class B> concept C ="
"std::same_as<std::iter_value_t<A>, std::iter_value_t<B>>;");
ASSERT_EQ(Tokens.size(), 31u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[6], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[8], tok::kw_concept, TT_Unknown);
EXPECT_TOKEN(Tokens[14], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[18], tok::less, TT_TemplateOpener);
Expand Down Expand Up @@ -1875,6 +1909,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::arrow, TT_LambdaArrow);
EXPECT_TOKEN(Tokens[4], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("foo([&](u32 bar) __attribute__((attr)) -> void {});");
Expand Down Expand Up @@ -2755,6 +2790,7 @@ TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) {

// Structured statements.
Tokens = Annotate("class Foo {}");
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_StartOfName);
EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_FunctionLBrace);
Tokens = Annotate("def Def: Foo {}");
EXPECT_TOKEN(Tokens[2], tok::colon, TT_InheritanceColon);
Expand Down Expand Up @@ -3220,6 +3256,7 @@ TEST_F(TokenAnnotatorTest, BraceKind) {

Tokens = annotate("class Foo<int> f() {}");
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[5], tok::identifier, TT_FunctionDeclarationName);
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_FunctionDeclarationLParen);
EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_FunctionLBrace);
Expand All @@ -3228,6 +3265,7 @@ TEST_F(TokenAnnotatorTest, BraceKind) {

Tokens = annotate("template <typename T> class Foo<T> f() {}");
ASSERT_EQ(Tokens.size(), 16u) << Tokens;
EXPECT_TOKEN(Tokens[6], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[10], tok::identifier, TT_FunctionDeclarationName);
EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_FunctionDeclarationLParen);
EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_FunctionLBrace);
Expand Down Expand Up @@ -3338,36 +3376,45 @@ TEST_F(TokenAnnotatorTest, BraceKind) {

Tokens = annotate("struct ::Foo {};");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
EXPECT_TOKEN(Tokens[2], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[3], BK_Block);
EXPECT_BRACE_KIND(Tokens[4], BK_Block);

Tokens = annotate("struct NS::Foo {};");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[4], BK_Block);
EXPECT_BRACE_KIND(Tokens[5], BK_Block);

Tokens = annotate("struct Foo<int> {};");
ASSERT_EQ(Tokens.size(), 9u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[5], BK_Block);
EXPECT_BRACE_KIND(Tokens[6], BK_Block);

Tokens = annotate("struct Foo<int>::Bar {};");
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[6], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[7], BK_Block);
EXPECT_BRACE_KIND(Tokens[8], BK_Block);

Tokens = annotate("struct Foo<int> : Base {};");
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[7], BK_Block);
EXPECT_BRACE_KIND(Tokens[8], BK_Block);

Tokens = annotate("struct Foo final {};");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[3], BK_Block);
EXPECT_BRACE_KIND(Tokens[4], BK_Block);

Tokens = annotate("struct [[foo]] [[bar]] Foo final : Base1, Base2 {};");
ASSERT_EQ(Tokens.size(), 21u) << Tokens;
EXPECT_TOKEN(Tokens[11], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[17], BK_Block);
EXPECT_BRACE_KIND(Tokens[18], BK_Block);

Expand Down Expand Up @@ -3403,6 +3450,7 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
"#endif\n"
"};");
ASSERT_EQ(Tokens.size(), 29u) << Tokens;
EXPECT_TOKEN(Tokens[8], tok::identifier, TT_ClassHeadName);
EXPECT_BRACE_KIND(Tokens[11], BK_Block);
EXPECT_BRACE_KIND(Tokens[17], BK_Block);
EXPECT_BRACE_KIND(Tokens[22], BK_Block);
Expand Down Expand Up @@ -3454,6 +3502,7 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
Tokens = annotate("a = class extends goog.a {};",
getGoogleStyle(FormatStyle::LK_JavaScript));
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_ClassLBrace);
EXPECT_BRACE_KIND(Tokens[7], BK_Block);
EXPECT_TOKEN(Tokens[8], tok::r_brace, TT_ClassRBrace);
Expand All @@ -3462,6 +3511,7 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
Tokens = annotate("a = class Foo extends goog.a {};",
getGoogleStyle(FormatStyle::LK_JavaScript));
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[4], tok::identifier, TT_Unknown); // Not TT_StartOfName
EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_ClassLBrace);
EXPECT_BRACE_KIND(Tokens[8], BK_Block);
Expand All @@ -3471,6 +3521,8 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
Tokens = annotate("#define FOO(X) \\\n"
" struct X##_tag_ {};");
ASSERT_EQ(Tokens.size(), 14u) << Tokens;
EXPECT_TOKEN(Tokens[7], tok::identifier, TT_Unknown);
EXPECT_TOKEN(Tokens[9], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[10], tok::l_brace, TT_StructLBrace);
EXPECT_BRACE_KIND(Tokens[10], BK_Block);
EXPECT_TOKEN(Tokens[11], tok::r_brace, TT_StructRBrace);
Expand All @@ -3481,6 +3533,7 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
" void f() { return; } \\\n"
" };");
ASSERT_EQ(Tokens.size(), 20u) << Tokens;
EXPECT_TOKEN(Tokens[4], tok::identifier, TT_ClassHeadName);
EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_StructLBrace);
EXPECT_BRACE_KIND(Tokens[8], BK_Block);
EXPECT_TOKEN(Tokens[10], tok::identifier, TT_FunctionDeclarationName);
Expand Down

0 comments on commit 1a25bea

Please sign in to comment.