[clangd] Add a new highlighting kind for typedefs
authorIlya Biryukov <ibiryukov@google.com>
Mon, 9 Sep 2019 14:33:10 +0000 (14:33 +0000)
committerIlya Biryukov <ibiryukov@google.com>
Mon, 9 Sep 2019 14:33:10 +0000 (14:33 +0000)
Summary:
We still attempt to highlight them as underlying types, but fallback to
the generic 'typedef' highlighting kind if the underlying type is too
complicated.

Reviewers: hokein

Reviewed By: hokein

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

Tags: #clang

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

llvm-svn: 371402

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 b5f1c40..5744e86 100644 (file)
@@ -17,6 +17,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/SourceLocation.h"
 #include <algorithm>
 
 namespace clang {
@@ -125,13 +126,12 @@ public:
   }
 
   bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
-    if (const auto *TSI = TD->getTypeSourceInfo())
-      addType(TD->getLocation(), TSI->getTypeLoc().getTypePtr());
+    addTokenForTypedef(TD->getLocation(), TD);
     return true;
   }
 
   bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
-    addType(TL.getBeginLoc(), TL.getTypePtr());
+    addTokenForTypedef(TL.getBeginLoc(), TL.getTypedefNameDecl());
     return true;
   }
 
@@ -182,17 +182,35 @@ public:
   }
 
 private:
-  void addType(SourceLocation Loc, const Type *TP) {
-    if (!TP)
+  void addTokenForTypedef(SourceLocation Loc, const TypedefNameDecl *TD) {
+    auto *TSI = TD->getTypeSourceInfo();
+    if (!TSI)
+      return;
+    // Try to highlight as underlying type.
+    if (addType(Loc, TSI->getType().getTypePtrOrNull()))
       return;
-    if (TP->isBuiltinType())
+    // Fallback to the typedef highlighting kind.
+    addToken(Loc, HighlightingKind::Typedef);
+  }
+
+  bool addType(SourceLocation Loc, const Type *TP) {
+    if (!TP)
+      return false;
+    if (TP->isBuiltinType()) {
       // Builtins must be special cased as they do not have a TagDecl.
       addToken(Loc, HighlightingKind::Primitive);
-    if (auto *TD = dyn_cast<TemplateTypeParmType>(TP))
+      return true;
+    }
+    if (auto *TD = dyn_cast<TemplateTypeParmType>(TP)) {
       // TemplateTypeParmType also do not have a TagDecl.
       addToken(Loc, TD->getDecl());
-    if (auto *TD = TP->getAsTagDecl())
+      return true;
+    }
+    if (auto *TD = TP->getAsTagDecl()) {
       addToken(Loc, TD);
+      return true;
+    }
+    return false;
   }
 
   void addToken(SourceLocation Loc, const NamedDecl *D) {
@@ -379,6 +397,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {
     return OS << "Enum";
   case HighlightingKind::EnumConstant:
     return OS << "EnumConstant";
+  case HighlightingKind::Typedef:
+    return OS << "Typedef";
   case HighlightingKind::Namespace:
     return OS << "Namespace";
   case HighlightingKind::TemplateParameter:
@@ -506,6 +526,8 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
     return "entity.name.type.enum.cpp";
   case HighlightingKind::EnumConstant:
     return "variable.other.enummember.cpp";
+  case HighlightingKind::Typedef:
+    return "entity.name.type.typedef.cpp";
   case HighlightingKind::Namespace:
     return "entity.name.namespace.cpp";
   case HighlightingKind::TemplateParameter:
index 930fcca..11c0564 100644 (file)
@@ -36,6 +36,7 @@ enum class HighlightingKind {
   Class,
   Enum,
   EnumConstant,
+  Typedef,
   Namespace,
   TemplateParameter,
   Primitive,
index 005d01c..d802efb 100644 (file)
@@ -38,6 +38,9 @@
 # CHECK-NEXT:            "variable.other.enummember.cpp"
 # CHECK-NEXT:          ],
 # CHECK-NEXT:          [
+# CHECK-NEXT:            "entity.name.type.typedef.cpp"
+# CHECK-NEXT:          ],
+# CHECK-NEXT:          [
 # CHECK-NEXT:            "entity.name.namespace.cpp"
 # CHECK-NEXT:          ],
 # CHECK-NEXT:          [
@@ -58,7 +61,7 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 0,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA0AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "textDocument": {
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 0,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA0AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 1,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA0AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "textDocument": {
@@ -92,7 +95,7 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 1,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA0AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:   ],
 # CHECK-NEXT:    "textDocument": {
index 92e6256..abc0f4e 100644 (file)
@@ -496,12 +496,16 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
         typedef $TemplateParameter[[T]] $TemplateParameter[[TemplateParam2]];
         using $Primitive[[IntType]] = $Primitive[[int]];
 
-        // These typedefs are not yet highlighted, their types are complicated.
-        using Pointer = $TemplateParameter[[T]] *;
-        using LVReference = $TemplateParameter[[T]] &;
-        using RVReference = $TemplateParameter[[T]]&&;
-        using Array = $TemplateParameter[[T]]*[3];
-        using MemberPointer = $Primitive[[int]] (A::*)($Primitive[[int]]);
+        using $Typedef[[Pointer]] = $TemplateParameter[[T]] *;
+        using $Typedef[[LVReference]] = $TemplateParameter[[T]] &;
+        using $Typedef[[RVReference]] = $TemplateParameter[[T]]&&;
+        using $Typedef[[Array]] = $TemplateParameter[[T]]*[3];
+        using $Typedef[[MemberPointer]] = $Primitive[[int]] (A::*)($Primitive[[int]]);
+
+        // Use various previously defined typedefs in a function type.
+        $Primitive[[void]] $Method[[func]](
+          $Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]],
+          $Typedef[[Array]], $Typedef[[MemberPointer]]);
       };
     )cpp"};
   for (const auto &TestCase : TestCases) {