Reparse document after save for code completion, but don't drop existing completion state until after reparse is done.

This commit is contained in:
Jacob Dufault 2017-05-10 23:25:41 -07:00
parent 20429ed397
commit 4c487ab797
3 changed files with 60 additions and 31 deletions

View File

@ -208,7 +208,43 @@ std::string BuildDetailString(CXCompletionString completion_string) {
return detail; return detail;
} }
void CompletionMain(CompletionManager* completion_manager) { void EnsureDocumentParsed(CompletionSession* session,
std::unique_ptr<clang::TranslationUnit>* tu,
std::unique_ptr<clang::Index>* index) {
// Nothing to do. We already have a translation unit and an index.
if (*tu && *index)
return;
std::vector<std::string> args = session->file.args;
args.push_back("-fparse-all-comments");
std::vector<CXUnsavedFile> unsaved = session->working_files->AsUnsavedFiles();
std::cerr << "[complete] Creating completion session with arguments " << StringJoin(args) << std::endl;
*index = MakeUnique<clang::Index>(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/);
*tu = MakeUnique<clang::TranslationUnit>(*index->get(), session->file.filename, args, unsaved, Flags());
std::cerr << "[complete] Done creating active; did_fail=" << (*tu)->did_fail << std::endl;
}
void CompletionParseMain(CompletionManager* completion_manager) {
while (true) {
// Fetching the completion request blocks until we have a request.
std::unique_ptr<std::string> path = completion_manager->reparse_request.Take();
CompletionSession* session = completion_manager->GetOrOpenSession(*path);
std::unique_ptr<clang::TranslationUnit> parsing;
std::unique_ptr<clang::Index> parsing_index;
EnsureDocumentParsed(session, &parsing, &parsing_index);
// Swap out active.
std::lock_guard<std::mutex> lock(session->usage_lock);
session->active = std::move(parsing);
session->active_index = std::move(parsing_index);
}
}
void CompletionQueryMain(CompletionManager* completion_manager) {
while (true) { while (true) {
// Fetching the completion request blocks until we have a request. // Fetching the completion request blocks until we have a request.
std::unique_ptr<CompletionManager::CompletionRequest> request = completion_manager->completion_request.Take(); std::unique_ptr<CompletionManager::CompletionRequest> request = completion_manager->completion_request.Take();
@ -219,7 +255,7 @@ void CompletionMain(CompletionManager* completion_manager) {
CompletionSession* session = completion_manager->GetOrOpenSession(request->location.textDocument.uri.GetPath()); CompletionSession* session = completion_manager->GetOrOpenSession(request->location.textDocument.uri.GetPath());
std::lock_guard<std::mutex> lock(session->usage_lock); std::lock_guard<std::mutex> lock(session->usage_lock);
session->EnsureCompletionState(); EnsureDocumentParsed(session, &session->active, &session->active_index);
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;
@ -232,8 +268,6 @@ void CompletionMain(CompletionManager* completion_manager) {
std::vector<CXUnsavedFile> unsaved = completion_manager->working_files->AsUnsavedFiles(); std::vector<CXUnsavedFile> unsaved = completion_manager->working_files->AsUnsavedFiles();
timer.ResetAndPrint("[complete] Fetching unsaved files"); timer.ResetAndPrint("[complete] Fetching unsaved files");
timer.Reset(); timer.Reset();
CXCodeCompleteResults* cx_results = clang_codeCompleteAt( CXCodeCompleteResults* cx_results = clang_codeCompleteAt(
session->active->cx_tu, session->active->cx_tu,
@ -284,30 +318,16 @@ CompletionSession::CompletionSession(const Project::Entry& file, WorkingFiles* w
CompletionSession::~CompletionSession() {} CompletionSession::~CompletionSession() {}
void CompletionSession::EnsureCompletionState() {
if (active && active_index) {
// TODO: Investigate if this helps performance. It causes crashes on windows.
//std::vector<CXUnsavedFile> unsaved = working_files->AsUnsavedFiles();
//active->ReparseTranslationUnit(unsaved);
return;
}
std::vector<std::string> args = file.args;
args.push_back("-fparse-all-comments");
std::vector<CXUnsavedFile> unsaved = working_files->AsUnsavedFiles();
std::cerr << "[complete] Creating completion session with arguments " << StringJoin(args) << std::endl;
active_index = MakeUnique<clang::Index>(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/);
active = MakeUnique<clang::TranslationUnit>(*active_index, file.filename, args, unsaved, Flags());
std::cerr << "[complete] Done creating active; did_fail=" << active->did_fail << std::endl;
}
CompletionManager::CompletionManager(IndexerConfig* config, Project* project, WorkingFiles* working_files) CompletionManager::CompletionManager(IndexerConfig* config, Project* project, WorkingFiles* working_files)
: config(config), project(project), working_files(working_files) { : config(config), project(project), working_files(working_files) {
new std::thread([&]() { new std::thread([&]() {
SetCurrentThreadName("complete"); SetCurrentThreadName("completequery");
CompletionMain(this); CompletionQueryMain(this);
});
new std::thread([&]() {
SetCurrentThreadName("completeparse");
CompletionParseMain(this);
}); });
} }
@ -340,7 +360,8 @@ CompletionSession* CompletionManager::GetOrOpenSession(const std::string& filena
return sessions[sessions.size() - 1].get(); return sessions[sessions.size() - 1].get();
} }
void CompletionManager::DropAllSessionsExcept(const std::string& filename) { void CompletionManager::UpdateActiveSession(const std::string& filename) {
// Drop all sessions except for |filename|.
for (auto& session : sessions) { for (auto& session : sessions) {
if (session->file.filename == filename) if (session->file.filename == filename)
continue; continue;
@ -349,4 +370,7 @@ void CompletionManager::DropAllSessionsExcept(const std::string& filename) {
session->active.reset(); session->active.reset();
session->active_index.reset(); session->active_index.reset();
} }
// Reparse |filename|.
reparse_request.Set(MakeUnique<std::string>(filename));
} }

View File

@ -31,9 +31,6 @@ struct CompletionSession {
CompletionSession(const Project::Entry& file, WorkingFiles* working_files); CompletionSession(const Project::Entry& file, WorkingFiles* working_files);
~CompletionSession(); ~CompletionSession();
// Validate that we have |active| and |active_index|.
void EnsureCompletionState();
}; };
struct CompletionManager { struct CompletionManager {
@ -43,6 +40,7 @@ struct CompletionManager {
WorkingFiles* working_files; WorkingFiles* working_files;
using OnComplete = std::function<void(NonElidedVector<lsCompletionItem> results)>; using OnComplete = std::function<void(NonElidedVector<lsCompletionItem> results)>;
struct CompletionRequest { struct CompletionRequest {
lsTextDocumentPositionParams location; lsTextDocumentPositionParams location;
OnComplete on_complete; OnComplete on_complete;
@ -50,6 +48,9 @@ struct CompletionManager {
AtomicObject<CompletionRequest> completion_request; AtomicObject<CompletionRequest> completion_request;
// Request that the given path be reparsed.
AtomicObject<std::string> reparse_request;
CompletionManager(IndexerConfig* config, Project* project, WorkingFiles* working_files); CompletionManager(IndexerConfig* config, Project* project, WorkingFiles* working_files);
// Start a code completion at the given location. |on_complete| will run when // Start a code completion at the given location. |on_complete| will run when
@ -57,5 +58,9 @@ struct CompletionManager {
void CodeComplete(const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete); void CodeComplete(const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete);
CompletionSession* GetOrOpenSession(const std::string& filename); CompletionSession* GetOrOpenSession(const std::string& filename);
void DropAllSessionsExcept(const std::string& filename);
// Set the new active session. We will drop clang state for all other
// sessions and begin reparsing the session for |filename| to ensure
// completions are always fast.
void UpdateActiveSession(const std::string& filename);
}; };

View File

@ -1543,7 +1543,7 @@ bool QueryDbMainLoop(
working_file->pending_new_index_content = working_file->buffer_content; working_file->pending_new_index_content = working_file->buffer_content;
queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::Parse, project->FindCompilationEntryForFile(path))); queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::Parse, project->FindCompilationEntryForFile(path)));
} }
completion_manager->DropAllSessionsExcept(""); completion_manager->UpdateActiveSession(path);
break; break;
} }