diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -32,6 +32,7 @@ Enum, EnumConstant, Namespace, + TemplateParameter, NumKinds, }; diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -93,6 +93,19 @@ return true; } + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc &TL) { + // TemplateTypeParmTypeLoc does not have a TagDecl in its type ptr. + addToken(TL.getBeginLoc(), TL.getDecl()); + return true; + } + + bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc &TL) { + if (const TemplateDecl *TD = + TL.getTypePtr()->getTemplateName().getAsTemplateDecl()) + addToken(TL.getBeginLoc(), TD); + return true; + } + bool VisitTypeLoc(TypeLoc &TL) { // This check is for not getting two entries when there are anonymous // structs. It also makes us not highlight certain namespace qualifiers @@ -125,6 +138,10 @@ // We highlight class decls, constructor decls and destructor decls as // `Class` type. The destructor decls are handled in `VisitTypeLoc` (we will // visit a TypeLoc where the underlying Type is a CXXRecordDecl). + if(isa(D)) { + addToken(Loc, HighlightingKind::Class); + return; + } if (isa(D)) { addToken(Loc, HighlightingKind::Class); return; @@ -165,6 +182,10 @@ addToken(Loc, HighlightingKind::Namespace); return; } + if(isa(D)) { + addToken(Loc, HighlightingKind::TemplateParameter); + return; + } } void addToken(SourceLocation Loc, HighlightingKind Kind) { @@ -287,6 +308,8 @@ return "variable.other.enummember.cpp"; case HighlightingKind::Namespace: return "entity.name.namespace.cpp"; + case HighlightingKind::TemplateParameter: + return "entity.name.type.template.cpp"; case HighlightingKind::NumKinds: llvm_unreachable("must not pass NumKinds to the function"); } diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test --- a/clang-tools-extra/clangd/test/semantic-highlighting.test +++ b/clang-tools-extra/clangd/test/semantic-highlighting.test @@ -27,6 +27,9 @@ # CHECK-NEXT: ], # CHECK-NEXT: [ # CHECK-NEXT: "entity.name.namespace.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.type.template.cpp" # CHECK-NEXT: ] # CHECK-NEXT: ] # CHECK-NEXT: }, diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -40,7 +40,8 @@ {HighlightingKind::Namespace, "Namespace"}, {HighlightingKind::EnumConstant, "EnumConstant"}, {HighlightingKind::Field, "Field"}, - {HighlightingKind::Method, "Method"}}; + {HighlightingKind::Method, "Method"}, + {HighlightingKind::TemplateParameter, "TemplateParameter"}}; std::vector ExpectedTokens; for (const auto &KindString : KindToString) { std::vector Toks = makeHighlightingTokens( @@ -80,14 +81,14 @@ )cpp", R"cpp( namespace $Namespace[[abc]] { - template + template struct $Class[[A]] { - T $Field[[t]]; + $TemplateParameter[[T]] $Field[[t]]; }; } - template - struct $Class[[C]] : $Namespace[[abc]]::A { - typename T::A* $Field[[D]]; + template + struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> { + typename $TemplateParameter[[T]]::A* $Field[[D]]; }; $Namespace[[abc]]::$Class[[A]] $Variable[[AA]]; typedef $Namespace[[abc]]::$Class[[A]] AAA; @@ -173,6 +174,19 @@ } int $Variable[[B]]; $Class[[AA]] $Variable[[A]]{$Variable[[B]]}; + )cpp", + R"cpp( + template + class $Class[[A]] { + $TemplateParameter[[T]] $Field[[AA]]; + $TemplateParameter[[T]] $Method[[foo]](); + }; + template + class $Class[[B]] { + $Class[[A]]<$TemplateParameter[[TT]]> $Field[[AA]]; + }; + template + void $Function[[foo]]($TemplateParameter[[T]] ...); )cpp"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase);