jvikstrom updated this revision to Diff 217618.
jvikstrom added a comment.

Added a RecursiveASTVisitor for finding 'underlying' types.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66516/new/

https://reviews.llvm.org/D66516

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -16,6 +16,10 @@
 
 namespace clang {
 namespace clangd {
+void PrintTo(const HighlightingToken &T, ::std::ostream *OS) {
+  *OS << "(" << T.R.start.line << ", " << T.R.start.character << ") -> (" << T.R.end.line << ", " << T.R.end.character << "): " << (int)T.Kind;
+}
+
 namespace {
 
 MATCHER_P(LineNumber, L, "") { return arg.Line == L; }
@@ -225,7 +229,9 @@
     )cpp",
     R"cpp(
       namespace $Namespace[[a]] {
-        struct $Class[[A]] {};
+        struct $Class[[A]] {
+          $Primitive[[void]] $Method[[foo]]($Class[[A]]*);
+        };
         typedef $Primitive[[char]] $Primitive[[C]];
       }
       typedef $Namespace[[a]]::$Class[[A]] $Class[[B]];
@@ -238,6 +244,12 @@
       $Enum[[CD]] $Function[[f]]($Class[[BB]]);
       typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]];
       typedef $Primitive[[float]] $Primitive[[F]];
+      using $Primitive[[Member]] =
+        $Primitive[[void]] (B::*)($Namespace[[a]]::$Class[[A]]*);
+      $Primitive[[void]] $Function[[foo]]($Primitive[[int]], $Class[[B]]);
+      typedef decltype($Function[[foo]]) $Primitive[[fooo]];
+      typedef $Class[[B]] (*$Class[[func]])();
+      typedef $Primitive[[int]] (*$Primitive[[func]])();
     )cpp",
     R"cpp(
       template<typename $TemplateParameter[[T]], typename = $Primitive[[void]]>
@@ -431,6 +443,20 @@
         assert($Variable[[x]] != $Variable[[y]]);
         assert($Variable[[x]] != $Function[[f]]());
       }
+    )cpp",
+    R"cpp(
+      template<class $TemplateParameter[[T]]>
+      class $Class[[A]] {
+        using $TemplateParameter[[D]] = $TemplateParameter[[T]];
+        using $TemplateParameter[[DD]] = $TemplateParameter[[T]] *;
+        using $TemplateParameter[[DDD]] = $TemplateParameter[[T]] &;
+        using $TemplateParameter[[B]] = $TemplateParameter[[T]]*[3];
+        using $TemplateParameter[[BB]] = $TemplateParameter[[T]]&&;
+        using $TemplateParameter[[Member]] =
+          BB (T::*)($Primitive[[int]]);
+        using $TemplateParameter[[MemberT]] =
+          $TemplateParameter[[T]]*& (T::*)($Class[[A]]);
+      };
     )cpp"};
   for (const auto &TestCase : TestCases) {
     checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -14,12 +14,83 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
 #include <algorithm>
 
 namespace clang {
 namespace clangd {
 namespace {
 
+/// Gets an underlying type in a type hierarchy. Should be used to find the type
+/// in a hieracrchy when the HighlightingTokenCollector's RecursiveASTVisitor
+/// can not recurse to it by default and the addType function is used outside a
+/// Visit*TypeLoc.
+class UnderlyingTypeVisitor
+    : public RecursiveASTVisitor<UnderlyingTypeVisitor> {
+  const Type *Underlying;
+
+public:
+  /// Gets an underlying type in the \p T type hierarchy.
+  /// Gets the first type ptr with a Tag decl if one exists.
+  /// Else gets the first Leaf type ptr.
+  /// If neither are found returns the type ptr.
+  const Type *getUnderlyingType(QualType T) {
+    Underlying = &(*T);
+    TraverseType(T);
+    return Underlying;
+  }
+
+  // Check if T has a tag decl and if so stop traversing the type hierachy as we
+  // want to return this.
+  bool VisitType(Type *T) {
+    if (T->getAsTagDecl()) {
+      Underlying = T;
+      return false;
+    }
+    return true;
+  }
+
+  // The default behaviour for RecursiveASTVisitor is to traverse the class type
+  // as well. This makes member pointers become highlighted as classes which is
+  // incorrect.
+  bool TraverseMemberPointerType(MemberPointerType *T) {
+    return RecursiveASTVisitor<UnderlyingTypeVisitor>::TraverseType(
+        T->getPointeeType());
+  }
+
+  // RecursiveASTVisitor does not traverse the underlying type of a decltype.
+  bool TraverseDecltypeType(DecltypeType *T) {
+    return RecursiveASTVisitor<UnderlyingTypeVisitor>::TraverseType(
+        T->getUnderlyingType());
+  }
+
+  // RecursiveASTVisitor also traverses parameter and exception types. Only want
+  // return type for this.
+  bool TraverseFunctionProtoType(FunctionProtoType *T) {
+    return RecursiveASTVisitor<UnderlyingTypeVisitor>::TraverseType(
+        T->getReturnType());
+  }
+
+  // RecursiveASTVisitor does not traverse a typedef's underlying type.
+  bool TraverseTypedefType(TypedefType *T) {
+    return RecursiveASTVisitor<UnderlyingTypeVisitor>::TraverseType(
+        T->getDecl()->getUnderlyingType());
+  }
+
+// Create Visit functions for all leaf types that set the Leaf type. Don't want
+// to create any functions for non leaf Types.
+#define TYPE(X, Y)
+#define LEAF_TYPE(CLASS)                                                       \
+  bool Visit##CLASS##Type(CLASS##Type *T) {                                    \
+    Underlying = T;                                                            \
+    return true;                                                               \
+  }
+#include "clang/AST/TypeNodes.def"
+#undef TYPE
+#undef LEAF_TYPE
+};
+
 // Collects all semantic tokens in an ASTContext.
 class HighlightingTokenCollector
     : public RecursiveASTVisitor<HighlightingTokenCollector> {
@@ -119,13 +190,8 @@
 
   bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
     if (const auto *TSI = TD->getTypeSourceInfo())
-      addType(TD->getLocation(), TSI->getTypeLoc().getTypePtr());
-    return true;
-  }
-
-  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc &TL) {
-    // TemplateTypeParmTypeLoc does not have a TagDecl in its type ptr.
-    addToken(TL.getBeginLoc(), TL.getDecl());
+      addType(TD->getLocation(), UnderlyingTypeVisitor().getUnderlyingType(
+                                     TSI->getTypeLoc().getType()));
     return true;
   }
 
@@ -182,6 +248,9 @@
     if (TP->isBuiltinType())
       // Builtins must be special cased as they do not have a TagDecl.
       addToken(Loc, HighlightingKind::Primitive);
+    if (const TemplateTypeParmType *TD = dyn_cast<TemplateTypeParmType>(TP))
+      // TemplateTypeParmType also do not have a TagDecl.
+      addToken(Loc, TD->getDecl());
     if (const TagDecl *TD = TP->getAsTagDecl())
       addToken(Loc, TD);
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to