From d9bcaecf25fdd72c3f7a6b59d731b6988f98ecda Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 3 Apr 2018 23:05:41 -0700 Subject: [PATCH] Use global config. --- src/cache_manager.cc | 20 ++-- src/clang_complete.cc | 22 ++--- src/clang_complete.h | 5 +- src/clang_indexer.cc | 34 +++---- src/clang_utils.cc | 2 +- src/command_line.cc | 29 +++--- src/config.cc | 2 +- src/config.h | 14 +-- src/diagnostics_engine.cc | 8 +- src/diagnostics_engine.h | 2 +- src/fuzzy_match.cc | 2 +- src/iindexer.cc | 6 +- src/iindexer.h | 2 - src/import_pipeline.cc | 50 +++++----- src/import_pipeline.h | 8 +- src/include_complete.cc | 43 +++++---- src/include_complete.h | 3 +- src/indexer.h | 2 - src/lex_utils.cc | 1 - src/lsp.cc | 1 - src/message_handler.cc | 6 +- src/message_handler.h | 3 +- src/messages/ccls_base.cc | 10 +- src/messages/ccls_callers.cc | 4 +- src/messages/ccls_derived.cc | 10 +- src/messages/ccls_freshen_index.cc | 3 +- src/messages/ccls_random.cc | 10 +- src/messages/ccls_vars.cc | 5 +- src/messages/initialize.cc | 31 +++---- src/messages/text_document_code_lens.cc | 2 +- src/messages/text_document_completion.cc | 14 +-- src/messages/text_document_definition.cc | 6 +- src/messages/text_document_did_change.cc | 2 +- src/messages/text_document_did_save.cc | 2 +- src/messages/text_document_references.cc | 6 +- src/messages/text_document_type_definition.cc | 2 +- .../workspace_did_change_configuration.cc | 5 +- src/messages/workspace_symbol.cc | 12 +-- src/project.cc | 92 ++++++++----------- src/project.h | 8 +- src/query_utils.cc | 11 +-- src/query_utils.h | 4 +- src/test.cc | 6 +- 43 files changed, 211 insertions(+), 299 deletions(-) diff --git a/src/cache_manager.cc b/src/cache_manager.cc index 0fc06613..19e7bb59 100644 --- a/src/cache_manager.cc +++ b/src/cache_manager.cc @@ -21,7 +21,7 @@ struct RealCacheManager : ICacheManager { std::string cache_path = GetCachePath(file.path); WriteToFile(cache_path, file.file_contents); - std::string indexed_content = Serialize(g_config.cacheFormat, file); + std::string indexed_content = Serialize(g_config->cacheFormat, file); WriteToFile(AppendSerializationFormat(cache_path), indexed_content); } @@ -38,34 +38,32 @@ struct RealCacheManager : ICacheManager { if (!file_content || !serialized_indexed_content) return nullptr; - return Deserialize(g_config.cacheFormat, path, *serialized_indexed_content, + return Deserialize(g_config->cacheFormat, path, *serialized_indexed_content, *file_content, IndexFile::kMajorVersion); } std::string GetCachePath(const std::string& source_file) { - assert(!g_config.cacheDirectory.empty()); + assert(!g_config->cacheDirectory.empty()); std::string cache_file; - size_t len = g_config.projectRoot.size(); - if (StartsWith(source_file, g_config.projectRoot)) { - cache_file = EscapeFileName(g_config.projectRoot) + + size_t len = g_config->projectRoot.size(); + if (StartsWith(source_file, g_config->projectRoot)) { + cache_file = EscapeFileName(g_config->projectRoot) + EscapeFileName(source_file.substr(len)); } else { - cache_file = '@' + EscapeFileName(g_config.projectRoot) + + cache_file = '@' + EscapeFileName(g_config->projectRoot) + EscapeFileName(source_file); } - return g_config.cacheDirectory + cache_file; + return g_config->cacheDirectory + cache_file; } std::string AppendSerializationFormat(const std::string& base) { - switch (g_config.cacheFormat) { + switch (g_config->cacheFormat) { case SerializeFormat::Json: return base + ".json"; case SerializeFormat::MessagePack: return base + ".mpack"; } - assert(false); - return ".json"; } }; diff --git a/src/clang_complete.cc b/src/clang_complete.cc index d76dbf81..465df042 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -383,7 +383,7 @@ void TryEnsureDocumentParsed(ClangCompleteManager* manager, unsaved, Flags()); // Build diagnostics. - if (manager->config_->diagnostics.onParse && *tu) { + if (g_config->diagnostics.onParse && *tu) { // If we're emitting diagnostics, do an immediate reparse, otherwise we will // emit stale/bad diagnostics. *tu = ClangTranslationUnit::Reparse(std::move(*tu), unsaved); @@ -450,7 +450,7 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { completion_manager->completion_request_.Dequeue(); // Drop older requests if we're not buffering. - while (completion_manager->config_->completion.dropOldRequests && + while (g_config->completion.dropOldRequests && !completion_manager->completion_request_.IsEmpty()) { completion_manager->on_dropped_(request->id); request = completion_manager->completion_request_.Dequeue(); @@ -528,7 +528,7 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { clang_getCompletionBriefComment(result.CompletionString)); // label/detail/filterText/insertText/priority - if (completion_manager->config_->completion.detailedLabel) { + if (g_config->completion.detailedLabel) { ls_completion_item.detail = ToString( clang_getCompletionParent(result.CompletionString, nullptr)); @@ -538,10 +538,10 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { // label/filterText/insertText BuildCompletionItemTexts( ls_result, result.CompletionString, - completion_manager->config_->client.snippetSupport); + g_config->client.snippetSupport); for (auto i = first_idx; i < ls_result.size(); ++i) { - if (completion_manager->config_->client.snippetSupport && + if (g_config->client.snippetSupport && ls_result[i].insertTextFormat == lsInsertTextFormat::Snippet) { ls_result[i].insertText += "$0"; @@ -558,8 +558,8 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { ls_completion_item.detail, ls_completion_item.insertText, do_insert, ls_completion_item.insertTextFormat, &ls_completion_item.parameters_, - completion_manager->config_->client.snippetSupport); - if (completion_manager->config_->client.snippetSupport && + g_config->client.snippetSupport); + if (g_config->client.snippetSupport && ls_completion_item.insertTextFormat == lsInsertTextFormat::Snippet) { ls_completion_item.insertText += "$0"; @@ -658,14 +658,12 @@ ClangCompleteManager::CompletionRequest::CompletionRequest( on_complete(on_complete), emit_diagnostics(emit_diagnostics) {} -ClangCompleteManager::ClangCompleteManager(Config* config, - Project* project, +ClangCompleteManager::ClangCompleteManager(Project* project, WorkingFiles* working_files, OnDiagnostic on_diagnostic, OnIndex on_index, OnDropped on_dropped) - : config_(config), - project_(project), + : project_(project), working_files_(working_files), on_diagnostic_(on_diagnostic), on_index_(on_index), @@ -683,8 +681,6 @@ ClangCompleteManager::ClangCompleteManager(Config* config, }); } -ClangCompleteManager::~ClangCompleteManager() {} - void ClangCompleteManager::CodeComplete( const lsRequestId& id, const lsTextDocumentPositionParams& completion_location, diff --git a/src/clang_complete.h b/src/clang_complete.h index 8080c0e5..015609a8 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.h @@ -72,13 +72,11 @@ struct ClangCompleteManager { bool emit_diagnostics = false; }; - ClangCompleteManager(Config* config, - Project* project, + ClangCompleteManager(Project* project, WorkingFiles* working_files, OnDiagnostic on_diagnostic, OnIndex on_index, OnDropped on_dropped); - ~ClangCompleteManager(); // Start a code completion at the given location. |on_complete| will run when // completion results are available. |on_complete| may run on any thread. @@ -120,7 +118,6 @@ struct ClangCompleteManager { const int kMaxCompletionSessions = 5; // Global state. - Config* config_; Project* project_; WorkingFiles* working_files_; OnDiagnostic on_diagnostic_; diff --git a/src/clang_indexer.cc b/src/clang_indexer.cc index 489eed31..fac4d740 100644 --- a/src/clang_indexer.cc +++ b/src/clang_indexer.cc @@ -13,7 +13,6 @@ #include #include #include -#include // TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on // |Foobar| in DISALLOW_COPY(Foobar) @@ -279,8 +278,6 @@ struct ConstructorCache { }; struct IndexParam { - Config* config = nullptr; - std::unordered_set seen_cx_files; std::vector seen_files; FileContentsMap file_contents; @@ -300,10 +297,9 @@ struct IndexParam { NamespaceHelper ns; ConstructorCache ctors; - IndexParam(Config* config, - ClangTranslationUnit* tu, + IndexParam(ClangTranslationUnit* tu, FileConsumer* file_consumer) - : config(config), tu(tu), file_consumer(file_consumer) {} + : tu(tu), file_consumer(file_consumer) {} #if CINDEX_HAVE_PRETTY CXPrintingPolicy print_policy = nullptr; @@ -585,7 +581,7 @@ void SetVarDetail(IndexVar* var, // string. Shorten it to just "lambda". if (type_name.find("(lambda at") != std::string::npos) type_name = "lambda"; - if (param->config->index.comments) + if (g_config->index.comments) def.comments = cursor.get_comments(); def.storage = GetStorageClass(clang_Cursor_getStorageClass(cursor.cx_cursor)); @@ -870,10 +866,8 @@ CXIdxClientFile OnIndexIncludedFile(CXClientData client_data, ClangCursor::VisitResult DumpVisitor(ClangCursor cursor, ClangCursor parent, int* level) { - for (int i = 0; i < *level; ++i) - std::cerr << " "; - std::cerr << ToString(cursor.get_kind()) << " " << cursor.get_spell_name() - << std::endl; + fprintf(stderr, "%*s%s %s\n", *level * 2, "", + ToString(cursor.get_kind()).c_str(), cursor.get_spell_name().c_str()); *level += 1; cursor.VisitChildren(&DumpVisitor, level); @@ -1248,7 +1242,7 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor, var_def->def.hover = "#define " + GetDocumentContentInRange(param->tu->cx_tu, cx_extent); var_def->def.kind = lsSymbolKind::Macro; - if (param->config->index.comments) + if (g_config->index.comments) var_def->def.comments = cursor.get_comments(); var_def->def.spell = SetUse(db, decl_loc_spelling, parent, Role::Definition); @@ -1615,7 +1609,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { IndexFuncId func_id = db->ToFuncId(decl_cursor_resolved.cx_cursor); IndexFunc* func = db->Resolve(func_id); - if (param->config->index.comments) + if (g_config->index.comments) func->def.comments = cursor.get_comments(); func->def.kind = GetSymbolKind(decl->entityInfo->kind); func->def.storage = @@ -1763,7 +1757,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { SetTypeName(type, decl_cursor, decl->semanticContainer, decl->entityInfo->name, param); type->def.kind = GetSymbolKind(decl->entityInfo->kind); - if (param->config->index.comments) + if (g_config->index.comments) type->def.comments = decl_cursor.get_comments(); // For Typedef/CXXTypeAlias spanning a few lines, display the declaration @@ -1808,7 +1802,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { SetTypeName(type, cursor, decl->semanticContainer, decl->entityInfo->name, param); type->def.kind = GetSymbolKind(decl->entityInfo->kind); - if (param->config->index.comments) + if (g_config->index.comments) type->def.comments = cursor.get_comments(); // } @@ -2099,7 +2093,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { bool is_template = ref->referencedEntity->templateKind != CXIdxEntityCXXTemplateKind::CXIdxEntity_NonTemplate; - if (param->config->index.attributeMakeCallsToCtor && is_template && + if (g_config->index.attributeMakeCallsToCtor && is_template && str_begin("make", ref->referencedEntity->name)) { // Try to find the return type of called function. That type will have // the constructor function we add a usage to. @@ -2154,7 +2148,6 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { } std::vector> Parse( - Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, const std::vector& args, @@ -2162,7 +2155,7 @@ std::vector> Parse( PerformanceImportFile* perf, ClangIndex* index, bool dump_ast) { - if (!config->index.enabled) + if (!g_config->index.enabled) return {}; file = NormalizePath(file); @@ -2190,12 +2183,11 @@ std::vector> Parse( if (dump_ast) Dump(clang_getTranslationUnitCursor(tu->cx_tu)); - return ParseWithTu(config, file_consumer_shared, perf, tu.get(), index, file, + return ParseWithTu(file_consumer_shared, perf, tu.get(), index, file, args, unsaved_files); } std::vector> ParseWithTu( - Config* config, FileConsumerSharedState* file_consumer_shared, PerformanceImportFile* perf, ClangTranslationUnit* tu, @@ -2218,7 +2210,7 @@ std::vector> ParseWithTu( callback.indexEntityReference = &OnIndexReference; FileConsumer file_consumer(file_consumer_shared, file); - IndexParam param(config, tu, &file_consumer); + IndexParam param(tu, &file_consumer); for (const CXUnsavedFile& contents : file_contents) { param.file_contents[contents.Filename] = FileContents( contents.Filename, std::string(contents.Contents, contents.Length)); diff --git a/src/clang_utils.cc b/src/clang_utils.cc index 20b55ff5..4a62db7d 100644 --- a/src/clang_utils.cc +++ b/src/clang_utils.cc @@ -109,7 +109,7 @@ std::string FileName(CXFile file) { CXString cx_name = clang_getFileName(file); std::string ret = NormalizePath(ToString(cx_name)); // Resolve /usr/include/c++/7.3.0 symlink. - if (!StartsWith(ret, g_config.projectRoot)) + if (!StartsWith(ret, g_config->projectRoot)) ret = fs::canonical(ret); return ret; } diff --git a/src/command_line.cc b/src/command_line.cc index 10027c34..215290ea 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -110,8 +110,7 @@ See more on https://github.com/MaskRay/ccls/wiki // QUERYDB MAIN //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -bool QueryDbMainLoop(Config* config, - QueryDatabase* db, +bool QueryDbMainLoop(QueryDatabase* db, MultiQueueWaiter* waiter, Project* project, FileConsumerSharedState* file_consumer_shared, @@ -147,7 +146,7 @@ bool QueryDbMainLoop(Config* config, // TODO: consider rate-limiting and checking for IPC messages so we don't // block requests / we can serve partial requests. - if (QueryDb_ImportMain(config, db, import_manager, status, semantic_cache, + if (QueryDb_ImportMain(db, import_manager, status, semantic_cache, working_files)) { did_work = true; } @@ -156,7 +155,6 @@ bool QueryDbMainLoop(Config* config, } void RunQueryDbThread(const std::string& bin_name, - Config* config, MultiQueueWaiter* querydb_waiter, MultiQueueWaiter* indexer_waiter) { Project project; @@ -166,14 +164,14 @@ void RunQueryDbThread(const std::string& bin_name, DiagnosticsEngine diag_engine; ClangCompleteManager clang_complete( - config, &project, &working_files, + &project, &working_files, [&](std::string path, std::vector diagnostics) { diag_engine.Publish(&working_files, path, diagnostics); }, [&](ClangTranslationUnit* tu, const std::vector& unsaved, const std::string& path, const std::vector& args) { - IndexWithTuFromCodeCompletion(config, &file_consumer_shared, tu, - unsaved, path, args); + IndexWithTuFromCodeCompletion(&file_consumer_shared, tu, unsaved, path, + args); }, [](lsRequestId id) { if (!std::holds_alternative(id)) { @@ -187,7 +185,7 @@ void RunQueryDbThread(const std::string& bin_name, } }); - IncludeComplete include_complete(config, &project); + IncludeComplete include_complete(&project); auto global_code_complete_cache = std::make_unique(); auto non_global_code_complete_cache = std::make_unique(); auto signature_cache = std::make_unique(); @@ -198,7 +196,6 @@ void RunQueryDbThread(const std::string& bin_name, // Setup shared references. for (MessageHandler* handler : *MessageHandler::message_handlers) { - handler->config = config; handler->db = &db; handler->waiter = indexer_waiter; handler->project = &project; @@ -221,7 +218,7 @@ void RunQueryDbThread(const std::string& bin_name, SetCurrentThreadName("querydb"); while (true) { bool did_work = QueryDbMainLoop( - config, &db, querydb_waiter, &project, &file_consumer_shared, + &db, querydb_waiter, &project, &file_consumer_shared, &import_manager, &import_pipeline_status, ×tamp_manager, &semantic_cache, &working_files, &clang_complete, &include_complete, global_code_complete_cache.get(), non_global_code_complete_cache.get(), @@ -247,8 +244,7 @@ void RunQueryDbThread(const std::string& bin_name, // blocks. // // |ipc| is connected to a server. -void LaunchStdinLoop(Config* config, - std::unordered_map* request_times) { +void LaunchStdinLoop(std::unordered_map* request_times) { // If flushing cin requires flushing cout there could be deadlocks in some // clients. std::cin.tie(nullptr); @@ -317,13 +313,12 @@ void LaunchStdoutThread(std::unordered_map* request_times, } void LanguageServerMain(const std::string& bin_name, - Config* config, MultiQueueWaiter* querydb_waiter, MultiQueueWaiter* indexer_waiter, MultiQueueWaiter* stdout_waiter) { std::unordered_map request_times; - LaunchStdinLoop(config, &request_times); + LaunchStdinLoop(&request_times); // We run a dedicated thread for writing to stdout because there can be an // unknown number of delays when output information. @@ -331,7 +326,7 @@ void LanguageServerMain(const std::string& bin_name, // Start querydb which takes over this thread. The querydb will launch // indexer threads as needed. - RunQueryDbThread(bin_name, config, querydb_waiter, indexer_waiter); + RunQueryDbThread(bin_name, querydb_waiter, indexer_waiter); } int main(int argc, char** argv) { @@ -410,9 +405,7 @@ int main(int argc, char** argv) { } } - // std::cerr << "Running language server" << std::endl; - auto config = std::make_unique(); - LanguageServerMain(argv[0], config.get(), &querydb_waiter, &indexer_waiter, + LanguageServerMain(argv[0], &querydb_waiter, &indexer_waiter, &stdout_waiter); } diff --git a/src/config.cc b/src/config.cc index a98b1a1a..68cdecc4 100644 --- a/src/config.cc +++ b/src/config.cc @@ -1,3 +1,3 @@ #include "config.h" -Config g_config; +std::unique_ptr g_config; diff --git a/src/config.h b/src/config.h index 5968b91c..196e564f 100644 --- a/src/config.h +++ b/src/config.h @@ -2,6 +2,7 @@ #include "serializer.h" +#include #include /* @@ -197,6 +198,10 @@ struct Config { // be logged. bool logSkippedPaths = false; + // Allow indexing on textDocument/didChange. + // May be too slow for big projects, so it is off by default. + bool onDidChange = false; + // Number of indexer threads. If 0, 80% of cores are used. int threads = 0; @@ -212,10 +217,6 @@ struct Config { bool sort = true; } workspaceSymbol; - // Allow indexing on textDocument/didChange. - // May be too slow for big projects, so it is off by default. - bool enableIndexOnDidChange = false; - struct Xref { // If true, |Location[]| response will include lexical container. bool container = false; @@ -249,6 +250,7 @@ MAKE_REFLECT_STRUCT(Config::Index, comments, enabled, logSkippedPaths, + onDidChange, threads, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, maxNum, sort); @@ -276,9 +278,7 @@ MAKE_REFLECT_STRUCT(Config, index, workspaceSymbol, xref, - - enableIndexOnDidChange, dumpAST); -extern Config g_config; +extern std::unique_ptr g_config; diff --git a/src/diagnostics_engine.cc b/src/diagnostics_engine.cc index 75dfe4a4..3e7ce0f7 100644 --- a/src/diagnostics_engine.cc +++ b/src/diagnostics_engine.cc @@ -4,10 +4,10 @@ #include -void DiagnosticsEngine::Init(Config* config) { - frequencyMs_ = config->diagnostics.frequencyMs; - match_ = std::make_unique(config->diagnostics.whitelist, - config->diagnostics.blacklist); +void DiagnosticsEngine::Init() { + frequencyMs_ = g_config->diagnostics.frequencyMs; + match_ = std::make_unique(g_config->diagnostics.whitelist, + g_config->diagnostics.blacklist); } void DiagnosticsEngine::Publish(WorkingFiles* working_files, diff --git a/src/diagnostics_engine.h b/src/diagnostics_engine.h index ec1066fb..2d3e7aee 100644 --- a/src/diagnostics_engine.h +++ b/src/diagnostics_engine.h @@ -9,7 +9,7 @@ class DiagnosticsEngine { int frequencyMs_; public: - void Init(Config*); + void Init(); void Publish(WorkingFiles* working_files, std::string path, std::vector diagnostics); diff --git a/src/fuzzy_match.cc b/src/fuzzy_match.cc index 006290d5..8bbd6b8c 100644 --- a/src/fuzzy_match.cc +++ b/src/fuzzy_match.cc @@ -160,7 +160,7 @@ TEST_SUITE("fuzzy_match") { CHECK(Ranks("ab", {"ab", "aoo_boo", "acb"})); CHECK(Ranks("CC", {"CamelCase", "camelCase", "camelcase"})); CHECK(Ranks("cC", {"camelCase", "CamelCase", "camelcase"})); - CHECK(Ranks("c c", {"camel case", "camelCase", "CamelCase", "camelcase", + CHECK(Ranks("c c", {"camelCase", "camel case", "CamelCase", "camelcase", "camel ace"})); CHECK(Ranks("Da.Te", {"Data.Text", "Data.Text.Lazy", "Data.Aeson.Encoding.text"})); diff --git a/src/iindexer.cc b/src/iindexer.cc index 1c77005d..9b28942d 100644 --- a/src/iindexer.cc +++ b/src/iindexer.cc @@ -7,19 +7,18 @@ struct ClangIndexer : IIndexer { ~ClangIndexer() override = default; std::vector> Index( - Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, const std::vector& args, const std::vector& file_contents, PerformanceImportFile* perf) override { bool dump_ast = false; - for (const std::string& pattern : config->dumpAST) + for (const std::string& pattern : g_config->dumpAST) if (file.find(pattern) != std::string::npos) { dump_ast = true; break; } - return Parse(config, file_consumer_shared, file, args, file_contents, perf, + return Parse(file_consumer_shared, file, args, file_contents, perf, &index, dump_ast); } @@ -51,7 +50,6 @@ struct TestIndexer : IIndexer { ~TestIndexer() override = default; std::vector> Index( - Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, const std::vector& args, diff --git a/src/iindexer.h b/src/iindexer.h index df0e2d8b..84b73a84 100644 --- a/src/iindexer.h +++ b/src/iindexer.h @@ -12,7 +12,6 @@ // like IndexFile // - rename this file to indexer.h -struct Config; struct IndexFile; struct FileContents; struct FileConsumerSharedState; @@ -35,7 +34,6 @@ struct IIndexer { virtual ~IIndexer() = default; virtual std::vector> Index( - Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, const std::vector& args, diff --git a/src/import_pipeline.cc b/src/import_pipeline.cc index 9e0eb346..3f8d8939 100644 --- a/src/import_pipeline.cc +++ b/src/import_pipeline.cc @@ -95,15 +95,15 @@ long long GetCurrentTimeInMilliseconds() { } struct ActiveThread { - ActiveThread(Config* config, ImportPipelineStatus* status) - : config_(config), status_(status) { - if (config_->progressReportFrequencyMs < 0) + ActiveThread(ImportPipelineStatus* status) + : status_(status) { + if (g_config->progressReportFrequencyMs < 0) return; ++status_->num_active_threads; } ~ActiveThread() { - if (config_->progressReportFrequencyMs < 0) + if (g_config->progressReportFrequencyMs < 0) return; --status_->num_active_threads; @@ -122,7 +122,7 @@ struct ActiveThread { out.params.activeThreads = status_->num_active_threads; // Ignore this progress update if the last update was too recent. - if (config_->progressReportFrequencyMs != 0) { + if (g_config->progressReportFrequencyMs != 0) { // Make sure we output a status update if queue lengths are zero. bool all_zero = out.params.indexRequestCount == 0 && out.params.doIdMapCount == 0 && @@ -133,13 +133,12 @@ struct ActiveThread { GetCurrentTimeInMilliseconds() < status_->next_progress_output) return; status_->next_progress_output = - GetCurrentTimeInMilliseconds() + config_->progressReportFrequencyMs; + GetCurrentTimeInMilliseconds() + g_config->progressReportFrequencyMs; } QueueManager::WriteStdout(kMethodType_Unknown, out); } - Config* config_; ImportPipelineStatus* status_; }; @@ -356,8 +355,7 @@ std::vector PreloadFileContents( return file_contents; } -void ParseFile(Config* config, - DiagnosticsEngine* diag_engine, +void ParseFile(DiagnosticsEngine* diag_engine, WorkingFiles* working_files, FileConsumerSharedState* file_consumer_shared, TimestampManager* timestamp_manager, @@ -390,11 +388,11 @@ void ParseFile(Config* config, std::vector result; PerformanceImportFile perf; - auto indexes = indexer->Index(config, file_consumer_shared, path_to_index, - entry.args, file_contents, &perf); + auto indexes = indexer->Index(file_consumer_shared, path_to_index, entry.args, + file_contents, &perf); if (indexes.empty()) { - if (config->index.enabled && + if (g_config->index.enabled && !std::holds_alternative(request.id)) { Out_Error out; out.id = request.id; @@ -428,7 +426,6 @@ void ParseFile(Config* config, } bool IndexMain_DoParse( - Config* config, DiagnosticsEngine* diag_engine, WorkingFiles* working_files, FileConsumerSharedState* file_consumer_shared, @@ -444,7 +441,7 @@ bool IndexMain_DoParse( Project::Entry entry; entry.filename = request->path; entry.args = request->args; - ParseFile(config, diag_engine, working_files, file_consumer_shared, + ParseFile(diag_engine, working_files, file_consumer_shared, timestamp_manager, modification_timestamp_fetcher, import_manager, indexer, request.value(), entry); return true; @@ -544,7 +541,6 @@ ImportPipelineStatus::ImportPipelineStatus() // real-time indexing. // TODO: add option to disable this. void IndexWithTuFromCodeCompletion( - Config* config, FileConsumerSharedState* file_consumer_shared, ClangTranslationUnit* tu, const std::vector& file_contents, @@ -554,10 +550,10 @@ void IndexWithTuFromCodeCompletion( PerformanceImportFile perf; ClangIndex index; - auto indexes = ParseWithTu(config, file_consumer_shared, &perf, tu, &index, - path, args, file_contents); + auto indexes = ParseWithTu(file_consumer_shared, &perf, tu, &index, path, + args, file_contents); if (indexes.empty()) - return; + return; std::vector result; for (std::unique_ptr& new_index : indexes) { @@ -579,8 +575,7 @@ void IndexWithTuFromCodeCompletion( QueueManager::instance()->do_id_map.EnqueueAll(std::move(result)); } -void Indexer_Main(Config* config, - DiagnosticsEngine* diag_engine, +void Indexer_Main(DiagnosticsEngine* diag_engine, FileConsumerSharedState* file_consumer_shared, TimestampManager* timestamp_manager, ImportManager* import_manager, @@ -597,7 +592,7 @@ void Indexer_Main(Config* config, bool did_work = false; { - ActiveThread active_thread(config, status); + ActiveThread active_thread(status); // TODO: process all off IndexMain_DoIndex before calling // IndexMain_DoCreateIndexUpdate for better icache behavior. We need to @@ -608,7 +603,7 @@ void Indexer_Main(Config* config, // IndexMain_DoCreateIndexUpdate so we don't starve querydb from doing any // work. Running both also lets the user query the partially constructed // index. - did_work = IndexMain_DoParse(config, diag_engine, working_files, + did_work = IndexMain_DoParse(diag_engine, working_files, file_consumer_shared, timestamp_manager, &modification_timestamp_fetcher, import_manager, indexer.get()) || @@ -723,15 +718,14 @@ void QueryDb_OnIndexed(QueueManager* queue, } // namespace -bool QueryDb_ImportMain(Config* config, - QueryDatabase* db, +bool QueryDb_ImportMain(QueryDatabase* db, ImportManager* import_manager, ImportPipelineStatus* status, SemanticHighlightSymbolCache* semantic_cache, WorkingFiles* working_files) { auto* queue = QueueManager::instance(); - ActiveThread active_thread(config, status); + ActiveThread active_thread(status); bool did_work = false; @@ -760,16 +754,17 @@ bool QueryDb_ImportMain(Config* config, TEST_SUITE("ImportPipeline") { struct Fixture { Fixture() { + g_config = std::make_unique(); QueueManager::Init(&querydb_waiter, &indexer_waiter, &stdout_waiter); queue = QueueManager::instance(); cache_manager = ICacheManager::MakeFake({}); indexer = IIndexer::MakeTestIndexer({}); - diag_engine.Init(&config); + diag_engine.Init(); } bool PumpOnce() { - return IndexMain_DoParse(&config, &diag_engine, &working_files, + return IndexMain_DoParse(&diag_engine, &working_files, &file_consumer_shared, ×tamp_manager, &modification_timestamp_fetcher, &import_manager, indexer.get()); @@ -788,7 +783,6 @@ TEST_SUITE("ImportPipeline") { MultiQueueWaiter stdout_waiter; QueueManager* queue = nullptr; - Config config; DiagnosticsEngine diag_engine; WorkingFiles working_files; FileConsumerSharedState file_consumer_shared; diff --git a/src/import_pipeline.h b/src/import_pipeline.h index 7ede6ae6..f7e750f9 100644 --- a/src/import_pipeline.h +++ b/src/import_pipeline.h @@ -9,7 +9,6 @@ #include struct ClangTranslationUnit; -struct Config; class DiagnosticsEngine; struct FileConsumerSharedState; struct ImportManager; @@ -28,15 +27,13 @@ struct ImportPipelineStatus { }; void IndexWithTuFromCodeCompletion( - Config* config, FileConsumerSharedState* file_consumer_shared, ClangTranslationUnit* tu, const std::vector& file_contents, const std::string& path, const std::vector& args); -void Indexer_Main(Config* config, - DiagnosticsEngine* diag_engine, +void Indexer_Main(DiagnosticsEngine* diag_engine, FileConsumerSharedState* file_consumer_shared, TimestampManager* timestamp_manager, ImportManager* import_manager, @@ -45,8 +42,7 @@ void Indexer_Main(Config* config, WorkingFiles* working_files, MultiQueueWaiter* waiter); -bool QueryDb_ImportMain(Config* config, - QueryDatabase* db, +bool QueryDb_ImportMain(QueryDatabase* db, ImportManager* import_manager, ImportPipelineStatus* status, SemanticHighlightSymbolCache* semantic_cache, diff --git a/src/include_complete.cc b/src/include_complete.cc index 2e2ef83e..f9d55f92 100644 --- a/src/include_complete.cc +++ b/src/include_complete.cc @@ -13,14 +13,14 @@ struct CompletionCandidate { lsCompletionItem completion_item; }; -std::string ElideLongPath(Config* config, const std::string& path) { - if (config->completion.includeMaxPathSize <= 0) +std::string ElideLongPath(const std::string& path) { + if (g_config->completion.includeMaxPathSize <= 0) return path; - if ((int)path.size() <= config->completion.includeMaxPathSize) + if ((int)path.size() <= g_config->completion.includeMaxPathSize) return path; - size_t start = path.size() - config->completion.includeMaxPathSize; + size_t start = path.size() - g_config->completion.includeMaxPathSize; return ".." + path.substr(start + 2); } @@ -73,12 +73,11 @@ bool TrimPath(Project* project, return angle; } -lsCompletionItem BuildCompletionItem(Config* config, - const std::string& path, +lsCompletionItem BuildCompletionItem(const std::string& path, bool use_angle_brackets, bool is_stl) { lsCompletionItem item; - item.label = ElideLongPath(config, path); + item.label = ElideLongPath(path); item.detail = path; // the include path, used in de-duplicating item.textEdit = lsTextEdit(); item.textEdit->newText = path; @@ -96,8 +95,8 @@ lsCompletionItem BuildCompletionItem(Config* config, } // namespace -IncludeComplete::IncludeComplete(Config* config, Project* project) - : is_scanning(false), config_(config), project_(project) {} +IncludeComplete::IncludeComplete(Project* project) + : is_scanning(false), project_(project) {} void IncludeComplete::Rescan() { if (is_scanning) @@ -107,17 +106,17 @@ void IncludeComplete::Rescan() { absolute_path_to_completion_item.clear(); inserted_paths.clear(); - if (!match_ && (!config_->completion.includeWhitelist.empty() || - !config_->completion.includeBlacklist.empty())) - match_ = std::make_unique(config_->completion.includeWhitelist, - config_->completion.includeBlacklist); + if (!match_ && (g_config->completion.includeWhitelist.size() || + g_config->completion.includeBlacklist.size())) + match_ = std::make_unique(g_config->completion.includeWhitelist, + g_config->completion.includeBlacklist); is_scanning = true; StartThread("scan_includes", [this]() { Timer timer; InsertStlIncludes(); - InsertIncludesFromDirectory(config_->projectRoot, + InsertIncludesFromDirectory(g_config->projectRoot, false /*use_angle_brackets*/); for (const std::string& dir : project_->quote_include_directories) InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/); @@ -150,16 +149,16 @@ void IncludeComplete::InsertCompletionItem(const std::string& absolute_path, } void IncludeComplete::AddFile(const std::string& absolute_path) { - if (!EndsWithAny(absolute_path, config_->completion.includeSuffixWhitelist)) + if (!EndsWithAny(absolute_path, g_config->completion.includeSuffixWhitelist)) return; if (match_ && !match_->IsMatch(absolute_path)) return; std::string trimmed_path = absolute_path; bool use_angle_brackets = - TrimPath(project_, config_->projectRoot, &trimmed_path); - lsCompletionItem item = BuildCompletionItem( - config_, trimmed_path, use_angle_brackets, false /*is_stl*/); + TrimPath(project_, g_config->projectRoot, &trimmed_path); + lsCompletionItem item = + BuildCompletionItem(trimmed_path, use_angle_brackets, false /*is_stl*/); std::unique_lock lock(completion_items_mutex, std::defer_lock); if (is_scanning) @@ -180,15 +179,15 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory, GetFilesInFolder( directory, true /*recursive*/, false /*add_folder_to_path*/, [&](const std::string& path) { - if (!EndsWithAny(path, config_->completion.includeSuffixWhitelist)) + if (!EndsWithAny(path, g_config->completion.includeSuffixWhitelist)) return; if (match_ && !match_->IsMatch(directory + path)) return; CompletionCandidate candidate; candidate.absolute_path = directory + path; - candidate.completion_item = BuildCompletionItem( - config_, path, use_angle_brackets, false /*is_stl*/); + candidate.completion_item = + BuildCompletionItem(path, use_angle_brackets, false /*is_stl*/); results.push_back(candidate); }); @@ -202,7 +201,7 @@ void IncludeComplete::InsertStlIncludes() { std::lock_guard 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*/)); + stl_header, true /*use_angle_brackets*/, true /*is_stl*/)); } } diff --git a/src/include_complete.h b/src/include_complete.h index 47438113..9cbee1ab 100644 --- a/src/include_complete.h +++ b/src/include_complete.h @@ -10,7 +10,7 @@ struct GroupMatch; struct Project; struct IncludeComplete { - IncludeComplete(Config* config, Project* project); + IncludeComplete(Project* project); // Starts scanning directories. Clears existing cache. void Rescan(); @@ -45,7 +45,6 @@ struct IncludeComplete { std::unordered_map inserted_paths; // Cached references - Config* config_; Project* project_; std::unique_ptr match_; }; diff --git a/src/indexer.h b/src/indexer.h index 8857c2bd..8a6decea 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -518,7 +518,6 @@ struct NamespaceHelper { // |dependencies| are the existing dependencies of |import_file| if this is a // reparse. std::vector> Parse( - Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, const std::vector& args, @@ -527,7 +526,6 @@ std::vector> Parse( ClangIndex* index, bool dump_ast = false); std::vector> ParseWithTu( - Config* config, FileConsumerSharedState* file_consumer_shared, PerformanceImportFile* perf, ClangTranslationUnit* tu, diff --git a/src/lex_utils.cc b/src/lex_utils.cc index cb3ad0f5..deb6ece9 100644 --- a/src/lex_utils.cc +++ b/src/lex_utils.cc @@ -3,7 +3,6 @@ #include #include -#include // VSCode (UTF-16) disagrees with Emacs lsp-mode (UTF-8) on how to represent // text documents. diff --git a/src/lsp.cc b/src/lsp.cc index eb1825a6..251a52d7 100644 --- a/src/lsp.cc +++ b/src/lsp.cc @@ -7,7 +7,6 @@ #include #include -#include MessageRegistry* MessageRegistry::instance_ = nullptr; diff --git a/src/message_handler.cc b/src/message_handler.cc index 897d9137..cdc2d98a 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -101,9 +101,9 @@ SemanticHighlightSymbolCache::Entry::GetMapForSymbol_(SymbolKind kind) { SemanticHighlightSymbolCache::SemanticHighlightSymbolCache() : cache_(kCacheSize) {} -void SemanticHighlightSymbolCache::Init(Config* config) { - match_ = std::make_unique(config->highlight.whitelist, - config->highlight.blacklist); +void SemanticHighlightSymbolCache::Init() { + match_ = std::make_unique(g_config->highlight.whitelist, + g_config->highlight.blacklist); } std::shared_ptr diff --git a/src/message_handler.h b/src/message_handler.h index ea6c67e3..ca6c7a2f 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -55,7 +55,7 @@ struct SemanticHighlightSymbolCache { std::unique_ptr match_; SemanticHighlightSymbolCache(); - void Init(Config*); + void Init(); std::shared_ptr GetCacheForFile(const std::string& path); }; @@ -103,7 +103,6 @@ MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting, static type type##message_handler_instance_; struct MessageHandler { - Config* config = nullptr; QueryDatabase* db = nullptr; MultiQueueWaiter* waiter = nullptr; Project* project = nullptr; diff --git a/src/messages/ccls_base.cc b/src/messages/ccls_base.cc index f1c31f29..cc681986 100644 --- a/src/messages/ccls_base.cc +++ b/src/messages/ccls_base.cc @@ -33,15 +33,13 @@ struct Handler_CclsBase : BaseMessageHandler { FindSymbolsAtLocation(working_file, file, request->params.position)) { if (sym.kind == SymbolKind::Type) { if (const auto* def = db->GetType(sym).AnyDef()) - out.result = GetLsLocationExs( - db, working_files, GetDeclarations(db, def->bases), - config->xref.container, config->xref.maxNum); + out.result = GetLsLocationExs(db, working_files, + GetDeclarations(db, def->bases)); break; } else if (sym.kind == SymbolKind::Func) { if (const auto* def = db->GetFunc(sym).AnyDef()) - out.result = GetLsLocationExs( - db, working_files, GetDeclarations(db, def->bases), - config->xref.container, config->xref.maxNum); + out.result = GetLsLocationExs(db, working_files, + GetDeclarations(db, def->bases)); break; } } diff --git a/src/messages/ccls_callers.cc b/src/messages/ccls_callers.cc index 0e7904fc..db781be9 100644 --- a/src/messages/ccls_callers.cc +++ b/src/messages/ccls_callers.cc @@ -35,9 +35,7 @@ struct Handler_CclsCallers : BaseMessageHandler { uses.push_back(func_ref); for (Use func_ref : GetUsesForAllDerived(db, func)) uses.push_back(func_ref); - out.result = - GetLsLocationExs(db, working_files, uses, config->xref.container, - config->xref.maxNum); + out.result = GetLsLocationExs(db, working_files, uses); break; } } diff --git a/src/messages/ccls_derived.cc b/src/messages/ccls_derived.cc index ad415ace..d8676211 100644 --- a/src/messages/ccls_derived.cc +++ b/src/messages/ccls_derived.cc @@ -30,15 +30,13 @@ struct Handler_CclsDerived : BaseMessageHandler { FindSymbolsAtLocation(working_file, file, request->params.position)) { if (sym.kind == SymbolKind::Type) { QueryType& type = db->GetType(sym); - out.result = GetLsLocationExs( - db, working_files, GetDeclarations(db, type.derived), - config->xref.container, config->xref.maxNum); + out.result = GetLsLocationExs(db, working_files, + GetDeclarations(db, type.derived)); break; } else if (sym.kind == SymbolKind::Func) { QueryFunc& func = db->GetFunc(sym); - out.result = GetLsLocationExs( - db, working_files, GetDeclarations(db, func.derived), - config->xref.container, config->xref.maxNum); + out.result = GetLsLocationExs(db, working_files, + GetDeclarations(db, func.derived)); break; } } diff --git a/src/messages/ccls_freshen_index.cc b/src/messages/ccls_freshen_index.cc index b56701db..10220b53 100644 --- a/src/messages/ccls_freshen_index.cc +++ b/src/messages/ccls_freshen_index.cc @@ -87,8 +87,7 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler { Timer time; // Send index requests for every file. - project->Index(config, QueueManager::instance(), working_files, - std::monostate()); + project->Index(QueueManager::instance(), working_files, std::monostate()); time.ResetAndPrint("[perf] Dispatched $ccls/freshenIndex index requests"); } }; diff --git a/src/messages/ccls_random.cc b/src/messages/ccls_random.cc index f24471e7..ce0bb437 100644 --- a/src/messages/ccls_random.cc +++ b/src/messages/ccls_random.cc @@ -132,12 +132,10 @@ struct Handler_CclsRandom : BaseMessageHandler { for (int i = 0; i < n; i++) { sum += x[i]; if (sum >= roulette) { - Maybe use = GetDefinitionExtent(db, syms[i]); - if (!use) - continue; - if (auto ls_loc = GetLsLocationEx(db, working_files, *use, - config->xref.container)) - out.result.push_back(*ls_loc); + if (Maybe use = GetDefinitionExtent(db, syms[i])) + if (auto ls_loc = GetLsLocationEx(db, working_files, *use, + g_config->xref.container)) + out.result.push_back(*ls_loc); break; } } diff --git a/src/messages/ccls_vars.cc b/src/messages/ccls_vars.cc index b9426487..a19803c5 100644 --- a/src/messages/ccls_vars.cc +++ b/src/messages/ccls_vars.cc @@ -43,9 +43,8 @@ struct Handler_CclsVars : BaseMessageHandler { // fallthrough case SymbolKind::Type: { QueryType& type = db->types[id.id]; - out.result = GetLsLocationExs( - db, working_files, GetDeclarations(db, type.instances), - config->xref.container, config->xref.maxNum); + out.result = GetLsLocationExs(db, working_files, + GetDeclarations(db, type.instances)); break; } } diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index d10b971a..1bc34c10 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -428,6 +428,7 @@ struct Handler_Initialize : BaseMessageHandler { JsonWriter json_writer(&writer); Reflect(json_writer, request->params.initializationOptions); LOG_S(INFO) << "Init parameters: " << output.GetString(); + std::unique_ptr config; if (request->params.rootUri) { std::string project_path = @@ -437,9 +438,9 @@ struct Handler_Initialize : BaseMessageHandler { { if (request->params.initializationOptions) - *config = *request->params.initializationOptions; + config = std::make_unique(*request->params.initializationOptions); else - *config = Config(); + config = std::make_unique(); rapidjson::Document reader; reader.Parse(g_init_options.c_str()); if (!reader.HasParseError()) { @@ -508,32 +509,29 @@ struct Handler_Initialize : BaseMessageHandler { MakeDirectoryRecursive(config->cacheDirectory + '@' + EscapeFileName(config->projectRoot)); - g_config = *config; + g_config = std::move(config); Timer time; - diag_engine->Init(config); - semantic_cache->Init(config); + diag_engine->Init(); + semantic_cache->Init(); // Open up / load the project. - project->Load(config, project_path); + project->Load(project_path); time.ResetAndPrint("[perf] Loaded compilation entries (" + std::to_string(project->entries.size()) + " files)"); // Start indexer threads. Start this after loading the project, as that // may take a long time. Indexer threads will emit status/progress // reports. - if (config->index.threads == 0) { + if (g_config->index.threads == 0) { // If the user has not specified how many indexers to run, try to // guess an appropriate value. Default to 80% utilization. - const float kDefaultTargetUtilization = 0.8f; - config->index.threads = (int)(std::thread::hardware_concurrency() * - kDefaultTargetUtilization); - if (config->index.threads <= 0) - config->index.threads = 1; + g_config->index.threads = + std::max(int(std::thread::hardware_concurrency() * 0.8), 1); } - LOG_S(INFO) << "Starting " << config->index.threads << " indexers"; - for (int i = 0; i < config->index.threads; ++i) { + LOG_S(INFO) << "Starting " << g_config->index.threads << " indexers"; + for (int i = 0; i < g_config->index.threads; ++i) { StartThread("indexer" + std::to_string(i), [=]() { - Indexer_Main(config, diag_engine, file_consumer_shared, + Indexer_Main(diag_engine, file_consumer_shared, timestamp_manager, import_manager, import_pipeline_status, project, working_files, waiter); }); @@ -544,8 +542,7 @@ struct Handler_Initialize : BaseMessageHandler { include_complete->Rescan(); time.Reset(); - project->Index(config, QueueManager::instance(), working_files, - request->id); + project->Index(QueueManager::instance(), working_files, request->id); // We need to support multiple concurrent index processes. time.ResetAndPrint("[perf] Dispatched initial index requests"); } diff --git a/src/messages/text_document_code_lens.cc b/src/messages/text_document_code_lens.cc index 521268c0..cbe065cb 100644 --- a/src/messages/text_document_code_lens.cc +++ b/src/messages/text_document_code_lens.cc @@ -206,7 +206,7 @@ struct Handler_TextDocumentCodeLens case SymbolKind::Var: { QueryVar& var = db->GetVar(sym); const QueryVar::Def* def = var.AnyDef(); - if (!def || (def->is_local() && !config->codeLens.localVariables)) + if (!def || (def->is_local() && !g_config->codeLens.localVariables)) continue; bool force_display = true; diff --git a/src/messages/text_document_completion.cc b/src/messages/text_document_completion.cc index 3c9831b0..b0f62960 100644 --- a/src/messages/text_document_completion.cc +++ b/src/messages/text_document_completion.cc @@ -160,9 +160,8 @@ char* tofixedbase64(T input, char* out) { // when given 1000+ completion items. void FilterAndSortCompletionResponse( Out_TextDocumentComplete* complete_response, - const std::string& complete_text, - bool enable) { - if (!enable) + const std::string& complete_text) { + if (!g_config->completion.filterAndSort) return; ScopedPerfTimer timer{"FilterAndSortCompletionResponse"}; @@ -327,8 +326,7 @@ struct Handler_TextDocumentCompletion : MessageHandler { return k == result.keyword; })) { out.result.items = preprocessorKeywordCompletionItems(result.match); - FilterAndSortCompletionResponse(&out, result.keyword, - config->completion.filterAndSort); + FilterAndSortCompletionResponse(&out, result.keyword); } } else if (result.keyword.compare("include") == 0) { { @@ -342,8 +340,7 @@ struct Handler_TextDocumentCompletion : MessageHandler { if (quote.empty() || quote == (item.use_angle_brackets_ ? "<" : "\"")) out.result.items.push_back(item); } - FilterAndSortCompletionResponse(&out, result.pattern, - config->completion.filterAndSort); + FilterAndSortCompletionResponse(&out, result.pattern); DecorateIncludePaths(result.match, &out.result.items); } @@ -365,8 +362,7 @@ struct Handler_TextDocumentCompletion : MessageHandler { out.result.items = results; // Emit completion results. - FilterAndSortCompletionResponse(&out, existing_completion, - config->completion.filterAndSort); + FilterAndSortCompletionResponse(&out, existing_completion); QueueManager::WriteStdout(kMethodType, out); // Cache completion results. diff --git a/src/messages/text_document_definition.cc b/src/messages/text_document_definition.cc index e6e4caf7..15216ace 100644 --- a/src/messages/text_document_definition.cc +++ b/src/messages/text_document_definition.cc @@ -105,9 +105,7 @@ struct Handler_TextDocumentDefinition if (uses.empty() && on_def) uses.push_back(*on_def); } - AddRange(&out.result, - GetLsLocationExs(db, working_files, uses, config->xref.container, - config->xref.maxNum)); + AddRange(&out.result, GetLsLocationExs(db, working_files, uses)); if (!out.result.empty()) break; } @@ -172,7 +170,7 @@ struct Handler_TextDocumentDefinition Maybe use = GetDefinitionSpell(db, db->symbols[best_i]); assert(use); if (auto ls_loc = GetLsLocationEx(db, working_files, *use, - config->xref.container)) + g_config->xref.container)) out.result.push_back(*ls_loc); } } diff --git a/src/messages/text_document_did_change.cc b/src/messages/text_document_did_change.cc index 4f978bc3..5f5d2a71 100644 --- a/src/messages/text_document_did_change.cc +++ b/src/messages/text_document_did_change.cc @@ -25,7 +25,7 @@ struct Handler_TextDocumentDidChange void Run(In_TextDocumentDidChange* request) override { std::string path = request->params.textDocument.uri.GetPath(); working_files->OnChange(request->params); - if (config->enableIndexOnDidChange) { + if (g_config->index.onDidChange) { std::optional content = ReadContent(path); if (!content) { LOG_S(ERROR) << "Unable to read file content after saving " << path; diff --git a/src/messages/text_document_did_save.cc b/src/messages/text_document_did_save.cc index 9596ddb4..29ceffa8 100644 --- a/src/messages/text_document_did_save.cc +++ b/src/messages/text_document_did_save.cc @@ -47,7 +47,7 @@ struct Handler_TextDocumentDidSave // mutex and check to see if we should skip the current request. // if so, ignore that index response. // TODO: send as priority request - if (!config->enableIndexOnDidChange) { + if (!g_config->index.onDidChange) { std::optional content = ReadContent(path); if (!content) { LOG_S(ERROR) << "Unable to read file content after saving " << path; diff --git a/src/messages/text_document_references.cc b/src/messages/text_document_references.cc index 40f99531..ba90af9a 100644 --- a/src/messages/text_document_references.cc +++ b/src/messages/text_document_references.cc @@ -56,7 +56,7 @@ struct Handler_TextDocumentReferences Out_TextDocumentReferences out; out.id = request->id; - bool container = config->xref.container; + bool container = g_config->xref.container; for (const SymbolRef& sym : FindSymbolsAtLocation(working_file, file, request->params.position)) { @@ -94,8 +94,8 @@ struct Handler_TextDocumentReferences break; } - if ((int)out.result.size() >= config->xref.maxNum) - out.result.resize(config->xref.maxNum); + if ((int)out.result.size() >= g_config->xref.maxNum) + out.result.resize(g_config->xref.maxNum); QueueManager::WriteStdout(kMethodType, out); } }; diff --git a/src/messages/text_document_type_definition.cc b/src/messages/text_document_type_definition.cc index 4226c558..738636e6 100644 --- a/src/messages/text_document_type_definition.cc +++ b/src/messages/text_document_type_definition.cc @@ -50,7 +50,7 @@ struct Handler_TextDocumentTypeDefinition for (const auto& def : type.def) if (def.spell) { if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell, - config->xref.container)) + g_config->xref.container)) out.result.push_back(*ls_loc); } break; diff --git a/src/messages/workspace_did_change_configuration.cc b/src/messages/workspace_did_change_configuration.cc index c2ad85cb..8d81b892 100644 --- a/src/messages/workspace_did_change_configuration.cc +++ b/src/messages/workspace_did_change_configuration.cc @@ -28,13 +28,12 @@ struct Handler_WorkspaceDidChangeConfiguration MethodType GetMethodType() const override { return kMethodType; } void Run(In_WorkspaceDidChangeConfiguration* request) override { Timer time; - project->Load(config, config->projectRoot); + project->Load(g_config->projectRoot); time.ResetAndPrint("[perf] Loaded compilation entries (" + std::to_string(project->entries.size()) + " files)"); time.Reset(); - project->Index(config, QueueManager::instance(), working_files, - std::monostate()); + project->Index(QueueManager::instance(), working_files, std::monostate()); time.ResetAndPrint( "[perf] Dispatched workspace/didChangeConfiguration index requests"); diff --git a/src/messages/workspace_symbol.cc b/src/messages/workspace_symbol.cc index 4294bd05..06140b50 100644 --- a/src/messages/workspace_symbol.cc +++ b/src/messages/workspace_symbol.cc @@ -77,8 +77,8 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler { // db->detailed_names indices of each lsSymbolInformation in out.result std::vector result_indices; std::vector unsorted_results; - inserted_results.reserve(config->workspaceSymbol.maxNum); - result_indices.reserve(config->workspaceSymbol.maxNum); + inserted_results.reserve(g_config->workspaceSymbol.maxNum); + result_indices.reserve(g_config->workspaceSymbol.maxNum); // We use detailed_names without parameters for matching. @@ -93,14 +93,14 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler { if (InsertSymbolIntoResult(db, working_files, db->symbols[i], &unsorted_results)) { result_indices.push_back(i); - if (unsorted_results.size() >= config->workspaceSymbol.maxNum) + if (unsorted_results.size() >= g_config->workspaceSymbol.maxNum) break; } } } // Find subsequence matches. - if (unsorted_results.size() < config->workspaceSymbol.maxNum) { + if (unsorted_results.size() < g_config->workspaceSymbol.maxNum) { std::string query_without_space; query_without_space.reserve(query.size()); for (char c : query) @@ -118,14 +118,14 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler { if (InsertSymbolIntoResult(db, working_files, db->symbols[i], &unsorted_results)) { result_indices.push_back(i); - if (unsorted_results.size() >= config->workspaceSymbol.maxNum) + if (unsorted_results.size() >= g_config->workspaceSymbol.maxNum) break; } } } } - if (config->workspaceSymbol.sort && query.size() <= FuzzyMatcher::kMaxPat) { + if (g_config->workspaceSymbol.sort && query.size() <= FuzzyMatcher::kMaxPat) { // Sort results with a fuzzy matching algorithm. int longest = 0; for (int i : result_indices) diff --git a/src/project.cc b/src/project.cc index 7357557d..9370c3ac 100644 --- a/src/project.cc +++ b/src/project.cc @@ -21,10 +21,7 @@ #include #endif -#include -#include #include -#include #include #include @@ -61,7 +58,7 @@ struct ProjectConfig { // of clang for the same platform are incompatible). Note that libclang always generate it's own pch // internally. For details, see https://github.com/Valloric/ycmd/issues/892 . std::vector kBlacklistMulti = { - "-MF", "-MT", "-MQ", "-o", "--serialize-diagnostics", "-Xclang", "-include", "-include-pch"}; + "-MF", "-MT", "-MQ", "-o", "--serialize-diagnostics", "-Xclang"}; // Blacklisted flags which are always removed from the command line. std::vector kBlacklist = { @@ -106,7 +103,6 @@ LanguageId SourceFileLanguage(const std::string& path) { } Project::Entry GetCompilationEntryFromCompileCommandEntry( - Config* init_opts, ProjectConfig* config, const CompileCommandsEntry& entry) { Project::Entry result; @@ -240,7 +236,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( // Add -resource-dir so clang can correctly resolve system includes like // if (!AnyStartsWith(result.args, "-resource-dir")) - result.args.push_back("-resource-dir=" + init_opts->resourceDirectory); + result.args.push_back("-resource-dir=" + g_config->resourceDirectory); // There could be a clang version mismatch between what the project uses and // what ccls uses. Make sure we do not emit warnings for mismatched options. @@ -249,7 +245,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( // Using -fparse-all-comments enables documentation in the indexer and in // code completion. - if (init_opts->index.comments > 1 && + if (g_config->index.comments > 1 && !AnyStartsWith(result.args, "-fparse-all-comments")) { result.args.push_back("-fparse-all-comments"); } @@ -269,8 +265,7 @@ std::vector ReadCompilerArgumentsFromFile( return args; } -std::vector LoadFromDirectoryListing(Config* init_opts, - ProjectConfig* config) { +std::vector LoadFromDirectoryListing(ProjectConfig* config) { std::vector result; config->mode = ProjectMode::DotCcls; LOG_IF_S(WARNING, !FileExists(config->project_dir + "/.ccls") && @@ -322,24 +317,22 @@ std::vector LoadFromDirectoryListing(Config* init_opts, if (e.args.empty()) e.args.push_back("%clang"); // Add a Dummy. e.args.push_back(e.file); - result.push_back( - GetCompilationEntryFromCompileCommandEntry(init_opts, config, e)); + result.push_back(GetCompilationEntryFromCompileCommandEntry(config, e)); } return result; } std::vector LoadCompilationEntriesFromDirectory( - Config* config, ProjectConfig* project, const std::string& opt_compilation_db_dir) { // If there is a .ccls file always load using directory listing. if (FileExists(project->project_dir + ".ccls")) - return LoadFromDirectoryListing(config, project); + return LoadFromDirectoryListing(project); // If |compilationDatabaseCommand| is specified, execute it to get the compdb. - std::string comp_db_dir; - if (config->compilationDatabaseCommand.empty()) { + fs::path comp_db_dir; + if (g_config->compilationDatabaseCommand.empty()) { project->mode = ProjectMode::CompileCommandsJson; // Try to load compile_commands.json, but fallback to a project listing. comp_db_dir = opt_compilation_db_dir.empty() ? project->project_dir @@ -356,32 +349,35 @@ std::vector LoadCompilationEntriesFromDirectory( rapidjson::StringBuffer input; rapidjson::Writer writer(input); JsonWriter json_writer(&writer); - Reflect(json_writer, *config); + Reflect(json_writer, *g_config); std::string contents = GetExternalCommandOutput( - std::vector{config->compilationDatabaseCommand, + std::vector{g_config->compilationDatabaseCommand, project->project_dir}, input.GetString()); - std::ofstream(comp_db_dir + "/compile_commands.json") << contents; + FILE* fout = fopen((comp_db_dir / "compile_commands.json").c_str(), "wb"); + fwrite(contents.c_str(), contents.size(), 1, fout); + fclose(fout); #endif } - LOG_S(INFO) << "Trying to load compile_commands.json"; + fs::path comp_db_path = comp_db_dir / "compile_commands.json"; + LOG_S(INFO) << "Trying to load " << comp_db_path.string(); CXCompilationDatabase_Error cx_db_load_error; CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory( comp_db_dir.c_str(), &cx_db_load_error); - if (!config->compilationDatabaseCommand.empty()) { + if (!g_config->compilationDatabaseCommand.empty()) { #ifdef _WIN32 // TODO #else - unlink((comp_db_dir + "/compile_commands.json").c_str()); + unlink(comp_db_path.c_str()); rmdir(comp_db_dir.c_str()); #endif } if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) { - LOG_S(INFO) << "Unable to load compile_commands.json located at \"" - << comp_db_dir << "\"; using directory listing instead."; - return LoadFromDirectoryListing(config, project); + LOG_S(INFO) << "Unable to load " << comp_db_path.string() + << "; using directory listing instead."; + return LoadFromDirectoryListing(project); } Timer clang_time; @@ -421,7 +417,7 @@ std::vector LoadCompilationEntriesFromDirectory( entry.file = entry.ResolveIfRelative(relative_filename); result.push_back( - GetCompilationEntryFromCompileCommandEntry(config, project, entry)); + GetCompilationEntryFromCompileCommandEntry(project, entry)); our_time.Pause(); } @@ -452,13 +448,13 @@ int ComputeGuessScore(std::string_view a, std::string_view b) { } // namespace -void Project::Load(Config* config, const std::string& root_directory) { +void Project::Load(const std::string& root_directory) { // Load data. ProjectConfig project; - project.extra_flags = config->extraClangArguments; + project.extra_flags = g_config->extraClangArguments; project.project_dir = root_directory; entries = LoadCompilationEntriesFromDirectory( - config, &project, config->compilationDatabaseDirectory); + &project, g_config->compilationDatabaseDirectory); // Cleanup / postprocess include directories. quote_include_directories.assign(project.quote_dirs.begin(), @@ -539,28 +535,24 @@ Project::Entry Project::FindCompilationEntryForFile( } void Project::ForAllFilteredFiles( - Config* config, std::function action) { - GroupMatch matcher(config->index.whitelist, config->index.blacklist); + GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist); for (int i = 0; i < entries.size(); ++i) { const Project::Entry& entry = entries[i]; std::string failure_reason; if (matcher.IsMatch(entry.filename, &failure_reason)) action(i, entries[i]); - else { - if (config->index.logSkippedPaths) { - LOG_S(INFO) << "[" << i + 1 << "/" << entries.size() << "]: Failed " - << failure_reason << "; skipping " << entry.filename; - } + else if (g_config->index.logSkippedPaths) { + LOG_S(INFO) << "[" << i + 1 << "/" << entries.size() << "]: Failed " + << failure_reason << "; skipping " << entry.filename; } } } -void Project::Index(Config* config, - QueueManager* queue, +void Project::Index(QueueManager* queue, WorkingFiles* wfiles, lsRequestId id) { - ForAllFilteredFiles(config, [&](int i, const Project::Entry& entry) { + ForAllFilteredFiles([&](int i, const Project::Entry& entry) { std::optional content = ReadContent(entry.filename); if (!content) { LOG_S(ERROR) << "When loading project, canont read file " @@ -578,30 +570,22 @@ TEST_SUITE("Project") { void CheckFlags(const std::string& directory, const std::string& file, std::vector raw, std::vector expected) { - Config config; + g_config = std::make_unique(); + g_config->resourceDirectory = "/w/resource_dir/"; ProjectConfig project; project.project_dir = "/w/c/s/"; - config.resourceDirectory = "/w/resource_dir/"; CompileCommandsEntry entry; entry.directory = directory; entry.args = raw; entry.file = file; Project::Entry result = - GetCompilationEntryFromCompileCommandEntry(&config, &project, entry); + GetCompilationEntryFromCompileCommandEntry(&project, entry); if (result.args != expected) { - std::cout << "Raw: " << StringJoin(raw) << std::endl; - std::cout << "Expected: " << StringJoin(expected) << std::endl; - std::cout << "Actual: " << StringJoin(result.args) << std::endl; - } - for (int i = 0; i < std::min(result.args.size(), expected.size()); ++i) { - if (result.args[i] != expected[i]) { - std::cout << std::endl; - std::cout << "mismatch at " << i << std::endl; - std::cout << " expected: " << expected[i] << std::endl; - std::cout << " actual: " << result.args[i] << std::endl; - } + fprintf(stderr, "Raw: %s\n", StringJoin(raw).c_str()); + fprintf(stderr, "Expected: %s\n", StringJoin(expected).c_str()); + fprintf(stderr, "Actual: %s\n", StringJoin(result.args).c_str()); } REQUIRE(result.args == expected); } @@ -671,7 +655,7 @@ TEST_SUITE("Project") { } TEST_CASE("Directory extraction") { - Config init_opts; + g_config = std::make_unique(); ProjectConfig config; config.project_dir = "/w/c/s/"; @@ -701,7 +685,7 @@ TEST_SUITE("Project") { "foo.cc"}; entry.file = "foo.cc"; Project::Entry result = - GetCompilationEntryFromCompileCommandEntry(&init_opts, &config, entry); + GetCompilationEntryFromCompileCommandEntry(&config, entry); std::unordered_set angle_expected{ "/a_absolute1", "/a_absolute2", "/base/a_relative1", diff --git a/src/project.h b/src/project.h index 71fbd19a..d67562ab 100644 --- a/src/project.h +++ b/src/project.h @@ -40,7 +40,7 @@ struct Project { // will affect flags in their subtrees (relative paths are relative to the // project root, not subdirectories). For compile_commands.json, its entries // are indexed. - void Load(Config* config, const std::string& root_directory); + void Load(const std::string& root_directory); // Lookup the CompilationEntry for |filename|. If no entry was found this // will infer one based on existing project structure. @@ -55,11 +55,7 @@ struct Project { // Run |action| on every file in the project. void ForAllFilteredFiles( - Config* config, std::function action); - void Index(Config* config, - QueueManager* queue, - WorkingFiles* wfiles, - lsRequestId id); + void Index(QueueManager* queue, WorkingFiles* wfiles, lsRequestId id); }; diff --git a/src/query_utils.cc b/src/query_utils.cc index 72e756c1..e30b6d43 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -251,17 +251,16 @@ std::optional GetLsLocationEx(QueryDatabase* db, std::vector GetLsLocationExs(QueryDatabase* db, WorkingFiles* working_files, - const std::vector& uses, - bool container, - int limit) { + const std::vector& uses) { std::vector ret; for (Use use : uses) - if (auto loc = GetLsLocationEx(db, working_files, use, container)) + if (auto loc = + GetLsLocationEx(db, working_files, use, g_config->xref.container)) ret.push_back(*loc); std::sort(ret.begin(), ret.end()); ret.erase(std::unique(ret.begin(), ret.end()), ret.end()); - if (ret.size() > limit) - ret.resize(limit); + if (ret.size() > g_config->xref.maxNum) + ret.resize(g_config->xref.maxNum); return ret; } diff --git a/src/query_utils.h b/src/query_utils.h index a3bd30df..0365394a 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -41,9 +41,7 @@ std::optional GetLsLocationEx(QueryDatabase* db, bool container); std::vector GetLsLocationExs(QueryDatabase* db, WorkingFiles* working_files, - const std::vector& refs, - bool container, - int limit); + const std::vector& refs); // Returns a symbol. The symbol will have *NOT* have a location assigned. std::optional GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, diff --git a/src/test.cc b/src/test.cc index 07d083bc..7ba6b89e 100644 --- a/src/test.cc +++ b/src/test.cc @@ -262,11 +262,11 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) { flags.push_back(path); // Run test. - Config config; + g_config = std::make_unique(); FileConsumerSharedState file_consumer_shared; PerformanceImportFile perf; - auto dbs = Parse(&config, &file_consumer_shared, path, flags, {}, &perf, - &index, false /*dump_ast*/); + auto dbs = Parse(&file_consumer_shared, path, flags, {}, &perf, &index, + false /*dump_ast*/); for (const auto& entry : all_expected_output) { const std::string& expected_path = entry.first;