<div dir="ltr"><div><div>Also at least one more builder is affected:<br><a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/13517">http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/13517</a><br><br></div>Thanks<br><br></div>Galina<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 15, 2017 at 10:54 AM, Galina Kistanova <span dir="ltr"><<a href="mailto:gkistanova@gmail.com" target="_blank">gkistanova@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div>Hello Sam,<br><br></div>One of tests is failing on<br><a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/20638" target="_blank">http://lab.llvm.org:8011/<wbr>builders/llvm-clang-lld-x86_<wbr>64-scei-ps4-ubuntu-fast/<wbr>builds/20638</a></div><div><br></div><div>Please have a look?<br><br>Thanks<br><br>Galina<br><br></div>...<br><pre><span class="m_7010653508708904817gmail-stdout">Failing Tests (1):
    Clang Tools :: clangd/completion.test</span></pre></div></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 15, 2017 at 1:16 AM, Sam McCall via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: sammccall<br>
Date: Wed Nov 15 01:16:29 2017<br>
New Revision: 318287<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=318287&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=318287&view=rev</a><br>
Log:<br>
[clangd] Support returning a limited number of completion results.<br>
<br>
Summary:<br>
All results are scored, we only process CodeCompletionStrings for the winners.<br>
We now return CompletionList rather than CompletionItem[] (both are valid).<br>
sortText is now based on CodeCompletionResult::orderedN<wbr>ame (mostly the same).<br>
<br>
This is the first clangd-only completion option, so plumbing changed.<br>
It requires a small clangd patch (exposing CodeCompletionResult::orderedN<wbr>ame).<br>
<br>
(This can't usefully be enabled yet: we don't support server-side filtering)<br>
<br>
Reviewers: ilya-biryukov<br>
<br>
Subscribers: cfe-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D39852" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3985<wbr>2</a><br>
<br>
Modified:<br>
    clang-tools-extra/trunk/clangd<wbr>/ClangdLSPServer.cpp<br>
    clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp<br>
    clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h<br>
    clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.cpp<br>
    clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.h<br>
    clang-tools-extra/trunk/clangd<wbr>/Protocol.cpp<br>
    clang-tools-extra/trunk/clangd<wbr>/Protocol.h<br>
    clang-tools-extra/trunk/test/c<wbr>langd/authority-less-uri.test<br>
    clang-tools-extra/trunk/test/c<wbr>langd/completion-items-kinds.t<wbr>est<br>
    clang-tools-extra/trunk/test/c<wbr>langd/completion-priorities.te<wbr>st<br>
    clang-tools-extra/trunk/test/c<wbr>langd/completion-qualifiers.te<wbr>st<br>
    clang-tools-extra/trunk/test/c<wbr>langd/completion-snippet.test<br>
    clang-tools-extra/trunk/test/c<wbr>langd/completion.test<br>
    clang-tools-extra/trunk/test/c<wbr>langd/protocol.test<br>
    clang-tools-extra/trunk/unitte<wbr>sts/clangd/ClangdTests.cpp<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/ClangdLSPServer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/ClangdLSPServer.cpp?<wbr>rev=318287&r1=318286&r2=318287<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/ClangdLSPServer.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/ClangdLSPServer.cpp Wed Nov 15 01:16:29 2017<br>
@@ -195,15 +195,15 @@ void ClangdLSPServer::onCodeAction(<wbr>Ctx C<br>
 }<br>
<br>
 void ClangdLSPServer::onCompletion(<wbr>Ctx C, TextDocumentPositionParams &Params) {<br>
-  auto Items = Server<br>
-                   .codeComplete(Params.textDocu<wbr>ment.uri.file,<br>
-                                 Position{Params.position.<wbr>line,<br>
-                                          Params.position.character})<br>
-                   .get() // FIXME(ibiryukov): This could be made async if we<br>
-                          // had an API that would allow to attach callbacks to<br>
-                          // futures returned by ClangdServer.<br>
-                   .Value;<br>
-  C.reply(json::ary(Items));<br>
+  auto List = Server<br>
+                  .codeComplete(<br>
+                      Params.textDocument.uri.file,<br>
+                      Position{Params.position.line, Params.position.character})<br>
+                  .get() // FIXME(ibiryukov): This could be made async if we<br>
+                         // had an API that would allow to attach callbacks to<br>
+                         // futures returned by ClangdServer.<br>
+                  .Value;<br>
+  C.reply(List);<br>
 }<br>
<br>
 void ClangdLSPServer::onSignatureHe<wbr>lp(Ctx C,<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp?rev=<wbr>318287&r1=318286&r2=318287&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp Wed Nov 15 01:16:29 2017<br>
@@ -222,11 +222,11 @@ std::future<void> ClangdServer::forceRep<br>
                                  std::move(TaggedFS));<br>
 }<br>
