diff --git a/src/filesystem.cpp b/src/filesystem.cpp index ee10937..7a6792f 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -126,6 +126,24 @@ boost::filesystem::path filesystem::get_home_path() noexcept { return path; } +boost::filesystem::path filesystem::get_rust_sysroot_path() noexcept { + auto rust_sysroot_path = [] { + std::string path; + TinyProcessLib::Process process("rustc --print sysroot", "", [&path](const char *buffer, size_t length) { + path += std::string(buffer, length); + }); + if(process.get_exit_status() == 0) { + while(!path.empty() && (path.back() == '\n' || path.back() == '\r')) + path.pop_back(); + return boost::filesystem::path(path); + } + return boost::filesystem::path(); + }; + + static boost::filesystem::path path = rust_sysroot_path(); + return path; +} + boost::filesystem::path filesystem::get_short_path(const boost::filesystem::path &path) noexcept { #ifdef _WIN32 return path; diff --git a/src/filesystem.hpp b/src/filesystem.hpp index d8501b0..173faa3 100644 --- a/src/filesystem.hpp +++ b/src/filesystem.hpp @@ -20,6 +20,8 @@ public: static boost::filesystem::path get_current_path() noexcept; /// Returns empty path on failure static boost::filesystem::path get_home_path() noexcept; + /// Returns empty path on failure + static boost::filesystem::path get_rust_sysroot_path() noexcept; /// Replaces home path with ~ static boost::filesystem::path get_short_path(const boost::filesystem::path &path) noexcept; /// Replaces ~ with home path (boost::filesystem does not recognize ~) diff --git a/src/notebook.cpp b/src/notebook.cpp index 76a4dfa..c3b4678 100644 --- a/src/notebook.cpp +++ b/src/notebook.cpp @@ -173,7 +173,15 @@ bool Notebook::open(const boost::filesystem::path &file_path_, Position position if(language && (language->get_id() == "chdr" || language->get_id() == "cpphdr" || language->get_id() == "c" || language->get_id() == "cpp" || language->get_id() == "objc")) source_views.emplace_back(new Source::ClangView(file_path, language)); else if(language && !language_protocol_language_id.empty() && !filesystem::find_executable(language_protocol_language_id + "-language-server").empty()) - source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id)); + source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, language_protocol_language_id + "-language-server")); + else if(language && language_protocol_language_id == "rust" && !filesystem::get_rust_sysroot_path().empty()) { + auto rust_analyzer = filesystem::get_rust_sysroot_path().string() + "/bin/rust-analyzer"; + boost::system::error_code ec; + if(boost::filesystem::exists(rust_analyzer, ec)) + source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, rust_analyzer)); + else + source_views.emplace_back(new Source::GenericView(file_path, language)); + } else { if(language) { static std::set shown; diff --git a/src/project.cpp b/src/project.cpp index db3c335..0a03cdf 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -469,11 +469,8 @@ void Project::LLDB::debug_start() { std::vector startup_commands; if(dynamic_cast(self->build.get())) { - std::stringstream istream, ostream; - if(Terminal::get().process(istream, ostream, "rustc --print sysroot") == 0) { - auto sysroot = ostream.str(); - while(!sysroot.empty() && (sysroot.back() == '\n' || sysroot.back() == '\r')) - sysroot.pop_back(); + auto sysroot = filesystem::get_rust_sysroot_path().string(); + if(!sysroot.empty()) { std::string line; std::ifstream input(sysroot + "/lib/rustlib/etc/lldb_commands", std::ofstream::binary); if(input) { diff --git a/src/source_language_protocol.cpp b/src/source_language_protocol.cpp index 7609037..f76131e 100644 --- a/src/source_language_protocol.cpp +++ b/src/source_language_protocol.cpp @@ -55,9 +55,9 @@ LanguageProtocol::TextDocumentEdit::TextDocumentEdit(const boost::property_tree: edits.emplace_back(it->second); } -LanguageProtocol::Client::Client(boost::filesystem::path root_path_, std::string language_id_) : root_path(std::move(root_path_)), language_id(std::move(language_id_)) { +LanguageProtocol::Client::Client(boost::filesystem::path root_path_, std::string language_id_, const std::string &language_server) : root_path(std::move(root_path_)), language_id(std::move(language_id_)) { process = std::make_unique( - filesystem::escape_argument(language_id + "-language-server"), root_path.string(), + filesystem::escape_argument(language_server), root_path.string(), [this](const char *bytes, size_t n) { server_message_stream.write(bytes, n); parse_server_message(); @@ -68,7 +68,7 @@ LanguageProtocol::Client::Client(boost::filesystem::path root_path_, std::string true, TinyProcessLib::Config{1048576}); } -std::shared_ptr LanguageProtocol::Client::get(const boost::filesystem::path &file_path, const std::string &language_id) { +std::shared_ptr LanguageProtocol::Client::get(const boost::filesystem::path &file_path, const std::string &language_id, const std::string &language_server) { boost::filesystem::path root_path; auto build = Project::Build::create(file_path); if(!build->project_path.empty()) @@ -87,7 +87,7 @@ std::shared_ptr LanguageProtocol::Client::get(const bo it = cache.emplace(cache_id, std::weak_ptr()).first; auto instance = it->second.lock(); if(!instance) - it->second = instance = std::shared_ptr(new Client(root_path, language_id), [](Client *client_ptr) { + it->second = instance = std::shared_ptr(new Client(root_path, language_id, language_server), [](Client *client_ptr) { std::thread delete_thread([client_ptr] { // Delete client in the background delete client_ptr; }); @@ -451,8 +451,8 @@ void LanguageProtocol::Client::handle_server_request(size_t id, const std::strin // write_response(*id, ""); } -Source::LanguageProtocolView::LanguageProtocolView(const boost::filesystem::path &file_path, const Glib::RefPtr &language, std::string language_id_) - : Source::BaseView(file_path, language), Source::View(file_path, language), uri(filesystem::get_uri_from_path(file_path)), language_id(std::move(language_id_)), client(LanguageProtocol::Client::get(file_path, language_id)) { +Source::LanguageProtocolView::LanguageProtocolView(const boost::filesystem::path &file_path, const Glib::RefPtr &language, std::string language_id_, std::string language_server_) + : Source::BaseView(file_path, language), Source::View(file_path, language), uri(filesystem::get_uri_from_path(file_path)), language_id(std::move(language_id_)), language_server(std::move(language_server_)), client(LanguageProtocol::Client::get(file_path, language_id, language_server)) { initialize(); } @@ -534,7 +534,7 @@ void Source::LanguageProtocolView::rename(const boost::filesystem::path &path) { dispatcher.reset(); Source::DiffView::rename(path); uri = filesystem::get_uri_from_path(path); - client = LanguageProtocol::Client::get(file_path, language_id); + client = LanguageProtocol::Client::get(file_path, language_id, language_server); initialize(); } diff --git a/src/source_language_protocol.hpp b/src/source_language_protocol.hpp index 05a6713..b4638c9 100644 --- a/src/source_language_protocol.hpp +++ b/src/source_language_protocol.hpp @@ -113,7 +113,7 @@ namespace LanguageProtocol { }; class Client { - Client(boost::filesystem::path root_path, std::string language_id); + Client(boost::filesystem::path root_path, std::string language_id, const std::string &language_server); boost::filesystem::path root_path; std::string language_id; @@ -141,7 +141,7 @@ namespace LanguageProtocol { std::vector timeout_threads GUARDED_BY(timeout_threads_mutex); public: - static std::shared_ptr get(const boost::filesystem::path &file_path, const std::string &language_id); + static std::shared_ptr get(const boost::filesystem::path &file_path, const std::string &language_id, const std::string &language_server); ~Client(); @@ -161,7 +161,7 @@ namespace LanguageProtocol { namespace Source { class LanguageProtocolView : public View { public: - LanguageProtocolView(const boost::filesystem::path &file_path, const Glib::RefPtr &language, std::string language_id_); + LanguageProtocolView(const boost::filesystem::path &file_path, const Glib::RefPtr &language, std::string language_id_, std::string language_server_); void initialize(); void close(); ~LanguageProtocolView() override; @@ -190,6 +190,7 @@ namespace Source { bool initialized = false; std::string language_id; + std::string language_server; LanguageProtocol::Capabilities capabilities; std::shared_ptr client;