[clangd] Added semantic highlighting support for primitives.
authorJohan Vikstrom <jvikstrom@google.com>
Thu, 8 Aug 2019 13:10:30 +0000 (13:10 +0000)
committerJohan Vikstrom <jvikstrom@google.com>
Thu, 8 Aug 2019 13:10:30 +0000 (13:10 +0000)
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

llvm-svn: 368291

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
clang-tools-extra/clangd/unittests/TweakTests.cpp

index 3bffe7f1a369bc2ad6a038204eb40c1c98506d54..be87dcc8ddacc486dd7435671b37a03fdae643df 100644 (file)
@@ -138,9 +138,13 @@ public:
 
 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 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
     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");
   }
index 2d9d2317c9e2bd595235991f5f89d71a409cc87c..24a83b957a5515e1dbd37092da9b4b100f7bcb2c 100644 (file)
@@ -33,6 +33,7 @@ enum class HighlightingKind {
   EnumConstant,
   Namespace,
   TemplateParameter,
+  Primitive,
 
   NumKinds,
 };
index 15342af6926fd3bd5b83d571250fee8cbc06508b..e22b34af1cdaf516f5a77e9bd865a0114f0d72a5 100644 (file)
@@ -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": {
 # 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": {
index 006766535d92c6323a71fc543c391fb76392e778..3ff7bbc8bbb30dbbedd7a84a89da21b320b05c16 100644 (file)
@@ -39,7 +39,8 @@ std::vector<HighlightingToken> getExpectedTokens(Annotations &Test) {
       {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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
   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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
       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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
         $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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
     )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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
           $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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
     )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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
       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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
       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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
       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 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
       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) {
index bbfa9583b18e045fcec222d54f8441bca1a4ea38..b3077000100b9e16db6850d27e336a44f11989af 100644 (file)
@@ -488,7 +488,7 @@ TEST(TweaksTest, AnnotateHighlightings) {
   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 @@ TEST(TweaksTest, AnnotateHighlightings) {
 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 @@ void f2() {^};
 
   R"cpp(
 void f1();
-void /* entity.name.function.cpp */f2() {};
+/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f2() {};
 )cpp");
 }