mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-26 01:21:57 +00:00
Some renames, promote view completion sessions to edit sessions
This commit is contained in:
parent
7840b7a015
commit
d816e2618a
@ -42,11 +42,13 @@ struct LruSessionCache {
|
||||
// Fetches the entry for |filename| and updates it's usage so it is less
|
||||
// likely to be evicted.
|
||||
CompletionSession* TryGetEntry(const std::string& filename);
|
||||
// TryGetEntry, except the return value captures ownership.
|
||||
std::unique_ptr<CompletionSession> TryTakeEntry(const std::string& fiilename);
|
||||
// Inserts an entry. Evicts the oldest unused entry if there is no space.
|
||||
void InsertEntry(std::unique_ptr<CompletionSession> session);
|
||||
};
|
||||
|
||||
struct CompletionManager {
|
||||
struct ClangCompleteManager {
|
||||
using OnComplete = std::function<void(NonElidedVector<lsCompletionItem> results, NonElidedVector<lsDiagnostic> diagnostics)>;
|
||||
|
||||
struct ParseRequest {
|
||||
@ -60,7 +62,7 @@ struct CompletionManager {
|
||||
OnComplete on_complete;
|
||||
};
|
||||
|
||||
CompletionManager(Config* config, Project* project, WorkingFiles* working_files);
|
||||
ClangCompleteManager(Config* config, Project* project, WorkingFiles* working_files);
|
||||
|
||||
// Start a code completion at the given location. |on_complete| will run when
|
||||
// completion results are available. |on_complete| may run on any thread.
|
@ -1,4 +1,4 @@
|
||||
#include "code_completion.h"
|
||||
#include "clang_complete.h"
|
||||
|
||||
#include "clang_utils.h"
|
||||
#include "libclangmm/Utility.h"
|
||||
@ -253,10 +253,10 @@ void EnsureDocumentParsed(CompletionSession* session,
|
||||
std::cerr << "[complete] Done creating active; did_fail=" << (*tu)->did_fail << std::endl;
|
||||
}
|
||||
|
||||
void CompletionParseMain(CompletionManager* completion_manager) {
|
||||
void CompletionParseMain(ClangCompleteManager* completion_manager) {
|
||||
while (true) {
|
||||
// Fetching the completion request blocks until we have a request.
|
||||
CompletionManager::ParseRequest request = completion_manager->parse_requests_.Dequeue();
|
||||
ClangCompleteManager::ParseRequest request = completion_manager->parse_requests_.Dequeue();
|
||||
|
||||
// If we don't get a session then that means we don't care about the file
|
||||
// anymore - abandon the request.
|
||||
@ -282,10 +282,10 @@ void CompletionParseMain(CompletionManager* completion_manager) {
|
||||
}
|
||||
}
|
||||
|
||||
void CompletionQueryMain(CompletionManager* completion_manager) {
|
||||
void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
||||
while (true) {
|
||||
// Fetching the completion request blocks until we have a request.
|
||||
std::unique_ptr<CompletionManager::CompletionRequest> request = completion_manager->completion_request_.Take();
|
||||
std::unique_ptr<ClangCompleteManager::CompletionRequest> request = completion_manager->completion_request_.Take();
|
||||
std::string path = request->location.textDocument.uri.GetPath();
|
||||
|
||||
CompletionSession* session = completion_manager->TryGetSession(path, true /*create_if_needed*/);
|
||||
@ -392,16 +392,27 @@ CompletionSession* LruSessionCache::TryGetEntry(const std::string& filename) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<CompletionSession> LruSessionCache::TryTakeEntry(const std::string& filename) {
|
||||
for (int i = 0; i < entries_.size(); ++i) {
|
||||
if (entries_[i]->file.filename == filename) {
|
||||
std::unique_ptr<CompletionSession> result = std::move(entries_[i]);
|
||||
entries_.erase(entries_.begin() + i);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void LruSessionCache::InsertEntry(std::unique_ptr<CompletionSession> session) {
|
||||
if (entries_.size() >= max_entries_)
|
||||
entries_.pop_back();
|
||||
entries_.insert(entries_.begin(), std::move(session));
|
||||
}
|
||||
|
||||
CompletionManager::ParseRequest::ParseRequest(const std::string& path)
|
||||
ClangCompleteManager::ParseRequest::ParseRequest(const std::string& path)
|
||||
: path(path), request_time(std::chrono::high_resolution_clock::now()) {}
|
||||
|
||||
CompletionManager::CompletionManager(Config* config, Project* project, WorkingFiles* working_files)
|
||||
ClangCompleteManager::ClangCompleteManager(Config* config, Project* project, WorkingFiles* working_files)
|
||||
: config_(config), project_(project), working_files_(working_files),
|
||||
view_sessions_(kMaxViewSessions), edit_sessions_(kMaxEditSessions) {
|
||||
new std::thread([&]() {
|
||||
@ -415,7 +426,7 @@ CompletionManager::CompletionManager(Config* config, Project* project, WorkingFi
|
||||
});
|
||||
}
|
||||
|
||||
void CompletionManager::CodeComplete(const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete) {
|
||||
void ClangCompleteManager::CodeComplete(const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete) {
|
||||
// completion thread will create the CompletionSession if needed.
|
||||
|
||||
auto request = MakeUnique<CompletionRequest>();
|
||||
@ -424,7 +435,7 @@ void CompletionManager::CodeComplete(const lsTextDocumentPositionParams& complet
|
||||
completion_request_.Set(std::move(request));
|
||||
}
|
||||
|
||||
void CompletionManager::NotifyView(const std::string& filename) {
|
||||
void ClangCompleteManager::NotifyView(const std::string& filename) {
|
||||
//
|
||||
// On view, we reparse only if the file has not been parsed. The existence of
|
||||
// a CompletionSession instance implies the file is already parsed or will be
|
||||
@ -442,7 +453,7 @@ void CompletionManager::NotifyView(const std::string& filename) {
|
||||
parse_requests_.Enqueue(ParseRequest(filename));
|
||||
}
|
||||
|
||||
void CompletionManager::NotifyEdit(const std::string& filename) {
|
||||
void ClangCompleteManager::NotifyEdit(const std::string& filename) {
|
||||
//
|
||||
// On edit, we reparse only if the file has not been parsed. The existence of
|
||||
// a CompletionSession instance implies the file is already parsed or will be
|
||||
@ -454,13 +465,17 @@ void CompletionManager::NotifyEdit(const std::string& filename) {
|
||||
if (edit_sessions_.TryGetEntry(filename))
|
||||
return;
|
||||
|
||||
if (std::unique_ptr<CompletionSession> session = view_sessions_.TryTakeEntry(filename)) {
|
||||
edit_sessions_.InsertEntry(std::move(session));
|
||||
}
|
||||
|
||||
std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl;
|
||||
edit_sessions_.InsertEntry(MakeUnique<CompletionSession>(
|
||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||
}
|
||||
|
||||
void CompletionManager::NotifySave(const std::string& filename) {
|
||||
void ClangCompleteManager::NotifySave(const std::string& filename) {
|
||||
//
|
||||
// On save, always reparse.
|
||||
//
|
||||
@ -476,7 +491,7 @@ void CompletionManager::NotifySave(const std::string& filename) {
|
||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||
}
|
||||
|
||||
CompletionSession* CompletionManager::TryGetSession(const std::string& filename, bool create_if_needed) {
|
||||
CompletionSession* ClangCompleteManager::TryGetSession(const std::string& filename, bool create_if_needed) {
|
||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||
|
||||
CompletionSession* session = edit_sessions_.TryGetEntry(filename);
|
@ -1,9 +1,9 @@
|
||||
// TODO: cleanup includes
|
||||
#include "cache.h"
|
||||
#include "code_completion.h"
|
||||
#include "clang_complete.h"
|
||||
#include "file_consumer.h"
|
||||
#include "match.h"
|
||||
#include "include_completion.h"
|
||||
#include "include_complete.h"
|
||||
#include "ipc_manager.h"
|
||||
#include "indexer.h"
|
||||
#include "query.h"
|
||||
@ -1525,8 +1525,8 @@ bool QueryDbMainLoop(
|
||||
Project* project,
|
||||
FileConsumer::SharedState* file_consumer_shared,
|
||||
WorkingFiles* working_files,
|
||||
CompletionManager* completion_manager,
|
||||
IncludeCompletion* include_completion,
|
||||
ClangCompleteManager* clang_complete,
|
||||
IncludeComplete* include_complete,
|
||||
CodeCompleteCache* global_code_complete_cache,
|
||||
CodeCompleteCache* non_global_code_complete_cache,
|
||||
CodeCompleteCache* signature_cache) {
|
||||
@ -1606,7 +1606,7 @@ bool QueryDbMainLoop(
|
||||
time.ResetAndPrint("[perf] Loaded compilation entries (" + std::to_string(project->entries.size()) + " files)");
|
||||
|
||||
// Start scanning include directories before dispatching project files, because that takes a long time.
|
||||
include_completion->Rescan();
|
||||
include_complete->Rescan();
|
||||
|
||||
time.Reset();
|
||||
project->ForAllFilteredFiles(config, [&](int i, const Project::Entry& entry) {
|
||||
@ -1884,8 +1884,8 @@ bool QueryDbMainLoop(
|
||||
|
||||
time.ResetAndPrint("[querydb] Loading cached index file for DidOpen (blocks CodeLens)");
|
||||
|
||||
include_completion->AddFile(working_file->filename);
|
||||
completion_manager->NotifyView(path);
|
||||
include_complete->AddFile(working_file->filename);
|
||||
clang_complete->NotifyView(path);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1894,7 +1894,7 @@ bool QueryDbMainLoop(
|
||||
auto msg = static_cast<Ipc_TextDocumentDidChange*>(message.get());
|
||||
std::string path = msg->params.textDocument.uri.GetPath();
|
||||
working_files->OnChange(msg->params);
|
||||
completion_manager->NotifyEdit(path);
|
||||
clang_complete->NotifyEdit(path);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1933,7 +1933,7 @@ bool QueryDbMainLoop(
|
||||
queue_do_index->PriorityEnqueue(Index_DoIndex(index_type, project->FindCompilationEntryForFile(path), working_file->buffer_content, true /*is_interactive*/));
|
||||
}
|
||||
|
||||
completion_manager->NotifySave(path);
|
||||
clang_complete->NotifySave(path);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1966,14 +1966,13 @@ bool QueryDbMainLoop(
|
||||
|
||||
case IpcId::TextDocumentCompletion: {
|
||||
auto msg = static_cast<Ipc_TextDocumentComplete*>(message.get());
|
||||
lsTextDocumentPositionParams& params = msg->params;
|
||||
|
||||
std::string path = params.textDocument.uri.GetPath();
|
||||
std::string path = msg->params.textDocument.uri.GetPath();
|
||||
WorkingFile* file = working_files->GetFileByFilename(path);
|
||||
|
||||
// TODO: We should scan include directories to add any missing paths
|
||||
|
||||
std::string buffer_line = file->all_buffer_lines[params.position.line];
|
||||
std::string buffer_line = file->all_buffer_lines[msg->params.position.line];
|
||||
|
||||
if (ShouldRunIncludeCompletion(buffer_line)) {
|
||||
Out_TextDocumentComplete complete_response;
|
||||
@ -1981,20 +1980,20 @@ bool QueryDbMainLoop(
|
||||
complete_response.result.isIncomplete = false;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(include_completion->completion_items_mutex, std::defer_lock);
|
||||
if (include_completion->is_scanning)
|
||||
std::unique_lock<std::mutex> lock(include_complete->completion_items_mutex, std::defer_lock);
|
||||
if (include_complete->is_scanning)
|
||||
lock.lock();
|
||||
complete_response.result.items.assign(
|
||||
include_completion->completion_items.begin(),
|
||||
include_completion->completion_items.end());
|
||||
include_complete->completion_items.begin(),
|
||||
include_complete->completion_items.end());
|
||||
if (lock)
|
||||
lock.unlock();
|
||||
|
||||
// Update textEdit params.
|
||||
for (lsCompletionItem& item : complete_response.result.items) {
|
||||
item.textEdit->range.start.line = params.position.line;
|
||||
item.textEdit->range.start.line = msg->params.position.line;
|
||||
item.textEdit->range.start.character = 0;
|
||||
item.textEdit->range.end.line = params.position.line;
|
||||
item.textEdit->range.end.line = msg->params.position.line;
|
||||
item.textEdit->range.end.character = (int)buffer_line.size();
|
||||
}
|
||||
}
|
||||
@ -2005,9 +2004,9 @@ bool QueryDbMainLoop(
|
||||
else {
|
||||
bool is_global_completion = false;
|
||||
if (file)
|
||||
params.position = file->FindStableCompletionSource(params.position, &is_global_completion);
|
||||
msg->params.position = file->FindStableCompletionSource(msg->params.position, &is_global_completion);
|
||||
|
||||
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) {
|
||||
ClangCompleteManager::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 ipc = IpcManager::instance();
|
||||
|
||||
@ -2049,25 +2048,25 @@ bool QueryDbMainLoop(
|
||||
}, message.release(), std::placeholders::_1, std::placeholders::_2);
|
||||
|
||||
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;
|
||||
std::cerr << "[complete] Early-returning cached global completion results at " << msg->params.position.ToString() << std::endl;
|
||||
|
||||
CompletionManager::OnComplete update_global = std::bind([global_code_complete_cache](NonElidedVector<lsCompletionItem> results, NonElidedVector<lsDiagnostic> diagnostics) {
|
||||
ClangCompleteManager::OnComplete freshen_global = [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));
|
||||
};
|
||||
clang_complete->CodeComplete(msg->params, std::move(freshen_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;
|
||||
else if (non_global_code_complete_cache->IsCacheValid(msg->params)) {
|
||||
std::cerr << "[complete] Using cached completion results at " << msg->params.position.ToString() << std::endl;
|
||||
callback(non_global_code_complete_cache->cached_results, non_global_code_complete_cache->cached_diagnostics);
|
||||
}
|
||||
else {
|
||||
completion_manager->CodeComplete(params, std::move(callback));
|
||||
clang_complete->CodeComplete(msg->params, std::move(callback));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2089,7 +2088,7 @@ bool QueryDbMainLoop(
|
||||
if (search.empty())
|
||||
break;
|
||||
|
||||
CompletionManager::OnComplete callback = std::bind([signature_cache](BaseIpcMessage* message, std::string search, int active_param, const NonElidedVector<lsCompletionItem>& results) {
|
||||
ClangCompleteManager::OnComplete callback = std::bind([signature_cache](BaseIpcMessage* message, std::string search, int active_param, const NonElidedVector<lsCompletionItem>& results) {
|
||||
auto msg = static_cast<Ipc_TextDocumentSignatureHelp*>(message);
|
||||
auto ipc = IpcManager::instance();
|
||||
|
||||
@ -2142,7 +2141,7 @@ bool QueryDbMainLoop(
|
||||
callback(signature_cache->cached_results, signature_cache->cached_diagnostics);
|
||||
}
|
||||
else {
|
||||
completion_manager->CodeComplete(params, std::move(callback));
|
||||
clang_complete->CodeComplete(params, std::move(callback));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -2449,7 +2448,7 @@ bool QueryDbMainLoop(
|
||||
lsDocumentUri file_as_uri = msg->params.textDocument.uri;
|
||||
std::string path = file_as_uri.GetPath();
|
||||
|
||||
completion_manager->NotifyView(path);
|
||||
clang_complete->NotifyView(path);
|
||||
|
||||
QueryFile* file = FindFile(db, path);
|
||||
if (!file) {
|
||||
@ -2669,8 +2668,8 @@ void QueryDbMain(Config* config, MultiQueueWaiter* waiter) {
|
||||
|
||||
Project project;
|
||||
WorkingFiles working_files;
|
||||
CompletionManager completion_manager(config, &project, &working_files);
|
||||
IncludeCompletion include_completion(config, &project);
|
||||
ClangCompleteManager clang_complete(config, &project, &working_files);
|
||||
IncludeComplete include_complete(config, &project);
|
||||
CodeCompleteCache global_code_complete_cache;
|
||||
CodeCompleteCache non_global_code_complete_cache;
|
||||
CodeCompleteCache signature_cache;
|
||||
@ -2683,7 +2682,7 @@ void QueryDbMain(Config* config, MultiQueueWaiter* waiter) {
|
||||
bool did_work = QueryDbMainLoop(
|
||||
config, &db, waiter, &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed,
|
||||
&project, &file_consumer_shared, &working_files,
|
||||
&completion_manager, &include_completion, &global_code_complete_cache, &non_global_code_complete_cache, &signature_cache);
|
||||
&clang_complete, &include_complete, &global_code_complete_cache, &non_global_code_complete_cache, &signature_cache);
|
||||
if (!did_work) {
|
||||
IpcManager* ipc = IpcManager::instance();
|
||||
waiter->Wait({
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "include_completion.h"
|
||||
#include "include_complete.h"
|
||||
|
||||
#include "match.h"
|
||||
#include "platform.h"
|
||||
@ -100,10 +100,10 @@ lsCompletionItem BuildCompletionItem(Config* config, const std::string& path, bo
|
||||
|
||||
} // namespace
|
||||
|
||||
IncludeCompletion::IncludeCompletion(Config* config, Project* project)
|
||||
IncludeComplete::IncludeComplete(Config* config, Project* project)
|
||||
: is_scanning(false), config_(config), project_(project) {}
|
||||
|
||||
void IncludeCompletion::Rescan() {
|
||||
void IncludeComplete::Rescan() {
|
||||
if (is_scanning)
|
||||
return;
|
||||
|
||||
@ -130,7 +130,7 @@ void IncludeCompletion::Rescan() {
|
||||
});
|
||||
}
|
||||
|
||||
void IncludeCompletion::AddFile(const std::string& absolute_path) {
|
||||
void IncludeComplete::AddFile(const std::string& absolute_path) {
|
||||
if (!EndsWithAny(absolute_path, config_->includeCompletionWhitelistLiteralEnding))
|
||||
return;
|
||||
if (match_ && !match_->IsMatch(absolute_path))
|
||||
@ -151,7 +151,7 @@ void IncludeCompletion::AddFile(const std::string& absolute_path) {
|
||||
}
|
||||
}
|
||||
|
||||
void IncludeCompletion::InsertIncludesFromDirectory(
|
||||
void IncludeComplete::InsertIncludesFromDirectory(
|
||||
std::string directory,
|
||||
bool use_angle_brackets) {
|
||||
directory = NormalizePath(directory);
|
||||
@ -177,7 +177,7 @@ void IncludeCompletion::InsertIncludesFromDirectory(
|
||||
}
|
||||
}
|
||||
|
||||
void IncludeCompletion::InsertStlIncludes() {
|
||||
void IncludeComplete::InsertStlIncludes() {
|
||||
std::lock_guard<std::mutex> lock(completion_items_mutex);
|
||||
for (const char* stl_header : kStandardLibraryIncludes) {
|
||||
completion_items.push_back(BuildCompletionItem(config_, stl_header, true /*use_angle_brackets*/, true /*is_stl*/));
|
@ -9,8 +9,8 @@
|
||||
struct GroupMatch;
|
||||
struct Project;
|
||||
|
||||
struct IncludeCompletion {
|
||||
IncludeCompletion(Config* config, Project* project);
|
||||
struct IncludeComplete {
|
||||
IncludeComplete(Config* config, Project* project);
|
||||
|
||||
// Starts scanning directories. Clears existing cache.
|
||||
void Rescan();
|
Loading…
Reference in New Issue
Block a user