// Copyright 2017-2018 ccls Authors // SPDX-License-Identifier: Apache-2.0 #include "clang_complete.hh" #include "match.h" #include "message_handler.h" #include "pipeline.hh" #include "project.h" #include "working_files.h" #include #include using namespace ccls; namespace { MethodType kMethodType = "$ccls/reload"; struct In_cclsReload : public NotificationMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { bool dependencies = true; std::vector whitelist; std::vector blacklist; } params; }; MAKE_REFLECT_STRUCT(In_cclsReload::Params, dependencies, whitelist, blacklist); MAKE_REFLECT_STRUCT(In_cclsReload, params); REGISTER_IN_MESSAGE(In_cclsReload); struct Handler_cclsReload : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } void Run(In_cclsReload *request) override { const auto ¶ms = request->params; // Send index requests for every file. if (params.whitelist.empty() && params.blacklist.empty()) { vfs->Clear(); db->clear(); project->Index(working_files, lsRequestId()); clang_complete->FlushAllSessions(); return; } // TODO GroupMatch matcher(params.whitelist, params.blacklist); 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); 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); } } } } }; REGISTER_MESSAGE_HANDLER(Handler_cclsReload); } // namespace