[clangd] Added highlightings for template parameters and specializations.
authorJohan Vikstrom <jvikstrom@google.com>
Thu, 18 Jul 2019 09:56:38 +0000 (09:56 +0000)
committerJohan Vikstrom <jvikstrom@google.com>
Thu, 18 Jul 2019 09:56:38 +0000 (09:56 +0000)
Summary: Template parameters and specializations were not being highlighted before. This adds highlightings to those types of tokens by adding two Visit* methods.

Reviewers: hokein, sammccall, ilya-biryukov

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64855

llvm-svn: 366420

clang-tools-extra/clangd/SemanticHighlighting.cpp
clang-tools-extra/clangd/SemanticHighlighting.h
clang-tools-extra/clangd/test/semantic-highlighting.test
clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

index b6b1c8d..59fa531 100644 (file)
@@ -99,6 +99,19 @@ public:
     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
@@ -135,6 +148,10 @@ private:
     // 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<ClassTemplateDecl>(D)) {
+      addToken(Loc, HighlightingKind::Class);
+      return;
+    }
     if (isa<RecordDecl>(D)) {
       addToken(Loc, HighlightingKind::Class);
       return;
@@ -175,6 +192,14 @@ private:
       addToken(Loc, HighlightingKind::Namespace);
       return;
     }
+    if (isa<TemplateTemplateParmDecl>(D)) {
+      addToken(Loc, HighlightingKind::TemplateParameter);
+      return;
+    }
+    if (isa<TemplateTypeParmDecl>(D)) {
+      addToken(Loc, HighlightingKind::TemplateParameter);
+      return;
+    }
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
@@ -297,6 +322,8 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
     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");
   }
index eaeeb86..f38fa46 100644 (file)
@@ -32,6 +32,7 @@ enum class HighlightingKind {
   Enum,
   EnumConstant,
   Namespace,
+  TemplateParameter,
 
   NumKinds,
 };
index 7de25d1..732fb7b 100644 (file)
@@ -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:      },
index f69e336..2943780 100644 (file)
@@ -40,7 +40,8 @@ void checkHighlightings(llvm::StringRef Code) {
       {HighlightingKind::Namespace, "Namespace"},
       {HighlightingKind::EnumConstant, "EnumConstant"},
       {HighlightingKind::Field, "Field"},
-      {HighlightingKind::Method, "Method"}};
+      {HighlightingKind::Method, "Method"},
+      {HighlightingKind::TemplateParameter, "TemplateParameter"}};
   std::vector<HighlightingToken> ExpectedTokens;
   for (const auto &KindString : KindToString) {
     std::vector<HighlightingToken> Toks = makeHighlightingTokens(
@@ -80,14 +81,14 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
     )cpp",
     R"cpp(
       namespace $Namespace[[abc]] {
-        template<typename T>
+        template<typename $TemplateParameter[[T]]>
         struct $Class[[A]] {
-          T $Field[[t]];
+          $TemplateParameter[[T]] $Field[[t]];
         };
       }
-      template<typename T>
-      struct $Class[[C]] : $Namespace[[abc]]::A<T> {
-        typename T::A* $Field[[D]];
+      template<typename $TemplateParameter[[T]]>
+      struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
+        typename $TemplateParameter[[T]]::A* $Field[[D]];
       };
       $Namespace[[abc]]::$Class[[A]]<int> $Variable[[AA]];
       typedef $Namespace[[abc]]::$Class[[A]]<int> $Class[[AAA]];
@@ -186,6 +187,32 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
       using $Enum[[CD]] = $Enum[[CC]];
       $Enum[[CC]] $Function[[f]]($Class[[B]]);
       $Enum[[CD]] $Function[[f]]($Class[[BB]]);
+    )cpp",
+    R"cpp(
+      template<typename $TemplateParameter[[T]], typename = void>
+      class $Class[[A]] {
+        $TemplateParameter[[T]] $Field[[AA]];
+        $TemplateParameter[[T]] $Method[[foo]]();
+      };
+      template<class $TemplateParameter[[TT]]>
+      class $Class[[B]] {
+        $Class[[A]]<$TemplateParameter[[TT]]> $Field[[AA]];
+      };
+      template<class $TemplateParameter[[TT]], class $TemplateParameter[[GG]]>
+      class $Class[[BB]] {};
+      template<class $TemplateParameter[[T]]>
+      class $Class[[BB]]<$TemplateParameter[[T]], int> {};
+      template<class $TemplateParameter[[T]]>
+      class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {};
+
+      template<template<class> class $TemplateParameter[[T]], class $TemplateParameter[[C]]>
+      $TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function[[f]]();
+
+      template<typename>
+      class $Class[[Foo]] {};
+
+      template<typename $TemplateParameter[[T]]>
+      void $Function[[foo]]($TemplateParameter[[T]] ...);
     )cpp"};
   for (const auto &TestCase : TestCases) {
     checkHighlightings(TestCase);