kadircet updated this revision to Diff 190800.
kadircet marked 11 inline comments as done.
kadircet added a comment.

- Add more tests
- Replace switch with if
- Use SmallVector


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D59354

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/index/MemIndex.cpp
  clang-tools-extra/clangd/index/dex/Dex.cpp
  clang-tools-extra/unittests/clangd/DexTests.cpp
  clang-tools-extra/unittests/clangd/IndexTests.cpp
  clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
  clang/lib/AST/TypePrinter.cpp

Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1632,6 +1632,21 @@
   return A.getArgument();
 }
 
+static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
+                          llvm::raw_ostream &OS) {
+  A.print(PP, OS);
+}
+
+static void printArgument(const TemplateArgumentLoc &A,
+                          const PrintingPolicy &PP, llvm::raw_ostream &OS) {
+  const auto &Kind = A.getArgument().getKind();
+  assert(Kind != TemplateArgument::Null &&
+         "TemplateArgumentKind can not be null!");
+  if (Kind == TemplateArgument::ArgKind::Type)
+    return A.getTypeSourceInfo()->getType().print(OS, PP);
+  return A.getArgument().print(PP, OS);
+}
+
 template<typename TA>
 static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
                     const PrintingPolicy &Policy, bool SkipBrackets) {
@@ -1653,7 +1668,7 @@
     } else {
       if (!FirstArg)
         OS << Comma;
-      Argument.print(Policy, ArgOS);
+      printArgument(Arg, Policy, ArgOS);
     }
     StringRef ArgString = ArgOS.str();
 
Index: clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
===================================================================
--- clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
+++ clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
@@ -394,23 +394,80 @@
   Annotations Header(R"(
     // Primary template and explicit specialization are indexed, instantiation
     // is not.
-    template <class T, class U> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
-    template <> struct $specdecl[[Tmpl]]<int, bool> {};
-    template <class U> struct $partspecdecl[[Tmpl]]<bool, U> {};
-    extern template struct Tmpl<float, bool>;
-    template struct Tmpl<double, bool>;
+    template <class X> class $barclasstemp[[Bar]] {};
+    template <class T, class U, template<typename> class Z, int Q>
+    struct [[Tmpl]] { T $xdecl[[x]] = 0; };
+
+    // template-template, non-type and type full spec
+    template <> struct $specdecl[[Tmpl]]<int, bool, Bar, 3> {};
+
+    // template-template, non-type and type partial spec
+    template <class U, int T> struct $partspecdecl[[Tmpl]]<bool, U, Bar, T> {};
+    // instantiation
+    extern template struct Tmpl<float, bool, Bar, 8>;
+    // instantiation
+    template struct Tmpl<double, bool, Bar, 2>;
+
+    template <typename ...> class $fooclasstemp[[Foo]] {};
+    // parameter-packs full spec
+    template<> class $parampack[[Foo]]<Bar<int>, int, double> {};
+    // parameter-packs partial spec
+    template<class T> class $parampackpartial[[Foo]]<T, T> {};
+
+    template <int ...> class $bazclasstemp[[Baz]] {};
+    // non-type parameter-packs full spec
+    template<> class $parampacknontype[[Baz]]<3, 5, 8> {};
+    // non-type parameter-packs partial spec
+    template<int T> class $parampacknontypepartial[[Baz]]<T, T> {};
+
+    template <template <class> class ...> class $fozclasstemp[[Foz]] {};
+    // template-template parameter-packs full spec
+    template<> class $parampacktempltempl[[Foz]]<Bar, Bar> {};
+    // template-template parameter-packs partial spec
+    template<template <class> class T>
+    class $parampacktempltemplpartial[[Foz]]<T, T> {};
   )");
   runSymbolCollector(Header.code(), /*Main=*/"");
