[clang-tools-extra] r322097 - [clangd] Add more symbol information for code completion.

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 9 09:32:00 PST 2018


Author: ioeric
Date: Tue Jan  9 09:32:00 2018
New Revision: 322097

URL: http://llvm.org/viewvc/llvm-project?rev=322097&view=rev
Log:
[clangd] Add more symbol information for code completion.

Reviewers: hokein, sammccall

Reviewed By: sammccall

Subscribers: klimek, ilya-biryukov, cfe-commits

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

Modified:
    clang-tools-extra/trunk/clangd/ClangdUnit.cpp
    clang-tools-extra/trunk/clangd/ClangdUnit.h
    clang-tools-extra/trunk/clangd/CodeComplete.cpp
    clang-tools-extra/trunk/clangd/index/FileIndex.cpp
    clang-tools-extra/trunk/clangd/index/Index.cpp
    clang-tools-extra/trunk/clangd/index/Index.h
    clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp
    clang-tools-extra/trunk/clangd/index/SymbolCollector.h
    clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp
    clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
    clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp

Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Tue Jan  9 09:32:00 2018
@@ -316,6 +316,10 @@ const ASTContext &ParsedAST::getASTConte
 
 Preprocessor &ParsedAST::getPreprocessor() { return Clang->getPreprocessor(); }
 
+std::shared_ptr<Preprocessor> ParsedAST::getPreprocessorPtr() {
+  return Clang->getPreprocessorPtr();
+}
+
 const Preprocessor &ParsedAST::getPreprocessor() const {
   return Clang->getPreprocessor();
 }

Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h Tue Jan  9 09:32:00 2018
@@ -79,6 +79,7 @@ public:
   const ASTContext &getASTContext() const;
 
   Preprocessor &getPreprocessor();
+  std::shared_ptr<Preprocessor> getPreprocessorPtr();
   const Preprocessor &getPreprocessor() const;
 
   /// This function returns all top-level decls, including those that come

Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Tue Jan  9 09:32:00 2018
@@ -556,16 +556,19 @@ CompletionItem indexCompletionItem(const
   Item.kind = toCompletionItemKind(Sym.SymInfo.Kind);
   Item.label = Sym.Name;
   // FIXME(ioeric): support inserting/replacing scope qualifiers.
-  Item.insertText = Sym.Name;
+
   // FIXME(ioeric): support snippets.
+  Item.insertText = Sym.CompletionPlainInsertText;
   Item.insertTextFormat = InsertTextFormat::PlainText;
   Item.filterText = Sym.Name;
 
   // FIXME(ioeric): sort symbols appropriately.
   Item.sortText = "";
 
-  // FIXME(ioeric): use more symbol information (e.g. documentation, label) to
-  // populate the completion item.
+  if (Sym.Detail) {
+    Item.documentation = Sym.Detail->Documentation;
+    Item.detail = Sym.Detail->CompletionDetail;
+  }
 
   return Item;
 }

