mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-21 16:09:40 +00:00
Cache global completion results.
This commit is contained in:
parent
cdc268d549
commit
7840b7a015
@ -297,7 +297,6 @@ void CompletionQueryMain(CompletionManager* completion_manager) {
|
|||||||
unsigned line = request->location.position.line + 1;
|
unsigned line = request->location.position.line + 1;
|
||||||
unsigned column = request->location.position.character + 1;
|
unsigned column = request->location.position.character + 1;
|
||||||
|
|
||||||
std::cerr << std::endl;
|
|
||||||
std::cerr << "[complete] Completing at " << line << ":" << column << std::endl;
|
std::cerr << "[complete] Completing at " << line << ":" << column << std::endl;
|
||||||
|
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
@ -1527,7 +1527,8 @@ bool QueryDbMainLoop(
|
|||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
CompletionManager* completion_manager,
|
CompletionManager* completion_manager,
|
||||||
IncludeCompletion* include_completion,
|
IncludeCompletion* include_completion,
|
||||||
CodeCompleteCache* code_complete_cache,
|
CodeCompleteCache* global_code_complete_cache,
|
||||||
|
CodeCompleteCache* non_global_code_complete_cache,
|
||||||
CodeCompleteCache* signature_cache) {
|
CodeCompleteCache* signature_cache) {
|
||||||
IpcManager* ipc = IpcManager::instance();
|
IpcManager* ipc = IpcManager::instance();
|
||||||
|
|
||||||
@ -1967,7 +1968,8 @@ bool QueryDbMainLoop(
|
|||||||
auto msg = static_cast<Ipc_TextDocumentComplete*>(message.get());
|
auto msg = static_cast<Ipc_TextDocumentComplete*>(message.get());
|
||||||
lsTextDocumentPositionParams& params = msg->params;
|
lsTextDocumentPositionParams& params = msg->params;
|
||||||
|
|
||||||
WorkingFile* file = working_files->GetFileByFilename(params.textDocument.uri.GetPath());
|
std::string path = params.textDocument.uri.GetPath();
|
||||||
|
WorkingFile* file = working_files->GetFileByFilename(path);
|
||||||
|
|
||||||
// TODO: We should scan include directories to add any missing paths
|
// TODO: We should scan include directories to add any missing paths
|
||||||
|
|
||||||
@ -2001,10 +2003,11 @@ bool QueryDbMainLoop(
|
|||||||
ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, complete_response);
|
ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, complete_response);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
bool is_global_completion = false;
|
||||||
if (file)
|
if (file)
|
||||||
params.position = file->FindStableCompletionSource(params.position);
|
params.position = file->FindStableCompletionSource(params.position, &is_global_completion);
|
||||||
|
|
||||||
CompletionManager::OnComplete callback = std::bind([working_files, code_complete_cache](BaseIpcMessage* message, NonElidedVector<lsCompletionItem> results, NonElidedVector<lsDiagnostic> diagnostics) {
|
CompletionManager::OnComplete callback = std::bind([working_files, global_code_complete_cache, non_global_code_complete_cache, is_global_completion](BaseIpcMessage* message, NonElidedVector<lsCompletionItem> results, NonElidedVector<lsDiagnostic> diagnostics) {
|
||||||
auto msg = static_cast<Ipc_TextDocumentComplete*>(message);
|
auto msg = static_cast<Ipc_TextDocumentComplete*>(message);
|
||||||
auto ipc = IpcManager::instance();
|
auto ipc = IpcManager::instance();
|
||||||
|
|
||||||
@ -2022,23 +2025,46 @@ bool QueryDbMainLoop(
|
|||||||
diagnostic_response.params.diagnostics = diagnostics;
|
diagnostic_response.params.diagnostics = diagnostics;
|
||||||
ipc->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diagnostic_response);
|
ipc->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diagnostic_response);
|
||||||
|
|
||||||
|
std::string path = msg->params.textDocument.uri.GetPath();
|
||||||
|
|
||||||
// Cache diagnostics so we can show fixits.
|
// Cache diagnostics so we can show fixits.
|
||||||
WorkingFile* working_file = working_files->GetFileByFilename(msg->params.textDocument.uri.GetPath());
|
WorkingFile* working_file = working_files->GetFileByFilename(path);
|
||||||
if (working_file)
|
if (working_file)
|
||||||
working_file->diagnostics = diagnostics;
|
working_file->diagnostics = diagnostics;
|
||||||
|
|
||||||
// Cache completion results so if the user types backspace we can respond faster.
|
// Cache completion results.
|
||||||
code_complete_cache->cached_path = msg->params.textDocument.uri.GetPath();
|
if (is_global_completion) {
|
||||||
code_complete_cache->cached_completion_position = msg->params.position;
|
global_code_complete_cache->cached_path = path;
|
||||||
code_complete_cache->cached_results = results;
|
global_code_complete_cache->cached_results = results;
|
||||||
code_complete_cache->cached_diagnostics = diagnostics;
|
global_code_complete_cache->cached_diagnostics = diagnostics;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
non_global_code_complete_cache->cached_path = path;
|
||||||
|
non_global_code_complete_cache->cached_completion_position = msg->params.position;
|
||||||
|
non_global_code_complete_cache->cached_results = results;
|
||||||
|
non_global_code_complete_cache->cached_diagnostics = diagnostics;
|
||||||
|
}
|
||||||
|
|
||||||
delete message;
|
delete message;
|
||||||
}, message.release(), std::placeholders::_1, std::placeholders::_2);
|
}, message.release(), std::placeholders::_1, std::placeholders::_2);
|
||||||
|
|
||||||
if (code_complete_cache->IsCacheValid(params)) {
|
if (is_global_completion && global_code_complete_cache->cached_path == path && !global_code_complete_cache->cached_results.empty()) {
|
||||||
|
std::cerr << "[complete] Early-returning cached global completion results at " << params.position.ToString() << std::endl;
|
||||||
|
|
||||||
|
CompletionManager::OnComplete update_global = std::bind([global_code_complete_cache](NonElidedVector<lsCompletionItem> results, NonElidedVector<lsDiagnostic> diagnostics) {
|
||||||
|
std::cerr << "[complete] Updated global completion cache" << std::endl;
|
||||||
|
// note: path is updated in the normal completion handler.
|
||||||
|
global_code_complete_cache->cached_results = results;
|
||||||
|
global_code_complete_cache->cached_diagnostics = diagnostics;
|
||||||
|
}, std::placeholders::_1, std::placeholders::_2);
|
||||||
|
completion_manager->CodeComplete(params, std::move(update_global));
|
||||||
|
|
||||||
|
// Note: callback will delete the message (ie, |params|) so we need to run completion_manager->CodeComplete before |callback|.
|
||||||
|
callback(global_code_complete_cache->cached_results, global_code_complete_cache->cached_diagnostics);
|
||||||
|
}
|
||||||
|
else if (non_global_code_complete_cache->IsCacheValid(params)) {
|
||||||
std::cerr << "[complete] Using cached completion results at " << params.position.ToString() << std::endl;
|
std::cerr << "[complete] Using cached completion results at " << params.position.ToString() << std::endl;
|
||||||
callback(code_complete_cache->cached_results, code_complete_cache->cached_diagnostics);
|
callback(non_global_code_complete_cache->cached_results, non_global_code_complete_cache->cached_diagnostics);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
completion_manager->CodeComplete(params, std::move(callback));
|
completion_manager->CodeComplete(params, std::move(callback));
|
||||||
@ -2645,7 +2671,8 @@ void QueryDbMain(Config* config, MultiQueueWaiter* waiter) {
|
|||||||
WorkingFiles working_files;
|
WorkingFiles working_files;
|
||||||
CompletionManager completion_manager(config, &project, &working_files);
|
CompletionManager completion_manager(config, &project, &working_files);
|
||||||
IncludeCompletion include_completion(config, &project);
|
IncludeCompletion include_completion(config, &project);
|
||||||
CodeCompleteCache code_complete_cache;
|
CodeCompleteCache global_code_complete_cache;
|
||||||
|
CodeCompleteCache non_global_code_complete_cache;
|
||||||
CodeCompleteCache signature_cache;
|
CodeCompleteCache signature_cache;
|
||||||
FileConsumer::SharedState file_consumer_shared;
|
FileConsumer::SharedState file_consumer_shared;
|
||||||
|
|
||||||
@ -2656,7 +2683,7 @@ void QueryDbMain(Config* config, MultiQueueWaiter* waiter) {
|
|||||||
bool did_work = QueryDbMainLoop(
|
bool did_work = QueryDbMainLoop(
|
||||||
config, &db, waiter, &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed,
|
config, &db, waiter, &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed,
|
||||||
&project, &file_consumer_shared, &working_files,
|
&project, &file_consumer_shared, &working_files,
|
||||||
&completion_manager, &include_completion, &code_complete_cache, &signature_cache);
|
&completion_manager, &include_completion, &global_code_complete_cache, &non_global_code_complete_cache, &signature_cache);
|
||||||
if (!did_work) {
|
if (!did_work) {
|
||||||
IpcManager* ipc = IpcManager::instance();
|
IpcManager* ipc = IpcManager::instance();
|
||||||
waiter->Wait({
|
waiter->Wait({
|
||||||
|
@ -226,13 +226,28 @@ std::string WorkingFile::FindClosestCallNameInBuffer(lsPosition position, int* a
|
|||||||
|
|
||||||
// Returns a position which contains the most recent ., ->, :, or ( for code
|
// Returns a position which contains the most recent ., ->, :, or ( for code
|
||||||
// completion purposes.
|
// completion purposes.
|
||||||
lsPosition WorkingFile::FindStableCompletionSource(lsPosition position) const {
|
lsPosition WorkingFile::FindStableCompletionSource(lsPosition position, bool* is_global_completion) const {
|
||||||
|
*is_global_completion = true;
|
||||||
|
|
||||||
int offset = GetOffsetForPosition(position, buffer_content);
|
int offset = GetOffsetForPosition(position, buffer_content);
|
||||||
|
|
||||||
while (offset > 0) {
|
while (offset > 0) {
|
||||||
char c = buffer_content[offset - 1];
|
char c = buffer_content[offset - 1];
|
||||||
if (!isalnum(c))
|
if (!isalnum(c)) {
|
||||||
|
// Global completion is everything except for dot (.), arrow (->), and
|
||||||
|
// double colon (::)
|
||||||
|
if (c == '.')
|
||||||
|
*is_global_completion = false;
|
||||||
|
if (offset > 2) {
|
||||||
|
char pc = buffer_content[offset - 2];
|
||||||
|
if (pc == ':' && c == ':')
|
||||||
|
*is_global_completion = false;
|
||||||
|
else if (pc == '-' && c == '>')
|
||||||
|
*is_global_completion = false;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
--offset;
|
--offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,10 @@ struct WorkingFile {
|
|||||||
|
|
||||||
// Returns a relatively stable completion position (it jumps back until there
|
// Returns a relatively stable completion position (it jumps back until there
|
||||||
// is a non-alphanumeric character).
|
// is a non-alphanumeric character).
|
||||||
lsPosition FindStableCompletionSource(lsPosition position) const;
|
//
|
||||||
|
// The out param |is_global_completion| is set to true if this looks like a
|
||||||
|
// global completion.
|
||||||
|
lsPosition FindStableCompletionSource(lsPosition position, bool* is_global_completion) const;
|
||||||
|
|
||||||
CXUnsavedFile AsUnsavedFile() const;
|
CXUnsavedFile AsUnsavedFile() const;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user