From fae959e0ee84a87ffe81e40e758d7f91e2634c87 Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Wed, 21 Feb 2018 23:13:42 -0800 Subject: [PATCH] Drop old completion requests. Also increase xref limit. --- src/clang_complete.cc | 43 +++++++++++++++----- src/clang_complete.h | 22 ++++++---- src/command_line.cc | 12 +++++- src/config.h | 6 +++ src/messages/text_document_completion.cc | 8 ++-- src/messages/text_document_did_change.cc | 1 + src/messages/text_document_signature_help.cc | 2 +- 7 files changed, 71 insertions(+), 23 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 55b0a961..7726c988 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -440,6 +440,14 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { // Fetching the completion request blocks until we have a request. std::unique_ptr request = completion_manager->completion_request_.Dequeue(); + + // Drop older requests if we're not buffering. + while (completion_manager->config_->completion.dropOldRequests && + !completion_manager->completion_request_.IsEmpty()) { + completion_manager->on_dropped_(request->id); + request = completion_manager->completion_request_.Dequeue(); + } + std::string path = request->document.uri.GetPath(); std::shared_ptr session = @@ -625,25 +633,35 @@ CompletionSession::~CompletionSession() {} ClangCompleteManager::ParseRequest::ParseRequest(const std::string& path) : request_time(std::chrono::high_resolution_clock::now()), path(path) {} -ClangCompleteManager::CompletionRequest::CompletionRequest(const lsTextDocumentIdentifier& document, - const bool& emit_diagnostics) - : document(document), emit_diagnostics(emit_diagnostics) {} -ClangCompleteManager::CompletionRequest::CompletionRequest(const lsTextDocumentIdentifier& document, - const lsPosition& position, - const OnComplete& on_complete, - const bool& emit_diagnostics) - : document(document), position(position), on_complete(on_complete), emit_diagnostics(emit_diagnostics) {} +ClangCompleteManager::CompletionRequest::CompletionRequest( + const lsRequestId& id, + const lsTextDocumentIdentifier& document, + bool emit_diagnostics) + : id(id), document(document), emit_diagnostics(emit_diagnostics) {} +ClangCompleteManager::CompletionRequest::CompletionRequest( + const lsRequestId& id, + const lsTextDocumentIdentifier& document, + const lsPosition& position, + const OnComplete& on_complete, + bool emit_diagnostics) + : id(id), + document(document), + position(position), + on_complete(on_complete), + emit_diagnostics(emit_diagnostics) {} ClangCompleteManager::ClangCompleteManager(Config* config, Project* project, WorkingFiles* working_files, OnDiagnostic on_diagnostic, - OnIndex on_index) + OnIndex on_index, + OnDropped on_dropped) : config_(config), project_(project), working_files_(working_files), on_diagnostic_(on_diagnostic), on_index_(on_index), + on_dropped_(on_dropped), preloaded_sessions_(kMaxPreloadedSessions), completion_sessions_(kMaxCompletionSessions) { new std::thread([&]() { @@ -660,16 +678,19 @@ ClangCompleteManager::ClangCompleteManager(Config* config, ClangCompleteManager::~ClangCompleteManager() {} void ClangCompleteManager::CodeComplete( + const lsRequestId& id, const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete) { completion_request_.PushBack(MakeUnique( - completion_location.textDocument, completion_location.position, + id, completion_location.textDocument, completion_location.position, on_complete, false)); } void ClangCompleteManager::DiagnosticsUpdate( + const lsRequestId& id, const lsTextDocumentIdentifier& document) { - completion_request_.PushBack(MakeUnique(document, true)); + completion_request_.PushBack( + MakeUnique(id, document, true)); } void ClangCompleteManager::NotifyView(const std::string& filename) { diff --git a/src/clang_complete.h b/src/clang_complete.h index 7cb06871..48124d3e 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.h @@ -47,6 +47,7 @@ struct ClangCompleteManager { using OnComplete = std::function& results, bool is_cached_result)>; + using OnDropped = std::function; struct ParseRequest { ParseRequest(const std::string& path); @@ -55,13 +56,16 @@ struct ClangCompleteManager { std::string path; }; struct CompletionRequest { - CompletionRequest(const lsTextDocumentIdentifier& document, - const bool& emit_diagnostics); - CompletionRequest(const lsTextDocumentIdentifier& document, + CompletionRequest(const lsRequestId& id, + const lsTextDocumentIdentifier& document, + bool emit_diagnostics); + CompletionRequest(const lsRequestId& id, + const lsTextDocumentIdentifier& document, const lsPosition& position, const OnComplete& on_complete, - const bool& emit_diagnostics); + bool emit_diagnostics); + lsRequestId id; lsTextDocumentIdentifier document; optional position; OnComplete on_complete; // May be null/empty. @@ -72,15 +76,18 @@ struct ClangCompleteManager { Project* project, WorkingFiles* working_files, OnDiagnostic on_diagnostic, - OnIndex on_index); + OnIndex on_index, + OnDropped on_dropped); ~ClangCompleteManager(); // Start a code completion at the given location. |on_complete| will run when // completion results are available. |on_complete| may run on any thread. - void CodeComplete(const lsTextDocumentPositionParams& completion_location, + void CodeComplete(const lsRequestId& request_id, + const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete); // Request a diagnostics update. - void DiagnosticsUpdate(const lsTextDocumentIdentifier& document); + void DiagnosticsUpdate(const lsRequestId& request_id, + const lsTextDocumentIdentifier& document); // Notify the completion manager that |filename| has been viewed and we // should begin preloading completion data. @@ -113,6 +120,7 @@ struct ClangCompleteManager { WorkingFiles* working_files_; OnDiagnostic on_diagnostic_; OnIndex on_index_; + OnDropped on_dropped_; using LruSessionCache = LruCache; diff --git a/src/command_line.cc b/src/command_line.cc index c34d5fb7..d22c9449 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -71,7 +71,8 @@ bool ShouldDisplayIpcTiming(IpcId id) { REGISTER_IPC_MESSAGE(Ipc_CancelRequest); void PrintHelp() { - std::cout << R"help(cquery is a low-latency C/C++/Objective-C language server. + std::cout + << R"help(cquery is a low-latency C/C++/Objective-C language server. Mode: --clang-sanity-check @@ -186,6 +187,15 @@ void RunQueryDbThread(const std::string& bin_name, const std::string& path, const std::vector& args) { IndexWithTuFromCodeCompletion(config, &file_consumer_shared, tu, unsaved, path, args); + }, + [](lsRequestId id) { + if (!std::holds_alternative(id)) { + Out_Error out; + out.id = id; + out.error.code = lsErrorCodes::InternalError; + out.error.message = "Dropped completion request"; + QueueManager::WriteStdout(IpcId::Unknown, out); + } }); IncludeComplete include_complete(config, &project); diff --git a/src/config.h b/src/config.h index 900da7e3..91c333b8 100644 --- a/src/config.h +++ b/src/config.h @@ -110,6 +110,12 @@ struct Config { // items can end up truncated by the UIs. bool detailedLabel = false; + // On large projects, completion can take a long time. By default if cquery + // receives multiple completion requests while completion is still running + // it will only service the newest request. If this is set to false then all + // completion requests will be serviced. + bool dropOldRequests = true; + // If true, filter and sort completion response. cquery filters and sorts // completions to try to be nicer to clients that can't handle big numbers // of completion candidates. This behaviour can be disabled by specifying diff --git a/src/messages/text_document_completion.cc b/src/messages/text_document_completion.cc index d62cb4fe..39dce46c 100644 --- a/src/messages/text_document_completion.cc +++ b/src/messages/text_document_completion.cc @@ -223,7 +223,8 @@ struct TextDocumentCompletionHandler : MessageHandler { std::string character = *request->params.context->triggerCharacter; int preceding_index = request->params.position.character - 2; - // If the character is '"', '<' or '/', make sure that the line starts with '#'. + // If the character is '"', '<' or '/', make sure that the line starts + // with '#'. if (character == "\"" || character == "<" || character == "/") { size_t i = 0; while (i < buffer_line.size() && isspace(buffer_line[i])) @@ -361,7 +362,8 @@ struct TextDocumentCompletionHandler : MessageHandler { callback(global_code_complete_cache->cached_results_, true /*is_cached_result*/); }); - clang_complete->CodeComplete(request->params, freshen_global); + clang_complete->CodeComplete(request->id, request->params, + freshen_global); } else if (non_global_code_complete_cache->IsCacheValid( request->params)) { non_global_code_complete_cache->WithLock([&]() { @@ -369,7 +371,7 @@ struct TextDocumentCompletionHandler : MessageHandler { true /*is_cached_result*/); }); } else { - clang_complete->CodeComplete(request->params, callback); + clang_complete->CodeComplete(request->id, request->params, callback); } } } diff --git a/src/messages/text_document_did_change.cc b/src/messages/text_document_did_change.cc index b6673a33..90e6dc9c 100644 --- a/src/messages/text_document_did_change.cc +++ b/src/messages/text_document_did_change.cc @@ -19,6 +19,7 @@ struct TextDocumentDidChangeHandler working_files->OnChange(request->params); clang_complete->NotifyEdit(path); clang_complete->DiagnosticsUpdate( + std::monostate(), request->params.textDocument.AsTextDocumentIdentifier()); } }; diff --git a/src/messages/text_document_signature_help.cc b/src/messages/text_document_signature_help.cc index 2c3edb03..ec1a9c90 100644 --- a/src/messages/text_document_signature_help.cc +++ b/src/messages/text_document_signature_help.cc @@ -164,7 +164,7 @@ struct TextDocumentSignatureHelpHandler : MessageHandler { callback(signature_cache->cached_results_, true /*is_cached_result*/); }); } else { - clang_complete->CodeComplete(params, std::move(callback)); + clang_complete->CodeComplete(request->id, params, std::move(callback)); } } };