-  EXPECT_THAT(Symbols,
-              UnorderedElementsAre(
-                  AllOf(QName("Tmpl"), DeclRange(Header.range()),
-                        ForCodeCompletion(true)),
-                  AllOf(QName("Tmpl"), DeclRange(Header.range("specdecl")),
-                        ForCodeCompletion(false)),
-                  AllOf(QName("Tmpl"), DeclRange(Header.range("partspecdecl")),
-                        ForCodeCompletion(false)),
-                  AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")),
-                        ForCodeCompletion(false))));
+  EXPECT_THAT(Symbols.size(), 14U);
+  EXPECT_THAT(
+      Symbols,
+      AllOf(
+          Contains(AllOf(QName("Tmpl"), DeclRange(Header.range()),
+                         ForCodeCompletion(true))),
+          Contains(AllOf(QName("Bar"), DeclRange(Header.range("barclasstemp")),
+                         ForCodeCompletion(true))),
+          Contains(AllOf(QName("Foo"), DeclRange(Header.range("fooclasstemp")),
+                         ForCodeCompletion(true))),
+          Contains(AllOf(QName("Baz"), DeclRange(Header.range("bazclasstemp")),
+                         ForCodeCompletion(true))),
+          Contains(AllOf(QName("Foz"), DeclRange(Header.range("fozclasstemp")),
+                         ForCodeCompletion(true))),
+          Contains(AllOf(QName("Tmpl<int, bool, Bar, 3>"),
+                         DeclRange(Header.range("specdecl")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Tmpl<bool, U, Bar, T>"),
+                         DeclRange(Header.range("partspecdecl")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Foo<Bar<int>, int, double>"),
+                         DeclRange(Header.range("parampack")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Foo<T, T>"),
+                         DeclRange(Header.range("parampackpartial")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Baz<3, 5, 8>"),
+                         DeclRange(Header.range("parampacknontype")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Baz<T, T>"),
+                         DeclRange(Header.range("parampacknontypepartial")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Foz<Bar, Bar>"),
+                         DeclRange(Header.range("parampacktempltempl")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Foz<T, T>"),
+                         DeclRange(Header.range("parampacktempltemplpartial")),
+                         ForCodeCompletion(false))),
+          Contains(AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")),
+                         ForCodeCompletion(false)))));
 }
 
 TEST_F(SymbolCollectorTest, ObjCSymbols) {
Index: clang-tools-extra/unittests/clangd/IndexTests.cpp
===================================================================
--- clang-tools-extra/unittests/clangd/IndexTests.cpp
+++ clang-tools-extra/unittests/clangd/IndexTests.cpp
@@ -187,35 +187,30 @@
   SymbolSlab::Builder B;
 
   Symbol S = symbol("TempSpec");
-  S.ID = SymbolID("0");
   B.insert(S);
 
-  S = symbol("TempSpec");
-  S.ID = SymbolID("1");
+  S = symbol("TempSpec<int, bool>");
   S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
       index::SymbolProperty::TemplateSpecialization);
   B.insert(S);
 
-  S = symbol("TempSpec");
-  S.ID = SymbolID("2");
+  S = symbol("TempSpec<int, U>");
   S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
       index::SymbolProperty::TemplatePartialSpecialization);
   B.insert(S);
 
   auto I = MemIndex::build(std::move(B).build(), RefSlab());
   FuzzyFindRequest Req;
-  Req.Query = "TempSpec";
   Req.AnyScope = true;
 
-  std::vector<Symbol> Symbols;
-  I->fuzzyFind(Req, [&Symbols](const Symbol &Sym) { Symbols.push_back(Sym); });
-  EXPECT_EQ(Symbols.size(), 1U);
-  EXPECT_FALSE(Symbols.front().SymInfo.Properties &
-               static_cast<index::SymbolPropertySet>(
-                   index::SymbolProperty::TemplateSpecialization));
-  EXPECT_FALSE(Symbols.front().SymInfo.Properties &
-               static_cast<index::SymbolPropertySet>(
-                   index::SymbolProperty::TemplatePartialSpecialization));
+  Req.Query = "TempSpec";
+  EXPECT_THAT(match(*I, Req),
+              UnorderedElementsAre("TempSpec", "TempSpec<int, bool>",
+                                   "TempSpec<int, U>"));
+
+  Req.Query = "TempSpec<int";
+  EXPECT_THAT(match(*I, Req),
+              UnorderedElementsAre("TempSpec<int, bool>", "TempSpec<int, U>"));
 }
 
 TEST(MergeIndexTest, Lookup) {
Index: clang-tools-extra/unittests/clangd/DexTests.cpp
===================================================================
--- clang-tools-extra/unittests/clangd/DexTests.cpp
+++ clang-tools-extra/unittests/clangd/DexTests.cpp
@@ -714,35 +714,30 @@
   SymbolSlab::Builder B;
 
   Symbol S = symbol("TempSpec");
-  S.ID = SymbolID("0");
   B.insert(S);
 
-  S = symbol("TempSpec");
-  S.ID = SymbolID("1");
+  S = symbol("TempSpec<int, bool>");
   S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
       index::SymbolProperty::TemplateSpecialization);
   B.insert(S);
 
-  S = symbol("TempSpec");
-  S.ID = SymbolID("2");
+  S = symbol("TempSpec<int, U>");
   S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
       index::SymbolProperty::TemplatePartialSpecialization);
   B.insert(S);
 
   auto I = dex::Dex::build(std::move(B).build(), RefSlab());
   FuzzyFindRequest Req;
-  Req.Query = "TempSpec";
   Req.AnyScope = true;
 
-  std::vector<Symbol> Symbols;
-  I->fuzzyFind(Req, [&Symbols](const Symbol &Sym) { Symbols.push_back(Sym); });
-  EXPECT_EQ(Symbols.size(), 1U);
-  EXPECT_FALSE(Symbols.front().SymInfo.Properties &
-               static_cast<index::SymbolPropertySet>(
-                   index::SymbolProperty::TemplateSpecialization));
-  EXPECT_FALSE(Symbols.front().SymInfo.Properties &
-               static_cast<index::SymbolPropertySet>(
-                   index::SymbolProperty::TemplatePartialSpecialization));
+  Req.Query = "TempSpec";
+  EXPECT_THAT(match(*I, Req),
+              UnorderedElementsAre("TempSpec", "TempSpec<int, bool>",
+                                   "TempSpec<int, U>"));
+
+  Req.Query = "TempSpec<int";
+  EXPECT_THAT(match(*I, Req),
+              UnorderedElementsAre("TempSpec<int, bool>", "TempSpec<int, U>"));
 }
 
 } // namespace
