From 228056820eaea82d83190c5a37338bc05b5e0786 Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 8 Oct 2021 14:57:42 +0200 Subject: [PATCH] Language protocol: no longer show tooltips when no completion is selected --- src/autocomplete.cpp | 2 +- src/autocomplete.hpp | 1 + src/source_language_protocol.cpp | 71 ++++++++++++++++++++------------ src/source_language_protocol.hpp | 3 +- 4 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/autocomplete.cpp b/src/autocomplete.cpp index 5dd915f..2ea5d87 100644 --- a/src/autocomplete.cpp +++ b/src/autocomplete.cpp @@ -169,7 +169,7 @@ void Autocomplete::setup_dialog() { on_change(index, text); if(!index) { - tooltips.hide(); + clear_tooltips(); return; } diff --git a/src/autocomplete.hpp b/src/autocomplete.hpp index f8d1e51..cee731a 100644 --- a/src/autocomplete.hpp +++ b/src/autocomplete.hpp @@ -56,6 +56,7 @@ public: std::function on_select; std::function(unsigned int)> set_tooltip_buffer = [](unsigned int index) { return nullptr; }; + std::function clear_tooltips = [this] { tooltips.hide(); }; Autocomplete(Source::BaseView *view, bool &interactive_completion, guint &last_keyval, bool pass_buffer_and_strip_word, bool use_thread); diff --git a/src/source_language_protocol.cpp b/src/source_language_protocol.cpp index 92504e4..a8121e0 100644 --- a/src/source_language_protocol.cpp +++ b/src/source_language_protocol.cpp @@ -715,6 +715,7 @@ void Source::LanguageProtocolView::initialize() { Source::LanguageProtocolView::~LanguageProtocolView() { autocomplete_delayed_show_arguments_connection.disconnect(); + resolve_completion_item_connection.disconnect(); update_type_coverage_connection.disconnect(); if(initialize_thread.joinable()) @@ -1504,7 +1505,7 @@ void Source::LanguageProtocolView::setup_autocomplete() { // Activate argument completions get_buffer()->signal_changed().connect( [this] { - autocompete_possibly_no_arguments = false; + autocomplete_possibly_no_arguments = false; if(!interactive_completion) return; if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) @@ -1732,7 +1733,7 @@ void Source::LanguageProtocolView::setup_autocomplete() { if(autocomplete_rows.empty()) { dispatcher.post([this] { // Move cursor forward if no arguments in completed function and if cursor is still inside () - if(autocompete_possibly_no_arguments) { + if(autocomplete_possibly_no_arguments) { auto iter = get_buffer()->get_insert()->get_iter(); auto prev = iter; if(prev.backward_char() && *prev == '(' && *iter == ')' && iter.forward_char()) @@ -1882,7 +1883,7 @@ void Source::LanguageProtocolView::setup_autocomplete() { if(*iter == ')' && iter.backward_char() && *iter == '(') { // If no arguments, try signatureHelp last_keyval = '('; if(is_js) // Workaround for typescript-language-server - autocompete_possibly_no_arguments = true; + autocomplete_possibly_no_arguments = true; autocomplete->run(); } } @@ -1916,32 +1917,42 @@ void Source::LanguageProtocolView::setup_autocomplete() { }; if(capabilities.completion_resolve && autocomplete_row.detail.empty() && autocomplete_row.documentation.value.empty() && autocomplete_row.item_object) { - std::stringstream ss; - bool first = true; - for(auto &child : autocomplete_row.item_object->children_or_empty()) { - ss << (!first ? ",\"" : "\"") << JSON::escape_string(child.first) << "\":" << child.second; - first = false; - } - write_request("completionItem/resolve", ss.str(), [this, last_count](JSON &&result, bool error) { - if(!error) { - if(last_count != set_tooltip_count) - return; - auto detail = result.string_or("detail", ""); - auto documentation = LanguageProtocol::Documentation(result.child_optional("documentation")); - if(detail.empty() && documentation.value.empty()) - return; - dispatcher.post([this, last_count, detail = std::move(detail), documentation = std::move(documentation)] { + // Prevent several completionItem/resolve requests when no completion item is found from written source (for instance when autocompleting in python : math.___). + // This seems to be a bug in Gtk::TreeView::signal_cursor_changed. + resolve_completion_item_connection.disconnect(); + resolve_completion_item_connection = Glib::signal_timeout().connect( + [this, last_count, item_object = autocomplete_row.item_object] { if(last_count != set_tooltip_count) - return; - autocomplete->tooltips.clear(); - auto iter = CompletionDialog::get()->start_mark->get_iter(); - autocomplete->tooltips.emplace_back(this, iter, iter, [this, detail = std::move(detail), documentation = std::move(documentation)](Tooltip &tooltip) { - insert_documentation(this, tooltip, detail, documentation); + return false; + std::stringstream ss; + bool first = true; + for(auto &child : item_object->children_or_empty()) { + ss << (!first ? ",\"" : "\"") << JSON::escape_string(child.first) << "\":" << child.second; + first = false; + } + write_request("completionItem/resolve", ss.str(), [this, last_count](JSON &&result, bool error) { + if(!error) { + if(last_count != set_tooltip_count) + return; + auto detail = result.string_or("detail", ""); + auto documentation = LanguageProtocol::Documentation(result.child_optional("documentation")); + if(detail.empty() && documentation.value.empty()) + return; + dispatcher.post([this, last_count, detail = std::move(detail), documentation = std::move(documentation)] { + if(last_count != set_tooltip_count) + return; + autocomplete->tooltips.clear(); + auto iter = CompletionDialog::get()->start_mark->get_iter(); + autocomplete->tooltips.emplace_back(this, iter, iter, [this, detail = std::move(detail), documentation = std::move(documentation)](Tooltip &tooltip) { + insert_documentation(this, tooltip, detail, documentation); + }); + autocomplete->tooltips.show(true); + }); + } }); - autocomplete->tooltips.show(true); - }); - } - }); + return false; + }, + 0); return nullptr; } if(autocomplete_row.detail.empty() && autocomplete_row.documentation.value.empty()) @@ -1951,6 +1962,12 @@ void Source::LanguageProtocolView::setup_autocomplete() { insert_documentation(this, tooltip, autocomplete_row.detail, autocomplete_row.documentation); }; }; + + autocomplete->clear_tooltips = [this] { + resolve_completion_item_connection.disconnect(); + ++set_tooltip_count; + autocomplete->tooltips.hide(); + }; } void Source::LanguageProtocolView::update_diagnostics_async(std::vector &&diagnostics) { diff --git a/src/source_language_protocol.hpp b/src/source_language_protocol.hpp index f379f9f..db8b71b 100644 --- a/src/source_language_protocol.hpp +++ b/src/source_language_protocol.hpp @@ -288,12 +288,13 @@ namespace Source { sigc::connection autocomplete_delayed_show_arguments_connection; /// Workaround for typescript-language-server. /// Used to move cursor forward if no arguments in completed function and if cursor is still inside () - bool autocompete_possibly_no_arguments = false; + bool autocomplete_possibly_no_arguments = false; /// If language supports named parameters, returns the symbol separating the named parameter and value, /// for instance '=' for Python boost::optional get_named_parameter_symbol(); + sigc::connection resolve_completion_item_connection; /// Used when calling completionItem/resolve. Also increased in autocomplete->on_hide. std::atomic set_tooltip_count = {0};