[clang-tools-extra] r318287 - [clangd] Support returning a limited number of completion results.

Galina Kistanova via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 15 10:58:14 PST 2017


Also at least one more builder is affected:
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/13517

Thanks

Galina

On Wed, Nov 15, 2017 at 10:54 AM, Galina Kistanova <gkistanova at gmail.com>
wrote:

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


More information about the cfe-commits mailing list