Modified: clang-tools-extra/trunk/clangd/index/FileIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/FileIndex.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/FileIndex.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/FileIndex.cpp Tue Jan  9 09:32:00 2018
@@ -17,8 +17,10 @@ namespace {
 
 /// Retrieves namespace and class level symbols in \p Decls.
 std::unique_ptr<SymbolSlab> indexAST(ASTContext &Ctx,
+                                     std::shared_ptr<Preprocessor> PP,
                                      llvm::ArrayRef<const Decl *> Decls) {
   auto Collector = std::make_shared<SymbolCollector>();
+  Collector->setPreprocessor(std::move(PP));
   index::IndexingOptions IndexOpts;
   IndexOpts.SystemSymbolFilter =
       index::IndexingOptions::SystemSymbolFilterKind::All;
@@ -67,7 +69,8 @@ void FileIndex::update(const Context &Ct
   if (!AST) {
     FSymbols.update(Path, nullptr);
   } else {
-    auto Slab = indexAST(AST->getASTContext(), AST->getTopLevelDecls());
+    auto Slab = indexAST(AST->getASTContext(), AST->getPreprocessorPtr(),
+                         AST->getTopLevelDecls());
     FSymbols.update(Path, std::move(Slab));
   }
   auto Symbols = FSymbols.allSymbols();

Modified: clang-tools-extra/trunk/clangd/index/Index.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Index.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Index.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/Index.cpp Tue Jan  9 09:32:00 2018
@@ -55,6 +55,23 @@ static void own(Symbol &S, DenseSet<Stri
   Intern(S.Name);
   Intern(S.Scope);
   Intern(S.CanonicalDeclaration.FilePath);
+
+  Intern(S.CompletionLabel);
+  Intern(S.CompletionFilterText);
+  Intern(S.CompletionPlainInsertText);
+  Intern(S.CompletionSnippetInsertText);
+
+  if (S.Detail) {
+    // Copy values of StringRefs into arena.
+    auto *Detail = Arena.Allocate<Symbol::Details>();
+    Detail->Documentation = S.Detail->Documentation;
+    Detail->CompletionDetail = S.Detail->CompletionDetail;
+    S.Detail = Detail;
+
+    // Intern the actual strings.
+    Intern(S.Detail->Documentation);
+    Intern(S.Detail->CompletionDetail);
+  }
 }
 
 void SymbolSlab::Builder::insert(const Symbol &S) {

Modified: clang-tools-extra/trunk/clangd/index/Index.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Index.h?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Index.h (original)
+++ clang-tools-extra/trunk/clangd/index/Index.h Tue Jan  9 09:32:00 2018
@@ -15,6 +15,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringExtras.h"
 #include <array>
 #include <string>
@@ -126,10 +127,39 @@ struct Symbol {
   //     (not a definition), which is usually declared in ".h" file.
   SymbolLocation CanonicalDeclaration;
 
+  /// A brief description of the symbol that can be displayed in the completion
+  /// candidate list. For example, "Foo(X x, Y y) const" is a labal for a
+  /// function.
+  llvm::StringRef CompletionLabel;
+  /// The piece of text that the user is expected to type to match the
+  /// code-completion string, typically a keyword or the name of a declarator or
+  /// macro.
+  llvm::StringRef CompletionFilterText;
+  /// What to insert when completing this symbol (plain text version).
+  llvm::StringRef CompletionPlainInsertText;
+  /// What to insert when completing this symbol (snippet version). This is
+  /// empty if it is the same as the plain insert text above.
+  llvm::StringRef CompletionSnippetInsertText;
+
+  /// Optional symbol details that are not required to be set. For example, an
+  /// index fuzzy match can return a large number of symbol candidates, and it
+  /// is preferable to send only core symbol information in the batched results
+  /// and have clients resolve full symbol information for a specific candidate
+  /// if needed.
+  struct Details {
+    // Documentation including comment for the symbol declaration.
+    llvm::StringRef Documentation;
+    // This is what goes into the LSP detail field in a completion item. For
+    // example, the result type of a function.
+    llvm::StringRef CompletionDetail;
+  };
+
+  // Optional details of the symbol.
+  Details *Detail = nullptr;
+
   // FIXME: add definition location of the symbol.
   // FIXME: add all occurrences support.
   // FIXME: add extra fields for index scoring signals.
-  // FIXME: add code completion information.
 };
 
 // An immutable symbol container that stores a set of symbols.

Modified: clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp Tue Jan  9 09:32:00 2018
@@ -8,8 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SymbolCollector.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
+#include "../CodeCompletionStrings.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Index/IndexSymbol.h"
@@ -56,7 +55,6 @@ std::string makeAbsolutePath(const Sourc
   return AbsolutePath.str();
 }
 
-// Split a qualified symbol name into scope and unqualified name, e.g. given
 // "a::b::c", return {"a::b", "c"}. Scope is empty if it doesn't exist.
 std::pair<llvm::StringRef, llvm::StringRef>
 splitQualifiedName(llvm::StringRef QName) {
@@ -69,6 +67,13 @@ splitQualifiedName(llvm::StringRef QName
 
 } // namespace
 
+void SymbolCollector::initialize(ASTContext &Ctx) {
+  ASTCtx = &Ctx;
+  CompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
+  CompletionTUInfo =
+      llvm::make_unique<CodeCompletionTUInfo>(CompletionAllocator);
+}
+
 // Always return true to continue indexing.
 bool SymbolCollector::handleDeclOccurence(
     const Decl *D, index::SymbolRoleSet Roles,
@@ -79,6 +84,8 @@ bool SymbolCollector::handleDeclOccurenc
         Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
     return true;
 
+  assert(CompletionAllocator && CompletionTUInfo);
+
   if (const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D)) {
     // FIXME: figure out a way to handle internal linkage symbols (e.g. static
     // variables, function) defined in the .cc files. Also we skip the symbols
@@ -113,6 +120,35 @@ bool SymbolCollector::handleDeclOccurenc
     S.Name = ScopeAndName.second;
     S.SymInfo = index::getSymbolInfo(D);
     S.CanonicalDeclaration = Location;
+
+    // Add completion info.
+    assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
+    CodeCompletionResult SymbolCompletion(ND, 0);
+    const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
+        *ASTCtx, *PP, CodeCompletionContext::CCC_Name, *CompletionAllocator,
+        *CompletionTUInfo,
+        /*IncludeBriefComments*/ true);
+    std::string Label;
+    std::string SnippetInsertText;
+    std::string IgnoredLabel;
+    std::string PlainInsertText;
+    getLabelAndInsertText(*CCS, &Label, &SnippetInsertText,
+                          /*EnableSnippets=*/true);
+    getLabelAndInsertText(*CCS, &IgnoredLabel, &PlainInsertText,
+                          /*EnableSnippets=*/false);
+    std::string FilterText = getFilterText(*CCS);
+    std::string Documentation = getDocumentation(*CCS);
+    std::string CompletionDetail = getDetail(*CCS);
+
+    S.CompletionFilterText = FilterText;
+    S.CompletionLabel = Label;
+    S.CompletionPlainInsertText = PlainInsertText;
+    S.CompletionSnippetInsertText = SnippetInsertText;
+    Symbol::Details Detail;
+    Detail.Documentation = Documentation;
+    Detail.CompletionDetail = CompletionDetail;
+    S.Detail = &Detail;
+
     Symbols.insert(S);
   }
 

Modified: clang-tools-extra/trunk/clangd/index/SymbolCollector.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/SymbolCollector.h?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/SymbolCollector.h (original)
+++ clang-tools-extra/trunk/clangd/index/SymbolCollector.h Tue Jan  9 09:32:00 2018
@@ -8,8 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "Index.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
 #include "clang/Index/IndexDataConsumer.h"
 #include "clang/Index/IndexSymbol.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
 
 namespace clang {
 namespace clangd {
@@ -21,7 +24,11 @@ namespace clangd {
 // changed.
 class SymbolCollector : public index::IndexDataConsumer {
 public:
-  SymbolCollector() = default;
+  void initialize(ASTContext &Ctx) override;
+
+  void setPreprocessor(std::shared_ptr<Preprocessor> PP) override {
+    this->PP = std::move(PP);
+  }
 
   bool
   handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
@@ -34,6 +41,10 @@ public:
 private:
   // All Symbols collected from the AST.
   SymbolSlab::Builder Symbols;
+  ASTContext *ASTCtx;
+  std::shared_ptr<Preprocessor> PP;
+  std::shared_ptr<GlobalCodeCompletionAllocator> CompletionAllocator;
+  std::unique_ptr<CodeCompletionTUInfo> CompletionTUInfo;
 };
 
 } // namespace clangd

Modified: clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp Tue Jan  9 09:32:00 2018
@@ -9,6 +9,7 @@
 
 #include "SymbolYAML.h"
 #include "Index.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/YAMLTraits.h"
@@ -59,15 +60,39 @@ template <> struct MappingTraits<SymbolI
   }
 };
 
-template<> struct MappingTraits<Symbol> {
+template <>
+struct MappingTraits<Symbol::Details *> {
+  static void mapping(IO &io, Symbol::Details *&Detail) {
+    if (!io.outputting()) {
+      assert(io.getContext() && "Expecting an arena (as context) to allocate "
+                                "data for new symbols.");
+      Detail = static_cast<llvm::BumpPtrAllocator *>(io.getContext())
+                   ->Allocate<Symbol::Details>();
+    } else if (!Detail) {
+      // Detail is optional in outputting.
+      return;
+    }
+    assert(Detail);
+    io.mapOptional("Documentation", Detail->Documentation);
+    io.mapOptional("CompletionDetail", Detail->CompletionDetail);
+  }
+};
+
+template <> struct MappingTraits<Symbol> {
   static void mapping(IO &IO, Symbol &Sym) {
-    MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(
-        IO, Sym.ID);
+    MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, Sym.ID);
     IO.mapRequired("ID", NSymbolID->HexString);
     IO.mapRequired("Name", Sym.Name);
     IO.mapRequired("Scope", Sym.Scope);
     IO.mapRequired("SymInfo", Sym.SymInfo);
     IO.mapRequired("CanonicalDeclaration", Sym.CanonicalDeclaration);
+    IO.mapRequired("CompletionLabel", Sym.CompletionLabel);
+    IO.mapRequired("CompletionFilterText", Sym.CompletionFilterText);
+    IO.mapRequired("CompletionPlainInsertText", Sym.CompletionPlainInsertText);
+
+    IO.mapOptional("CompletionSnippetInsertText",
+                   Sym.CompletionSnippetInsertText);
+    IO.mapOptional("Detail", Sym.Detail);
   }
 };
 
@@ -124,11 +149,14 @@ namespace clang {
 namespace clangd {
 
 SymbolSlab SymbolFromYAML(llvm::StringRef YAMLContent) {
+  // Store data of pointer fields (excl. `StringRef`) like `Detail`.
+  llvm::BumpPtrAllocator Arena;
+  llvm::yaml::Input Yin(YAMLContent, &Arena);
   std::vector<Symbol> S;
-  llvm::yaml::Input Yin(YAMLContent);
   Yin >> S;
+
   SymbolSlab::Builder Syms;
-  for (auto& Sym : S)
+  for (auto &Sym : S)
     Syms.insert(Sym);
   return std::move(Syms).build();
 }
@@ -138,7 +166,7 @@ std::string SymbolsToYAML(const SymbolSl
   llvm::raw_string_ostream OS(Str);
   llvm::yaml::Output Yout(OS);
   for (Symbol S : Symbols) // copy: Yout<< requires mutability.
-    Yout<< S;
+    Yout << S;
   return OS.str();
 }
 

Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Tue Jan  9 09:32:00 2018
@@ -68,6 +68,8 @@ MATCHER_P(Named, Name, "") { return arg.
 MATCHER_P(Labeled, Label, "") { return arg.label == Label; }
 MATCHER_P(Kind, K, "") { return arg.kind == K; }
 MATCHER_P(Filter, F, "") { return arg.filterText == F; }
+MATCHER_P(Doc, D, "") { return arg.documentation == D; }
+MATCHER_P(Detail, D, "") { return arg.detail == D; }
 MATCHER_P(PlainText, Text, "") {
   return arg.insertTextFormat == clangd::InsertTextFormat::PlainText &&
          arg.insertText == Text;
@@ -472,6 +474,7 @@ std::unique_ptr<SymbolIndex> simpleIndex
       Sym.Name = QName.substr(Pos + 2);
       Sym.Scope = QName.substr(0, Pos);
     }
+    Sym.CompletionPlainInsertText = Sym.Name;
     Sym.SymInfo.Kind = Pair.second;
     Slab.insert(Sym);
   }
@@ -561,13 +564,17 @@ TEST(CompletionTest, ASTIndexMultiFile)
 
   Server
       .addDocument(Context::empty(), getVirtualTestFilePath("foo.cpp"), R"cpp(
-      namespace ns { class XYZ {}; void foo() {} }
+      namespace ns { class XYZ {}; void foo(int x) {} }
   )cpp")
       .wait();
 
   auto File = getVirtualTestFilePath("bar.cpp");
   Annotations Test(R"cpp(
-      namespace ns { class XXX {}; void fooooo() {} }
+      namespace ns {
+      class XXX {};
+      /// Doooc
+      void fooooo() {}
+      }
       void f() { ns::^ }
   )cpp");
   Server.addDocument(Context::empty(), File, Test.code()).wait();
@@ -580,7 +587,9 @@ TEST(CompletionTest, ASTIndexMultiFile)
   EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
   EXPECT_THAT(Results.items, Has("foo", CompletionItemKind::Function));
   EXPECT_THAT(Results.items, Has("XXX", CompletionItemKind::Class));
-  EXPECT_THAT(Results.items, Has("fooooo", CompletionItemKind::Function));
+  EXPECT_THAT(Results.items, Contains(AllOf(Named("fooooo"), Filter("fooooo"),
+                                            Kind(CompletionItemKind::Function),
+                                            Doc("Doooc"), Detail("void"))));
 }
 
 } // namespace

Modified: clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp?rev=322097&r1=322096&r2=322097&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp Tue Jan  9 09:32:00 2018
@@ -9,7 +9,6 @@
 
 #include "index/SymbolCollector.h"
 #include "index/SymbolYAML.h"
-#include "clang/Index/IndexingAction.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/FileSystemOptions.h"
 #include "clang/Basic/VirtualFileSystem.h"
@@ -26,12 +25,24 @@
 #include <memory>
 #include <string>
 
+using testing::AllOf;
 using testing::Eq;
 using testing::Field;
+using testing::Not;
 using testing::UnorderedElementsAre;
 using testing::UnorderedElementsAreArray;
 
 // GMock helpers for matching Symbol.
+MATCHER_P(Labeled, Label, "") { return arg.CompletionLabel == Label; }
+MATCHER(HasDetail, "") { return arg.Detail; }
+MATCHER_P(Detail, D, "") {
+  return arg.Detail && arg.Detail->CompletionDetail == D;
+}
+MATCHER_P(Doc, D, "") { return arg.Detail && arg.Detail->Documentation == D; }
+MATCHER_P(Plain, Text, "") { return arg.CompletionPlainInsertText == Text; }
+MATCHER_P(Snippet, S, "") {
+  return arg.CompletionSnippetInsertText == S;
+}
 MATCHER_P(QName, Name, "") {
   return (arg.Scope + (arg.Scope.empty() ? "" : "::") + arg.Name).str() == Name;
 }
@@ -147,6 +158,38 @@ TEST_F(SymbolCollectorTest, CollectSymbo
                    QName("foo::baz")}));
 }
 
+TEST_F(SymbolCollectorTest, SymbolWithDocumentation) {
+  const std::string Main = R"(
+    namespace nx {
+    /// Foo comment.
+    int ff(int x, double y) { return 0; }
+    }
+  )";
+  runSymbolCollector(/*Header=*/"", Main);
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(QName("nx"),
+                                   AllOf(QName("nx::ff"),
+                                         Labeled("ff(int x, double y)"),
+                                         Detail("int"), Doc("Foo comment."))));
+}
+
+TEST_F(SymbolCollectorTest, PlainAndSnippet) {
+  const std::string Main = R"(
+    namespace nx {
+    void f() {}
+    int ff(int x, double y) { return 0; }
+    }
+  )";
+  runSymbolCollector(/*Header=*/"", Main);
+  EXPECT_THAT(
+      Symbols,
+      UnorderedElementsAre(
+          QName("nx"),
+          AllOf(QName("nx::f"), Labeled("f()"), Plain("f"), Snippet("f()")),
+          AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"), Plain("ff"),
+                Snippet("ff(${1:int x}, ${2:double y})"))));
+}
+
 TEST_F(SymbolCollectorTest, YAMLConversions) {
   const std::string YAML1 = R"(
 ---
@@ -160,6 +203,12 @@ CanonicalDeclaration:
   StartOffset:     0
   EndOffset:       1
   FilePath:        /path/foo.h
+CompletionLabel:    'Foo1-label'
+CompletionFilterText:    'filter'
+CompletionPlainInsertText:    'plain'
+Detail:
+  Documentation:    'Foo doc'
+  CompletionDetail:    'int'
 ...
 )";
   const std::string YAML2 = R"(
