diff --git a/src/code_completion.cc b/src/code_completion.cc index 14b3752f..906d1575 100644 --- a/src/code_completion.cc +++ b/src/code_completion.cc @@ -208,7 +208,43 @@ std::string BuildDetailString(CXCompletionString completion_string) { return detail; } -void CompletionMain(CompletionManager* completion_manager) { +void EnsureDocumentParsed(CompletionSession* session, + std::unique_ptr* tu, + std::unique_ptr* index) { + // Nothing to do. We already have a translation unit and an index. + if (*tu && *index) + return; + + std::vector args = session->file.args; + args.push_back("-fparse-all-comments"); + + std::vector unsaved = session->working_files->AsUnsavedFiles(); + + std::cerr << "[complete] Creating completion session with arguments " << StringJoin(args) << std::endl; + *index = MakeUnique(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/); + *tu = MakeUnique(*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 path = completion_manager->reparse_request.Take(); + + CompletionSession* session = completion_manager->GetOrOpenSession(*path); + std::unique_ptr parsing; + std::unique_ptr parsing_index; + + EnsureDocumentParsed(session, &parsing, &parsing_index); + + // Swap out active. + std::lock_guard lock(session->usage_lock); + session->active = std::move(parsing); + session->active_index = std::move(parsing_index); + } +} + +void CompletionQueryMain(CompletionManager* completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. std::unique_ptr 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()); std::lock_guard lock(session->usage_lock); - session->EnsureCompletionState(); + EnsureDocumentParsed(session, &session->active, &session->active_index); unsigned line = request->location.position.line + 1; unsigned column = request->location.position.character + 1; @@ -232,8 +268,6 @@ void CompletionMain(CompletionManager* completion_manager) { std::vector unsaved = completion_manager->working_files->AsUnsavedFiles(); timer.ResetAndPrint("[complete] Fetching unsaved files"); - - timer.Reset(); CXCodeCompleteResults* cx_results = clang_codeCompleteAt( session->active->cx_tu, @@ -284,30 +318,16 @@ CompletionSession::CompletionSession(const Project::Entry& file, WorkingFiles* w CompletionSession::~CompletionSession() {} -void CompletionSession::EnsureCompletionState() { - if (active && active_index) { - // TODO: Investigate if this helps performance. It causes crashes on windows. - //std::vector unsaved = working_files->AsUnsavedFiles(); - //active->ReparseTranslationUnit(unsaved); - return; - } - - std::vector args = file.args; - args.push_back("-fparse-all-comments"); - - std::vector unsaved = working_files->AsUnsavedFiles(); - - std::cerr << "[complete] Creating completion session with arguments " << StringJoin(args) << std::endl; - active_index = MakeUnique(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/); - active = MakeUnique(*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) : config(config), project(project), working_files(working_files) { new std::thread([&]() { - SetCurrentThreadName("complete"); - CompletionMain(this); + SetCurrentThreadName("completequery"); + 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(); } -void CompletionManager::DropAllSessionsExcept(const std::string& filename) { +void CompletionManager::UpdateActiveSession(const std::string& filename) { + // Drop all sessions except for |filename|. for (auto& session : sessions) { if (session->file.filename == filename) continue; @@ -349,4 +370,7 @@ void CompletionManager::DropAllSessionsExcept(const std::string& filename) { session->active.reset(); session->active_index.reset(); } + + // Reparse |filename|. + reparse_request.Set(MakeUnique(filename)); } \ No newline at end of file diff --git a/src/code_completion.h b/src/code_completion.h index a9f8b1ed..6c1c4fa5 100644 --- a/src/code_completion.h +++ b/src/code_completion.h @@ -31,9 +31,6 @@ struct CompletionSession { CompletionSession(const Project::Entry& file, WorkingFiles* working_files); ~CompletionSession(); - - // Validate that we have |active| and |active_index|. - void EnsureCompletionState(); }; struct CompletionManager { @@ -43,6 +40,7 @@ struct CompletionManager { WorkingFiles* working_files; using OnComplete = std::function results)>; + struct CompletionRequest { lsTextDocumentPositionParams location; OnComplete on_complete; @@ -50,6 +48,9 @@ struct CompletionManager { AtomicObject completion_request; + // Request that the given path be reparsed. + AtomicObject reparse_request; + CompletionManager(IndexerConfig* config, Project* project, WorkingFiles* working_files); // 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); 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); }; \ No newline at end of file diff --git a/src/command_line.cc b/src/command_line.cc index 5936f7f7..714b03c3 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -1543,7 +1543,7 @@ bool QueryDbMainLoop( working_file->pending_new_index_content = working_file->buffer_content; queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::Parse, project->FindCompilationEntryForFile(path))); } - completion_manager->DropAllSessionsExcept(""); + completion_manager->UpdateActiveSession(path); break; }