[clang-tools-extra] r316327 - [clangd] Allow to pass code completion opts to ClangdServer.

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 23 07:46:48 PDT 2017


Author: ibiryukov
Date: Mon Oct 23 07:46:48 2017
New Revision: 316327

URL: http://llvm.org/viewvc/llvm-project?rev=316327&view=rev
Log:
[clangd] Allow to pass code completion opts to ClangdServer.

Reviewers: bkramer, krasimir, sammccall

Reviewed By: krasimir

Subscribers: klimek, cfe-commits

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

Modified:
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
    clang-tools-extra/trunk/clangd/ClangdServer.cpp
    clang-tools-extra/trunk/clangd/ClangdServer.h
    clang-tools-extra/trunk/clangd/ClangdUnit.cpp
    clang-tools-extra/trunk/clangd/ClangdUnit.h
    clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=316327&r1=316326&r2=316327&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Mon Oct 23 07:46:48 2017
@@ -193,7 +193,9 @@ ClangdLSPServer::ClangdLSPServer(JSONOut
                                  llvm::Optional<Path> CompileCommandsDir)
     : Out(Out), CDB(/*Logger=*/Out, std::move(CompileCommandsDir)),
       Server(CDB, /*DiagConsumer=*/*this, FSProvider, AsyncThreadsCount,
-             SnippetCompletions, /*Logger=*/Out, ResourceDir) {}
+             clangd::CodeCompleteOptions(
+                 /*EnableSnippetsAndCodePatterns=*/SnippetCompletions),
+             /*Logger=*/Out, ResourceDir) {}
 
 void ClangdLSPServer::run(std::istream &In) {
   assert(!IsDone && "Run was called before");

Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=316327&r1=316326&r2=316327&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Mon Oct 23 07:46:48 2017
@@ -144,15 +144,15 @@ ClangdScheduler::~ClangdScheduler() {
 ClangdServer::ClangdServer(GlobalCompilationDatabase &CDB,
                            DiagnosticsConsumer &DiagConsumer,
                            FileSystemProvider &FSProvider,
-                           unsigned AsyncThreadsCount, bool SnippetCompletions,
+                           unsigned AsyncThreadsCount,
+                           clangd::CodeCompleteOptions CodeCompleteOpts,
                            clangd::Logger &Logger,
                            llvm::Optional<StringRef> ResourceDir)
     : Logger(Logger), CDB(CDB), DiagConsumer(DiagConsumer),
       FSProvider(FSProvider),
       ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()),
       PCHs(std::make_shared<PCHContainerOperations>()),
-      SnippetCompletions(SnippetCompletions), WorkScheduler(AsyncThreadsCount) {
-}
+      CodeCompleteOpts(CodeCompleteOpts), WorkScheduler(AsyncThreadsCount) {}
 
 void ClangdServer::setRootPath(PathRef RootPath) {
   std::string NewRootPath = llvm::sys::path::convert_to_slash(
@@ -237,7 +237,7 @@ ClangdServer::codeComplete(PathRef File,
     std::vector<CompletionItem> Result = clangd::codeComplete(
         File, Resources->getCompileCommand(),
         Preamble ? &Preamble->Preamble : nullptr, Contents, Pos, TaggedFS.Value,
-        PCHs, SnippetCompletions, Logger);
+        PCHs, CodeCompleteOpts, Logger);
     return make_tagged(std::move(Result), std::move(TaggedFS.Tag));
   });
 

Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=316327&r1=316326&r2=316327&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.h Mon Oct 23 07:46:48 2017
@@ -209,7 +209,8 @@ public:
   ClangdServer(GlobalCompilationDatabase &CDB,
                DiagnosticsConsumer &DiagConsumer,
                FileSystemProvider &FSProvider, unsigned AsyncThreadsCount,
-               bool SnippetCompletions, clangd::Logger &Logger,
+               clangd::CodeCompleteOptions CodeCompleteOpts,
+               clangd::Logger &Logger,
                llvm::Optional<StringRef> ResourceDir = llvm::None);
 
   /// Set the root path of the workspace.
@@ -309,7 +310,7 @@ private:
   // If set, this represents the workspace path.
   llvm::Optional<std::string> RootPath;
   std::shared_ptr<PCHContainerOperations> PCHs;
-  bool SnippetCompletions;
+  clangd::CodeCompleteOptions CodeCompleteOpts;
   /// Used to serialize diagnostic callbacks.
   /// FIXME(ibiryukov): get rid of an extra map and put all version counters
   /// into CppFile.

Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=316327&r1=316326&r2=316327&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Mon Oct 23 07:46:48 2017
@@ -369,7 +369,7 @@ std::string getDocumentation(const CodeC
 
 class CompletionItemsCollector : public CodeCompleteConsumer {
 public:
-  CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+  CompletionItemsCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
                            std::vector<CompletionItem> &Items)
       : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
         Items(Items),
@@ -471,8 +471,9 @@ class PlainTextCompletionItemsCollector
     : public CompletionItemsCollector {
 
 public:
-  PlainTextCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
-                                    std::vector<CompletionItem> &Items)
+  PlainTextCompletionItemsCollector(
+      const clang::CodeCompleteOptions &CodeCompleteOpts,
+      std::vector<CompletionItem> &Items)
       : CompletionItemsCollector(CodeCompleteOpts, Items) {}
 
 private:
@@ -507,8 +508,9 @@ private:
 class SnippetCompletionItemsCollector final : public CompletionItemsCollector {
 
 public:
-  SnippetCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
-                                  std::vector<CompletionItem> &Items)
+  SnippetCompletionItemsCollector(
+      const clang::CodeCompleteOptions &CodeCompleteOpts,
+      std::vector<CompletionItem> &Items)
       : CompletionItemsCollector(CodeCompleteOpts, Items) {}
 
 private:
@@ -617,7 +619,7 @@ private:
 class SignatureHelpCollector final : public CodeCompleteConsumer {
 
 public:
-  SignatureHelpCollector(const CodeCompleteOptions &CodeCompleteOpts,
+  SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
                          SignatureHelp &SigHelp)
       : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
         SigHelp(SigHelp),
@@ -708,7 +710,8 @@ private:
 }; // SignatureHelpCollector
 
 bool invokeCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
-                        const CodeCompleteOptions &Options, PathRef FileName,
+                        const clang::CodeCompleteOptions &Options,
+                        PathRef FileName,
                         const tooling::CompileCommand &Command,
                         PrecompiledPreamble const *Preamble, StringRef Contents,
                         Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
@@ -774,29 +777,51 @@ bool invokeCodeComplete(std::unique_ptr<
 
 } // namespace
 
+clangd::CodeCompleteOptions::CodeCompleteOptions(
+    bool EnableSnippetsAndCodePatterns)
+    : CodeCompleteOptions() {
+  EnableSnippets = EnableSnippetsAndCodePatterns;
+  IncludeCodePatterns = EnableSnippetsAndCodePatterns;
+}
+
+clangd::CodeCompleteOptions::CodeCompleteOptions(bool EnableSnippets,
+                                                 bool IncludeCodePatterns,
+                                                 bool IncludeMacros,
+                                                 bool IncludeGlobals,
+                                                 bool IncludeBriefComments)
+    : EnableSnippets(EnableSnippets), IncludeCodePatterns(IncludeCodePatterns),
+      IncludeMacros(IncludeMacros), IncludeGlobals(IncludeGlobals),
+      IncludeBriefComments(IncludeBriefComments) {}
+
+clang::CodeCompleteOptions clangd::CodeCompleteOptions::getClangCompleteOpts() {
+  clang::CodeCompleteOptions Result;
+  Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
+  Result.IncludeMacros = IncludeMacros;
+  Result.IncludeGlobals = IncludeGlobals;
+  Result.IncludeBriefComments = IncludeBriefComments;
+
+  return Result;
+}
+
 std::vector<CompletionItem>
 clangd::codeComplete(PathRef FileName, tooling::CompileCommand Command,
                      PrecompiledPreamble const *Preamble, StringRef Contents,
                      Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
                      std::shared_ptr<PCHContainerOperations> PCHs,
-                     bool SnippetCompletions, clangd::Logger &Logger) {
+                     clangd::CodeCompleteOptions Opts, clangd::Logger &Logger) {
   std::vector<CompletionItem> Results;
-  CodeCompleteOptions Options;
   std::unique_ptr<CodeCompleteConsumer> Consumer;
-  Options.IncludeGlobals = true;
-  Options.IncludeMacros = true;
-  Options.IncludeBriefComments = true;
-  if (SnippetCompletions) {
-    Options.IncludeCodePatterns = true;
-    Consumer =
-        llvm::make_unique<SnippetCompletionItemsCollector>(Options, Results);
+  clang::CodeCompleteOptions ClangCompleteOpts = Opts.getClangCompleteOpts();
+  if (Opts.EnableSnippets) {
+    Consumer = llvm::make_unique<SnippetCompletionItemsCollector>(
+        ClangCompleteOpts, Results);
   } else {
-    Options.IncludeCodePatterns = false;
-    Consumer =
-        llvm::make_unique<PlainTextCompletionItemsCollector>(Options, Results);
+    Consumer = llvm::make_unique<PlainTextCompletionItemsCollector>(
+        ClangCompleteOpts, Results);
   }
-  invokeCodeComplete(std::move(Consumer), Options, FileName, Command, Preamble,
-                     Contents, Pos, std::move(VFS), std::move(PCHs), Logger);
+  invokeCodeComplete(std::move(Consumer), ClangCompleteOpts, FileName, Command,
+                     Preamble, Contents, Pos, std::move(VFS), std::move(PCHs),
+                     Logger);
   return Results;
 }
 
@@ -807,7 +832,7 @@ clangd::signatureHelp(PathRef FileName,
                       std::shared_ptr<PCHContainerOperations> PCHs,
                       clangd::Logger &Logger) {
   SignatureHelp Result;
-  CodeCompleteOptions Options;
+  clang::CodeCompleteOptions Options;
   Options.IncludeGlobals = false;
   Options.IncludeMacros = false;
   Options.IncludeCodePatterns = false;

Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=316327&r1=316326&r2=316327&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h Mon Oct 23 07:46:48 2017
@@ -251,13 +251,49 @@ private:
   clangd::Logger &Logger;
 };
 
+struct CodeCompleteOptions {
+  CodeCompleteOptions() = default;
+
+  /// Uses default values for all flags, but sets EnableSnippets and
+  /// IncludeCodePatterns to the value of EnableSnippetsAndCodePatterns.
+  explicit CodeCompleteOptions(bool EnableSnippetsAndCodePatterns);
+
+  CodeCompleteOptions(bool EnableSnippets, bool IncludeCodePatterns,
+                      bool IncludeMacros, bool IncludeGlobals,
+                      bool IncludeBriefComments);
+
+  /// Returns options that can be passed to clang's completion engine.
+  clang::CodeCompleteOptions getClangCompleteOpts();
+
+  /// When true, completion items will contain expandable code snippets in
+  /// completion (e.g.  `return ${1:expression}` or `foo(${1:int a}, ${2:int
+  /// b})).
+  bool EnableSnippets = false;
+
+  /// Add code patterns to completion results.
+  /// If EnableSnippets is false, this options is ignored and code patterns will
+  /// always be omitted.
+  bool IncludeCodePatterns = false;
+
+  /// Add macros to code completion results.
+  bool IncludeMacros = true;
+
+  /// Add globals to code completion results.
+  bool IncludeGlobals = true;
+
+  /// Add brief comments to completion items, if available.
+  /// FIXME(ibiryukov): it looks like turning this option on significantly slows
+  /// down completion, investigate if it can be made faster.
+  bool IncludeBriefComments = true;
+};
+
 /// Get code completions at a specified \p Pos in \p FileName.
 std::vector<CompletionItem>
 codeComplete(PathRef FileName, tooling::CompileCommand Command,
              PrecompiledPreamble const *Preamble, StringRef Contents,
              Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
              std::shared_ptr<PCHContainerOperations> PCHs,
-             bool SnippetCompletions, clangd::Logger &Logger);
+             clangd::CodeCompleteOptions Opts, clangd::Logger &Logger);
 
 /// Get signature help at a specified \p Pos in \p FileName.
 SignatureHelp signatureHelp(PathRef FileName, tooling::CompileCommand Command,

Modified: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=316327&r1=316326&r2=316327&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Mon Oct 23 07:46:48 2017
@@ -135,6 +135,33 @@ IntrusiveRefCntPtr<vfs::FileSystem> getT
 namespace clangd {
 namespace {
 
+struct StringWithPos {
+  std::string Text;
+  clangd::Position MarkerPos;
+};
+
+/// Returns location of "{mark}" substring in \p Text and removes it from \p
+/// Text. Note that \p Text must contain exactly one occurence of "{mark}".
+///
+/// Marker name can be configured using \p MarkerName parameter.
+StringWithPos parseTextMarker(StringRef Text, StringRef MarkerName = "mark") {
+  SmallString<16> Marker;
+  Twine("{" + MarkerName + "}").toVector(/*ref*/ Marker);
+
+  std::size_t MarkerOffset = Text.find(Marker);
+  assert(MarkerOffset != StringRef::npos && "{mark} wasn't found in Text.");
+
+  std::string WithoutMarker;
+  WithoutMarker += Text.take_front(MarkerOffset);
+  WithoutMarker += Text.drop_front(MarkerOffset + Marker.size());
+  assert(StringRef(WithoutMarker).find(Marker) == StringRef::npos &&
+         "There were multiple occurences of {mark} inside Text");
+
+  clangd::Position MarkerPos =
+      clangd::offsetToPosition(WithoutMarker, MarkerOffset);
+  return {std::move(WithoutMarker), MarkerPos};
+}
+
 // Don't wait for async ops in clangd test more than that to avoid blocking
 // indefinitely in case of bugs.
 static const std::chrono::seconds DefaultFutureTimeout =
@@ -305,7 +332,7 @@ protected:
     ErrorCheckingDiagConsumer DiagConsumer;
     MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
     ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                        /*SnippetCompletions=*/false,
+                        clangd::CodeCompleteOptions(),
                         EmptyLogger::getInstance());
     for (const auto &FileWithContents : ExtraFiles)
       FS.Files[getVirtualTestFilePath(FileWithContents.first)] =
@@ -369,7 +396,8 @@ TEST_F(ClangdVFSTest, Reparse) {
   ErrorCheckingDiagConsumer DiagConsumer;
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
   ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
+                      clangd::CodeCompleteOptions(),
+                      EmptyLogger::getInstance());
 
   const auto SourceContents = R"cpp(
 #include "foo.h"
@@ -414,7 +442,8 @@ TEST_F(ClangdVFSTest, ReparseOnHeaderCha
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
 
   ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
+                      clangd::CodeCompleteOptions(),
+                      EmptyLogger::getInstance());
 
   const auto SourceContents = R"cpp(
 #include "foo.h"
@@ -461,7 +490,7 @@ TEST_F(ClangdVFSTest, CheckVersions) {
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
   // Run ClangdServer synchronously.
   ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      /*AsyncThreadsCount=*/0, clangd::CodeCompleteOptions(),
                       EmptyLogger::getInstance());
 
   auto FooCpp = getVirtualTestFilePath("foo.cpp");
@@ -495,7 +524,7 @@ TEST_F(ClangdVFSTest, SearchLibDir) {
                               "-stdlib=libstdc++"});
   // Run ClangdServer synchronously.
   ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      /*AsyncThreadsCount=*/0, clangd::CodeCompleteOptions(),
                       EmptyLogger::getInstance());
 
   // Just a random gcc version string
@@ -544,7 +573,7 @@ TEST_F(ClangdVFSTest, ForceReparseCompil
   ErrorCheckingDiagConsumer DiagConsumer;
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
   ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      /*AsyncThreadsCount=*/0, clangd::CodeCompleteOptions(),
                       EmptyLogger::getInstance());
   // No need to sync reparses, because reparses are performed on the calling
   // thread to true.
@@ -589,13 +618,22 @@ struct bar { T x; };
 
 class ClangdCompletionTest : public ClangdVFSTest {
 protected:
-  bool ContainsItem(std::vector<CompletionItem> const &Items, StringRef Name) {
+  template <class Predicate>
+  bool ContainsItemPred(std::vector<CompletionItem> const &Items,
+                        Predicate Pred) {
     for (const auto &Item : Items) {
-      if (Item.insertText == Name)
+      if (Pred(Item))
         return true;
     }
     return false;
   }
+
+  bool ContainsItem(std::vector<CompletionItem> const &Items, StringRef Name) {
+    return ContainsItemPred(Items, [Name](clangd::CompletionItem Item) {
+      return Item.insertText == Name;
+    });
+    return false;
+  }
 };
 
 TEST_F(ClangdCompletionTest, CheckContentsOverride) {
@@ -604,7 +642,8 @@ TEST_F(ClangdCompletionTest, CheckConten
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
 
   ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
+                      clangd::CodeCompleteOptions(),
+                      EmptyLogger::getInstance());
 
   auto FooCpp = getVirtualTestFilePath("foo.cpp");
   const auto SourceContents = R"cpp(
@@ -655,6 +694,166 @@ int b =   ;
   }
 }
 
+TEST_F(ClangdCompletionTest, CompletionOptions) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+  CDB.ExtraClangFlags.push_back("-xc++");
+
+  auto FooCpp = getVirtualTestFilePath("foo.cpp");
+  FS.Files[FooCpp] = "";
+  FS.ExpectedFile = FooCpp;
+
+  const auto GlobalCompletionSourceTemplate = R"cpp(
+#define MACRO X
+
+int global_var;
+int global_func();
+
+struct GlobalClass {};
+
+struct ClassWithMembers {
+  /// Doc for method.
+  int method();
+};
+
+int test() {
+  struct LocalClass {};
+
+  /// Doc for local_var.
+  int local_var;
+
+  {complete}
+}
+)cpp";
+  const auto MemberCompletionSourceTemplate = R"cpp(
+#define MACRO X
+
+int global_var;
+
+int global_func();
+
+struct GlobalClass {};
+
+struct ClassWithMembers {
+  /// Doc for method.
+  int method();
+
+  int field;
+};
+
+int test() {
+  struct LocalClass {};
+
+  /// Doc for local_var.
+  int local_var;
+
+  ClassWithMembers().{complete}
+}
+)cpp";
+
+  StringWithPos GlobalCompletion =
+      parseTextMarker(GlobalCompletionSourceTemplate, "complete");
+  StringWithPos MemberCompletion =
+      parseTextMarker(MemberCompletionSourceTemplate, "complete");
+
+  auto TestWithOpts = [&](clangd::CodeCompleteOptions Opts) {
+    ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                        Opts, EmptyLogger::getInstance());
+    // No need to sync reparses here as there are no asserts on diagnostics (or
+    // other async operations).
+    Server.addDocument(FooCpp, GlobalCompletion.Text);
+
+    StringRef MethodItemText = Opts.EnableSnippets ? "method()" : "method";
+    StringRef GlobalFuncItemText =
+        Opts.EnableSnippets ? "global_func()" : "global_func";
+
+    /// For after-dot completion we must always get consistent results.
+    {
+      auto Results = Server
+                         .codeComplete(FooCpp, MemberCompletion.MarkerPos,
+                                       StringRef(MemberCompletion.Text))
+                         .get()
+                         .Value;
+
+      // Class members. The only items that must be present in after-dor
+      // completion.
+      EXPECT_TRUE(ContainsItem(Results, MethodItemText));
+      EXPECT_TRUE(ContainsItem(Results, "field"));
+      // Global items.
+      EXPECT_FALSE(ContainsItem(Results, "global_var"));
+      EXPECT_FALSE(ContainsItem(Results, GlobalFuncItemText));
+      EXPECT_FALSE(ContainsItem(Results, "GlobalClass"));
+      // A macro.
+      EXPECT_FALSE(ContainsItem(Results, "MACRO"));
+      // Local items.
+      EXPECT_FALSE(ContainsItem(Results, "LocalClass"));
+      // There should be no code patterns (aka snippets) in after-dot
+      // completion. At least there aren't any we're aware of.
+      EXPECT_FALSE(
+          ContainsItemPred(Results, [](clangd::CompletionItem const &Item) {
+            return Item.kind == clangd::CompletionItemKind::Snippet;
+          }));
+      // Check documentation.
+      EXPECT_EQ(
+          Opts.IncludeBriefComments,
+          ContainsItemPred(Results, [](clangd::CompletionItem const &Item) {
+            return !Item.documentation.empty();
+          }));
+    }
+    // Global completion differs based on the Opts that were passed.
+    {
+      auto Results = Server
+                         .codeComplete(FooCpp, GlobalCompletion.MarkerPos,
+                                       StringRef(GlobalCompletion.Text))
+                         .get()
+                         .Value;
+
+      // Class members. Should never be present in global completions.
+      EXPECT_FALSE(ContainsItem(Results, MethodItemText));
+      EXPECT_FALSE(ContainsItem(Results, "field"));
+      // Global items.
+      EXPECT_EQ(ContainsItem(Results, "global_var"), Opts.IncludeGlobals);
+      EXPECT_EQ(ContainsItem(Results, GlobalFuncItemText), Opts.IncludeGlobals);
+      EXPECT_EQ(ContainsItem(Results, "GlobalClass"), Opts.IncludeGlobals);
+      // A macro.
+      EXPECT_EQ(ContainsItem(Results, "MACRO"), Opts.IncludeMacros);
+      // Local items. Must be present always.
+      EXPECT_TRUE(ContainsItem(Results, "local_var"));
+      EXPECT_TRUE(ContainsItem(Results, "LocalClass"));
+      // FIXME(ibiryukov): snippets have wrong Item.kind now. Reenable this
+      // check after https://reviews.llvm.org/D38720 makes it in.
+      //
+      // Code patterns (aka snippets).
+      // EXPECT_EQ(
+      //     Opts.IncludeCodePatterns && Opts.EnableSnippets,
+      //     ContainsItemPred(Results, [](clangd::CompletionItem const &Item) {
+      //       return Item.kind == clangd::CompletionItemKind::Snippet;
+      //     }));
+
+      // Check documentation.
+      EXPECT_EQ(
+          Opts.IncludeBriefComments,
+          ContainsItemPred(Results, [](clangd::CompletionItem const &Item) {
+            return !Item.documentation.empty();
+          }));
+    }
+  };
+
+  for (bool IncludeMacros : {true, false})
+    for (bool IncludeGlobals : {true, false})
+      for (bool IncludeBriefComments : {true, false})
+        for (bool EnableSnippets : {true, false})
+          for (bool IncludeCodePatterns : {true, false}) {
+            TestWithOpts(clangd::CodeCompleteOptions(
+                /*EnableSnippets=*/EnableSnippets,
+                /*IncludeCodePatterns=*/IncludeCodePatterns,
+                /*IncludeMacros=*/IncludeMacros,
+                /*IncludeGlobals=*/IncludeGlobals,
+                /*IncludeBriefComments=*/IncludeBriefComments));
+          }
+}
+
 class ClangdThreadingTest : public ClangdVFSTest {};
 
 TEST_F(ClangdThreadingTest, StressTest) {
@@ -753,7 +952,7 @@ int d;
   {
     MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
     ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                        /*SnippetCompletions=*/false,
+                        clangd::CodeCompleteOptions(),
                         EmptyLogger::getInstance());
 
     // Prepare some random distributions for the test.
@@ -913,7 +1112,8 @@ TEST_F(ClangdVFSTest, CheckSourceHeaderS
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
 
   ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
+                      clangd::CodeCompleteOptions(),
+                      EmptyLogger::getInstance());
 
   auto SourceContents = R"cpp(
   #include "foo.h"
@@ -1038,7 +1238,7 @@ int d;
       std::move(StartSecondReparsePromise));
 
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
-  ClangdServer Server(CDB, DiagConsumer, FS, 4, /*SnippetCompletions=*/false,
+  ClangdServer Server(CDB, DiagConsumer, FS, 4, clangd::CodeCompleteOptions(),
                       EmptyLogger::getInstance());
   Server.addDocument(FooCpp, SourceContentsWithErrors);
   StartSecondReparse.wait();




More information about the cfe-commits mailing list