|
|
|
|
@ -747,6 +747,9 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
|
|
|
|
|
result_processed.get_future().get(); |
|
|
|
|
|
|
|
|
|
std::vector<Changes *> changes_renamed; |
|
|
|
|
|
|
|
|
|
std::vector<Changes *> changes_in_unopened_files; |
|
|
|
|
std::vector<std::pair<Changes *, Source::View *>> changes_in_opened_files; |
|
|
|
|
for(auto &change : changes) { |
|
|
|
|
auto view_it = views.end(); |
|
|
|
|
for(auto it = views.begin(); it != views.end(); ++it) { |
|
|
|
|
@ -755,46 +758,28 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(view_it != views.end()) { |
|
|
|
|
auto buffer = (*view_it)->get_buffer(); |
|
|
|
|
buffer->begin_user_action(); |
|
|
|
|
|
|
|
|
|
auto end_iter = buffer->end(); |
|
|
|
|
// If entire buffer is replaced
|
|
|
|
|
if(change.text_edits.size() == 1 && |
|
|
|
|
change.text_edits[0].range.start.line == 0 && change.text_edits[0].range.start.character == 0 && |
|
|
|
|
(change.text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
|
(change.text_edits[0].range.end.line == end_iter.get_line() && change.text_edits[0].range.end.character >= end_iter.get_line_offset()))) |
|
|
|
|
(*view_it)->replace_text(change.text_edits[0].new_text); |
|
|
|
|
else { |
|
|
|
|
for(auto edit_it = change.text_edits.rbegin(); edit_it != change.text_edits.rend(); ++edit_it) { |
|
|
|
|
auto start_iter = (*view_it)->get_iter_at_line_pos(edit_it->range.start.line, edit_it->range.start.character); |
|
|
|
|
auto end_iter = (*view_it)->get_iter_at_line_pos(edit_it->range.end.line, edit_it->range.end.character); |
|
|
|
|
buffer->erase(start_iter, end_iter); |
|
|
|
|
start_iter = (*view_it)->get_iter_at_line_pos(edit_it->range.start.line, edit_it->range.start.character); |
|
|
|
|
buffer->insert(start_iter, edit_it->new_text); |
|
|
|
|
} |
|
|
|
|
if(view_it != views.end()) |
|
|
|
|
changes_in_opened_files.emplace_back(&change, *view_it); |
|
|
|
|
else |
|
|
|
|
changes_in_unopened_files.emplace_back(&change); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buffer->end_user_action(); |
|
|
|
|
(*view_it)->save(); |
|
|
|
|
changes_renamed.emplace_back(&change); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
// Write changes to unopened files first, since this might improve server handling of opened files that will be changed after
|
|
|
|
|
for(auto &change : changes_in_unopened_files) { |
|
|
|
|
Glib::ustring buffer; |
|
|
|
|
{ |
|
|
|
|
std::ifstream stream(change.file, std::ifstream::binary); |
|
|
|
|
std::ifstream stream(change->file, std::ifstream::binary); |
|
|
|
|
if(stream) |
|
|
|
|
buffer.assign(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>()); |
|
|
|
|
} |
|
|
|
|
std::ofstream stream(change.file, std::ifstream::binary); |
|
|
|
|
std::ofstream stream(change->file, std::ifstream::binary); |
|
|
|
|
if(!buffer.empty() && stream) { |
|
|
|
|
std::vector<size_t> lines_start_pos = {0}; |
|
|
|
|
for(size_t c = 0; c < buffer.size(); ++c) { |
|
|
|
|
if(buffer[c] == '\n') |
|
|
|
|
lines_start_pos.emplace_back(c + 1); |
|
|
|
|
} |
|
|
|
|
for(auto edit_it = change.text_edits.rbegin(); edit_it != change.text_edits.rend(); ++edit_it) { |
|
|
|
|
for(auto edit_it = change->text_edits.rbegin(); edit_it != change->text_edits.rend(); ++edit_it) { |
|
|
|
|
auto start_line = edit_it->range.start.line; |
|
|
|
|
auto end_line = edit_it->range.end.line; |
|
|
|
|
if(static_cast<size_t>(start_line) < lines_start_pos.size()) { |
|
|
|
|
@ -810,11 +795,38 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
stream.write(buffer.data(), buffer.bytes()); |
|
|
|
|
changes_renamed.emplace_back(&change); |
|
|
|
|
changes_renamed.emplace_back(change); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
Terminal::get().print("Error: could not write to file " + change.file + '\n', true); |
|
|
|
|
Terminal::get().print("Error: could not write to file " + change->file + '\n', true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for(auto &pair : changes_in_opened_files) { |
|
|
|
|
auto change = pair.first; |
|
|
|
|
auto view = pair.second; |
|
|
|
|
auto buffer = view->get_buffer(); |
|
|
|
|
buffer->begin_user_action(); |
|
|
|
|
|
|
|
|
|
auto end_iter = buffer->end(); |
|
|
|
|
// If entire buffer is replaced
|
|
|
|
|
if(change->text_edits.size() == 1 && |
|
|
|
|
change->text_edits[0].range.start.line == 0 && change->text_edits[0].range.start.character == 0 && |
|
|
|
|
(change->text_edits[0].range.end.line > end_iter.get_line() || |
|
|
|
|
(change->text_edits[0].range.end.line == end_iter.get_line() && change->text_edits[0].range.end.character >= end_iter.get_line_offset()))) |
|
|
|
|
view->replace_text(change->text_edits[0].new_text); |
|
|
|
|
else { |
|
|
|
|
for(auto edit_it = change->text_edits.rbegin(); edit_it != change->text_edits.rend(); ++edit_it) { |
|
|
|
|
auto start_iter = view->get_iter_at_line_pos(edit_it->range.start.line, edit_it->range.start.character); |
|
|
|
|
auto end_iter = view->get_iter_at_line_pos(edit_it->range.end.line, edit_it->range.end.character); |
|
|
|
|
buffer->erase(start_iter, end_iter); |
|
|
|
|
start_iter = view->get_iter_at_line_pos(edit_it->range.start.line, edit_it->range.start.character); |
|
|
|
|
buffer->insert(start_iter, edit_it->new_text); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buffer->end_user_action(); |
|
|
|
|
view->save(); |
|
|
|
|
changes_renamed.emplace_back(change); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(!changes_renamed.empty()) { |
|
|
|
|
|