|
|
|
@ -1,4 +1,5 @@ |
|
|
|
#include "source_language_protocol.hpp" |
|
|
|
#include "source_language_protocol.hpp" |
|
|
|
|
|
|
|
#include "directories.hpp" |
|
|
|
#include "filesystem.hpp" |
|
|
|
#include "filesystem.hpp" |
|
|
|
#include "info.hpp" |
|
|
|
#include "info.hpp" |
|
|
|
#include "notebook.hpp" |
|
|
|
#include "notebook.hpp" |
|
|
|
@ -71,32 +72,42 @@ LanguageProtocol::WorkspaceEdit::WorkspaceEdit(const JSON &workspace_edit, boost |
|
|
|
else |
|
|
|
else |
|
|
|
project_path = file_path.parent_path(); |
|
|
|
project_path = file_path.parent_path(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
if(auto children = workspace_edit.children_optional("changes")) { |
|
|
|
if(auto changes = workspace_edit.children_optional("changes")) { |
|
|
|
for(auto &child : *children) { |
|
|
|
for(auto &change : *changes) { |
|
|
|
auto file = filesystem::get_path_from_uri(child.first); |
|
|
|
auto file = filesystem::get_path_from_uri(change.first); |
|
|
|
if(filesystem::file_in_path(file, project_path)) { |
|
|
|
if(filesystem::file_in_path(file, project_path)) { |
|
|
|
std::vector<LanguageProtocol::TextEdit> text_edits; |
|
|
|
std::vector<LanguageProtocol::TextEdit> text_edits; |
|
|
|
for(auto &text_edit : child.second.array()) |
|
|
|
for(auto &text_edit : change.second.array()) |
|
|
|
text_edits.emplace_back(text_edit); |
|
|
|
text_edits.emplace_back(text_edit); |
|
|
|
document_edits.emplace_back(file.string(), std::move(text_edits)); |
|
|
|
document_changes.emplace_back(TextDocumentEdit(file.string(), std::move(text_edits))); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if(auto children = workspace_edit.array_optional("documentChanges")) { |
|
|
|
else { |
|
|
|
for(auto &child : *children) { |
|
|
|
auto document_changes = workspace_edit.array_or_empty("documentChanges"); |
|
|
|
LanguageProtocol::TextDocumentEdit document_edit(child); |
|
|
|
if(document_changes.empty()) { |
|
|
|
if(filesystem::file_in_path(document_edit.file, project_path)) |
|
|
|
if(auto child = workspace_edit.object_optional("documentChanges")) |
|
|
|
document_edits.emplace_back(std::move(document_edit.file), std::move(document_edit.text_edits)); |
|
|
|
document_changes.emplace_back(std::move(*child)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for(auto &document_change : document_changes) { |
|
|
|
|
|
|
|
if(auto kind = document_change.string_optional("kind")) { |
|
|
|
|
|
|
|
if(*kind == "rename") { |
|
|
|
|
|
|
|
auto old_path = filesystem::get_path_from_uri(document_change.string("oldUri")); |
|
|
|
|
|
|
|
auto new_path = filesystem::get_path_from_uri(document_change.string("newUri")); |
|
|
|
|
|
|
|
if(filesystem::file_in_path(old_path, project_path) && filesystem::file_in_path(new_path, project_path)) |
|
|
|
|
|
|
|
this->document_changes.emplace_back(RenameFile{std::move(old_path), std::move(new_path)}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if(auto child = workspace_edit.object_optional("documentChanges")) { |
|
|
|
else { |
|
|
|
LanguageProtocol::TextDocumentEdit document_edit(*child); |
|
|
|
LanguageProtocol::TextDocumentEdit document_edit(document_change); |
|
|
|
if(filesystem::file_in_path(document_edit.file, project_path)) |
|
|
|
if(filesystem::file_in_path(document_edit.file, project_path)) |
|
|
|
document_edits.emplace_back(std::move(document_edit.file), std::move(document_edit.text_edits)); |
|
|
|
this->document_changes.emplace_back(TextDocumentEdit(std::move(document_edit.file), std::move(document_edit.text_edits))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
catch(...) { |
|
|
|
catch(...) { |
|
|
|
document_edits.clear(); |
|
|
|
document_changes.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -544,51 +555,36 @@ void LanguageProtocol::Client::handle_server_request(size_t id, const std::strin |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct DocumentEditAndView { |
|
|
|
for(auto &document_change : workspace_edit.document_changes) { |
|
|
|
LanguageProtocol::TextDocumentEdit *document_edit; |
|
|
|
if(auto edit = boost::get<TextDocumentEdit>(&document_change)) { |
|
|
|
Source::View *view; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
std::vector<DocumentEditAndView> document_edits_and_views; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &document_edit : workspace_edit.document_edits) { |
|
|
|
|
|
|
|
Source::View *view = nullptr; |
|
|
|
Source::View *view = nullptr; |
|
|
|
for(auto it = Source::View::views.begin(); it != Source::View::views.end(); ++it) { |
|
|
|
for(auto &e : Source::View::views) { |
|
|
|
if((*it)->file_path == document_edit.file) { |
|
|
|
if(e->file_path == edit->file) { |
|
|
|
view = *it; |
|
|
|
view = e; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(!view) { |
|
|
|
if(!view) { |
|
|
|
if(!Notebook::get().open(document_edit.file)) { |
|
|
|
if(!Notebook::get().open(edit->file)) { |
|
|
|
applied = false; |
|
|
|
applied = false; |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
view = Notebook::get().get_current_view(); |
|
|
|
view = Notebook::get().get_current_view(); |
|
|
|
document_edits_and_views.emplace_back(DocumentEditAndView{&document_edit, view}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
document_edits_and_views.emplace_back(DocumentEditAndView{&document_edit, view}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(current_view) |
|
|
|
|
|
|
|
Notebook::get().open(current_view); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &document_edit_and_view : document_edits_and_views) { |
|
|
|
|
|
|
|
auto document_edit = document_edit_and_view.document_edit; |
|
|
|
|
|
|
|
auto view = document_edit_and_view.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 end_iter = buffer->end(); |
|
|
|
// If entire buffer is replaced
|
|
|
|
// If entire buffer is replaced
|
|
|
|
if(document_edit->text_edits.size() == 1 && |
|
|
|
if(edit->text_edits.size() == 1 && |
|
|
|
document_edit->text_edits[0].range.start.line == 0 && document_edit->text_edits[0].range.start.character == 0 && |
|
|
|
edit->text_edits[0].range.start.line == 0 && edit->text_edits[0].range.start.character == 0 && |
|
|
|
(document_edit->text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
(edit->text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
(document_edit->text_edits[0].range.end.line == end_iter.get_line() && document_edit->text_edits[0].range.end.character >= current_view->get_line_pos(end_iter)))) { |
|
|
|
(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(document_edit->text_edits[0].new_text); |
|
|
|
view->replace_text(edit->text_edits[0].new_text); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
for(auto text_edit_it = document_edit->text_edits.rbegin(); text_edit_it != document_edit->text_edits.rend(); ++text_edit_it) { |
|
|
|
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 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); |
|
|
|
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) |
|
|
|
if(view != current_view) |
|
|
|
@ -606,6 +602,10 @@ void LanguageProtocol::Client::handle_server_request(size_t id, const std::strin |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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") + '}'); |
|
|
|
@ -1007,19 +1007,19 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { |
|
|
|
++c; |
|
|
|
++c; |
|
|
|
usages.emplace_back(Offset(location.range.start.line, location.range.start.character, location.file), std::string()); |
|
|
|
usages.emplace_back(Offset(location.range.start.line, location.range.start.character, location.file), std::string()); |
|
|
|
auto &usage = usages.back(); |
|
|
|
auto &usage = usages.back(); |
|
|
|
auto view_it = views.end(); |
|
|
|
Source::View *view = nullptr; |
|
|
|
for(auto it = views.begin(); it != views.end(); ++it) { |
|
|
|
for(auto &e : views) { |
|
|
|
if(location.file == (*it)->file_path) { |
|
|
|
if(e->file_path == location.file) { |
|
|
|
view_it = it; |
|
|
|
view = e; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(view_it != views.end()) { |
|
|
|
if(view) { |
|
|
|
if(location.range.start.line < (*view_it)->get_buffer()->get_line_count()) { |
|
|
|
if(location.range.start.line < view->get_buffer()->get_line_count()) { |
|
|
|
auto start = (*view_it)->get_buffer()->get_iter_at_line(location.range.start.line); |
|
|
|
auto start = view->get_buffer()->get_iter_at_line(location.range.start.line); |
|
|
|
auto end = start; |
|
|
|
auto end = start; |
|
|
|
end.forward_to_line_end(); |
|
|
|
end.forward_to_line_end(); |
|
|
|
usage.second = Glib::Markup::escape_text((*view_it)->get_buffer()->get_text(start, end)); |
|
|
|
usage.second = Glib::Markup::escape_text(view->get_buffer()->get_text(start, end)); |
|
|
|
embolden_token(usage.second, location.range.start.character, location.range.end.character); |
|
|
|
embolden_token(usage.second, location.range.start.character, location.range.end.character); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1089,10 +1089,10 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { |
|
|
|
std::vector<LanguageProtocol::TextEdit> edits; |
|
|
|
std::vector<LanguageProtocol::TextEdit> edits; |
|
|
|
for(auto &edit : result.array_or_empty()) |
|
|
|
for(auto &edit : result.array_or_empty()) |
|
|
|
edits.emplace_back(edit, text); |
|
|
|
edits.emplace_back(edit, text); |
|
|
|
workspace_edit.document_edits.emplace_back(file_path.string(), std::move(edits)); |
|
|
|
workspace_edit.document_changes.emplace_back(LanguageProtocol::TextDocumentEdit(file_path.string(), std::move(edits))); |
|
|
|
} |
|
|
|
} |
|
|
|
catch(...) { |
|
|
|
catch(...) { |
|
|
|
workspace_edit.document_edits.clear(); |
|
|
|
workspace_edit.document_changes.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
result_processed.set_value(); |
|
|
|
result_processed.set_value(); |
|
|
|
@ -1100,57 +1100,46 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { |
|
|
|
} |
|
|
|
} |
|
|
|
result_processed.get_future().get(); |
|
|
|
result_processed.get_future().get(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(workspace_edit.document_changes.empty()) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Terminal::get().print("Renamed "); |
|
|
|
|
|
|
|
Terminal::get().print(previous_text, true); |
|
|
|
|
|
|
|
Terminal::get().print(" to "); |
|
|
|
|
|
|
|
Terminal::get().print(text, true); |
|
|
|
|
|
|
|
Terminal::get().print(" at:\n"); |
|
|
|
|
|
|
|
|
|
|
|
auto current_view = Notebook::get().get_current_view(); |
|
|
|
auto current_view = Notebook::get().get_current_view(); |
|
|
|
|
|
|
|
|
|
|
|
struct DocumentEditAndView { |
|
|
|
std::set<Source::View *> views_to_be_closed; |
|
|
|
LanguageProtocol::TextDocumentEdit *document_edit; |
|
|
|
|
|
|
|
Source::View *view; |
|
|
|
|
|
|
|
bool close; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
std::vector<DocumentEditAndView> document_edits_and_views; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &document_edit : workspace_edit.document_edits) { |
|
|
|
bool update_directories = false; |
|
|
|
|
|
|
|
for(auto &document_change : workspace_edit.document_changes) { |
|
|
|
|
|
|
|
if(auto edit = boost::get<LanguageProtocol::TextDocumentEdit>(&document_change)) { |
|
|
|
Source::View *view = nullptr; |
|
|
|
Source::View *view = nullptr; |
|
|
|
for(auto it = views.begin(); it != views.end(); ++it) { |
|
|
|
for(auto &e : views) { |
|
|
|
if((*it)->file_path == document_edit.file) { |
|
|
|
if(e->file_path == edit->file) { |
|
|
|
view = *it; |
|
|
|
view = e; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(!view) { |
|
|
|
if(!view) { |
|
|
|
if(!Notebook::get().open(document_edit.file)) |
|
|
|
if(!Notebook::get().open(edit->file)) |
|
|
|
return; |
|
|
|
return; |
|
|
|
view = Notebook::get().get_current_view(); |
|
|
|
view = Notebook::get().get_current_view(); |
|
|
|
document_edits_and_views.emplace_back(DocumentEditAndView{&document_edit, view, true}); |
|
|
|
views_to_be_closed.emplace(view); |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
document_edits_and_views.emplace_back(DocumentEditAndView{&document_edit, view, false}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(current_view) |
|
|
|
|
|
|
|
Notebook::get().open(current_view); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!document_edits_and_views.empty()) { |
|
|
|
|
|
|
|
Terminal::get().print("Renamed "); |
|
|
|
|
|
|
|
Terminal::get().print(previous_text, true); |
|
|
|
|
|
|
|
Terminal::get().print(" to "); |
|
|
|
|
|
|
|
Terminal::get().print(text, true); |
|
|
|
|
|
|
|
Terminal::get().print(" at:\n"); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(auto &document_edit_and_view : document_edits_and_views) { |
|
|
|
|
|
|
|
auto document_edit = document_edit_and_view.document_edit; |
|
|
|
|
|
|
|
auto view = document_edit_and_view.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 end_iter = buffer->end(); |
|
|
|
// If entire buffer is replaced
|
|
|
|
// If entire buffer is replaced
|
|
|
|
if(document_edit->text_edits.size() == 1 && |
|
|
|
if(edit->text_edits.size() == 1 && |
|
|
|
document_edit->text_edits[0].range.start.line == 0 && document_edit->text_edits[0].range.start.character == 0 && |
|
|
|
edit->text_edits[0].range.start.line == 0 && edit->text_edits[0].range.start.character == 0 && |
|
|
|
(document_edit->text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
(edit->text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
(document_edit->text_edits[0].range.end.line == end_iter.get_line() && document_edit->text_edits[0].range.end.character >= get_line_pos(end_iter)))) { |
|
|
|
(edit->text_edits[0].range.end.line == end_iter.get_line() && edit->text_edits[0].range.end.character >= get_line_pos(end_iter)))) { |
|
|
|
view->replace_text(document_edit->text_edits[0].new_text); |
|
|
|
view->replace_text(edit->text_edits[0].new_text); |
|
|
|
|
|
|
|
|
|
|
|
Terminal::get().print(filesystem::get_short_path(view->file_path).string() + ":1:1\n"); |
|
|
|
Terminal::get().print(filesystem::get_short_path(view->file_path).string() + ":1:1\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1162,7 +1151,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { |
|
|
|
}; |
|
|
|
}; |
|
|
|
std::list<TerminalOutput> terminal_output_list; |
|
|
|
std::list<TerminalOutput> terminal_output_list; |
|
|
|
|
|
|
|
|
|
|
|
for(auto text_edit_it = document_edit->text_edits.rbegin(); text_edit_it != document_edit->text_edits.rend(); ++text_edit_it) { |
|
|
|
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 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); |
|
|
|
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) |
|
|
|
if(view != current_view) |
|
|
|
@ -1194,12 +1183,41 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { |
|
|
|
if(!view->save()) |
|
|
|
if(!view->save()) |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if(auto rename_file = boost::get<LanguageProtocol::RenameFile>(&document_change)) { |
|
|
|
for(auto &document_edit_and_view : document_edits_and_views) { |
|
|
|
Source::View *view = nullptr; |
|
|
|
if(document_edit_and_view.close) |
|
|
|
for(auto &e : views) { |
|
|
|
Notebook::get().close(document_edit_and_view.view); |
|
|
|
if(e->file_path == rename_file->old_path) { |
|
|
|
document_edit_and_view.close = false; |
|
|
|
view = e; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(!view) { |
|
|
|
|
|
|
|
if(!Notebook::get().open(rename_file->new_path)) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
boost::system::error_code ec; |
|
|
|
|
|
|
|
boost::filesystem::rename(rename_file->old_path, rename_file->new_path, ec); |
|
|
|
|
|
|
|
if(ec) { |
|
|
|
|
|
|
|
Terminal::get().print("\e[31mError\e[m: could not rename file: " + ec.message() + '\n', true); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(view) |
|
|
|
|
|
|
|
view->rename(rename_file->new_path); |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
Notebook::get().get_current_view()->rename(rename_file->new_path); |
|
|
|
|
|
|
|
Notebook::get().close_current(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
update_directories = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(update_directories) |
|
|
|
|
|
|
|
Directories::get().update(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(current_view) |
|
|
|
|
|
|
|
Notebook::get().open(current_view); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &view : views_to_be_closed) |
|
|
|
|
|
|
|
Notebook::get().close(view); |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -1325,49 +1343,34 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { |
|
|
|
|
|
|
|
|
|
|
|
auto current_view = Notebook::get().get_current_view(); |
|
|
|
auto current_view = Notebook::get().get_current_view(); |
|
|
|
|
|
|
|
|
|
|
|
struct DocumentEditAndView { |
|
|
|
for(auto &document_change : workspace_edit.document_changes) { |
|
|
|
LanguageProtocol::TextDocumentEdit *document_edit; |
|
|
|
if(auto edit = boost::get<LanguageProtocol::TextDocumentEdit>(&document_change)) { |
|
|
|
Source::View *view; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
std::vector<DocumentEditAndView> document_edits_and_views; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &document_edit : workspace_edit.document_edits) { |
|
|
|
|
|
|
|
Source::View *view = nullptr; |
|
|
|
Source::View *view = nullptr; |
|
|
|
for(auto it = views.begin(); it != views.end(); ++it) { |
|
|
|
for(auto &e : views) { |
|
|
|
if((*it)->file_path == document_edit.file) { |
|
|
|
if(e->file_path == edit->file) { |
|
|
|
view = *it; |
|
|
|
view = e; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(!view) { |
|
|
|
if(!view) { |
|
|
|
if(!Notebook::get().open(document_edit.file)) |
|
|
|
if(!Notebook::get().open(edit->file)) |
|
|
|
return; |
|
|
|
return; |
|
|
|
view = Notebook::get().get_current_view(); |
|
|
|
view = Notebook::get().get_current_view(); |
|
|
|
document_edits_and_views.emplace_back(DocumentEditAndView{&document_edit, view}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
document_edits_and_views.emplace_back(DocumentEditAndView{&document_edit, view}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(current_view) |
|
|
|
|
|
|
|
Notebook::get().open(current_view); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &document_edit_and_view : document_edits_and_views) { |
|
|
|
|
|
|
|
auto document_edit = document_edit_and_view.document_edit; |
|
|
|
|
|
|
|
auto view = document_edit_and_view.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 end_iter = buffer->end(); |
|
|
|
// If entire buffer is replaced
|
|
|
|
// If entire buffer is replaced
|
|
|
|
if(document_edit->text_edits.size() == 1 && |
|
|
|
if(edit->text_edits.size() == 1 && |
|
|
|
document_edit->text_edits[0].range.start.line == 0 && document_edit->text_edits[0].range.start.character == 0 && |
|
|
|
edit->text_edits[0].range.start.line == 0 && edit->text_edits[0].range.start.character == 0 && |
|
|
|
(document_edit->text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
(edit->text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
(document_edit->text_edits[0].range.end.line == end_iter.get_line() && document_edit->text_edits[0].range.end.character >= get_line_pos(end_iter)))) { |
|
|
|
(edit->text_edits[0].range.end.line == end_iter.get_line() && edit->text_edits[0].range.end.character >= get_line_pos(end_iter)))) { |
|
|
|
view->replace_text(document_edit->text_edits[0].new_text); |
|
|
|
view->replace_text(edit->text_edits[0].new_text); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
for(auto text_edit_it = document_edit->text_edits.rbegin(); text_edit_it != document_edit->text_edits.rend(); ++text_edit_it) { |
|
|
|
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 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); |
|
|
|
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) |
|
|
|
if(view != current_view) |
|
|
|
@ -1384,6 +1387,10 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(current_view) |
|
|
|
|
|
|
|
Notebook::get().open(current_view); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(capabilities.execute_command) { |
|
|
|
if(capabilities.execute_command) { |
|
|
|
auto command = results[index].second->object_optional("command"); |
|
|
|
auto command = results[index].second->object_optional("command"); |
|
|
|
if(command) { |
|
|
|
if(command) { |
|
|
|
@ -1939,8 +1946,9 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector<Language |
|
|
|
} |
|
|
|
} |
|
|
|
if(edit) { |
|
|
|
if(edit) { |
|
|
|
LanguageProtocol::WorkspaceEdit workspace_edit(*edit, file_path); |
|
|
|
LanguageProtocol::WorkspaceEdit workspace_edit(*edit, file_path); |
|
|
|
for(auto &document_edit : workspace_edit.document_edits) { |
|
|
|
for(auto &document_change : workspace_edit.document_changes) { |
|
|
|
for(auto &text_edit : document_edit.text_edits) { |
|
|
|
if(auto edit = boost::get<LanguageProtocol::TextDocumentEdit>(&document_change)) { |
|
|
|
|
|
|
|
for(auto &text_edit : edit->text_edits) { |
|
|
|
if(!quickfix_diagnostics.empty()) { |
|
|
|
if(!quickfix_diagnostics.empty()) { |
|
|
|
for(auto &diagnostic : diagnostics) { |
|
|
|
for(auto &diagnostic : diagnostics) { |
|
|
|
for(auto &quickfix_diagnostic : quickfix_diagnostics) { |
|
|
|
for(auto &quickfix_diagnostic : quickfix_diagnostics) { |
|
|
|
@ -1948,7 +1956,7 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector<Language |
|
|
|
auto pair = diagnostic.quickfixes.emplace(title, std::set<Source::FixIt>{}); |
|
|
|
auto pair = diagnostic.quickfixes.emplace(title, std::set<Source::FixIt>{}); |
|
|
|
pair.first->second.emplace( |
|
|
|
pair.first->second.emplace( |
|
|
|
text_edit.new_text, |
|
|
|
text_edit.new_text, |
|
|
|
document_edit.file, |
|
|
|
edit->file, |
|
|
|
std::make_pair<Offset, Offset>(Offset(text_edit.range.start.line, text_edit.range.start.character), |
|
|
|
std::make_pair<Offset, Offset>(Offset(text_edit.range.start.line, text_edit.range.start.character), |
|
|
|
Offset(text_edit.range.end.line, text_edit.range.end.character))); |
|
|
|
Offset(text_edit.range.end.line, text_edit.range.end.character))); |
|
|
|
break; |
|
|
|
break; |
|
|
|
@ -1962,7 +1970,7 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector<Language |
|
|
|
auto pair = diagnostic.quickfixes.emplace(title, std::set<Source::FixIt>{}); |
|
|
|
auto pair = diagnostic.quickfixes.emplace(title, std::set<Source::FixIt>{}); |
|
|
|
pair.first->second.emplace( |
|
|
|
pair.first->second.emplace( |
|
|
|
text_edit.new_text, |
|
|
|
text_edit.new_text, |
|
|
|
document_edit.file, |
|
|
|
edit->file, |
|
|
|
std::make_pair<Offset, Offset>(Offset(text_edit.range.start.line, text_edit.range.start.character), |
|
|
|
std::make_pair<Offset, Offset>(Offset(text_edit.range.start.line, text_edit.range.start.character), |
|
|
|
Offset(text_edit.range.end.line, text_edit.range.end.character))); |
|
|
|
Offset(text_edit.range.end.line, text_edit.range.end.character))); |
|
|
|
break; |
|
|
|
break; |
|
|
|
@ -1975,6 +1983,7 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector<Language |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
catch(...) { |
|
|
|
catch(...) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|