[clangd] Added semantic highlighting support for primitives.

Summary:
Adds a new HighlightingKind "Primitive". Adds a special case for TypeLocs that have an underlying TypePtr that is are builtin types, adding them as primitives.
The primary reason for this change is because otherwise typedefs that typedef primitives `typedef int A` would not get highlighted (so in the example `A` would not get any highlightings.)

Reviewers: hokein, ilya-biryukov

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

Tags: #clang

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

git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@368291 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clangd/SemanticHighlighting.cpp b/clangd/SemanticHighlighting.cpp
index 3bffe7f..be87dcc 100644
--- a/clangd/SemanticHighlighting.cpp
+++ b/clangd/SemanticHighlighting.cpp
@@ -138,9 +138,13 @@
 
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc &TL) {
-    if (const Type *TP = TL.getTypePtr())
+    if (const Type *TP = TL.getTypePtr()) {
       if (const TagDecl *TD = TP->getAsTagDecl())
         addToken(Loc, TD);
+      if (TP->isBuiltinType())
+        // Builtins must be special cased as they do not have a TagDecl.
+        addToken(Loc, HighlightingKind::Primitive);
+    }
   }
 
   void addToken(SourceLocation Loc, const NamedDecl *D) {
@@ -386,6 +390,8 @@
     return "entity.name.namespace.cpp";
   case HighlightingKind::TemplateParameter:
     return "entity.name.type.template.cpp";
+  case HighlightingKind::Primitive:
+    return "storage.type.primitive.cpp";
   case HighlightingKind::NumKinds:
     llvm_unreachable("must not pass NumKinds to the function");
   }
diff --git a/clangd/SemanticHighlighting.h b/clangd/SemanticHighlighting.h
index 2d9d231..24a83b9 100644
--- a/clangd/SemanticHighlighting.h
+++ b/clangd/SemanticHighlighting.h
@@ -33,6 +33,7 @@
   EnumConstant,
   Namespace,
   TemplateParameter,
+  Primitive,
 
   NumKinds,
 };
diff --git a/clangd/test/semantic-highlighting.test b/clangd/test/semantic-highlighting.test
index 15342af..e22b34a 100644
--- a/clangd/test/semantic-highlighting.test
+++ b/clangd/test/semantic-highlighting.test
@@ -30,6 +30,9 @@
 # CHECK-NEXT:          ],
 # CHECK-NEXT:          [
 # CHECK-NEXT:            "entity.name.type.template.cpp"
+# CHECK-NEXT:          ],
+# CHECK-NEXT:          [
+# CHECK-NEXT:            "storage.type.primitive.cpp"
 # CHECK-NEXT:          ]
 # CHECK-NEXT:        ]
 # CHECK-NEXT:      },
@@ -40,7 +43,7 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 0,
-# CHECK-NEXT:        "tokens": "AAAABAABAAA="
+# CHECK-NEXT:        "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "textDocument": {
@@ -55,11 +58,11 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 0,
-# CHECK-NEXT:        "tokens": "AAAABAABAAA="
+# CHECK-NEXT:        "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 1,
-# CHECK-NEXT:        "tokens": "AAAABAABAAA="
+# CHECK-NEXT:        "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "textDocument": {
@@ -74,7 +77,7 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 1,
-# CHECK-NEXT:        "tokens": "AAAABAABAAA="
+# CHECK-NEXT:        "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:   ],
 # CHECK-NEXT:    "textDocument": {
diff --git a/clangd/unittests/SemanticHighlightingTests.cpp b/clangd/unittests/SemanticHighlightingTests.cpp
index 0067665..3ff7bbc 100644
--- a/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clangd/unittests/SemanticHighlightingTests.cpp
@@ -39,7 +39,8 @@
       {HighlightingKind::EnumConstant, "EnumConstant"},
       {HighlightingKind::Field, "Field"},
       {HighlightingKind::Method, "Method"},
