[clang-tools-extra] r374799 - [clangd] Improve semantic highlighting in dependent contexts (fixes #154)

Nathan Ridge via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 14 11:26:13 PDT 2019


Author: nridge
Date: Mon Oct 14 11:26:13 2019
New Revision: 374799

URL: http://llvm.org/viewvc/llvm-project?rev=374799&view=rev
Log:
[clangd] Improve semantic highlighting in dependent contexts (fixes #154)

Reviewers: hokein

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

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

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=374799&r1=374798&r2=374799&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp (original)
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp Mon Oct 14 11:26:13 2019
@@ -37,6 +37,10 @@ bool canHighlightName(DeclarationName Na
 
 llvm::Optional<HighlightingKind> kindForType(const Type *TP);
 llvm::Optional<HighlightingKind> kindForDecl(const NamedDecl *D) {
+  if (auto *TD = dyn_cast<TemplateDecl>(D)) {
+    if (auto *Templated = TD->getTemplatedDecl())
+      D = Templated;
+  }
   if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
     // We try to highlight typedefs as their underlying type.
     if (auto K = kindForType(TD->getUnderlyingType().getTypePtrOrNull()))
@@ -95,6 +99,20 @@ llvm::Optional<HighlightingKind> kindFor
     return kindForDecl(TD);
   return llvm::None;
 }
+// Given a set of candidate declarations for an unresolved name,
+// if the declarations all have the same highlighting kind, return
+// that highlighting kind, otherwise return None.
+llvm::Optional<HighlightingKind>
+kindForCandidateDecls(llvm::iterator_range<UnresolvedSetIterator> Decls) {
+  llvm::Optional<HighlightingKind> Result;
+  for (NamedDecl *Decl : Decls) {
+    auto Kind = kindForDecl(Decl);
+    if (!Kind || (Result && Kind != Result))
+      return llvm::None;
+    Result = Kind;
+  }
+  return Result;
+}
 
 // Collects all semantic tokens in an ASTContext.
 class HighlightingTokenCollector
@@ -152,6 +170,26 @@ public:
     return true;
   }
 
+  bool VisitOverloadExpr(OverloadExpr *E) {
+    if (canHighlightName(E->getName()))
+      addToken(E->getNameLoc(),
+               kindForCandidateDecls(E->decls())
+                   .getValueOr(HighlightingKind::DependentName));
+    return true;
+  }
+
+  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+    if (canHighlightName(E->getDeclName()))
+      addToken(E->getLocation(), HighlightingKind::DependentName);
+    return true;
+  }
+
+  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
+    if (canHighlightName(E->getMember()))
+      addToken(E->getMemberLoc(), HighlightingKind::DependentName);
+    return true;
+  }
+
   bool VisitNamedDecl(NamedDecl *ND) {
     if (canHighlightName(ND->getDeclName()))
       addToken(ND->getLocation(), ND);
@@ -187,6 +225,11 @@ public:
     return true;
   }
 
