[clang-tools-extra] r365602 - [clangd] Added highlighting for class and enum types.

Johan Vikstrom via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 10 01:41:25 PDT 2019


Author: jvikstrom
Date: Wed Jul 10 01:41:25 2019
New Revision: 365602

URL: http://llvm.org/viewvc/llvm-project?rev=365602&view=rev
Log:
[clangd] Added highlighting for class and enum types.

Summary: Added highlighting for non-builtin types using VisitTypeLoc. Ignoring namespace qualifiers as for now.

Reviewers: hokein, sammccall, ilya-biryukov

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

Tags: #clang

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

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

Modified: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp?rev=365602&r1=365601&r2=365602&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp (original)
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp Wed Jul 10 01:41:25 2019
@@ -11,6 +11,8 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 
 namespace clang {
@@ -35,13 +37,18 @@ public:
   }
 
   bool VisitNamedDecl(NamedDecl *ND) {
-    // FIXME: (De)Constructors/operator need to be highlighted some other way.
-    if (ND->getDeclName().getNameKind() != DeclarationName::Identifier)
+    // Constructors' TypeLoc has a TypePtr that is a FunctionProtoType. It has
+    // no tag decl and therefore constructors must be gotten as NamedDecls
+    // instead.
+    if (ND->getDeclName().getNameKind() ==
+        DeclarationName::CXXConstructorName) {
+      addToken(ND->getLocation(), ND);
       return true;
+    }
 
-    if (ND->getDeclName().isEmpty())
-      // Don't add symbols that don't have any length.
+    if (ND->getDeclName().getNameKind() != DeclarationName::Identifier)
       return true;
+
     addToken(ND->getLocation(), ND);
     return true;
   }
@@ -56,8 +63,39 @@ public:
     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 namespace qualifiers. For
+    // elaborated types the actual type is highlighted as an inner TypeLoc.
+    if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
+      return true;
+
+    if (const Type *TP = TL.getTypePtr())
+      if (const TagDecl *TD = TP->getAsTagDecl())
+          addToken(TL.getBeginLoc(), TD);
+    return true;
+  }
+
 private:
