mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-21 16:09:40 +00:00
Simplify completion session management code.
This commit is contained in:
parent
3e9cffcc62
commit
76cc110cc2
@ -336,8 +336,9 @@ void CompletionParseMain(ClangCompleteManager* completion_manager) {
|
|||||||
// If we don't get a session then that means we don't care about the file
|
// If we don't get a session then that means we don't care about the file
|
||||||
// anymore - abandon the request.
|
// anymore - abandon the request.
|
||||||
std::shared_ptr<CompletionSession> session =
|
std::shared_ptr<CompletionSession> session =
|
||||||
completion_manager->TryGetEditSession(request.path,
|
completion_manager->TryGetSession(request.path,
|
||||||
false /*create_if_needed*/);
|
false /*mark_as_completion*/,
|
||||||
|
false /*create_if_needed*/);
|
||||||
if (!session)
|
if (!session)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -369,7 +370,8 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
|||||||
std::string path = request->document.uri.GetPath();
|
std::string path = request->document.uri.GetPath();
|
||||||
|
|
||||||
std::shared_ptr<CompletionSession> session =
|
std::shared_ptr<CompletionSession> session =
|
||||||
completion_manager->TryGetEditSession(path, true /*create_if_needed*/);
|
completion_manager->TryGetSession(path, true /*mark_as_completion*/,
|
||||||
|
true /*create_if_needed*/);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(session->tu_lock);
|
std::lock_guard<std::mutex> lock(session->tu_lock);
|
||||||
Timer timer;
|
Timer timer;
|
||||||
@ -548,8 +550,8 @@ ClangCompleteManager::ClangCompleteManager(Config* config,
|
|||||||
working_files_(working_files),
|
working_files_(working_files),
|
||||||
on_diagnostic_(on_diagnostic),
|
on_diagnostic_(on_diagnostic),
|
||||||
on_index_(on_index),
|
on_index_(on_index),
|
||||||
view_sessions_(kMaxViewSessions),
|
preloaded_sessions_(kMaxPreloadedSessions),
|
||||||
edit_sessions_(kMaxEditSessions) {
|
completion_sessions_(kMaxCompletionSessions) {
|
||||||
new std::thread([&]() {
|
new std::thread([&]() {
|
||||||
SetCurrentThreadName("completequery");
|
SetCurrentThreadName("completequery");
|
||||||
CompletionQueryMain(this);
|
CompletionQueryMain(this);
|
||||||
@ -600,44 +602,19 @@ void ClangCompleteManager::NotifyView(const std::string& filename) {
|
|||||||
// parsed soon.
|
// parsed soon.
|
||||||
//
|
//
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
// Only reparse the file if we create a new CompletionSession.
|
||||||
|
if (EnsureCompletionOrCreatePreloadSession(filename))
|
||||||
// Already a view or edit session, do nothing.
|
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||||
if (view_sessions_.TryGetEntry(filename) ||
|
|
||||||
edit_sessions_.TryGetEntry(filename)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new view session.
|
|
||||||
view_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
|
||||||
parse_requests_.Enqueue(ParseRequest(filename));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangCompleteManager::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
|
// We treat an edit like a view, because the completion logic will handle
|
||||||
// a CompletionSession instance implies the file is already parsed or will be
|
// moving the CompletionSession instance from preloaded to completion
|
||||||
// parsed soon.
|
// storage.
|
||||||
//
|
//
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
NotifyView(filename);
|
||||||
|
|
||||||
if (edit_sessions_.TryGetEntry(filename))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Move the session from view to edit.
|
|
||||||
std::shared_ptr<CompletionSession> view_session =
|
|
||||||
view_sessions_.TryTakeEntry(filename);
|
|
||||||
if (view_session) {
|
|
||||||
edit_sessions_.InsertEntry(view_session);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No view session, create a new session.
|
|
||||||
edit_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
|
||||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangCompleteManager::NotifySave(const std::string& filename) {
|
void ClangCompleteManager::NotifySave(const std::string& filename) {
|
||||||
@ -645,22 +622,7 @@ void ClangCompleteManager::NotifySave(const std::string& filename) {
|
|||||||
// On save, always reparse.
|
// On save, always reparse.
|
||||||
//
|
//
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
EnsureCompletionOrCreatePreloadSession(filename);
|
||||||
|
|
||||||
// If for whatever reason we have a view session and not an edit session,
|
|
||||||
// move the session from view to edit.
|
|
||||||
std::shared_ptr<CompletionSession> view_session =
|
|
||||||
view_sessions_.TryTakeEntry(filename);
|
|
||||||
if (view_session) {
|
|
||||||
edit_sessions_.InsertEntry(view_session);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no edit session create one.
|
|
||||||
if (!edit_sessions_.TryGetEntry(filename)) {
|
|
||||||
edit_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,39 +635,60 @@ void ClangCompleteManager::NotifyClose(const std::string& filename) {
|
|||||||
|
|
||||||
// Take and drop. It's okay if we don't actually drop the file, it'll
|
// Take and drop. It's okay if we don't actually drop the file, it'll
|
||||||
// eventually get pushed out of the caches as the user opens other files.
|
// eventually get pushed out of the caches as the user opens other files.
|
||||||
auto view_ptr = view_sessions_.TryTakeEntry(filename);
|
auto preloaded_ptr = preloaded_sessions_.TryTakeEntry(filename);
|
||||||
LOG_IF_S(INFO, !!view_ptr)
|
LOG_IF_S(INFO, !!preloaded_ptr)
|
||||||
<< "Dropped view-based code completion session for " << filename;
|
<< "Dropped preloaded-based code completion session for " << filename;
|
||||||
auto edit_ptr = edit_sessions_.TryTakeEntry(filename);
|
auto completion_ptr = completion_sessions_.TryTakeEntry(filename);
|
||||||
LOG_IF_S(INFO, !!edit_ptr)
|
LOG_IF_S(INFO, !!completion_ptr)
|
||||||
<< "Dropped edit-based code completion session for " << filename;
|
<< "Dropped completion-based code completion session for " << filename;
|
||||||
|
|
||||||
// We should never have both a view and edit session.
|
// We should never have both a preloaded and completion session.
|
||||||
assert((view_ptr && edit_ptr) == false);
|
assert((preloaded_ptr && completion_ptr) == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CompletionSession> ClangCompleteManager::TryGetEditSession(
|
bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession(
|
||||||
|
const std::string& filename) {
|
||||||
|
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||||
|
if (!preloaded_sessions_.TryGetEntry(filename) &&
|
||||||
|
!completion_sessions_.TryGetEntry(filename)) {
|
||||||
|
auto session = std::make_shared<CompletionSession>(
|
||||||
|
project_->FindCompilationEntryForFile(filename), working_files_);
|
||||||
|
preloaded_sessions_.InsertEntry(session);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<CompletionSession> ClangCompleteManager::TryGetSession(
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
|
bool mark_as_completion,
|
||||||
bool create_if_needed) {
|
bool create_if_needed) {
|
||||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||||
|
|
||||||
// Try to find a view session. If found move it to |edit_sessions_|.
|
// Try to find a preloaded session.
|
||||||
std::shared_ptr<CompletionSession> view_session =
|
std::shared_ptr<CompletionSession> preloaded_session =
|
||||||
view_sessions_.TryTakeEntry(filename);
|
preloaded_sessions_.TryGetEntry(filename);
|
||||||
if (view_session) {
|
|
||||||
assert(!edit_sessions_.TryGetEntry(filename));
|
if (preloaded_session) {
|
||||||
edit_sessions_.InsertEntry(view_session);
|
// If this request is for a completion, we should move it to
|
||||||
return view_session;
|
// |completion_sessions|.
|
||||||
|
if (mark_as_completion) {
|
||||||
|
assert(!completion_sessions_.TryGetEntry(filename));
|
||||||
|
preloaded_sessions_.TryTakeEntry(filename);
|
||||||
|
completion_sessions_.InsertEntry(preloaded_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
return preloaded_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find an edit session. If none create if requested.
|
// Try to find a completion session. If none create one.
|
||||||
std::shared_ptr<CompletionSession> edit_session =
|
std::shared_ptr<CompletionSession> completion_session =
|
||||||
edit_sessions_.TryTakeEntry(filename);
|
completion_sessions_.TryTakeEntry(filename);
|
||||||
if (!edit_session && create_if_needed) {
|
if (!completion_session && create_if_needed) {
|
||||||
edit_session = std::make_shared<CompletionSession>(
|
completion_session = std::make_shared<CompletionSession>(
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_);
|
project_->FindCompilationEntryForFile(filename), working_files_);
|
||||||
edit_sessions_.InsertEntry(edit_session);
|
completion_sessions_.InsertEntry(completion_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
return edit_session;
|
return completion_session;
|
||||||
}
|
}
|
||||||
|
@ -99,15 +99,18 @@ struct ClangCompleteManager {
|
|||||||
// completion session will be dropped.
|
// completion session will be dropped.
|
||||||
void NotifyClose(const std::string& filename);
|
void NotifyClose(const std::string& filename);
|
||||||
|
|
||||||
|
// Ensures there is a completion or preloaded session. Returns true if a new
|
||||||
|
// session was created.
|
||||||
|
bool EnsureCompletionOrCreatePreloadSession(const std::string& filename);
|
||||||
// Tries to find an edit session for |filename|. This will move the session
|
// Tries to find an edit session for |filename|. This will move the session
|
||||||
// from view to edit.
|
// from view to edit.
|
||||||
std::shared_ptr<CompletionSession> TryGetEditSession(
|
std::shared_ptr<CompletionSession> TryGetSession(const std::string& filename,
|
||||||
const std::string& filename,
|
bool mark_as_completion,
|
||||||
bool create_if_needed);
|
bool create_if_needed);
|
||||||
|
|
||||||
// TODO: make these configurable.
|
// TODO: make these configurable.
|
||||||
const int kMaxViewSessions = 10;
|
const int kMaxPreloadedSessions = 10;
|
||||||
const int kMaxEditSessions = 5;
|
const int kMaxCompletionSessions = 5;
|
||||||
|
|
||||||
// Global state.
|
// Global state.
|
||||||
Config* config_;
|
Config* config_;
|
||||||
@ -116,11 +119,13 @@ struct ClangCompleteManager {
|
|||||||
OnDiagnostic on_diagnostic_;
|
OnDiagnostic on_diagnostic_;
|
||||||
OnIndex on_index_;
|
OnIndex on_index_;
|
||||||
|
|
||||||
// Sessions which have never had a real text-edit applied, but are preloaded
|
// CompletionSession instances which are preloaded, ie, files which the user
|
||||||
// to give a fast initial experience.
|
// has viewed but not requested code completion for.
|
||||||
LruSessionCache view_sessions_;
|
LruSessionCache preloaded_sessions_;
|
||||||
// Completion sessions which have been edited.
|
// CompletionSession instances which the user has actually performed
|
||||||
LruSessionCache edit_sessions_;
|
// completion on. This is more rare so these instances tend to stay alive
|
||||||
|
// much longer than the ones in |preloaded_sessions_|.
|
||||||
|
LruSessionCache completion_sessions_;
|
||||||
// Mutex which protects |view_sessions_| and |edit_sessions_|.
|
// Mutex which protects |view_sessions_| and |edit_sessions_|.
|
||||||
std::mutex sessions_lock_;
|
std::mutex sessions_lock_;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user