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