diff --git a/src/match.cc b/src/match.cc index 94499b67..40393a8e 100644 --- a/src/match.cc +++ b/src/match.cc @@ -41,7 +41,7 @@ optional Matcher::Create(const std::string& search) { bool Matcher::IsMatch(const std::string& value) const { // std::smatch match; // return std::regex_match(value, match, regex); - return std::regex_match(value, regex, std::regex_constants::match_any); + return std::regex_search(value, regex, std::regex_constants::match_any); } GroupMatch::GroupMatch(const std::vector& whitelist, diff --git a/src/messages/cquery_freshen_index.cc b/src/messages/cquery_freshen_index.cc index 32b72c87..a75334a4 100644 --- a/src/messages/cquery_freshen_index.cc +++ b/src/messages/cquery_freshen_index.cc @@ -8,14 +8,21 @@ #include "working_files.h" #include +#include +#include namespace { -struct Ipc_CqueryFreshenIndex : public RequestMessage { +struct Ipc_CqueryFreshenIndex : public NotificationMessage { const static IpcId kIpcId = IpcId::CqueryFreshenIndex; - std::vector whitelist; - std::vector blacklist; + struct Params { + bool dependencies = true; + std::vector whitelist; + std::vector blacklist; + }; + Params params; }; -MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, id, whitelist, blacklist); +MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex::Params, dependencies, whitelist, blacklist); +MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, params); REGISTER_IPC_MESSAGE(Ipc_CqueryFreshenIndex); struct CqueryFreshenIndexHandler : BaseMessageHandler { @@ -23,24 +30,52 @@ struct CqueryFreshenIndexHandler : BaseMessageHandler { LOG_S(INFO) << "Freshening " << project->entries.size() << " files"; // TODO: think about this flow and test it more. - GroupMatch matcher(request->whitelist, request->blacklist); + GroupMatch matcher(request->params.whitelist, request->params.blacklist); // Unmark all files whose timestamp has changed. std::unique_ptr cache_manager = ICacheManager::Make(config); - for (const auto& file : db->files) { - if (!file.def || !matcher.IsMatch(file.def->path)) - continue; + + std::queue q; + // |need_index| stores every filename ever enqueued. + std::unordered_set need_index; + // Reverse dependency graph. + std::unordered_map> graph; + // filename -> QueryFile mapping for files haven't enqueued. + std::unordered_map path_to_file; + + for (const auto& file : db->files) + if (file.def) { + if (matcher.IsMatch(file.def->path)) + q.push(&file); + else + path_to_file[file.def->path] = &file; + for (const std::string& dependency : file.def->dependencies) + graph[dependency].push_back(file.def->path); + } + + while (!q.empty()) { + const QueryFile* file = q.front(); + q.pop(); + need_index.insert(file->def->path); optional modification_timestamp = - GetLastModificationTime(file.def->path); + GetLastModificationTime(file->def->path); if (!modification_timestamp) continue; - optional cached_modification = timestamp_manager->GetLastCachedModificationTime(cache_manager.get(), - file.def->path); + file->def->path); if (modification_timestamp != cached_modification) - file_consumer_shared->Reset(file.def->path); + file_consumer_shared->Reset(file->def->path); + + if (request->params.dependencies) + for (const std::string& path : graph[file->def->path]) { + auto it = path_to_file.find(path); + if (it != path_to_file.end()) { + q.push(it->second); + path_to_file.erase(it); + } + } } auto* queue = QueueManager::instance(); @@ -48,7 +83,7 @@ struct CqueryFreshenIndexHandler : BaseMessageHandler { // Send index requests for every file. project->ForAllFilteredFiles( config, [&](int i, const Project::Entry& entry) { - if (!matcher.IsMatch(entry.filename)) + if (!need_index.count(entry.filename)) return; optional content = ReadContent(entry.filename); if (!content) { diff --git a/src/query.cc b/src/query.cc index 659bb4b6..ea4aaa8b 100644 --- a/src/query.cc +++ b/src/query.cc @@ -201,6 +201,7 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) { def.path = indexed.path; def.includes = indexed.includes; def.inactive_regions = indexed.skipped_by_preprocessor; + def.dependencies = indexed.dependencies; // Convert enum to markdown compatible strings def.language = [indexed]() { diff --git a/src/query.h b/src/query.h index 38d4ce6b..d2e4e69f 100644 --- a/src/query.h +++ b/src/query.h @@ -192,6 +192,8 @@ struct QueryFile { std::vector all_symbols; // Parts of the file which are disabled. std::vector inactive_regions; + // Used by |$cquery/freshenIndex|. + std::vector dependencies; }; using DefUpdate = Def; @@ -209,7 +211,8 @@ MAKE_REFLECT_STRUCT(QueryFile::Def, language, outline, all_symbols, - inactive_regions); + inactive_regions, + dependencies); struct QueryType { using Def = TypeDefDefinitionData