Commit 51cdd518 authored by Johan Vikstrom's avatar Johan Vikstrom
Browse files

[clangd] Added highlightings for template parameters and specializations.

Summary: Template parameters and specializations were not being highlighted before. This adds highlightings to those types of tokens by adding two Visit* methods.

Reviewers: hokein, sammccall, ilya-biryukov

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

Tags: #clang

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

llvm-svn: 366420
parent c38e3efe
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -99,6 +99,19 @@ public:
    return true;
  }

  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc &TL) {
    // TemplateTypeParmTypeLoc does not have a TagDecl in its type ptr.
    addToken(TL.getBeginLoc(), TL.getDecl());
    return true;
  }

  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc &TL) {
    if (const TemplateDecl *TD =
            TL.getTypePtr()->getTemplateName().getAsTemplateDecl())
      addToken(TL.getBeginLoc(), TD);
    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 certain namespace qualifiers
@@ -135,6 +148,10 @@ private:
    // 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<ClassTemplateDecl>(D)) {
      addToken(Loc, HighlightingKind::Class);
      return;
    }
    if (isa<RecordDecl>(D)) {
      addToken(Loc, HighlightingKind::Class);
      return;
@@ -175,6 +192,14 @@ private:
      addToken(Loc, HighlightingKind::Namespace);
      return;
    }
    if (isa<TemplateTemplateParmDecl>(D)) {
      addToken(Loc, HighlightingKind::TemplateParameter);
      return;
    }
    if (isa<TemplateTypeParmDecl>(D)) {
      addToken(Loc, HighlightingKind::TemplateParameter);
      return;
    }
  }

  void addToken(SourceLocation Loc, HighlightingKind Kind) {
@@ -297,6 +322,8 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
    return "variable.other.enummember.cpp";
  case HighlightingKind::Namespace:
    return "entity.name.namespace.cpp";
  case HighlightingKind::TemplateParameter:
    return "entity.name.type.template.cpp";
  case HighlightingKind::NumKinds:
    llvm_unreachable("must not pass NumKinds to the function");
  }
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ enum class HighlightingKind {
  Enum,
  EnumConstant,
  Namespace,
  TemplateParameter,

  NumKinds,
};
+3 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@
# CHECK-NEXT:          ],
# CHECK-NEXT:          [
# CHECK-NEXT:            "entity.name.namespace.cpp"
# CHECK-NEXT:          ],
# CHECK-NEXT:          [
# CHECK-NEXT:            "entity.name.type.template.cpp"
# CHECK-NEXT:          ]
# CHECK-NEXT:        ]
# CHECK-NEXT:      },
+33 −6
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ void checkHighlightings(llvm::StringRef Code) {
      {HighlightingKind::Namespace, "Namespace"},
      {HighlightingKind::EnumConstant, "EnumConstant"},
      {HighlightingKind::Field, "Field"},
      {HighlightingKind::Method, "Method"}};
      {HighlightingKind::Method, "Method"},
      {HighlightingKind::TemplateParameter, "TemplateParameter"}};
  std::vector<HighlightingToken> ExpectedTokens;
  for (const auto &KindString : KindToString) {
    std::vector<HighlightingToken> Toks = makeHighlightingTokens(
@@ -80,14 +81,14 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
    )cpp",
    R"cpp(
      namespace $Namespace[[abc]] {
        template<typename T>
        template<typename $TemplateParameter[[T]]>
        struct $Class[[A]] {
          T $Field[[t]];
          $TemplateParameter[[T]] $Field[[t]];
        };
      }
      template<typename T>
      struct $Class[[C]] : $Namespace[[abc]]::A<T> {
        typename T::A* $Field[[D]];
      template<typename $TemplateParameter[[T]]>
      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]];
@@ -186,6 +187,32 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
      using $Enum[[CD]] = $Enum[[CC]];
      $Enum[[CC]] $Function[[f]]($Class[[B]]);
      $Enum[[CD]] $Function[[f]]($Class[[BB]]);
    )cpp",
    R"cpp(
      template<typename $TemplateParameter[[T]], typename = void>
      class $Class[[A]] {
        $TemplateParameter[[T]] $Field[[AA]];
        $TemplateParameter[[T]] $Method[[foo]]();
      };
      template<class $TemplateParameter[[TT]]>
      class $Class[[B]] {
        $Class[[A]]<$TemplateParameter[[TT]]> $Field[[AA]];
      };
      template<class $TemplateParameter[[TT]], class $TemplateParameter[[GG]]>
      class $Class[[BB]] {};
      template<class $TemplateParameter[[T]]>
      class $Class[[BB]]<$TemplateParameter[[T]], int> {};
      template<class $TemplateParameter[[T]]>
      class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {};

      template<template<class> class $TemplateParameter[[T]], class $TemplateParameter[[C]]>
      $TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function[[f]]();

      template<typename>
      class $Class[[Foo]] {};

      template<typename $TemplateParameter[[T]]>
      void $Function[[foo]]($TemplateParameter[[T]] ...);
    )cpp"};
  for (const auto &TestCase : TestCases) {
    checkHighlightings(TestCase);