-  void addToken(SourceLocation Loc, const Decl *D) {
+  void addToken(SourceLocation Loc, const NamedDecl *D) {
+    if (D->getDeclName().isIdentifier() && D->getName().empty())
+      // Don't add symbols that don't have any length.
+      return;
+    // 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<RecordDecl>(D)) {
+      addToken(Loc, HighlightingKind::Class);
+      return;
+    }
+    if (isa<CXXConstructorDecl>(D)) {
+      addToken(Loc, HighlightingKind::Class);
+      return;
+    }
+    if (isa<EnumDecl>(D)) {
+      addToken(Loc, HighlightingKind::Enum);
+      return;
+    }
     if (isa<VarDecl>(D)) {
       addToken(Loc, HighlightingKind::Variable);
       return;
@@ -176,6 +214,10 @@ llvm::StringRef toTextMateScope(Highligh
     return "entity.name.function.cpp";
   case HighlightingKind::Variable:
     return "variable.cpp";
+  case HighlightingKind::Class:
+    return "entity.name.type.class.cpp";
+  case HighlightingKind::Enum:
+    return "entity.name.type.enum.cpp";
   case HighlightingKind::NumKinds:
     llvm_unreachable("must not pass NumKinds to the function");
   }

Modified: clang-tools-extra/trunk/clangd/SemanticHighlighting.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/SemanticHighlighting.h?rev=365602&r1=365601&r2=365602&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.h (original)
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.h Wed Jul 10 01:41:25 2019
@@ -26,6 +26,8 @@ namespace clangd {
 enum class HighlightingKind {
   Variable = 0,
   Function,
+  Class,
+  Enum,
 
   NumKinds,
 };

Modified: clang-tools-extra/trunk/clangd/test/semantic-highlighting.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/test/semantic-highlighting.test?rev=365602&r1=365601&r2=365602&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/test/semantic-highlighting.test (original)
+++ clang-tools-extra/trunk/clangd/test/semantic-highlighting.test Wed Jul 10 01:41:25 2019
@@ -10,6 +10,12 @@
 # CHECK-NEXT:          [
 # CHECK-NEXT:            "entity.name.function.cpp"
 # CHECK-NEXT:          ]
+# CHECK-NEXT:          [
+# CHECK-NEXT:            "entity.name.type.class.cpp"
+# CHECK-NEXT:          ],
+# CHECK-NEXT:          [
+# CHECK-NEXT:            "entity.name.type.enum.cpp"
+# CHECK-NEXT:          ]
 # CHECK-NEXT:        ]
 # CHECK-NEXT:      },
 ---

Modified: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp?rev=365602&r1=365601&r2=365602&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp Wed Jul 10 01:41:25 2019
@@ -34,11 +34,13 @@ void checkHighlightings(llvm::StringRef
   auto AST = TestTU::withCode(Test.code()).build();
   static const std::map<HighlightingKind, std::string> KindToString{
       {HighlightingKind::Variable, "Variable"},
-      {HighlightingKind::Function, "Function"}};
+      {HighlightingKind::Function, "Function"},
+      {HighlightingKind::Class, "Class"},
+      {HighlightingKind::Enum, "Enum"}};
   std::vector<HighlightingToken> ExpectedTokens;
   for (const auto &KindString : KindToString) {
-    std::vector<HighlightingToken> Toks =
-        makeHighlightingTokens(Test.ranges(KindString.second), KindString.first);
+    std::vector<HighlightingToken> Toks = makeHighlightingTokens(
+        Test.ranges(KindString.second), KindString.first);
     ExpectedTokens.insert(ExpectedTokens.end(), Toks.begin(), Toks.end());
   }
 
@@ -49,14 +51,14 @@ void checkHighlightings(llvm::StringRef
 TEST(SemanticHighlighting, GetsCorrectTokens) {
   const char *TestCases[] = {
     R"cpp(
-      struct AS {
+      struct $Class[[AS]] {
         double SomeMember;
       };
       struct {
       } $Variable[[S]];
-      void $Function[[foo]](int $Variable[[A]]) {
+      void $Function[[foo]](int $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
         auto $Variable[[VeryLongVariableName]] = 12312;
-        AS     $Variable[[AA]];
+        $Class[[AS]]     $Variable[[AA]];
         auto $Variable[[L]] = $Variable[[AA]].SomeMember + $Variable[[A]];
         auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {};
         $Variable[[FN]](12312);
@@ -68,13 +70,43 @@ TEST(SemanticHighlighting, GetsCorrectTo
       void $Function[[foo]]() {
         auto $Variable[[Bou]] = $Function[[Gah]];
       }
+      struct $Class[[A]] {
+        void $Function[[abc]]();
+      };
     )cpp",
     R"cpp(
-      struct A {
-        A();
-        ~A();
-        void $Function[[abc]]();
-        void operator<<(int);
+      namespace abc {
+        template<typename T>
+        struct $Class[[A]] {
+          T t;
+        };
+      }
+      template<typename T>
+      struct $Class[[C]] : abc::A<T> {
+        typename T::A* D;
+      };
+      abc::$Class[[A]]<int> $Variable[[AA]];
+      typedef abc::$Class[[A]]<int> AAA;
+      struct $Class[[B]] {
+        $Class[[B]]();
+        ~$Class[[B]]();
+        void operator<<($Class[[B]]);
+        $Class[[AAA]] AA;
+      };
+      $Class[[B]]::$Class[[B]]() {}
+      $Class[[B]]::~$Class[[B]]() {}
+      void $Function[[f]] () {
+        $Class[[B]] $Variable[[BB]] = $Class[[B]]();
+        $Variable[[BB]].~$Class[[B]]();
+        $Class[[B]]();
+      }
+    )cpp",
+    R"cpp(
+      enum class $Enum[[E]] {};
+      enum $Enum[[EE]] {};
+      struct $Class[[A]] {
+        $Enum[[E]] EEE;
+        $Enum[[EE]] EEEE;
       };
     )cpp"};
   for (const auto &TestCase : TestCases) {




More information about the cfe-commits mailing list