From 8de9f298d60ce7e25632e7415a4be63d8b65b4be Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 18 Jun 2019 20:12:07 +0200 Subject: [PATCH] Language protocol: now retries typeCoverage request on error during initialization since the request might fail while waiting for language server to start. --- src/dispatcher.cc | 11 ++++ src/dispatcher.h | 15 ++++-- src/source_language_protocol.cc | 94 ++++++++++++++++++++------------- src/source_language_protocol.h | 6 ++- 4 files changed, 83 insertions(+), 43 deletions(-) diff --git a/src/dispatcher.cc b/src/dispatcher.cc index f4f78f6..8382e43 100644 --- a/src/dispatcher.cc +++ b/src/dispatcher.cc @@ -2,6 +2,10 @@ #include Dispatcher::Dispatcher() { + connect(); +} + +void Dispatcher::connect() { connection = dispatcher.connect([this] { std::vector>::iterator> its; { @@ -29,3 +33,10 @@ Dispatcher::~Dispatcher() { void Dispatcher::disconnect() { connection.disconnect(); } + +void Dispatcher::reset() { + std::lock_guard lock(functions_mutex); + disconnect(); + functions.clear(); + connect(); +} diff --git a/src/dispatcher.h b/src/dispatcher.h index 7f735f4..2a2d3e7 100644 --- a/src/dispatcher.h +++ b/src/dispatcher.h @@ -11,18 +11,25 @@ private: Glib::Dispatcher dispatcher; sigc::connection connection; + void connect(); + public: + /// Must be called from main GUI thread Dispatcher(); ~Dispatcher(); + /// Queue function to main GUI thread. + /// Can be called from any thread. template void post(T &&function) { - { - std::lock_guard lock(functions_mutex); - functions.emplace_back(std::forward(function)); - } + std::lock_guard lock(functions_mutex); + functions.emplace_back(std::forward(function)); dispatcher(); } + /// Must be called from main GUI thread void disconnect(); + + /// Must be called from main GUI thread + void reset(); }; diff --git a/src/source_language_protocol.cc b/src/source_language_protocol.cc index 40b3763..b1c5949 100644 --- a/src/source_language_protocol.cc +++ b/src/source_language_protocol.cc @@ -354,7 +354,7 @@ Source::LanguageProtocolView::LanguageProtocolView(const boost::filesystem::path get_source_buffer()->set_language(language); get_source_buffer()->set_highlight_syntax(true); - initialize(true); + initialize(); get_buffer()->signal_insert().connect([this](const Gtk::TextBuffer::iterator &start, const Glib::ustring &text_, int bytes) { std::string content_changes; @@ -388,7 +388,7 @@ Source::LanguageProtocolView::LanguageProtocolView(const boost::filesystem::path }, false); } -void Source::LanguageProtocolView::initialize(bool setup) { +void Source::LanguageProtocolView::initialize() { status_diagnostics = std::make_tuple(0, 0, 0); if(update_status_diagnostics) update_status_diagnostics(this); @@ -398,10 +398,10 @@ void Source::LanguageProtocolView::initialize(bool setup) { update_status_state(this); set_editable(false); - initialize_thread = std::thread([this, setup] { + initialize_thread = std::thread([this] { auto capabilities = client->initialize(this); - dispatcher.post([this, capabilities, setup] { + dispatcher.post([this, capabilities] { this->capabilities = capabilities; set_editable(true); @@ -409,7 +409,7 @@ void Source::LanguageProtocolView::initialize(bool setup) { escape_text(text); client->write_notification("textDocument/didOpen", R"("textDocument":{"uri":")" + uri + R"(","languageId":")" + language_id + R"(","version":)" + std::to_string(document_version++) + R"(,"text":")" + text + "\"}"); - if(setup) { + if(!initialized) { setup_autocomplete(); setup_navigation_and_refactoring(); Menu::get().toggle_menu_items(); @@ -422,12 +422,15 @@ void Source::LanguageProtocolView::initialize(bool setup) { } update_type_coverage(); + + initialized = true; }); }); } void Source::LanguageProtocolView::close() { autocomplete_delayed_show_arguments_connection.disconnect(); + update_type_coverage_connection.disconnect(); if(initialize_thread.joinable()) initialize_thread.join(); @@ -446,11 +449,13 @@ Source::LanguageProtocolView::~LanguageProtocolView() { } void Source::LanguageProtocolView::rename(const boost::filesystem::path &path) { + // Reset view close(); + dispatcher.reset(); Source::DiffView::rename(path); uri = filesystem::get_uri_from_path(path); client = LanguageProtocol::Client::get(file_path, language_id); - initialize(false); + initialize(); } bool Source::LanguageProtocolView::save() { @@ -1485,41 +1490,54 @@ bool Source::LanguageProtocolView::has_named_parameters() { void Source::LanguageProtocolView::update_type_coverage() { if(capabilities.type_coverage) { client->write_request(this, "textDocument/typeCoverage", R"("textDocument": {"uri":")" + uri + "\"}", [this](const boost::property_tree::ptree &result, bool error) { - if(!error) { - std::vector ranges; - auto uncoveredRanges = result.get_child("uncoveredRanges", boost::property_tree::ptree()); - for(auto it = uncoveredRanges.begin(); it != uncoveredRanges.end(); ++it) { - try { - ranges.emplace_back(it->second.get_child("range")); - } - catch(...) { - } + if(error) { + if(update_type_coverage_retries > 0) { // Retry typeCoverage request, since these requests can fail while waiting for language server to start + dispatcher.post([this] { + update_type_coverage_connection.disconnect(); + update_type_coverage_connection = Glib::signal_timeout().connect([this]() { + --update_type_coverage_retries; + update_type_coverage(); + return false; + }, 1000); + }); } + return; + } + update_type_coverage_retries = 0; - dispatcher.post([this, ranges = std::move(ranges)] { - num_warnings = 0; - for(auto &mark : type_coverage_marks) { - get_buffer()->delete_mark(mark.first); - get_buffer()->delete_mark(mark.second); - } - type_coverage_marks.clear(); - get_buffer()->remove_tag_by_name("def:warning_underline", get_buffer()->begin(), get_buffer()->end()); - for(auto &range : ranges) { - auto start = get_iter_at_line_offset(range.start.line, range.start.character); - auto end = get_iter_at_line_offset(range.end.line, range.end.character); - add_diagnostic_tooltip(start, end, false, [](const Glib::RefPtr &buffer) { - buffer->insert_at_cursor(type_coverage_message); - }); - type_coverage_marks.emplace_back(get_buffer()->create_mark(start), get_buffer()->create_mark(end)); - - ++num_warnings; - } - - status_diagnostics = std::make_tuple(num_warnings, num_errors, num_fix_its); - if(update_status_diagnostics) - update_status_diagnostics(this); - }); + std::vector ranges; + auto uncoveredRanges = result.get_child("uncoveredRanges", boost::property_tree::ptree()); + for(auto it = uncoveredRanges.begin(); it != uncoveredRanges.end(); ++it) { + try { + ranges.emplace_back(it->second.get_child("range")); + } + catch(...) { + } } + + dispatcher.post([this, ranges = std::move(ranges)] { + num_warnings = 0; + for(auto &mark : type_coverage_marks) { + get_buffer()->delete_mark(mark.first); + get_buffer()->delete_mark(mark.second); + } + type_coverage_marks.clear(); + get_buffer()->remove_tag_by_name("def:warning_underline", get_buffer()->begin(), get_buffer()->end()); + for(auto &range : ranges) { + auto start = get_iter_at_line_offset(range.start.line, range.start.character); + auto end = get_iter_at_line_offset(range.end.line, range.end.character); + add_diagnostic_tooltip(start, end, false, [](const Glib::RefPtr &buffer) { + buffer->insert_at_cursor(type_coverage_message); + }); + type_coverage_marks.emplace_back(get_buffer()->create_mark(start), get_buffer()->create_mark(end)); + + ++num_warnings; + } + + status_diagnostics = std::make_tuple(num_warnings, num_errors, num_fix_its); + if(update_status_diagnostics) + update_status_diagnostics(this); + }); }); } } diff --git a/src/source_language_protocol.h b/src/source_language_protocol.h index 6f5a16a..4467c8c 100644 --- a/src/source_language_protocol.h +++ b/src/source_language_protocol.h @@ -144,7 +144,7 @@ namespace Source { class LanguageProtocolView : public View { public: LanguageProtocolView(const boost::filesystem::path &file_path, const Glib::RefPtr &language, std::string language_id_); - void initialize(bool setup); + void initialize(); void close(); ~LanguageProtocolView() override; @@ -163,6 +163,8 @@ namespace Source { void apply_clickable_tag(const Gtk::TextIter &iter) override; private: + bool initialized = false; + std::string language_id; LanguageProtocol::Capabilities capabilities; @@ -191,8 +193,10 @@ namespace Source { bool has_named_parameters(); + sigc::connection update_type_coverage_connection; std::vector, Glib::RefPtr>> type_coverage_marks; size_t num_warnings = 0, num_errors = 0, num_fix_its = 0; void update_type_coverage(); + std::atomic update_type_coverage_retries = {60}; }; } // namespace Source