#pragma once #include "autocomplete.h" #include "clangmm.h" #include "dispatcher.h" #include "source.h" #include "terminal.h" #include #include #include #include #include namespace Source { class ClangViewParse : public View { protected: enum class ParseState { PROCESSING, RESTARTING, STOP }; enum class ParseProcessState { IDLE, STARTING, PREPROCESSING, PROCESSING, POSTPROCESSING }; public: ClangViewParse(const boost::filesystem::path &file_path, const Glib::RefPtr &language); void rename(const boost::filesystem::path &path) override; bool save() override; void configure() override; void soft_reparse(bool delayed = false) override; protected: Dispatcher dispatcher; void parse_initialize(); std::unique_ptr clang_tu; std::unique_ptr clang_tokens; std::vector> clang_tokens_offsets; sigc::connection delayed_reparse_connection; void show_type_tooltips(const Gdk::Rectangle &rectangle) override; std::vector fix_its; std::thread parse_thread; std::mutex parse_mutex; std::atomic parse_state; std::atomic parse_process_state; CXCompletionString selected_completion_string = nullptr; private: Glib::ustring parse_thread_buffer; static const std::map &clang_types(); void update_syntax(); std::map> syntax_tags; void update_diagnostics(); std::vector clang_diagnostics; static clangmm::Index clang_index; }; class ClangViewAutocomplete : public virtual ClangViewParse { public: ClangViewAutocomplete(const boost::filesystem::path &file_path, const Glib::RefPtr &language); protected: Autocomplete autocomplete; std::unique_ptr code_complete_results; std::vector completion_strings; sigc::connection delayed_show_arguments_connection; private: bool is_possible_parameter(); bool show_arguments; const std::unordered_map &autocomplete_manipulators_map(); }; class ClangViewRefactor : public virtual ClangViewParse { class Identifier { public: Identifier(std::string spelling_, const clangmm::Cursor &cursor) : kind(cursor.get_kind()), spelling(std::move(spelling_)), usr_extended(cursor.get_usr_extended()), cursor(cursor) {} Identifier() : kind(static_cast(0)) {} operator bool() const { return static_cast(kind) != 0; } bool operator==(const Identifier &rhs) const { return spelling == rhs.spelling && usr_extended == rhs.usr_extended; } bool operator!=(const Identifier &rhs) const { return !(*this == rhs); } bool operator<(const Identifier &rhs) const { return spelling < rhs.spelling || (spelling == rhs.spelling && usr_extended < rhs.usr_extended); } clangmm::Cursor::Kind kind; std::string spelling; std::string usr_extended; clangmm::Cursor cursor; }; public: ClangViewRefactor(const boost::filesystem::path &file_path, const Glib::RefPtr &language); private: Identifier get_identifier(); void wait_parsing(); void tag_similar_identifiers(const Identifier &identifier); Identifier last_tagged_identifier; }; class ClangView : public ClangViewAutocomplete, public ClangViewRefactor { public: ClangView(const boost::filesystem::path &file_path, const Glib::RefPtr &language); void full_reparse() override; void async_delete(); private: Glib::Dispatcher do_delete_object; std::thread delete_thread; std::thread full_reparse_thread; bool full_reparse_running = false; }; } // namespace Source