+  bool WalkUpFromDependentNameTypeLoc(DependentNameTypeLoc L) {
+    addToken(L.getNameLoc(), HighlightingKind::DependentType);
+    return true;
+  }
+
   bool VisitTypeLoc(TypeLoc TL) {
     if (auto K = kindForType(TL.getTypePtr()))
       addToken(TL.getBeginLoc(), *K);
@@ -339,6 +382,10 @@ llvm::raw_ostream &operator<<(llvm::raw_
     return OS << "EnumConstant";
   case HighlightingKind::Typedef:
     return OS << "Typedef";
+  case HighlightingKind::DependentType:
+    return OS << "DependentType";
+  case HighlightingKind::DependentName:
+    return OS << "DependentName";
   case HighlightingKind::Namespace:
     return OS << "Namespace";
   case HighlightingKind::TemplateParameter:
@@ -468,6 +515,10 @@ llvm::StringRef toTextMateScope(Highligh
     return "variable.other.enummember.cpp";
   case HighlightingKind::Typedef:
     return "entity.name.type.typedef.cpp";
+  case HighlightingKind::DependentType:
+    return "entity.name.type.dependent.cpp";
+  case HighlightingKind::DependentName:
+    return "entity.name.other.dependent.cpp";
   case HighlightingKind::Namespace:
     return "entity.name.namespace.cpp";
   case HighlightingKind::TemplateParameter:

Modified: clang-tools-extra/trunk/clangd/SemanticHighlighting.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/SemanticHighlighting.h?rev=374799&r1=374798&r2=374799&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.h (original)
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.h Mon Oct 14 11:26:13 2019
@@ -37,6 +37,8 @@ enum class HighlightingKind {
   Enum,
   EnumConstant,
   Typedef,
+  DependentType,
+  DependentName,
   Namespace,
   TemplateParameter,
   Primitive,

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=374799&r1=374798&r2=374799&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/test/semantic-highlighting.test (original)
+++ clang-tools-extra/trunk/clangd/test/semantic-highlighting.test Mon Oct 14 11:26:13 2019
@@ -41,6 +41,12 @@
 # CHECK-NEXT:            "entity.name.type.typedef.cpp"
 # CHECK-NEXT:          ],
 # CHECK-NEXT:          [
+# CHECK-NEXT:            "entity.name.type.dependent.cpp"
+# CHECK-NEXT:          ],
+# CHECK-NEXT:          [
+# CHECK-NEXT:            "entity.name.other.dependent.cpp"
+# CHECK-NEXT:          ],
+# CHECK-NEXT:          [
 # CHECK-NEXT:            "entity.name.namespace.cpp"
 # CHECK-NEXT:          ],
 # CHECK-NEXT:          [
@@ -61,7 +67,7 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 0,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADABAAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "textDocument": {
@@ -76,11 +82,11 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 0,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADABAAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 1,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADABAAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "textDocument": {
@@ -95,7 +101,7 @@
 # CHECK-NEXT:    "lines": [
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "line": 1,
-# CHECK-NEXT:        "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
+# CHECK-NEXT:        "tokens": "AAAAAAADABAAAAAEAAEAAA=="
 # CHECK-NEXT:      }
 # CHECK-NEXT:   ],
 # CHECK-NEXT:    "textDocument": {

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=374799&r1=374798&r2=374799&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp Mon Oct 14 11:26:13 2019
@@ -51,6 +51,9 @@ std::vector<HighlightingToken> getExpect
       {HighlightingKind::StaticField, "StaticField"},
       {HighlightingKind::Method, "Method"},
       {HighlightingKind::StaticMethod, "StaticMethod"},
+      {HighlightingKind::Typedef, "Typedef"},
+      {HighlightingKind::DependentType, "DependentType"},
+      {HighlightingKind::DependentName, "DependentName"},
       {HighlightingKind::TemplateParameter, "TemplateParameter"},
       {HighlightingKind::Primitive, "Primitive"},
       {HighlightingKind::Macro, "Macro"}};
@@ -181,7 +184,7 @@ TEST(SemanticHighlighting, GetsCorrectTo
       }
       template<typename $TemplateParameter[[T]]>
       struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
-        typename $TemplateParameter[[T]]::A* $Field[[D]];
+        typename $TemplateParameter[[T]]::$DependentType[[A]]* $Field[[D]];
       };
       $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Variable[[AA]];
       typedef $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Class[[AAA]];
@@ -529,6 +532,58 @@ TEST(SemanticHighlighting, GetsCorrectTo
           $Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]],
           $Typedef[[Array]], $Typedef[[MemberPointer]]);
       };
+    )cpp",
+      R"cpp(
+      template <class $TemplateParameter[[T]]>
+      $Primitive[[void]] $Function[[phase1]]($TemplateParameter[[T]]);
+      template <class $TemplateParameter[[T]]>
+      $Primitive[[void]] $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
+        $Function[[phase1]]($Parameter[[P]]);
+        $DependentName[[phase2]]($Parameter[[P]]);
+      }
+    )cpp",
+      R"cpp(
+      class $Class[[A]] {
+        template <class $TemplateParameter[[T]]>
+        $Primitive[[void]] $Method[[bar]]($TemplateParameter[[T]]);
+      };
+
+      template <class $TemplateParameter[[U]]>
+      $Primitive[[void]] $Function[[foo]]($TemplateParameter[[U]] $Parameter[[P]]) {
+        $Class[[A]]().$Method[[bar]]($Parameter[[P]]);
+      }
+    )cpp",
+      R"cpp(
+      struct $Class[[A]] {
+        template <class $TemplateParameter[[T]]>
+        static $Primitive[[void]] $StaticMethod[[foo]]($TemplateParameter[[T]]);
+      };
+
+      template <class $TemplateParameter[[T]]>
+      struct $Class[[B]] {
+        $Primitive[[void]] $Method[[bar]]() {
+          $Class[[A]]::$StaticMethod[[foo]]($TemplateParameter[[T]]());
+        }
+      };
+    )cpp",
+      R"cpp(
+      template <class $TemplateParameter[[T]]>
+      $Primitive[[void]] $Function[[foo]](typename $TemplateParameter[[T]]::$DependentType[[Type]]
+                                            = $TemplateParameter[[T]]::$DependentName[[val]]);
+    )cpp",
+      R"cpp(
+      template <class $TemplateParameter[[T]]>
+      $Primitive[[void]] $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
+        $Parameter[[P]].$DependentName[[Field]];
+      }
+    )cpp",
+      R"cpp(
+      template <class $TemplateParameter[[T]]>
+      class $Class[[A]] {
+        $Primitive[[int]] $Method[[foo]]() {
+          return $TemplateParameter[[T]]::$DependentName[[Field]];
+        }
+      };
     )cpp"};
   for (const auto &TestCase : TestCases) {
     checkHighlightings(TestCase);




More information about the cfe-commits mailing list