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

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 15 13:36:15 PST 2017


Thanks! After thinking about it further, I can't see a simple combination
of flags to set that won't break other platforms.
So I've disabled the tests on PS4 for now, and will fix this properly once
I get some sleep.

On Wed, Nov 15, 2017 at 9:49 PM, Robinson, Paul <paul.robinson at sony.com>
wrote:

> You could build a PS4-target compiler yourself, actually, at least
> adequate for running lit tests. (Sorry it's not enough to build actual PS4
> code!)  In a new build directory, run cmake with
> `-DLLVM_DEFAULT_TRIPLE=x86_64-scei-ps4` and then it should all Just
> Work.  That's all the upstream PS4 bots are doing.
>
> --paulr
>
>
>
> *From:* Sam McCall [mailto:sam.mccall at gmail.com]
> *Sent:* Wednesday, November 15, 2017 12:42 PM
> *To:* Robinson, Paul
> *Cc:* Galina Kistanova; cfe-commits (cfe-commits at lists.llvm.org)
>
> *Subject:* Re: [clang-tools-extra] r318287 - [clangd] Support returning a
> limited number of completion results.
>
>
>
> On Wed, Nov 15, 2017 at 8:46 PM, Sam McCall <sam.mccall at gmail.com> wrote:
>
> That sounds great - I think using the same default std as clang is what we
> want.
>
> Unfortunately, passing --std=c++11 isn't ideal - we want to keep using the
> existing logic to derive the std from the language of the input file.
>
> For now r318327 explicitly sets the target triple to -pc-, which should
> get us back to uniform behavior across platforms.
>
> Well, this didn't fix it. Lacking a machine to test on, I'll try to
> disable the tests on PS4 until this can be fixed in some other way.
>
>
>
> This is obviously a hack and makes for a rocky -std transition, I'll look
> into this.
>
>
>
> (All this defaulting only happens if the user hasn't set up a compilation
> database to tell clangd how to build their project - unfortunately the
> tests do this)
>
>
>
> On Wed, Nov 15, 2017 at 8:13 PM, Robinson, Paul <paul.robinson at sony.com>
> wrote:
>
> Thanks for looking into it.
>
> I should point out that Clang is planning to update the default –std for
> everyone, hopefully before 6.0 branches, and it might be best to be ready
> for that rather than sticking with C++98.
>
> --paulr
>
>
>
> *From:* Sam McCall [mailto:sam.mccall at gmail.com]
> *Sent:* Wednesday, November 15, 2017 11:09 AM
> *To:* Robinson, Paul; Galina Kistanova
> *Cc:* cfe-commits (cfe-commits at lists.llvm.org)
> *Subject:* Re: [clang-tools-extra] r318287 - [clangd] Support returning a
> limited number of completion results.
>
>
>
> Sorry about these - I've finally understood what's going on.
>
> It looks like the PS4 has a different default --std, which probably
> doesn't make sense for clangd. I'll override it.
>
>
>
> On Wed, Nov 15, 2017 at 7:49 PM, Robinson, Paul <paul.robinson at sony.com>
> wrote:
>
> Hi Sam,
> It looks like llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast has been
> failing a couple of clangd tests ever since this went in.
>
> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_
> 64-scei-ps4-windows10pro-fast/builds/13517
>
> Please fix or revert ASAP when bots go red.  Failures like this interfere
> with our CI process.
>
> Thanks,
> --paulr
> PS4 code owner
>
>
> > -----Original Message-----
> > From: cfe-commits [mailto:cfe-commits-bounces at lists.llvm.org] On Behalf
> Of
> > Sam McCall via cfe-commits
> > Sent: Wednesday, November 15, 2017 1:16 AM
> > To: cfe-commits at lists.llvm.org
> > Subject: [clang-tools-extra] r318287 - [clangd] Support returning a
> > limited number of completion results.
> >
> > 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::orderedName).
> >
> > (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=di
> > ff
> > ============================================================
> ==============
> > ====
> > --- 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::GlobalCodeCompletionAllocator>()),
> >          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":{"text
> > Document":{"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":{"text
> > Document":{"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","insertText":"int","insertTextFormat":1,"kind":14,
> "lab
> > el":"int","sortText":"000050int"}
> > @@ -31,6 +31,6 @@ Content-Length: 58
> >  # Function
> >  # CHECK-DAG:
> > {"detail":"int","filterText":"function","insertText":"
> function()","insertT
> > extFormat":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":{"text
> > Document":{"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":{"text
> > Document":{"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":{"text
> > Document":{"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":{"text
> > Document":{"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":{"text
> > Document":{"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&vie
> > w=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":{"text
> > Document":{"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":{"text
> > Document":{"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":{"text
> > Document":{"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":{"text
> > Document":{"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=31828
> > 7&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/18d7b30f/attachment-0001.html>


More information about the cfe-commits mailing list