-      {HighlightingKind::TemplateParameter, "TemplateParameter"}};
+      {HighlightingKind::TemplateParameter, "TemplateParameter"},
+      {HighlightingKind::Primitive, "Primitive"}};
   std::vector<HighlightingToken> ExpectedTokens;
   for (const auto &KindString : KindToString) {
     std::vector<HighlightingToken> Toks = makeHighlightingTokens(
@@ -93,26 +94,26 @@
   const char *TestCases[] = {
     R"cpp(
       struct $Class[[AS]] {
-        double $Field[[SomeMember]];
+        $Primitive[[double]] $Field[[SomeMember]];
       };
       struct {
       } $Variable[[S]];
-      void $Function[[foo]](int $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
+      $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
         auto $Variable[[VeryLongVariableName]] = 12312;
         $Class[[AS]]     $Variable[[AA]];
         auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
-        auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {};
+        auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
         $Variable[[FN]](12312);
       }
     )cpp",
     R"cpp(
-      void $Function[[foo]](int);
-      void $Function[[Gah]]();
-      void $Function[[foo]]() {
+      $Primitive[[void]] $Function[[foo]]($Primitive[[int]]);
+      $Primitive[[void]] $Function[[Gah]]();
+      $Primitive[[void]] $Function[[foo]]() {
         auto $Variable[[Bou]] = $Function[[Gah]];
       }
       struct $Class[[A]] {
-        void $Method[[abc]]();
+        $Primitive[[void]] $Method[[abc]]();
       };
     )cpp",
     R"cpp(
@@ -126,17 +127,17 @@
       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]];
+      $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Variable[[AA]];
+      typedef $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Class[[AAA]];
       struct $Class[[B]] {
         $Class[[B]]();
         ~$Class[[B]]();
-        void operator<<($Class[[B]]);
+        $Primitive[[void]] operator<<($Class[[B]]);
         $Class[[AAA]] $Field[[AA]];
       };
       $Class[[B]]::$Class[[B]]() {}
       $Class[[B]]::~$Class[[B]]() {}
-      void $Function[[f]] () {
+      $Primitive[[void]] $Function[[f]] () {
         $Class[[B]] $Variable[[BB]] = $Class[[B]]();
         $Variable[[BB]].~$Class[[B]]();
         $Class[[B]]();
@@ -154,7 +155,7 @@
         $Enum[[E]] $Field[[EEE]];
         $Enum[[EE]] $Field[[EEEE]];
       };
-      int $Variable[[I]] = $EnumConstant[[Hi]];
+      $Primitive[[int]] $Variable[[I]] = $EnumConstant[[Hi]];
       $Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]];
     )cpp",
     R"cpp(
@@ -182,13 +183,13 @@
     )cpp",
     R"cpp(
       struct $Class[[D]] {
-        double $Field[[C]];
+        $Primitive[[double]] $Field[[C]];
       };
       struct $Class[[A]] {
-        double $Field[[B]];
+        $Primitive[[double]] $Field[[B]];
         $Class[[D]] $Field[[E]];
-        static double $Variable[[S]];
-        void $Method[[foo]]() {
+        static $Primitive[[double]] $Variable[[S]];
+        $Primitive[[void]] $Method[[foo]]() {
           $Field[[B]] = 123;
           this->$Field[[B]] = 156;
           this->$Method[[foo]]();
@@ -196,7 +197,7 @@
           $Variable[[S]] = 90.1;
         }
       };
-      void $Function[[foo]]() {
+      $Primitive[[void]] $Function[[foo]]() {
         $Class[[A]] $Variable[[AA]];
         $Variable[[AA]].$Field[[B]] += 2;
         $Variable[[AA]].$Method[[foo]]();
@@ -206,14 +207,15 @@
     )cpp",
     R"cpp(
       struct $Class[[AA]] {
-        int $Field[[A]];
+        $Primitive[[int]] $Field[[A]];
       }
-      int $Variable[[B]];
+      $Primitive[[int]] $Variable[[B]];
       $Class[[AA]] $Variable[[A]]{$Variable[[B]]};
     )cpp",
     R"cpp(
       namespace $Namespace[[a]] {
         struct $Class[[A]] {};
+        typedef $Primitive[[char]] $Primitive[[C]];
       }
       typedef $Namespace[[a]]::$Class[[A]] $Class[[B]];
       using $Class[[BB]] = $Namespace[[a]]::$Class[[A]];
@@ -223,9 +225,11 @@
       using $Enum[[CD]] = $Enum[[CC]];
       $Enum[[CC]] $Function[[f]]($Class[[B]]);
       $Enum[[CD]] $Function[[f]]($Class[[BB]]);
+      typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]];
+      typedef $Primitive[[float]] $Primitive[[F]];
     )cpp",
     R"cpp(