@@ -174,15 +223,21 @@ CanonicalDeclaration:
   StartOffset:     10
   EndOffset:       12
   FilePath:        /path/foo.h
+CompletionLabel:    'Foo2-label'
+CompletionFilterText:    'filter'
+CompletionPlainInsertText:    'plain'
+CompletionSnippetInsertText:    'snippet'
 ...
 )";
 
   auto Symbols1 = SymbolFromYAML(YAML1);
-  EXPECT_THAT(Symbols1,
-              UnorderedElementsAre(QName("clang::Foo1")));
+  EXPECT_THAT(Symbols1, UnorderedElementsAre(
+                            AllOf(QName("clang::Foo1"), Labeled("Foo1-label"),
+                                  Doc("Foo doc"), Detail("int"))));
   auto Symbols2 = SymbolFromYAML(YAML2);
-  EXPECT_THAT(Symbols2,
-              UnorderedElementsAre(QName("clang::Foo2")));
+  EXPECT_THAT(Symbols2, UnorderedElementsAre(AllOf(QName("clang::Foo2"),
+                                                   Labeled("Foo2-label"),
+                                                   Not(HasDetail()))));
 
   std::string ConcatenatedYAML =
       SymbolsToYAML(Symbols1) + SymbolsToYAML(Symbols2);




More information about the cfe-commits mailing list