Index: clang-tools-extra/clangd/index/dex/Dex.cpp
===================================================================
--- clang-tools-extra/clangd/index/dex/Dex.cpp
+++ clang-tools-extra/clangd/index/dex/Dex.cpp
@@ -86,15 +86,6 @@
   llvm::DenseMap<Token, std::vector<DocID>> TempInvertedIndex;
   for (DocID SymbolRank = 0; SymbolRank < Symbols.size(); ++SymbolRank) {
     const auto *Sym = Symbols[SymbolRank];
-    // FIXME: Enable fuzzy find on template specializations once we start
-    // storing template arguments in the name. Currently we only store name for
-    // class template, which would cause duplication in the results.
-    if (Sym->SymInfo.Properties &
-        (static_cast<index::SymbolPropertySet>(
-             index::SymbolProperty::TemplateSpecialization) |
-         static_cast<index::SymbolPropertySet>(
-             index::SymbolProperty::TemplatePartialSpecialization)))
-      continue;
     for (const auto &Token : generateSearchTokens(*Sym))
       TempInvertedIndex[Token].push_back(SymbolRank);
   }
Index: clang-tools-extra/clangd/index/MemIndex.cpp
===================================================================
--- clang-tools-extra/clangd/index/MemIndex.cpp
+++ clang-tools-extra/clangd/index/MemIndex.cpp
@@ -38,15 +38,6 @@
   for (const auto Pair : Index) {
     const Symbol *Sym = Pair.second;
 
-    // FIXME: Enable fuzzy find on template specializations once we start
-    // storing template arguments in the name. Currently we only store name for
-    // class template, which would cause duplication in the results.
-    if (Sym->SymInfo.Properties &
-        (static_cast<index::SymbolPropertySet>(
-             index::SymbolProperty::TemplateSpecialization) |
-         static_cast<index::SymbolPropertySet>(
-             index::SymbolProperty::TemplatePartialSpecialization)))
-      continue;
     // Exact match against all possible scopes.
     if (!Req.AnyScope && !llvm::is_contained(Req.Scopes, Sym->Scope))
       continue;
Index: clang-tools-extra/clangd/AST.cpp
===================================================================
--- clang-tools-extra/clangd/AST.cpp
+++ clang-tools-extra/clangd/AST.cpp
@@ -11,9 +11,12 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ScopedPrinter.h"
 
@@ -50,6 +53,22 @@
   return SM.getSpellingLoc(D->getLocation());
 }
 
+static llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>>
+getTemplateSpecializationArgLocs(const NamedDecl &ND) {
+  if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) {
+    if (auto *Args = Func->getTemplateSpecializationArgsAsWritten())
+      return Args->arguments();
+  } else if (auto *Cls =
+                 llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) {
+    if (auto *Args = Cls->getTemplateArgsAsWritten())
+      return Args->arguments();
+  } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND))
+    return Var->getTemplateArgsInfo().arguments();
+  // We return None for ClassTemplateSpecializationDecls because it does not
+  // contain TemplateArgumentLoc information.
+  return llvm::None;
+}
+
 std::string printQualifiedName(const NamedDecl &ND) {
   std::string QName;
   llvm::raw_string_ostream OS(QName);
@@ -60,6 +79,18 @@
   // namespaces to query: the preamble doesn't have a dedicated list.
   Policy.SuppressUnwrittenScope = true;
   ND.printQualifiedName(OS, Policy);
+  if (auto Args = getTemplateSpecializationArgLocs(ND))
+    printTemplateArgumentList(OS, *Args, Policy);
+  else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
+    auto TL = Cls->getTypeAsWritten()->getTypeLoc();
+    if (auto STL = TL.getAs<TemplateSpecializationTypeLoc>()) {
+      llvm::SmallVector<TemplateArgumentLoc, 8> ArgLocs;
+      ArgLocs.reserve(STL.getNumArgs());
+      for (unsigned I = 0; I < STL.getNumArgs(); I++)
+        ArgLocs.push_back(STL.getArgLoc(I));
+      printTemplateArgumentList(OS, ArgLocs, Policy);
+    }
+  }
   OS.flush();
   assert(!StringRef(QName).startswith("::"));
   return QName;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to