-      template<typename $TemplateParameter[[T]], typename = void>
+      template<typename $TemplateParameter[[T]], typename = $Primitive[[void]]>
       class $Class[[A]] {
         $TemplateParameter[[T]] $Field[[AA]];
         $TemplateParameter[[T]] $Method[[foo]]();
@@ -237,7 +241,7 @@
       template<class $TemplateParameter[[TT]], class $TemplateParameter[[GG]]>
       class $Class[[BB]] {};
       template<class $TemplateParameter[[T]]>
-      class $Class[[BB]]<$TemplateParameter[[T]], int> {};
+      class $Class[[BB]]<$TemplateParameter[[T]], $Primitive[[int]]> {};
       template<class $TemplateParameter[[T]]>
       class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {};
 
@@ -248,13 +252,13 @@
       class $Class[[Foo]] {};
 
       template<typename $TemplateParameter[[T]]>
-      void $Function[[foo]]($TemplateParameter[[T]] ...);
+      $Primitive[[void]] $Function[[foo]]($TemplateParameter[[T]] ...);
     )cpp",
     R"cpp(
       template <class $TemplateParameter[[T]]>
       struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;};
-      extern template struct $Class[[Tmpl]]<float>;
-      template struct $Class[[Tmpl]]<double>;
+      extern template struct $Class[[Tmpl]]<$Primitive[[float]]>;
+      template struct $Class[[Tmpl]]<$Primitive[[double]]>;
     )cpp",
     // This test is to guard against highlightings disappearing when using
     // conversion operators as their behaviour in the clang AST differ from
@@ -263,14 +267,14 @@
       class $Class[[Foo]] {};
       struct $Class[[Bar]] {
         explicit operator $Class[[Foo]]*() const;
-        explicit operator int() const;
+        explicit operator $Primitive[[int]]() const;
         operator $Class[[Foo]]();
       };
-      void $Function[[f]]() {
+      $Primitive[[void]] $Function[[f]]() {
         $Class[[Bar]] $Variable[[B]];
         $Class[[Foo]] $Variable[[F]] = $Variable[[B]];
         $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
-        int $Variable[[I]] = (int)$Variable[[B]];
+        $Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
       }
     )cpp"};
   for (const auto &TestCase : TestCases) {
diff --git a/clangd/unittests/TweakTests.cpp b/clangd/unittests/TweakTests.cpp
index bbfa958..b307700 100644
--- a/clangd/unittests/TweakTests.cpp
+++ b/clangd/unittests/TweakTests.cpp
@@ -488,7 +488,7 @@
   checkAvailable(ID, "^vo^id^ ^f(^) {^}^"); // available everywhere.
   checkAvailable(ID, "[[int a; int b;]]");
   const char *Input = "void ^f() {}";
-  const char *Output = "void /* entity.name.function.cpp */f() {}";
+  const char *Output = "/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f() {}";
   checkTransform(ID, Input, Output);
 
   checkTransform(ID,
@@ -497,8 +497,8 @@
 void f2();]]
 )cpp",
   R"cpp(
-void /* entity.name.function.cpp */f1();
-void /* entity.name.function.cpp */f2();
+/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f1();
+/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f2();
 )cpp");
 
    checkTransform(ID,
@@ -509,7 +509,7 @@
 
   R"cpp(
 void f1();
-void /* entity.name.function.cpp */f2() {};
+/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f2() {};
 )cpp");
 }