Browse Source

language client: cleanup of workspace/applyEdit

master
eidheim 1 month ago
parent
commit
dd11a9c1d8
  1. 108
      src/source_language_protocol.cpp
  2. 2
      src/source_language_protocol.hpp

108
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<TextEdit> text_edits) : file(std::move(file)), text_edits(std::move(text_edits)) {} LanguageProtocol::TextDocumentEdit::TextDocumentEdit(std::string file, std::vector<TextEdit> 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; 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()) if(!build->project_path.empty())
project_path = build->project_path; project_path = build->project_path;
else else
project_path = file_path.parent_path(); project_path = boost::filesystem::is_directory(path, ec) ? path : path.parent_path();
try { try {
if(auto changes = workspace_edit.children_optional("changes")) { if(auto changes = workspace_edit.children_optional("changes")) {
for(auto &change : *changes) { for(auto &change : *changes) {
@ -587,67 +588,70 @@ void LanguageProtocol::Client::handle_server_request(const boost::variant<size_t
if(method == "workspace/applyEdit") { if(method == "workspace/applyEdit") {
std::promise<void> result_processed; std::promise<void> result_processed;
bool applied = true; bool applied = true;
dispatcher->post([&result_processed, &applied, params = std::make_shared<JSON>(std::move(params))] { dispatcher->post([this, &result_processed, &applied, params = std::make_shared<JSON>(std::move(params))] {
ScopeGuard guard({[&result_processed] { ScopeGuard guard({[&result_processed] {
result_processed.set_value(); result_processed.set_value();
}}); }});
if(auto current_view = dynamic_cast<Source::LanguageProtocolView *>(Notebook::get().get_current_view())) { LanguageProtocol::WorkspaceEdit workspace_edit;
LanguageProtocol::WorkspaceEdit workspace_edit; try {
try { workspace_edit = LanguageProtocol::WorkspaceEdit(params->object("edit"), root_path);
workspace_edit = LanguageProtocol::WorkspaceEdit(params->object("edit"), current_view->file_path); }
} catch(...) {
catch(...) { applied = false;
applied = false; return;
return; }
}
for(auto &document_change : workspace_edit.document_changes) { auto current_view = Notebook::get().get_current_view();
if(auto edit = boost::get<TextDocumentEdit>(&document_change)) { for(auto &document_change : workspace_edit.document_changes) {
Source::View *view = nullptr; if(auto edit = boost::get<TextDocumentEdit>(&document_change)) {
for(auto &e : Source::View::views) { Source::View *view = nullptr;
if(e->file_path == edit->file) { for(auto &e : Source::View::views) {
view = e; if(e->file_path == edit->file) {
break; view = e;
} break;
} }
if(!view) { }
if(!Notebook::get().open(edit->file)) { if(!view) {
applied = false; if(!Notebook::get().open(edit->file)) {
return; applied = false;
} return;
view = Notebook::get().get_current_view();
} }
view = Notebook::get().get_current_view();
}
auto buffer = view->get_buffer(); auto buffer = view->get_buffer();
buffer->begin_user_action(); buffer->begin_user_action();
auto end_iter = buffer->end(); auto get_line_pos = [this](Source::View *view, const Gtk::TextIter &iter) -> int {
// If entire buffer is replaced if(capabilities.use_line_index)
if(edit->text_edits.size() == 1 && return iter.get_line_index();
edit->text_edits[0].range.start.line == 0 && edit->text_edits[0].range.start.character == 0 && return utf16_code_unit_count(view->get_line(iter), 0, iter.get_line_index());
(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)))) { auto end_iter = buffer->end();
view->replace_text(edit->text_edits[0].new_text); // If entire buffer is replaced
} if(edit->text_edits.size() == 1 &&
else { edit->text_edits[0].range.start.line == 0 && edit->text_edits[0].range.start.character == 0 &&
for(auto text_edit_it = edit->text_edits.rbegin(); text_edit_it != edit->text_edits.rend(); ++text_edit_it) { (edit->text_edits[0].range.end.line > end_iter.get_line() ||
auto start_iter = view->get_iter_at_line_pos(text_edit_it->range.start.line, text_edit_it->range.start.character); (edit->text_edits[0].range.end.line == end_iter.get_line() && edit->text_edits[0].range.end.character >= get_line_pos(view, end_iter)))) {
auto end_iter = view->get_iter_at_line_pos(text_edit_it->range.end.line, text_edit_it->range.end.character); view->replace_text(edit->text_edits[0].new_text);
if(view != current_view) }
view->get_buffer()->place_cursor(start_iter); else {
buffer->erase(start_iter, end_iter); for(auto text_edit_it = edit->text_edits.rbegin(); text_edit_it != edit->text_edits.rend(); ++text_edit_it) {
start_iter = view->get_iter_at_line_pos(text_edit_it->range.start.line, text_edit_it->range.start.character); auto 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 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) buffer->end_user_action();
Notebook::get().open(current_view); }
} }
if(current_view)
Notebook::get().open(current_view);
}); });
result_processed.get_future().get(); result_processed.get_future().get();
write_response(id, std::string("{\"applied\":") + (applied ? "true" : "false") + '}'); write_response(id, std::string("{\"applied\":") + (applied ? "true" : "false") + '}');

2
src/source_language_protocol.hpp

@ -111,7 +111,7 @@ namespace LanguageProtocol {
class WorkspaceEdit { class WorkspaceEdit {
public: public:
WorkspaceEdit() = default; WorkspaceEdit() = default;
WorkspaceEdit(const JSON &workspace_edit, boost::filesystem::path file_path); WorkspaceEdit(const JSON &workspace_edit, boost::filesystem::path path);
std::vector<boost::variant<TextDocumentEdit, RenameFile>> document_changes; std::vector<boost::variant<TextDocumentEdit, RenameFile>> document_changes;
}; };

Loading…
Cancel
Save