Browse Source

Language client: fixed didChange notification when test document sync is full

pipelines/143601543
eidheim 6 years ago
parent
commit
1380e6e2f4
  1. 142
      src/source_language_protocol.cc
  2. 3
      src/source_language_protocol.h

142
src/source_language_protocol.cc

@ -364,43 +364,12 @@ void LanguageProtocol::Client::handle_server_request(const std::string &method,
} }
Source::LanguageProtocolView::LanguageProtocolView(const boost::filesystem::path &file_path, const Glib::RefPtr<Gsv::Language> &language, std::string language_id_) Source::LanguageProtocolView::LanguageProtocolView(const boost::filesystem::path &file_path, const Glib::RefPtr<Gsv::Language> &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)), autocomplete(this, interactive_completion, last_keyval, false) { : 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)) {
configure(); configure();
get_source_buffer()->set_language(language); get_source_buffer()->set_language(language);
get_source_buffer()->set_highlight_syntax(true); get_source_buffer()->set_highlight_syntax(true);
initialize(); initialize();
get_buffer()->signal_insert().connect([this](const Gtk::TextBuffer::iterator &start, const Glib::ustring &text_, int bytes) {
std::string content_changes;
if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::none)
return;
if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::incremental) {
std::string text = text_;
escape_text(text);
content_changes = R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(}},"text":")" + text + "\"}";
}
else {
std::string text = get_buffer()->get_text();
escape_text(text);
content_changes = R"({"text":")" + text + "\"}";
}
client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + content_changes + "]");
}, false);
get_buffer()->signal_erase().connect([this](const Gtk::TextBuffer::iterator &start, const Gtk::TextBuffer::iterator &end) {
std::string content_changes;
if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::none)
return;
if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::incremental)
content_changes = R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(end.get_line()) + ",\"character\":" + std::to_string(end.get_line_offset()) + R"(}},"text":""})";
else {
std::string text = get_buffer()->get_text();
escape_text(text);
content_changes = R"({"text":")" + text + "\"}";
}
client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + content_changes + "]");
}, false);
} }
void Source::LanguageProtocolView::initialize() { void Source::LanguageProtocolView::initialize() {
@ -425,6 +394,7 @@ void Source::LanguageProtocolView::initialize() {
client->write_notification("textDocument/didOpen", R"("textDocument":{"uri":")" + uri + R"(","languageId":")" + language_id + R"(","version":)" + std::to_string(document_version++) + R"(,"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(!initialized) { if(!initialized) {
setup_signals();
setup_autocomplete(); setup_autocomplete();
setup_navigation_and_refactoring(); setup_navigation_and_refactoring();
Menu::get().toggle_menu_items(); Menu::get().toggle_menu_items();
@ -450,9 +420,9 @@ void Source::LanguageProtocolView::close() {
if(initialize_thread.joinable()) if(initialize_thread.joinable())
initialize_thread.join(); initialize_thread.join();
autocomplete.state = Autocomplete::State::idle; autocomplete->state = Autocomplete::State::idle;
if(autocomplete.thread.joinable()) if(autocomplete->thread.joinable())
autocomplete.thread.join(); autocomplete->thread.join();
client->write_notification("textDocument/didClose", R"("textDocument":{"uri":")" + uri + "\"}"); client->write_notification("textDocument/didClose", R"("textDocument":{"uri":")" + uri + "\"}");
client->close(this); client->close(this);
@ -1199,17 +1169,40 @@ Source::Offset Source::LanguageProtocolView::get_declaration(const Gtk::TextIter
return *offset; return *offset;
} }
void Source::LanguageProtocolView::setup_signals() {
if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::incremental) {
get_buffer()->signal_insert().connect([this](const Gtk::TextBuffer::iterator &start, const Glib::ustring &text_, int bytes) {
std::string text = text_;
escape_text(text);
client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(}},"text":")" + text + "\"}" + "]");
}, false);
get_buffer()->signal_erase().connect([this](const Gtk::TextBuffer::iterator &start, const Gtk::TextBuffer::iterator &end) {
client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(end.get_line()) + ",\"character\":" + std::to_string(end.get_line_offset()) + R"(}},"text":""})" + "]");
}, false);
}
else if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::full) {
get_buffer()->signal_changed().connect([this]() {
std::string text = get_buffer()->get_text();
escape_text(text);
client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + R"({"text":")" + text + "\"}" + "]");
});
}
}
void Source::LanguageProtocolView::setup_autocomplete() { void Source::LanguageProtocolView::setup_autocomplete() {
autocomplete = std::make_unique<Autocomplete>(this, interactive_completion, last_keyval, false);
if(!capabilities.completion) if(!capabilities.completion)
return; return;
non_interactive_completion = [this] { non_interactive_completion = [this] {
if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) if(CompletionDialog::get() && CompletionDialog::get()->is_visible())
return; return;
autocomplete.run(); autocomplete->run();
}; };
autocomplete.reparse = [this] { autocomplete->reparse = [this] {
autocomplete_comment.clear(); autocomplete_comment.clear();
autocomplete_insert.clear(); autocomplete_insert.clear();
}; };
@ -1224,7 +1217,7 @@ void Source::LanguageProtocolView::setup_autocomplete() {
if(!has_focus()) if(!has_focus())
return; return;
if(autocomplete_show_arguments) if(autocomplete_show_arguments)
autocomplete.stop(); autocomplete->stop();
autocomplete_show_arguments = false; autocomplete_show_arguments = false;
autocomplete_delayed_show_arguments_connection.disconnect(); autocomplete_delayed_show_arguments_connection.disconnect();
autocomplete_delayed_show_arguments_connection = Glib::signal_timeout().connect([this]() { autocomplete_delayed_show_arguments_connection = Glib::signal_timeout().connect([this]() {
@ -1235,8 +1228,8 @@ void Source::LanguageProtocolView::setup_autocomplete() {
if(!has_focus()) if(!has_focus())
return false; return false;
if(is_possible_argument()) { if(is_possible_argument()) {
autocomplete.stop(); autocomplete->stop();
autocomplete.run(); autocomplete->run();
} }
return false; return false;
}, 500); }, 500);
@ -1258,14 +1251,14 @@ void Source::LanguageProtocolView::setup_autocomplete() {
} }
} }
autocomplete.is_continue_key = [](guint keyval) { autocomplete->is_continue_key = [](guint keyval) {
if((keyval >= '0' && keyval <= '9') || (keyval >= 'a' && keyval <= 'z') || (keyval >= 'A' && keyval <= 'Z') || keyval == '_') if((keyval >= '0' && keyval <= '9') || (keyval >= 'a' && keyval <= 'z') || (keyval >= 'A' && keyval <= 'Z') || keyval == '_')
return true; return true;
return false; return false;
}; };
autocomplete.is_restart_key = [this](guint keyval) { autocomplete->is_restart_key = [this](guint keyval) {
auto iter = get_buffer()->get_insert()->get_iter(); auto iter = get_buffer()->get_insert()->get_iter();
iter.backward_chars(2); iter.backward_chars(2);
if(keyval == '.' || (keyval == ':' && *iter == ':')) if(keyval == '.' || (keyval == ':' && *iter == ':'))
@ -1273,7 +1266,7 @@ void Source::LanguageProtocolView::setup_autocomplete() {
return false; return false;
}; };
autocomplete.run_check = [this]() { autocomplete->run_check = [this]() {
auto iter = get_buffer()->get_insert()->get_iter(); auto iter = get_buffer()->get_insert()->get_iter();
iter.backward_char(); iter.backward_char();
if(!is_code_iter(iter)) if(!is_code_iter(iter))
@ -1289,8 +1282,8 @@ void Source::LanguageProtocolView::setup_autocomplete() {
std::smatch sm; std::smatch sm;
if(std::regex_match(line, sm, regex)) { if(std::regex_match(line, sm, regex)) {
{ {
LockGuard lock(autocomplete.prefix_mutex); LockGuard lock(autocomplete->prefix_mutex);
autocomplete.prefix = sm.length(2) ? sm[3].str() : sm.length(4) ? sm[5].str() : sm[6].str(); autocomplete->prefix = sm.length(2) ? sm[3].str() : sm.length(4) ? sm[5].str() : sm[6].str();
if(!sm.length(2) && !sm.length(4)) if(!sm.length(2) && !sm.length(4))
autocomplete_enable_snippets = true; autocomplete_enable_snippets = true;
} }
@ -1298,21 +1291,21 @@ void Source::LanguageProtocolView::setup_autocomplete() {
} }
else if(is_possible_argument()) { else if(is_possible_argument()) {
autocomplete_show_arguments = true; autocomplete_show_arguments = true;
LockGuard lock(autocomplete.prefix_mutex); LockGuard lock(autocomplete->prefix_mutex);
autocomplete.prefix = ""; autocomplete->prefix = "";
return true; return true;
} }
else if(!interactive_completion) { else if(!interactive_completion) {
auto end_iter = get_buffer()->get_insert()->get_iter(); auto end_iter = get_buffer()->get_insert()->get_iter();
auto iter = end_iter; auto iter = end_iter;
while(iter.backward_char() && autocomplete.is_continue_key(*iter)) { while(iter.backward_char() && autocomplete->is_continue_key(*iter)) {
} }
if(iter != end_iter) if(iter != end_iter)
iter.forward_char(); iter.forward_char();
{ {
LockGuard lock(autocomplete.prefix_mutex); LockGuard lock(autocomplete->prefix_mutex);
autocomplete.prefix = get_buffer()->get_text(iter, end_iter); autocomplete->prefix = get_buffer()->get_text(iter, end_iter);
} }
auto prev1 = iter; auto prev1 = iter;
if(prev1.backward_char() && *prev1 != '.') { if(prev1.backward_char() && *prev1 != '.') {
@ -1329,25 +1322,25 @@ void Source::LanguageProtocolView::setup_autocomplete() {
return false; return false;
}; };
autocomplete.before_add_rows = [this] { autocomplete->before_add_rows = [this] {
status_state = "autocomplete..."; status_state = "autocomplete...";
if(update_status_state) if(update_status_state)
update_status_state(this); update_status_state(this);
}; };
autocomplete.after_add_rows = [this] { autocomplete->after_add_rows = [this] {
status_state = ""; status_state = "";
if(update_status_state) if(update_status_state)
update_status_state(this); update_status_state(this);
}; };
autocomplete.on_add_rows_error = [this] { autocomplete->on_add_rows_error = [this] {
autocomplete_comment.clear(); autocomplete_comment.clear();
autocomplete_insert.clear(); autocomplete_insert.clear();
}; };
autocomplete.add_rows = [this](std::string &buffer, int line_number, int column) { autocomplete->add_rows = [this](std::string &buffer, int line_number, int column) {
if(autocomplete.state == Autocomplete::State::starting) { if(autocomplete->state == Autocomplete::State::starting) {
autocomplete_comment.clear(); autocomplete_comment.clear();
autocomplete_insert.clear(); autocomplete_insert.clear();
std::promise<void> result_processed; std::promise<void> result_processed;
@ -1363,7 +1356,7 @@ void Source::LanguageProtocolView::setup_autocomplete() {
auto label = parameter_it->second.get<std::string>("label", ""); auto label = parameter_it->second.get<std::string>("label", "");
auto insert = label; auto insert = label;
auto documentation = parameter_it->second.get<std::string>("documentation", ""); auto documentation = parameter_it->second.get<std::string>("documentation", "");
autocomplete.rows.emplace_back(std::move(label)); autocomplete->rows.emplace_back(std::move(label));
autocomplete_insert.emplace_back(std::move(insert)); autocomplete_insert.emplace_back(std::move(insert));
autocomplete_comment.emplace_back(std::move(documentation)); autocomplete_comment.emplace_back(std::move(documentation));
} }
@ -1375,12 +1368,15 @@ void Source::LanguageProtocolView::setup_autocomplete() {
else { else {
client->write_request(this, "textDocument/completion", R"("textDocument":{"uri":")" + uri + R"("}, "position": {"line": )" + std::to_string(line_number - 1) + ", \"character\": " + std::to_string(column - 1) + "}", [this, &result_processed](const boost::property_tree::ptree &result, bool error) { client->write_request(this, "textDocument/completion", R"("textDocument":{"uri":")" + uri + R"("}, "position": {"line": )" + std::to_string(line_number - 1) + ", \"character\": " + std::to_string(column - 1) + "}", [this, &result_processed](const boost::property_tree::ptree &result, bool error) {
if(!error) { if(!error) {
auto begin = result.begin(); // rust language server is bugged boost::property_tree::ptree::const_iterator begin, end;
auto end = result.end(); auto items = result.get_child_optional("items");
auto items_it = result.find("items"); // correct if(items) {
if(items_it != result.not_found()) { begin = items->begin();
begin = items_it->second.begin(); end = items->end();
end = items_it->second.end(); }
else {
begin = result.begin();
end = result.end();
} }
for(auto it = begin; it != end; ++it) { for(auto it = begin; it != end; ++it) {
auto label = it->second.get<std::string>("label", ""); auto label = it->second.get<std::string>("label", "");
@ -1419,11 +1415,11 @@ void Source::LanguageProtocolView::setup_autocomplete() {
if(!label.empty()) { if(!label.empty()) {
std::string prefix; std::string prefix;
{ {
LockGuard lock(autocomplete.prefix_mutex); LockGuard lock(autocomplete->prefix_mutex);
prefix = autocomplete.prefix; prefix = autocomplete->prefix;
} }
if(prefix.compare(0, prefix.size(), label, 0, prefix.size()) == 0) { if(prefix.compare(0, prefix.size(), label, 0, prefix.size()) == 0) {
autocomplete.rows.emplace_back(std::move(label)); autocomplete->rows.emplace_back(std::move(label));
autocomplete_comment.emplace_back(std::move(detail)); autocomplete_comment.emplace_back(std::move(detail));
if(!documentation.empty() && documentation != autocomplete_comment.back()) { if(!documentation.empty() && documentation != autocomplete_comment.back()) {
if(!autocomplete_comment.back().empty()) if(!autocomplete_comment.back().empty())
@ -1438,14 +1434,14 @@ void Source::LanguageProtocolView::setup_autocomplete() {
if(autocomplete_enable_snippets) { if(autocomplete_enable_snippets) {
std::string prefix; std::string prefix;
{ {
LockGuard lock(autocomplete.prefix_mutex); LockGuard lock(autocomplete->prefix_mutex);
prefix = autocomplete.prefix; prefix = autocomplete->prefix;
} }
LockGuard lock(snippets_mutex); LockGuard lock(snippets_mutex);
if(snippets) { if(snippets) {
for(auto &snippet : *snippets) { for(auto &snippet : *snippets) {
if(prefix.compare(0, prefix.size(), snippet.prefix, 0, prefix.size()) == 0) { if(prefix.compare(0, prefix.size(), snippet.prefix, 0, prefix.size()) == 0) {
autocomplete.rows.emplace_back(snippet.prefix); autocomplete->rows.emplace_back(snippet.prefix);
autocomplete_insert.emplace_back(snippet.body); autocomplete_insert.emplace_back(snippet.body);
autocomplete_comment.emplace_back(snippet.description); autocomplete_comment.emplace_back(snippet.description);
} }
@ -1460,16 +1456,16 @@ void Source::LanguageProtocolView::setup_autocomplete() {
} }
}; };
autocomplete.on_show = [this] { autocomplete->on_show = [this] {
hide_tooltips(); hide_tooltips();
}; };
autocomplete.on_hide = [this] { autocomplete->on_hide = [this] {
autocomplete_comment.clear(); autocomplete_comment.clear();
autocomplete_insert.clear(); autocomplete_insert.clear();
}; };
autocomplete.on_select = [this](unsigned int index, const std::string &text, bool hide_window) { autocomplete->on_select = [this](unsigned int index, const std::string &text, bool hide_window) {
Glib::ustring insert = hide_window ? autocomplete_insert[index] : text; Glib::ustring insert = hide_window ? autocomplete_insert[index] : text;
get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter());
@ -1500,14 +1496,14 @@ void Source::LanguageProtocolView::setup_autocomplete() {
auto iter = get_buffer()->get_insert()->get_iter(); auto iter = get_buffer()->get_insert()->get_iter();
if(*iter == ')' && iter.backward_char() && *iter == '(') { // If no arguments, try signatureHelp if(*iter == ')' && iter.backward_char() && *iter == '(') { // If no arguments, try signatureHelp
last_keyval = '('; last_keyval = '(';
autocomplete.run(); autocomplete->run();
} }
} }
else else
get_buffer()->insert(CompletionDialog::get()->start_mark->get_iter(), insert); get_buffer()->insert(CompletionDialog::get()->start_mark->get_iter(), insert);
}; };
autocomplete.get_tooltip = [this](unsigned int index) { autocomplete->get_tooltip = [this](unsigned int index) {
return autocomplete_comment[index]; return autocomplete_comment[index];
}; };
} }

3
src/source_language_protocol.h

@ -188,7 +188,8 @@ namespace Source {
Offset get_declaration(const Gtk::TextIter &iter); Offset get_declaration(const Gtk::TextIter &iter);
Autocomplete autocomplete; std::unique_ptr<Autocomplete> autocomplete;
void setup_signals();
void setup_autocomplete(); void setup_autocomplete();
std::vector<std::string> autocomplete_comment; std::vector<std::string> autocomplete_comment;
std::vector<std::string> autocomplete_insert; std::vector<std::string> autocomplete_insert;

Loading…
Cancel
Save