ilya-biryukov created this revision.

https://reviews.llvm.org/D38731

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/ClangdUnit.cpp
  clangd/ClangdUnit.h
  unittests/clangd/ClangdTests.cpp

Index: unittests/clangd/ClangdTests.cpp
===================================================================
--- unittests/clangd/ClangdTests.cpp
+++ unittests/clangd/ClangdTests.cpp
@@ -135,6 +135,33 @@
 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 @@
     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 @@
   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 @@
   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 @@
   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 @@
                               "-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 @@
   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,22 +618,32 @@
 
 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) {
   MockFSProvider FS;
   ErrorCheckingDiagConsumer DiagConsumer;
   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,168 @@
   }
 }
 
+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();
+          }));
+    }
+    // FIXME(ibiryukov): test Opts.IncludeBriefComments and
+    // Opts.IncludeCodePatterns.
+  };
+
+  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 +954,7 @@
   {
     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 +1114,8 @@
   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 +1240,7 @@
       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();
Index: clangd/ClangdUnit.h
===================================================================
--- clangd/ClangdUnit.h
+++ clangd/ClangdUnit.h
@@ -251,13 +251,51 @@
   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.
+  /// Note that it
+  /// when many items have comments.
+  /// FIXME(ibiryukov): it looks like this option 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,
@@ -272,6 +310,7 @@
                                       clangd::Logger &Logger);
 
 /// For testing/debugging purposes. Note that this method deserializes all
+
 /// unserialized Decls, so use with care.
 void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
 
Index: clangd/ClangdUnit.cpp
===================================================================
--- clangd/ClangdUnit.cpp
+++ clangd/ClangdUnit.cpp
@@ -353,7 +353,7 @@
 
 class CompletionItemsCollector : public CodeCompleteConsumer {
 public:
-  CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+  CompletionItemsCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
                            std::vector<CompletionItem> &Items)
       : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
         Items(Items),
@@ -455,8 +455,9 @@
     : public CompletionItemsCollector {
 
 public:
-  PlainTextCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
-                                    std::vector<CompletionItem> &Items)
+  PlainTextCompletionItemsCollector(
+      const clang::CodeCompleteOptions &CodeCompleteOpts,
+      std::vector<CompletionItem> &Items)
       : CompletionItemsCollector(CodeCompleteOpts, Items) {}
 
 private:
@@ -491,8 +492,9 @@
 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:
@@ -601,7 +603,7 @@
 class SignatureHelpCollector final : public CodeCompleteConsumer {
 
 public:
-  SignatureHelpCollector(const CodeCompleteOptions &CodeCompleteOpts,
+  SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
                          SignatureHelp &SigHelp)
       : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
         SigHelp(SigHelp),
@@ -692,7 +694,8 @@
 }; // 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,
@@ -758,29 +761,51 @@
 
 } // 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;
 }
 
@@ -791,7 +816,7 @@
                       std::shared_ptr<PCHContainerOperations> PCHs,
                       clangd::Logger &Logger) {
   SignatureHelp Result;
-  CodeCompleteOptions Options;
+  clang::CodeCompleteOptions Options;
   Options.IncludeGlobals = false;
   Options.IncludeMacros = false;
   Options.IncludeCodePatterns = false;
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -209,7 +209,8 @@
   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.
@@ -252,6 +253,13 @@
                llvm::Optional<StringRef> OverridenContents = llvm::None,
                IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
 
+  /// A version of `codeComplete` that runs \p Callback on the processing thread
+  /// when codeComplete results become available.
+  void codeComplete(
+      UniqueFunction<void(Tagged<std::vector<CompletionItem>>)> Callback,
+      PathRef File, Position Pos,
+      llvm::Optional<StringRef> OverridenContents = llvm::None,
+      IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
   /// Provide signature help for \p File at \p Pos. If \p OverridenContents is
   /// not None, they will used only for signature help, i.e. no diagnostics
   /// update will be scheduled and a draft for \p File will not be updated. If
@@ -309,7 +317,7 @@
   // 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.
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -144,15 +144,15 @@
 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 @@
     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));
   });
 
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -220,7 +220,9 @@
                                  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");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to