From dd11a9c1d83889a460887c6e38426fd47b76484d Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 23 Mar 2026 19:40:37 +0100 Subject: [PATCH] language client: cleanup of workspace/applyEdit --- src/source_language_protocol.cpp | 108 ++++++++++++++++--------------- src/source_language_protocol.hpp | 2 +- 2 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/source_language_protocol.cpp b/src/source_language_protocol.cpp index 6ade6c9..6522584 100644 --- a/src/source_language_protocol.cpp +++ b/src/source_language_protocol.cpp @@ -64,13 +64,14 @@ LanguageProtocol::TextDocumentEdit::TextDocumentEdit(const JSON &text_document_e LanguageProtocol::TextDocumentEdit::TextDocumentEdit(std::string file, std::vector text_edits) : file(std::move(file)), text_edits(std::move(text_edits)) {} -LanguageProtocol::WorkspaceEdit::WorkspaceEdit(const JSON &workspace_edit, boost::filesystem::path file_path) { +LanguageProtocol::WorkspaceEdit::WorkspaceEdit(const JSON &workspace_edit, boost::filesystem::path path) { boost::filesystem::path project_path; - auto build = Project::Build::create(file_path); + auto build = Project::Build::create(path); + boost::system::error_code ec; if(!build->project_path.empty()) project_path = build->project_path; else - project_path = file_path.parent_path(); + project_path = boost::filesystem::is_directory(path, ec) ? path : path.parent_path(); try { if(auto changes = workspace_edit.children_optional("changes")) { for(auto &change : *changes) { @@ -587,67 +588,70 @@ void LanguageProtocol::Client::handle_server_request(const boost::variant result_processed; bool applied = true; - dispatcher->post([&result_processed, &applied, params = std::make_shared(std::move(params))] { + dispatcher->post([this, &result_processed, &applied, params = std::make_shared(std::move(params))] { ScopeGuard guard({[&result_processed] { result_processed.set_value(); }}); - if(auto current_view = dynamic_cast(Notebook::get().get_current_view())) { - LanguageProtocol::WorkspaceEdit workspace_edit; - try { - workspace_edit = LanguageProtocol::WorkspaceEdit(params->object("edit"), current_view->file_path); - } - catch(...) { - applied = false; - return; - } + LanguageProtocol::WorkspaceEdit workspace_edit; + try { + workspace_edit = LanguageProtocol::WorkspaceEdit(params->object("edit"), root_path); + } + catch(...) { + applied = false; + return; + } - for(auto &document_change : workspace_edit.document_changes) { - if(auto edit = boost::get(&document_change)) { - Source::View *view = nullptr; - for(auto &e : Source::View::views) { - if(e->file_path == edit->file) { - view = e; - break; - } + auto current_view = Notebook::get().get_current_view(); + for(auto &document_change : workspace_edit.document_changes) { + if(auto edit = boost::get(&document_change)) { + Source::View *view = nullptr; + for(auto &e : Source::View::views) { + if(e->file_path == edit->file) { + view = e; + break; } - if(!view) { - if(!Notebook::get().open(edit->file)) { - applied = false; - return; - } - view = Notebook::get().get_current_view(); + } + if(!view) { + if(!Notebook::get().open(edit->file)) { + applied = false; + return; } + view = Notebook::get().get_current_view(); + } - auto buffer = view->get_buffer(); - buffer->begin_user_action(); + auto buffer = view->get_buffer(); + buffer->begin_user_action(); - auto end_iter = buffer->end(); - // If entire buffer is replaced - if(edit->text_edits.size() == 1 && - edit->text_edits[0].range.start.line == 0 && edit->text_edits[0].range.start.character == 0 && - (edit->text_edits[0].range.end.line > end_iter.get_line() || - (edit->text_edits[0].range.end.line == end_iter.get_line() && edit->text_edits[0].range.end.character >= current_view->get_line_pos(end_iter)))) { - view->replace_text(edit->text_edits[0].new_text); - } - else { - for(auto text_edit_it = edit->text_edits.rbegin(); text_edit_it != edit->text_edits.rend(); ++text_edit_it) { - auto start_iter = view->get_iter_at_line_pos(text_edit_it->range.start.line, text_edit_it->range.start.character); - auto end_iter = view->get_iter_at_line_pos(text_edit_it->range.end.line, text_edit_it->range.end.character); - if(view != current_view) - view->get_buffer()->place_cursor(start_iter); - buffer->erase(start_iter, end_iter); - start_iter = view->get_iter_at_line_pos(text_edit_it->range.start.line, text_edit_it->range.start.character); - buffer->insert(start_iter, text_edit_it->new_text); - } + auto get_line_pos = [this](Source::View *view, const Gtk::TextIter &iter) -> int { + if(capabilities.use_line_index) + return iter.get_line_index(); + return utf16_code_unit_count(view->get_line(iter), 0, iter.get_line_index()); + }; + auto end_iter = buffer->end(); + // If entire buffer is replaced + if(edit->text_edits.size() == 1 && + edit->text_edits[0].range.start.line == 0 && edit->text_edits[0].range.start.character == 0 && + (edit->text_edits[0].range.end.line > end_iter.get_line() || + (edit->text_edits[0].range.end.line == end_iter.get_line() && edit->text_edits[0].range.end.character >= get_line_pos(view, end_iter)))) { + view->replace_text(edit->text_edits[0].new_text); + } + else { + for(auto text_edit_it = edit->text_edits.rbegin(); text_edit_it != edit->text_edits.rend(); ++text_edit_it) { + auto start_iter = view->get_iter_at_line_pos(text_edit_it->range.start.line, text_edit_it->range.start.character); + auto end_iter = view->get_iter_at_line_pos(text_edit_it->range.end.line, text_edit_it->range.end.character); + if(view != current_view) + view->get_buffer()->place_cursor(start_iter); + buffer->erase(start_iter, end_iter); + start_iter = view->get_iter_at_line_pos(text_edit_it->range.start.line, text_edit_it->range.start.character); + buffer->insert(start_iter, text_edit_it->new_text); } - - buffer->end_user_action(); } - } - if(current_view) - Notebook::get().open(current_view); + buffer->end_user_action(); + } } + if(current_view) + Notebook::get().open(current_view); }); result_processed.get_future().get(); write_response(id, std::string("{\"applied\":") + (applied ? "true" : "false") + '}'); diff --git a/src/source_language_protocol.hpp b/src/source_language_protocol.hpp index e7f7a31..4d9cc93 100644 --- a/src/source_language_protocol.hpp +++ b/src/source_language_protocol.hpp @@ -111,7 +111,7 @@ namespace LanguageProtocol { class WorkspaceEdit { public: WorkspaceEdit() = default; - WorkspaceEdit(const JSON &workspace_edit, boost::filesystem::path file_path); + WorkspaceEdit(const JSON &workspace_edit, boost::filesystem::path path); std::vector> document_changes; };