#pragma once #include "clangmm.hpp" #include "mutex.hpp" #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace serialization { template void serialize(Archive &ar, boost::filesystem::path &path, const unsigned int version) { std::string path_str; if(Archive::is_saving::value) path_str = path.string(); ar &path_str; if(Archive::is_loading::value) path = path_str; } } // namespace serialization } // namespace boost namespace Usages { class Clang { public: using PathSet = std::set; class Usages { public: boost::filesystem::path path; std::vector> offsets; std::vector lines; }; class Cache { friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int version) { ar &project_path; ar &build_path; ar &tokens; ar &cursors; ar &paths_and_last_write_times; } public: class Cursor { friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int version) { ar &kind; ar &usrs; } public: clangmm::Cursor::Kind kind; std::unordered_set usrs; bool operator==(const Cursor &o); }; class Token { friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int version) { ar &spelling; ar &offsets.first.line &offsets.first.index; ar &offsets.second.line &offsets.second.index; ar &cursor_id; } public: std::string spelling; std::pair offsets; size_t cursor_id; }; boost::filesystem::path project_path; boost::filesystem::path build_path; std::vector tokens; std::vector cursors; std::map paths_and_last_write_times; Cache() = default; Cache(boost::filesystem::path project_path_, boost::filesystem::path build_path_, const boost::filesystem::path &path, std::time_t before_parse_time, clangmm::TranslationUnit *translation_unit, clangmm::Tokens *clang_tokens); operator bool() const { return !paths_and_last_write_times.empty(); } std::vector> get_similar_token_offsets(clangmm::Cursor::Kind kind, const std::string &spelling, const std::unordered_set &usrs) const; }; private: const static boost::filesystem::path cache_folder; static Mutex caches_mutex; static std::map caches GUARDED_BY(caches_mutex); static std::atomic cache_in_progress_count; public: static std::vector get_usages(const boost::filesystem::path &project_path, const boost::filesystem::path &build_path, const boost::filesystem::path &debug_path, const std::string &spelling, const clangmm::Cursor &cursor, const std::vector &translation_units); static void cache(const boost::filesystem::path &project_path, const boost::filesystem::path &build_path, const boost::filesystem::path &path, std::time_t before_parse_time, const PathSet &project_paths_in_use, clangmm::TranslationUnit *translation_unit, clangmm::Tokens *tokens); static void erase_unused_caches(const PathSet &project_paths_in_use); static void erase_cache(const boost::filesystem::path &path); static void erase_all_caches_for_project(const boost::filesystem::path &project_path, const boost::filesystem::path &build_path); static void cache_in_progress(); static void cancel_cache_in_progress(); private: static void add_usages(const boost::filesystem::path &project_path, const boost::filesystem::path &build_path, const boost::filesystem::path &path_, std::vector &usages, PathSet &visited, const std::string &spelling, clangmm::Cursor cursor, clangmm::TranslationUnit *translation_unit, bool store_in_cache); static bool add_usages_from_cache(const boost::filesystem::path &path, std::vector &usages, PathSet &visited, const std::string &spelling, const clangmm::Cursor &cursor, const Cache &cache); static void add_usages_from_includes(const boost::filesystem::path &project_path, const boost::filesystem::path &build_path, std::vector &usages, PathSet &visited, const std::string &spelling, const clangmm::Cursor &cursor, clangmm::TranslationUnit *translation_unit, bool store_in_cache); static PathSet find_paths(const boost::filesystem::path &project_path, const boost::filesystem::path &build_path, const boost::filesystem::path &debug_path); static std::pair, PathSet> parse_paths(const std::string &spelling, const PathSet &paths); /// Recursively find and return all the include paths of path static PathSet get_all_includes(const boost::filesystem::path &path, const std::map &paths_includes); /// Based on cursor paths, paths_includes and paths_with_spelling return potential paths that might contain the sought after symbol static std::pair find_potential_paths(const PathSet &paths, const boost::filesystem::path &project_path, const std::map &paths_includes, const PathSet &paths_with_spelling); static void write_cache(const boost::filesystem::path &path, const Cache &cache) REQUIRES(caches_mutex); static Cache read_cache(const boost::filesystem::path &project_path, const boost::filesystem::path &build_path, const boost::filesystem::path &path) REQUIRES(caches_mutex); }; } // namespace Usages