<br>
-std::future<Tagged<std::vecto<wbr>r<CompletionItem>>><br>
+std::future<Tagged<Completion<wbr>List>><br>
 ClangdServer::codeComplete(Pa<wbr>thRef File, Position Pos,<br>
                            llvm::Optional<StringRef> OverridenContents,<br>
                            IntrusiveRefCntPtr<vfs::FileSy<wbr>stem> *UsedFS) {<br>
-  using ResultType = Tagged<std::vector<CompletionI<wbr>tem>>;<br>
+  using ResultType = Tagged<CompletionList>;<br>
<br>
   std::promise<ResultType> ResultPromise;<br>
<br>
@@ -242,11 +242,10 @@ ClangdServer::codeComplete(Pat<wbr>hRef File,<br>
 }<br>
<br>
 void ClangdServer::codeComplete(<br>
-    UniqueFunction<void(Tagged<std<wbr>::vector<CompletionItem>>)> Callback,<br>
-    PathRef File, Position Pos, llvm::Optional<StringRef> OverridenContents,<br>
+    UniqueFunction<void(Tagged<Com<wbr>pletionList>)> Callback, PathRef File,<br>
+    Position Pos, llvm::Optional<StringRef> OverridenContents,<br>
     IntrusiveRefCntPtr<vfs::FileS<wbr>ystem> *UsedFS) {<br>
-  using CallbackType =<br>
-      UniqueFunction<void(Tagged<std<wbr>::vector<CompletionItem>>)>;<br>
+  using CallbackType = UniqueFunction<void(Tagged<Com<wbr>pletionList>)>;<br>
<br>
   std::string Contents;<br>
   if (OverridenContents) {<br>
@@ -283,7 +282,7 @@ void ClangdServer::codeComplete(<br>
         // FIXME(ibiryukov): even if Preamble is non-null, we may want to check<br>
         // both the old and the new version in case only one of them matches.<br>
<br>
-        std::vector<CompletionItem> Result = clangd::codeComplete(<br>
+        CompletionList Result = clangd::codeComplete(<br>
             File, Resources->getCompileCommand()<wbr>,<br>
             Preamble ? &Preamble->Preamble : nullptr, Contents, Pos,<br>
             TaggedFS.Value, PCHs, CodeCompleteOpts, Logger);<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/ClangdServer.h?rev=<wbr>318287&r1=318286&r2=318287&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h Wed Nov 15 01:16:29 2017<br>
@@ -251,18 +251,17 @@ public:<br>
   /// This method should only be called for currently tracked files. However, it<br>
   /// is safe to call removeDocument for \p File after this method returns, even<br>
   /// while returned future is not yet ready.<br>
-  std::future<Tagged<std::vector<wbr><CompletionItem>>><br>
+  std::future<Tagged<CompletionL<wbr>ist>><br>
   codeComplete(PathRef File, Position Pos,<br>
                llvm::Optional<StringRef> OverridenContents = llvm::None,<br>
                IntrusiveRefCntPtr<vfs::FileSy<wbr>stem> *UsedFS = nullptr);<br>
<br>
   /// A version of `codeComplete` that runs \p Callback on the processing thread<br>
   /// when codeComplete results become available.<br>
-  void codeComplete(<br>
-      UniqueFunction<void(Tagged<std<wbr>::vector<CompletionItem>>)> Callback,<br>
-      PathRef File, Position Pos,<br>
-      llvm::Optional<StringRef> OverridenContents = llvm::None,<br>
-      IntrusiveRefCntPtr<vfs::FileSy<wbr>stem> *UsedFS = nullptr);<br>
+  void codeComplete(UniqueFunction<vo<wbr>id(Tagged<CompletionList>)> Callback,<br>
+                    PathRef File, Position Pos,<br>
+                    llvm::Optional<StringRef> OverridenContents = llvm::None,<br>
+                    IntrusiveRefCntPtr<vfs::FileSy<wbr>stem> *UsedFS = nullptr);<br>
<br>
   /// Provide signature help for \p File at \p Pos. If \p OverridenContents is<br>
   /// not None, they will used only for signature help, i.e. no diagnostics<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.cpp?rev=<wbr>318287&r1=318286&r2=318287&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.cpp Wed Nov 15 01:16:29 2017<br>
@@ -368,28 +368,90 @@ std::string getDocumentation(const CodeC<br>
   return Result;<br>
 }<br>
<br>
+/// A scored code completion result.<br>
+/// It may be promoted to a CompletionItem if it's among the top-ranked results.<br>
+struct CompletionCandidate {<br>
+  CompletionCandidate(CodeComple<wbr>tionResult &Result)<br>
+      : Result(&Result), Score(score(Result)) {}<br>
+<br>
+  CodeCompletionResult *Result;<br>
+  // Higher score is worse. FIXME: use a more natural scale!<br>
+  int Score;<br>
+<br>
+  // Comparison reflects rank: better candidates are smaller.<br>
+  bool operator<(const CompletionCandidate &C) const {<br>
+    if (Score != C.Score)<br>
+      return Score < C.Score;<br>
+    return *Result < *C.Result;<br>
+  }<br>
+<br>
+  std::string sortText() const {<br>
+    // Fill in the sortText of the CompletionItem.<br>
+    assert(Score <= 999999 && "Expecting score to have at most 6-digits");<br>
+    std::string S, NameStorage;<br>
+    StringRef Name = Result->getOrderedName(NameSto<wbr>rage);<br>
+    llvm::raw_string_ostream(S)<br>
+        << llvm::format("%06d%.*s", Score, Name.size(), Name.data());<br>
+    return S;<br>
+  }<br>
+<br>
+private:<br>
+  static int score(const CodeCompletionResult &Result) {<br>
+    int Score = Result.Priority;<br>
+    // Fill in the sortText of the CompletionItem.<br>
+    assert(Score <= 99999 && "Expecting code completion result "<br>
+                             "priority to have at most 5-digits");<br>
+<br>
+    const int Penalty = 100000;<br>
+    switch (static_cast<CXAvailabilityKin<wbr>d>(Result.Availability)) {<br>
+    case CXAvailability_Available:<br>
+      // No penalty.<br>
+      break;<br>
+    case CXAvailability_Deprecated:<br>
+      Score += Penalty;<br>
+      break;<br>
+    case CXAvailability_NotAccessible:<br>
+      Score += 2 * Penalty;<br>
+      break;<br>
+    case CXAvailability_NotAvailable:<br>
+      Score += 3 * Penalty;<br>
+      break;<br>
+    }<br>
+    return Score;<br>
+  }<br>
+};<br>
+<br>
 class CompletionItemsCollector : public CodeCompleteConsumer {<br>
 public:<br>
-  CompletionItemsCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,<br>
-                           std::vector<CompletionItem> &Items)<br>
-      : CodeCompleteConsumer(CodeCompl<wbr>eteOpts, /*OutputIsBinary=*/false),<br>
-        Items(Items),<br>
+  CompletionItemsCollector(const clangd::CodeCompleteOptions &CodeCompleteOpts,<br>
+                           CompletionList &Items)<br>
+      : CodeCompleteConsumer(CodeCompl<wbr>eteOpts.getClangCompleteOpts()<wbr>,<br>
+                             /*OutputIsBinary=*/false),<br>
+        ClangdOpts(CodeCompleteOpts), Items(Items),<br>
         Allocator(std::make_shared<cl<wbr>ang::GlobalCodeCompletionAlloc<wbr>ator>()),<br>
         CCTUInfo(Allocator) {}<br>
<br>
   void ProcessCodeCompleteResults(Sem<wbr>a &S, CodeCompletionContext Context,<br>
                                   CodeCompletionResult *Results,<br>
                                   unsigned NumResults) override final {<br>
-    Items.reserve(NumResults);<br>
+    std::priority_queue<Completion<wbr>Candidate> Candidates;<br>
     for (unsigned I = 0; I < NumResults; ++I) {<br>
-      auto &Result = Results[I];<br>
-      const auto *CCS = Result.CreateCodeCompletionStr<wbr>ing(<br>
+      Candidates.emplace(Results[I])<wbr>;<br>
+      if (ClangdOpts.Limit && Candidates.size() > ClangdOpts.Limit) {<br>
+        Candidates.pop();<br>
+        Items.isIncomplete = true;<br>
+      }<br>
+    }<br>
+    while (!Candidates.empty()) {<br>
+      auto &Candidate = Candidates.top();<br>
+      const auto *CCS = Candidate.Result->CreateCodeCo<wbr>mpletionString(<br>
           S, Context, *Allocator, CCTUInfo,<br>
           CodeCompleteOpts.IncludeBrief<wbr>Comments);<br>
       assert(CCS && "Expected the CodeCompletionString to be non-null");<br>
-      Items.push_back(ProcessCodeCom<wbr>pleteResult(Result, *CCS));<br>
+      Items.items.push_back(ProcessC<wbr>odeCompleteResult(Candidate, *CCS));<br>
+      Candidates.pop();<br>
     }<br>
-    std::sort(Items.begin(), Items.end());<br>
+    std::reverse(Items.items.begin<wbr>(), Items.items.end());<br>
   }<br>
<br>
   GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }<br>
@@ -398,7 +460,7 @@ public:<br>
<br>
 private:<br>
   CompletionItem<br>
-  ProcessCodeCompleteResult(cons<wbr>t CodeCompletionResult &Result,<br>
+  ProcessCodeCompleteResult(cons<wbr>t CompletionCandidate &Candidate,<br>
                             const CodeCompletionString &CCS) const {<br>
<br>
     // Adjust this to InsertTextFormat::Snippet iff we encounter a<br>
@@ -407,15 +469,14 @@ private:<br>
     Item.insertTextFormat = InsertTextFormat::PlainText;<br>
<br>
     Item.documentation = getDocumentation(CCS);<br>
+    Item.sortText = Candidate.sortText();<br>
<br>
     // Fill in the label, detail, insertText and filterText fields of the<br>
     // CompletionItem.<br>
     ProcessChunks(CCS, Item);<br>
<br>
     // Fill in the kind field of the CompletionItem.<br>
-    Item.kind = getKind(Result.Kind, Result.CursorKind);<br>
-<br>
-    FillSortText(CCS, Item);<br>
+    Item.kind = getKind(Candidate.Result->Kind<wbr>, Candidate.Result->CursorKind);<br>
<br>
     return Item;<br>
   }<br>
@@ -423,42 +484,8 @@ private:<br>
   virtual void ProcessChunks(const CodeCompletionString &CCS,<br>
                              CompletionItem &Item) const = 0;<br>
<br>
-  static int GetSortPriority(const CodeCompletionString &CCS) {<br>
-    int Score = CCS.getPriority();<br>
-    // Fill in the sortText of the CompletionItem.<br>
-    assert(Score <= 99999 && "Expecting code completion result "<br>
-                             "priority to have at most 5-digits");<br>
-<br>
-    const int Penalty = 100000;<br>
-    switch (static_cast<CXAvailabilityKin<wbr>d>(CCS.getAvailability())) {<br>
-    case CXAvailability_Available:<br>
-      // No penalty.<br>
-      break;<br>
-    case CXAvailability_Deprecated:<br>
-      Score += Penalty;<br>
-      break;<br>
-    case CXAvailability_NotAccessible:<br>
-      Score += 2 * Penalty;<br>
-      break;<br>
-    case CXAvailability_NotAvailable:<br>
-      Score += 3 * Penalty;<br>
-      break;<br>
-    }<br>
-<br>
-    return Score;<br>
-  }<br>
-<br>
-  static void FillSortText(const CodeCompletionString &CCS,<br>
-                           CompletionItem &Item) {<br>
-    int Priority = GetSortPriority(CCS);<br>
-    // Fill in the sortText of the CompletionItem.<br>
-    assert(Priority <= 999999 &&<br>
-           "Expecting sort priority to have at most 6-digits");<br>
-    llvm::raw_string_ostream(Item.<wbr>sortText)<br>
-        << llvm::format("%06d%s", Priority, Item.filterText.c_str());<br>
-  }<br>
-<br>
-  std::vector<CompletionItem> &Items;<br>
+  clangd::CodeCompleteOptions ClangdOpts;<br>
+  CompletionList &Items;<br>
   std::shared_ptr<clang::Global<wbr>CodeCompletionAllocator> Allocator;<br>
   CodeCompletionTUInfo CCTUInfo;<br>
<br>
@@ -474,8 +501,8 @@ class PlainTextCompletionItemsCollec<wbr>tor<br>
<br>
 public:<br>
   <wbr>PlainTextCompletionItemsCollec<wbr>tor(<br>
-      const clang::CodeCompleteOptions &CodeCompleteOpts,<br>
-      std::vector<CompletionItem> &Items)<br>
+      const clangd::CodeCompleteOptions &CodeCompleteOpts,<br>
+      CompletionList &Items)<br>
       : CompletionItemsCollector(CodeC<wbr>ompleteOpts, Items) {}<br>
<br>
 private:<br>
@@ -511,8 +538,8 @@ class SnippetCompletionItemsCollecto<wbr>r fi<br>
<br>
 public:<br>
   <wbr>SnippetCompletionItemsCollecto<wbr>r(<br>
-      const clang::CodeCompleteOptions &CodeCompleteOpts,<br>
-      std::vector<CompletionItem> &Items)<br>
+      const clangd::CodeCompleteOptions &CodeCompleteOpts,<br>
+      CompletionList &Items)<br>
       : CompletionItemsCollector(CodeC<wbr>ompleteOpts, Items) {}<br>
<br>
 private:<br>
@@ -795,7 +822,8 @@ clangd::CodeCompleteOptions::C<wbr>odeComplet<br>
       IncludeMacros(IncludeMacros), IncludeGlobals(IncludeGlobals)<wbr>,<br>
       IncludeBriefComments(IncludeB<wbr>riefComments) {}<br>
<br>
-clang::CodeCompleteOptions clangd::CodeCompleteOptions::g<wbr>etClangCompleteOpts() {<br>
+clang::CodeCompleteOptions<br>
+clangd::CodeCompleteOptions::<wbr>getClangCompleteOpts() const {<br>
   clang::CodeCompleteOptions Result;<br>
   Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;<br>
   Result.IncludeMacros = IncludeMacros;<br>
@@ -805,25 +833,24 @@ clang::CodeCompleteOptions clangd::CodeC<br>
   return Result;<br>
 }<br>
<br>
-std::vector<CompletionItem><br>
+CompletionList<br>
 clangd::codeComplete(PathRef FileName, const tooling::CompileCommand &Command,<br>
                      PrecompiledPreamble const *Preamble, StringRef Contents,<br>
                      Position Pos, IntrusiveRefCntPtr<vfs::FileSy<wbr>stem> VFS,<br>
                      std::shared_ptr<PCHContainerOp<wbr>erations> PCHs,<br>
                      clangd::CodeCompleteOptions Opts, clangd::Logger &Logger) {<br>
-  std::vector<CompletionItem> Results;<br>
+  CompletionList Results;<br>
   std::unique_ptr<CodeCompleteC<wbr>onsumer> Consumer;<br>
-  clang::CodeCompleteOptions ClangCompleteOpts = Opts.getClangCompleteOpts();<br>
   if (Opts.EnableSnippets) {<br>
-    Consumer = llvm::make_unique<SnippetCompl<wbr>etionItemsCollector>(<br>
-        ClangCompleteOpts, Results);<br>
+    Consumer =<br>
+        llvm::make_unique<SnippetCompl<wbr>etionItemsCollector>(Opts, Results);<br>
   } else {<br>
-    Consumer = llvm::make_unique<PlainTextCom<wbr>pletionItemsCollector>(<br>
-        ClangCompleteOpts, Results);<br>
+    Consumer =<br>
+        llvm::make_unique<PlainTextCom<wbr>pletionItemsCollector>(Opts, Results);<br>
   }<br>
-  invokeCodeComplete(std::move(C<wbr>onsumer), ClangCompleteOpts, FileName, Command,<br>
-                     Preamble, Contents, Pos, std::move(VFS), std::move(PCHs),<br>
-                     Logger);<br>
+  invokeCodeComplete(std::move(C<wbr>onsumer), Opts.getClangCompleteOpts(), FileName,<br>
+                     Command, Preamble, Contents, Pos, std::move(VFS),<br>
+                     std::move(PCHs), Logger);<br>
   return Results;<br>
 }<br>
<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.h?rev=318287<wbr>&r1=318286&r2=318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.h (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/ClangdUnit.h Wed Nov 15 01:16:29 2017<br>
@@ -263,7 +263,7 @@ struct CodeCompleteOptions {<br>
                       bool IncludeBriefComments);<br>
<br>
   /// Returns options that can be passed to clang's completion engine.<br>
-  clang::CodeCompleteOptions getClangCompleteOpts();<br>
+  clang::CodeCompleteOptions getClangCompleteOpts() const;<br>
<br>
   /// When true, completion items will contain expandable code snippets in<br>
   /// completion (e.g.  `return ${1:expression}` or `foo(${1:int a}, ${2:int<br>
@@ -285,10 +285,14 @@ struct CodeCompleteOptions {<br>
   /// FIXME(ibiryukov): it looks like turning this option on significantly slows<br>
   /// down completion, investigate if it can be made faster.<br>
   bool IncludeBriefComments = true;<br>
+<br>
+  /// Limit the number of results returned (0 means no limit).<br>
+  /// If more results are available, we set CompletionList.isIncomplete.<br>
+  size_t Limit = 0;<br>
 };<br>
<br>
 /// Get code completions at a specified \p Pos in \p FileName.<br>
-std::vector<CompletionItem><br>
+CompletionList<br>
 codeComplete(PathRef FileName, const tooling::CompileCommand &Command,<br>
              PrecompiledPreamble const *Preamble, StringRef Contents,<br>
              Position Pos, IntrusiveRefCntPtr<vfs::FileSy<wbr>stem> VFS,<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/Protocol.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/Protocol.cpp?rev=318287<wbr>&r1=318286&r2=318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/Protocol.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/Protocol.cpp Wed Nov 15 01:16:29 2017<br>
@@ -1043,6 +1043,13 @@ bool clangd::operator<(const CompletionI<br>
          (R.sortText.empty() ? R.label : R.sortText);<br>
 }<br>
<br>
+json::Expr CompletionList::unparse(const CompletionList &L) {<br>
+  return json::obj{<br>
+      {"isIncomplete", L.isIncomplete},<br>
+      {"items", json::ary(L.items)},<br>
+  };<br>
+}<br>
+<br>
 json::Expr ParameterInformation::unparse(<wbr>const ParameterInformation &PI) {<br>
   assert(!PI.label.empty() && "parameter information label is required");<br>
   json::obj Result{{"label", PI.label}};<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/Protocol.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/Protocol.h?rev=318287&<wbr>r1=318286&r2=318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/Protocol.h (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/Protocol.h Wed Nov 15 01:16:29 2017<br>
@@ -547,6 +547,18 @@ struct CompletionItem {<br>
<br>
 bool operator<(const CompletionItem &, const CompletionItem &);<br>
<br>
+/// Represents a collection of completion items to be presented in the editor.<br>
+struct CompletionList {<br>
+  /// The list is not complete. Further typing should result in recomputing the<br>
+  /// list.<br>
+  bool isIncomplete = false;<br>
+<br>
+  /// The completion items.<br>
+  std::vector<CompletionItem> items;<br>
+<br>
+  static json::Expr unparse(const CompletionList &);<br>
+};<br>
+<br>
 /// A single parameter of a particular signature.<br>
 struct ParameterInformation {<br>
<br>
<br>
Modified: clang-tools-extra/trunk/test/c<wbr>langd/authority-less-uri.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/authority-less-uri.test?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>test/clangd/authority-less-<wbr>uri.test?rev=318287&r1=318286&<wbr>r2=318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/test/c<wbr>langd/authority-less-uri.test (original)<br>
+++ clang-tools-extra/trunk/test/c<wbr>langd/authority-less-uri.test Wed Nov 15 01:16:29 2017<br>
@@ -17,14 +17,17 @@ Content-Length: 146<br>
 #<br>
 #      CHECK:  "id": 1,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-#      CHECK:      "filterText": "fake",<br>
-# CHECK-NEXT:      "insertText": "fake",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 7,<br>
-# CHECK-NEXT:      "label": "fake::",<br>
-# CHECK-NEXT:      "sortText": "000075fake"<br>
-#      CHECK:  ]<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+#      CHECK:        "filterText": "fake",<br>
+# CHECK-NEXT:        "insertText": "fake",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 7,<br>
+# CHECK-NEXT:        "label": "fake::",<br>
+# CHECK-NEXT:        "sortText": "000075fake"<br>
+#      CHECK:    ]<br>
+# CHECK-NEXT:  }<br>
 Content-Length: 172<br>
<br>
 {"jsonrpc":"2.0","id":2,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"uri"<wbr>:"file:///main.cpp","position"<wbr>:{"line":3,"character":5}}}<br>
@@ -32,14 +35,17 @@ Content-Length: 172<br>
 #<br>
 #      CHECK:  "id": 2,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-#      CHECK:      "filterText": "fake",<br>
-# CHECK-NEXT:      "insertText": "fake",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 7,<br>
-# CHECK-NEXT:      "label": "fake::",<br>
-# CHECK-NEXT:      "sortText": "000075fake"<br>
-#      CHECK:  ]<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+#      CHECK:        "filterText": "fake",<br>
+# CHECK-NEXT:        "insertText": "fake",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 7,<br>
+# CHECK-NEXT:        "label": "fake::",<br>
+# CHECK-NEXT:        "sortText": "000075fake"<br>
+#      CHECK:    ]<br>
+# CHECK-NEXT:  }<br>
 Content-Length: 44<br>
<br>
 {"jsonrpc":"2.0","id":3,"meth<wbr>od":"shutdown"}<br>
<br>
Modified: clang-tools-extra/trunk/test/c<wbr>langd/completion-items-kinds.t<wbr>est<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-items-kinds.test?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>test/clangd/completion-items-<wbr>kinds.test?rev=318287&r1=<wbr>318286&r2=318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/test/c<wbr>langd/completion-items-kinds.t<wbr>est (original)<br>
+++ clang-tools-extra/trunk/test/c<wbr>langd/completion-items-kinds.t<wbr>est Wed Nov 15 01:16:29 2017<br>
@@ -11,7 +11,7 @@ Content-Length: 148<br>
<br>
 {"jsonrpc":"2.0","id":1,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":4,"<wbr>character":7}}}<br>
 Content-Length: 58<br>
-# CHECK: {"id":1,"jsonrpc":"2.0","resul<wbr>t":[<br>
+# CHECK: {"id":1,"jsonrpc":"2.0","resul<wbr>t":{"isIncomplete":false,"<wbr>items":<br>
 #<br>
 # Keyword<br>
 # CHECK-DAG: {"filterText":"int","insertTex<wbr>t":"int","insertTextFormat":1,<wbr>"kind":14,"label":"int","<wbr>sortText":"000050int"}<br>
@@ -31,6 +31,6 @@ Content-Length: 58<br>
 # Function<br>
 # CHECK-DAG: {"detail":"int","filterText":"<wbr>function","insertText":"functi<wbr>on()","insertTextFormat":1,"<wbr>kind":3,"label":"function()","<wbr>sortText":"000012function"}<br>
 #<br>
-# CHECK-SAME: ]}<br>
+# CHECK-SAME: ]}}<br>
<br>
 {"jsonrpc":"2.0","id":3,"meth<wbr>od":"shutdown","params":null}<br>
<br>
Modified: clang-tools-extra/trunk/test/c<wbr>langd/completion-priorities.te<wbr>st<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-priorities.test?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>test/clangd/completion-priorit<wbr>ies.test?rev=318287&r1=318286&<wbr>r2=318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/test/c<wbr>langd/completion-priorities.te<wbr>st (original)<br>
+++ clang-tools-extra/trunk/test/c<wbr>langd/completion-priorities.te<wbr>st Wed Nov 15 01:16:29 2017<br>
@@ -15,69 +15,74 @@ Content-Length: 151<br>
 {"jsonrpc":"2.0","id":2,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":12,"<wbr>character":8}}}<br>
 #      CHECK:  "id": 2,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "void",<br>
-# CHECK-NEXT:      "filterText": "priv",<br>
-# CHECK-NEXT:      "insertText": "priv",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "priv()",<br>
-# CHECK-NEXT:      "sortText": "000034priv"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "void",<br>
-# CHECK-NEXT:      "filterText": "prot",<br>
-# CHECK-NEXT:      "insertText": "prot",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "prot()",<br>
-# CHECK-NEXT:      "sortText": "000034prot"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "void",<br>
-# CHECK-NEXT:      "filterText": "pub",<br>
-# CHECK-NEXT:      "insertText": "pub",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "pub()",<br>
-# CHECK-NEXT:      "sortText": "000034pub"<br>
-# CHECK-NEXT:    },<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "void",<br>
+# CHECK-NEXT:        "filterText": "priv",<br>
+# CHECK-NEXT:        "insertText": "priv",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "priv()",<br>
+# CHECK-NEXT:        "sortText": "000034priv"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "void",<br>
+# CHECK-NEXT:        "filterText": "prot",<br>
+# CHECK-NEXT:        "insertText": "prot",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "prot()",<br>
+# CHECK-NEXT:        "sortText": "000034prot"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "void",<br>
+# CHECK-NEXT:        "filterText": "pub",<br>
+# CHECK-NEXT:        "insertText": "pub",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "pub()",<br>
+# CHECK-NEXT:        "sortText": "000034pub"<br>
+# CHECK-NEXT:      },<br>
 Content-Length: 151<br>
<br>
 {"jsonrpc":"2.0","id":3,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":17,"<wbr>character":4}}}<br>
 #      CHECK:  "id": 3,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "void",<br>
-# CHECK-NEXT:      "filterText": "pub",<br>
-# CHECK-NEXT:      "insertText": "pub",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "pub()",<br>
-# CHECK-NEXT:      "sortText": "000034pub"<br>
-# CHECK-NEXT:    },<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "void",<br>
+# CHECK-NEXT:        "filterText": "pub",<br>
+# CHECK-NEXT:        "insertText": "pub",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "pub()",<br>
+# CHECK-NEXT:        "sortText": "000034pub"<br>
+# CHECK-NEXT:      },<br>
 # priv() and prot() are at the end of the list<br>
-# CHECK-NEXT:    {<br>
-#      CHECK:      "detail": "void",<br>
-#      CHECK:      "filterText": "priv",<br>
-# CHECK-NEXT:      "insertText": "priv",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "priv()",<br>
-# CHECK-NEXT:      "sortText": "200034priv"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "void",<br>
-# CHECK-NEXT:      "filterText": "prot",<br>
-# CHECK-NEXT:      "insertText": "prot",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "prot()",<br>
-# CHECK-NEXT:      "sortText": "200034prot"<br>
-# CHECK-NEXT:    }<br>
-# CHECK-NEXT:  ]<br>
+# CHECK-NEXT:      {<br>
+#      CHECK:        "detail": "void",<br>
+#      CHECK:        "filterText": "priv",<br>
+# CHECK-NEXT:        "insertText": "priv",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "priv()",<br>
+# CHECK-NEXT:        "sortText": "200034priv"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "void",<br>
+# CHECK-NEXT:        "filterText": "prot",<br>
+# CHECK-NEXT:        "insertText": "prot",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "prot()",<br>
+# CHECK-NEXT:        "sortText": "200034prot"<br>
+# CHECK-NEXT:      }<br>
+# CHECK-NEXT:    ]<br>
+# CHECK-NEXT:  }<br>
 Content-Length: 58<br>
<br>
 {"jsonrpc":"2.0","id":4,"meth<wbr>od":"shutdown","params":null}<br>
<br>
Modified: clang-tools-extra/trunk/test/c<wbr>langd/completion-qualifiers.te<wbr>st<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-qualifiers.test?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>test/clangd/completion-qualifi<wbr>ers.test?rev=318287&r1=318286&<wbr>r2=318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/test/c<wbr>langd/completion-qualifiers.te<wbr>st (original)<br>
+++ clang-tools-extra/trunk/test/c<wbr>langd/completion-qualifiers.te<wbr>st Wed Nov 15 01:16:29 2017<br>
@@ -10,37 +10,40 @@ Content-Length: 151<br>
 {"jsonrpc":"2.0","id":2,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":11,"<wbr>character":8}}}<br>
 #      CHECK:  "id": 2,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
 # Eligible const functions are at the top of the list.<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "int",<br>
-# CHECK-NEXT:      "filterText": "bar",<br>
-# CHECK-NEXT:      "insertText": "bar",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "bar() const",<br>
-# CHECK-NEXT:      "sortText": "000037bar"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "int",<br>
-# CHECK-NEXT:      "filterText": "foo",<br>
-# CHECK-NEXT:      "insertText": "foo",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "Foo::foo() const",<br>
-# CHECK-NEXT:      "sortText": "000037foo"<br>
-# CHECK-NEXT:    },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "int",<br>
+# CHECK-NEXT:        "filterText": "bar",<br>
+# CHECK-NEXT:        "insertText": "bar",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "bar() const",<br>
+# CHECK-NEXT:        "sortText": "000037bar"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "int",<br>
+# CHECK-NEXT:        "filterText": "foo",<br>
+# CHECK-NEXT:        "insertText": "foo",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "Foo::foo() const",<br>
+# CHECK-NEXT:        "sortText": "000037foo"<br>
+# CHECK-NEXT:      },<br>
 # Ineligible non-const function is at the bottom of the list.<br>
-# CHECK-NEXT:    {<br>
-#      CHECK:      "detail": "int",<br>
-#      CHECK:      "filterText": "foo",<br>
-# CHECK-NEXT:      "insertText": "foo",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "foo() const",<br>
-# CHECK-NEXT:      "sortText": "200035foo"<br>
-# CHECK-NEXT:    }<br>
-# CHECK-NEXT:  ]<br>
+# CHECK-NEXT:      {<br>
+#      CHECK:        "detail": "int",<br>
+#      CHECK:        "filterText": "foo",<br>
+# CHECK-NEXT:        "insertText": "foo",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "foo() const",<br>
+# CHECK-NEXT:        "sortText": "200035foo"<br>
+# CHECK-NEXT:      }<br>
+# CHECK-NEXT:    ]<br>
+# CHECK-NEXT:  }<br>
 Content-Length: 44<br>
<br>
 {"jsonrpc":"2.0","id":4,"meth<wbr>od":"shutdown"}<br>
<br>
Modified: clang-tools-extra/trunk/test/c<wbr>langd/completion-snippet.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-snippet.test?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>test/clangd/completion-snippet<wbr>.test?rev=318287&r1=318286&r2=<wbr>318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/test/c<wbr>langd/completion-snippet.test (original)<br>
+++ clang-tools-extra/trunk/test/c<wbr>langd/completion-snippet.test Wed Nov 15 01:16:29 2017<br>
@@ -14,71 +14,74 @@ Content-Length: 148<br>
 {"jsonrpc":"2.0","id":1,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":3,"<wbr>character":5}}}<br>
 #      CHECK:  "id": 1,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "int",<br>
-# CHECK-NEXT:      "filterText": "a",<br>
-# CHECK-NEXT:      "insertText": "a",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 5,<br>
-# CHECK-NEXT:      "label": "a",<br>
-# CHECK-NEXT:      "sortText": "000035a"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "int",<br>
-# CHECK-NEXT:      "filterText": "bb",<br>
-# CHECK-NEXT:      "insertText": "bb",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 5,<br>
-# CHECK-NEXT:      "label": "bb",<br>
-# CHECK-NEXT:      "sortText": "000035bb"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "int",<br>
-# CHECK-NEXT:      "filterText": "ccc",<br>
-# CHECK-NEXT:      "insertText": "ccc",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 5,<br>
-# CHECK-NEXT:      "label": "ccc",<br>
-# CHECK-NEXT:      "sortText": "000035ccc"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "int",<br>
-# CHECK-NEXT:      "filterText": "f",<br>
-# CHECK-NEXT:      "insertText": "f(${1:int i}, ${2:const float f})",<br>
-# CHECK-NEXT:      "insertTextFormat": 2,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "f(int i, const float f) const",<br>
-# CHECK-NEXT:      "sortText": "000035f"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "filterText": "fake",<br>
-# CHECK-NEXT:      "insertText": "fake::",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 7,<br>
-# CHECK-NEXT:      "label": "fake::",<br>
-# CHECK-NEXT:      "sortText": "000075fake"<br>
-# CHECK-NEXT:    },<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "fake &",<br>
-# CHECK-NEXT:      "filterText": "operator=",<br>
-# CHECK-NEXT:      "insertText": "operator=(${1:const fake &})",<br>
-# CHECK-NEXT:      "insertTextFormat": 2,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "operator=(const fake &)",<br>
-# CHECK-NEXT:      "sortText": "000079operator="<br>
-# CHECK-NEXT:    },<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "int",<br>
+# CHECK-NEXT:        "filterText": "a",<br>
+# CHECK-NEXT:        "insertText": "a",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 5,<br>
+# CHECK-NEXT:        "label": "a",<br>
+# CHECK-NEXT:        "sortText": "000035a"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "int",<br>
+# CHECK-NEXT:        "filterText": "bb",<br>
+# CHECK-NEXT:        "insertText": "bb",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 5,<br>
+# CHECK-NEXT:        "label": "bb",<br>
+# CHECK-NEXT:        "sortText": "000035bb"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "int",<br>
+# CHECK-NEXT:        "filterText": "ccc",<br>
+# CHECK-NEXT:        "insertText": "ccc",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 5,<br>
+# CHECK-NEXT:        "label": "ccc",<br>
+# CHECK-NEXT:        "sortText": "000035ccc"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "int",<br>
+# CHECK-NEXT:        "filterText": "f",<br>
+# CHECK-NEXT:        "insertText": "f(${1:int i}, ${2:const float f})",<br>
+# CHECK-NEXT:        "insertTextFormat": 2,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "f(int i, const float f) const",<br>
+# CHECK-NEXT:        "sortText": "000035f"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "filterText": "fake",<br>
+# CHECK-NEXT:        "insertText": "fake::",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 7,<br>
+# CHECK-NEXT:        "label": "fake::",<br>
+# CHECK-NEXT:        "sortText": "000075fake"<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "fake &",<br>
+# CHECK-NEXT:        "filterText": "operator=",<br>
+# CHECK-NEXT:        "insertText": "operator=(${1:const fake &})",<br>
+# CHECK-NEXT:        "insertTextFormat": 2,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "operator=(const fake &)",<br>
+# CHECK-NEXT:        "sortText": "000079operator="<br>
+# CHECK-NEXT:      },<br>
 # FIXME: Why do some buildbots show an extra operator==(fake&&) here?<br>
-#      CHECK:    {<br>
-#      CHECK:      "detail": "void",<br>
-# CHECK-NEXT:      "filterText": "~fake",<br>
-# CHECK-NEXT:      "insertText": "~fake()",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 4,<br>
-# CHECK-NEXT:      "label": "~fake()",<br>
-# CHECK-NEXT:      "sortText": "000079~fake"<br>
-# CHECK-NEXT:    }<br>
-# CHECK-NEXT:  ]<br>
+#      CHECK:      {<br>
+#      CHECK:        "detail": "void",<br>
+# CHECK-NEXT:        "filterText": "~fake",<br>
+# CHECK-NEXT:        "insertText": "~fake()",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 4,<br>
+# CHECK-NEXT:        "label": "~fake()",<br>
+# CHECK-NEXT:        "sortText": "000079~fake"<br>
+# CHECK-NEXT:      }<br>
+# CHECK-NEXT:    ]<br>
+# CHECK-NEXT:  }<br>
 # Update the source file and check for completions again.<br>
 Content-Length: 226<br>
<br>
@@ -89,16 +92,18 @@ Content-Length: 148<br>
 {"jsonrpc":"2.0","id":3,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":3,"<wbr>character":5}}}<br>
 #      CHECK:  "id": 3,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-# CHECK-NEXT:    {<br>
-# CHECK-NEXT:      "detail": "int (*)(int, int)",<br>
-# CHECK-NEXT:      "filterText": "func",<br>
-# CHECK-NEXT:      "insertText": "func()",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 2,<br>
-# CHECK-NEXT:      "label": "func()",<br>
-# CHECK-NEXT:      "sortText": "000034func"<br>
-# CHECK-NEXT:    },<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "detail": "int (*)(int, int)",<br>
+# CHECK-NEXT:        "filterText": "func",<br>
+# CHECK-NEXT:        "insertText": "func()",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 2,<br>
+# CHECK-NEXT:        "label": "func()",<br>
+# CHECK-NEXT:        "sortText": "000034func"<br>
+# CHECK-NEXT:      },<br>
 Content-Length: 44<br>
<br>
 {"jsonrpc":"2.0","id":4,"meth<wbr>od":"shutdown"}<br>
<br>
Modified: clang-tools-extra/trunk/test/c<wbr>langd/completion.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion.test?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>test/clangd/completion.test?<wbr>rev=318287&r1=318286&r2=318287<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/test/c<wbr>langd/completion.test (original)<br>
+++ clang-tools-extra/trunk/test/c<wbr>langd/completion.test Wed Nov 15 01:16:29 2017<br>
@@ -14,7 +14,9 @@ Content-Length: 148<br>
 {"jsonrpc":"2.0","id":1,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":3,"<wbr>character":5}}}<br>
 #      CHECK:  "id": 1<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
 # CHECK-NEXT:    {<br>
 # CHECK-NEXT:      "detail": "int",<br>
 # CHECK-NEXT:      "filterText": "a",<br>
@@ -84,7 +86,9 @@ Content-Length: 148<br>
 {"jsonrpc":"2.0","id":2,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":3,"<wbr>character":5}}}<br>
 #      CHECK:  "id": 2<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
 # CHECK-NEXT:    {<br>
 # CHECK-NEXT:      "detail": "int",<br>
 # CHECK-NEXT:      "filterText": "a",<br>
@@ -158,7 +162,9 @@ Content-Length: 148<br>
 {"jsonrpc":"2.0","id":3,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:///main.cpp"},"<wbr>position":{"line":3,"<wbr>character":5}}}<br>
 #      CHECK:    "id": 3,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
 # CHECK-NEXT:    {<br>
 # CHECK-NEXT:      "detail": "int (*)(int, int)",<br>
 # CHECK-NEXT:      "filterText": "func",<br>
<br>
Modified: clang-tools-extra/trunk/test/c<wbr>langd/protocol.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/protocol.test?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>test/clangd/protocol.test?rev=<wbr>318287&r1=318286&r2=318287&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/test/c<wbr>langd/protocol.test (original)<br>
+++ clang-tools-extra/trunk/test/c<wbr>langd/protocol.test Wed Nov 15 01:16:29 2017<br>
@@ -31,14 +31,17 @@ Content-Length: 146<br>
 #<br>
 #      CHECK:  "id": 1,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-#      CHECK:      "filterText": "fake",<br>
-# CHECK-NEXT:      "insertText": "fake",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 7,<br>
-# CHECK-NEXT:      "label": "fake::",<br>
-# CHECK-NEXT:      "sortText": "000075fake"<br>
-#      CHECK:  ]<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+#      CHECK:        "filterText": "fake",<br>
+# CHECK-NEXT:        "insertText": "fake",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 7,<br>
+# CHECK-NEXT:        "label": "fake::",<br>
+# CHECK-NEXT:        "sortText": "000075fake"<br>
+#      CHECK:    ]<br>
+# CHECK-NEXT:  }<br>
<br>
 X-Test: Testing<br>
 Content-Type: application/vscode-jsonrpc; charset-utf-8<br>
@@ -57,14 +60,17 @@ Content-Length: 146<br>
 #<br>
 #      CHECK:  "id": 3,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-#      CHECK:      "filterText": "fake",<br>
-# CHECK-NEXT:      "insertText": "fake",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 7,<br>
-# CHECK-NEXT:      "label": "fake::",<br>
-# CHECK-NEXT:      "sortText": "000075fake"<br>
-#      CHECK:  ]<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+#      CHECK:        "filterText": "fake",<br>
+# CHECK-NEXT:        "insertText": "fake",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 7,<br>
+# CHECK-NEXT:        "label": "fake::",<br>
+# CHECK-NEXT:        "sortText": "000075fake"<br>
+#      CHECK:    ]<br>
+# CHECK-NEXT:  }<br>
 # STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored.<br>
<br>
 Content-Type: application/vscode-jsonrpc; charset-utf-8<br>
@@ -83,14 +89,17 @@ Content-Length: 146<br>
 #<br>
 #      CHECK:  "id": 5,<br>
 # CHECK-NEXT:  "jsonrpc": "2.0",<br>
-# CHECK-NEXT:  "result": [<br>
-#      CHECK:      "filterText": "fake",<br>
-# CHECK-NEXT:      "insertText": "fake",<br>
-# CHECK-NEXT:      "insertTextFormat": 1,<br>
-# CHECK-NEXT:      "kind": 7,<br>
-# CHECK-NEXT:      "label": "fake::",<br>
-# CHECK-NEXT:      "sortText": "000075fake"<br>
-#      CHECK:  ]<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "isIncomplete": false,<br>
+# CHECK-NEXT:    "items": [<br>
+#      CHECK:        "filterText": "fake",<br>
+# CHECK-NEXT:        "insertText": "fake",<br>
+# CHECK-NEXT:        "insertTextFormat": 1,<br>
+# CHECK-NEXT:        "kind": 7,<br>
+# CHECK-NEXT:        "label": "fake::",<br>
+# CHECK-NEXT:        "sortText": "000075fake"<br>
+#      CHECK:    ]<br>
+# CHECK-NEXT:  }<br>
 Content-Length: 1024<br>
<br>
 {"jsonrpc":"2.0","id":5,"meth<wbr>od":"textDocument/completion",<wbr>"params":{"textDocument":{"<wbr>uri":"file:/main.cpp"},"<wbr>position":{"line":3,"<wbr>character":5}}}<br>
<br>
Modified: clang-tools-extra/trunk/unitte<wbr>sts/clangd/ClangdTests.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=318287&r1=318286&r2=318287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>unittests/clangd/ClangdTests.<wbr>cpp?rev=318287&r1=318286&r2=<wbr>318287&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/unitte<wbr>sts/clangd/ClangdTests.cpp (original)<br>
+++ clang-tools-extra/trunk/unitte<wbr>sts/clangd/ClangdTests.cpp Wed Nov 15 01:16:29 2017<br>
@@ -619,16 +619,15 @@ struct bar { T x; };<br>
 class ClangdCompletionTest : public ClangdVFSTest {<br>
 protected:<br>
   template <class Predicate><br>
-  bool ContainsItemPred(std::vector<C<wbr>ompletionItem> const &Items,<br>
-                        Predicate Pred) {<br>
-    for (const auto &Item : Items) {<br>
+  bool ContainsItemPred(CompletionLis<wbr>t const &Items, Predicate Pred) {<br>
+    for (const auto &Item : Items.items) {<br>
       if (Pred(Item))<br>
         return true;<br>
     }<br>
     return false;<br>
   }<br>
<br>
-  bool ContainsItem(std::vector<Compl<wbr>etionItem> const &Items, StringRef Name) {<br>
+  bool ContainsItem(CompletionList const &Items, StringRef Name) {<br>
     return ContainsItemPred(Items, [Name](clangd::CompletionItem Item) {<br>
       return Item.insertText == Name;<br>
     });<br>
@@ -694,6 +693,44 @@ int b =   ;<br>
   }<br>
 }<br>
<br>
+TEST_F(ClangdCompletionTest, Limit) {<br>
+  MockFSProvider FS;<br>
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/tr<wbr>ue);<br>
+  CDB.ExtraClangFlags.push_back(<wbr>"-xc++");<br>
+  ErrorCheckingDiagConsumer DiagConsumer;<br>
+  clangd::CodeCompleteOptions Opts;<br>
+  Opts.Limit = 2;<br>
+  ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),<br>
+                      Opts, EmptyLogger::getInstance());<br>
+<br>
+  auto FooCpp = getVirtualTestFilePath("foo.cp<wbr>p");<br>
+  FS.Files[FooCpp] = "";<br>
+  FS.ExpectedFile = FooCpp;<br>
+  StringWithPos Completion = parseTextMarker(R"cpp(<br>
+struct ClassWithMembers {<br>
+  int AAA();<br>
+  int BBB();<br>
+  int CCC();<br>
+}<br>
+int main() { ClassWithMembers().{complete} }<br>
+      )cpp",<br>
+                                             "complete");<br>
+  Server.addDocument(FooCpp, Completion.Text);<br>
+<br>
+  /// For after-dot completion we must always get consistent results.<br>
+  auto Results = Server<br>
+                     .codeComplete(FooCpp, Completion.MarkerPos,<br>
+                                   StringRef(Completion.Text))<br>
+                     .get()<br>
+                     .Value;<br>
+<br>
+  EXPECT_TRUE(Results.isIncomple<wbr>te);<br>
+  EXPECT_EQ(Opts.Limit, Results.items.size());<br>
+  EXPECT_TRUE(ContainsItem(Resul<wbr>ts, "AAA"));<br>
+  EXPECT_TRUE(ContainsItem(Resul<wbr>ts, "BBB"));<br>
+  EXPECT_FALSE(ContainsItem(Resu<wbr>lts, "CCC"));<br>
+}<br>
+<br>
 TEST_F(ClangdCompletionTest, CompletionOptions) {<br>
   MockFSProvider FS;<br>
   ErrorCheckingDiagConsumer DiagConsumer;<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>