From 401f057027f1df248849e754d768bc9ab4e28073 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 1 Mar 2019 18:35:13 -0800 Subject: [PATCH] textDocument/rename: mitigate edits in the same place and edits in macro replacement Mitigate edits in the same place (#294) and: // textDocument/rename on `f` void f(); void g() { m(); } // incorrectly rewrote m() before --- src/messages/textDocument_completion.cc | 2 +- src/messages/textDocument_rename.cc | 67 +++++++++++++--------- src/messages/textDocument_signatureHelp.cc | 2 +- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index 8e0a4772..cf60847a 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -526,7 +526,7 @@ void MessageHandler::textDocument_completion(CompletionParam ¶m, } std::string filter; - Position end_pos = param.position; + Position end_pos; Position begin_pos = wf->GetCompletionPosition(param.position, &filter, &end_pos); diff --git a/src/messages/textDocument_rename.cc b/src/messages/textDocument_rename.cc index 7c478b12..68d7c924 100644 --- a/src/messages/textDocument_rename.cc +++ b/src/messages/textDocument_rename.cc @@ -16,54 +16,65 @@ limitations under the License. #include "message_handler.hh" #include "query.hh" +#include + +#include + +using namespace clang; + namespace ccls { namespace { WorkspaceEdit BuildWorkspaceEdit(DB *db, WorkingFiles *wfiles, SymbolRef sym, + std::string_view old_text, const std::string &new_text) { - std::unordered_map path_to_edit; + std::unordered_map> path2edit; + std::unordered_map> edited; EachOccurrence(db, sym, true, [&](Use use) { - std::optional ls_location = GetLsLocation(db, wfiles, use); - if (!ls_location) + int file_id = use.file_id; + QueryFile &file = db->files[file_id]; + if (!file.def || !edited[file_id].insert(use.range).second) + return; + std::optional loc = GetLsLocation(db, wfiles, use); + if (!loc) return; - int file_id = use.file_id; - if (path_to_edit.find(file_id) == path_to_edit.end()) { - path_to_edit[file_id] = TextDocumentEdit(); - - QueryFile &file = db->files[file_id]; - if (!file.def) - return; - + auto [it, inserted] = path2edit.try_emplace(file_id); + auto &edit = it->second.second; + if (inserted) { const std::string &path = file.def->path; - path_to_edit[file_id].textDocument.uri = DocumentUri::FromPath(path); - - WorkingFile *wf = wfiles->GetFile(path); - if (wf) - path_to_edit[file_id].textDocument.version = wf->version; + edit.textDocument.uri = DocumentUri::FromPath(path); + if ((it->second.first = wfiles->GetFile(path))) + edit.textDocument.version = it->second.first->version; } - - TextEdit &edit = path_to_edit[file_id].edits.emplace_back(); - edit.range = ls_location->range; - edit.newText = new_text; + // TODO LoadIndexedContent if wf is nullptr. + if (WorkingFile *wf = it->second.first) { + int start = GetOffsetForPosition(loc->range.start, wf->buffer_content), + end = GetOffsetForPosition(loc->range.end, wf->buffer_content); + if (wf->buffer_content.compare(start, end - start, old_text)) + return; + } + edit.edits.push_back({loc->range, new_text}); }); - WorkspaceEdit edit; - for (const auto &changes : path_to_edit) - edit.documentChanges.push_back(changes.second); - return edit; + WorkspaceEdit ret; + for (auto &x : path2edit) + ret.documentChanges.push_back(std::move(x.second.second)); + return ret; } } // namespace void MessageHandler::textDocument_rename(RenameParam ¶m, ReplyOnce &reply) { auto [file, wf] = FindOrFail(param.textDocument.uri.GetPath(), reply); - if (!wf) { + if (!wf) return; - } - WorkspaceEdit result; + for (SymbolRef sym : FindSymbolsAtLocation(wf, file, param.position)) { - result = BuildWorkspaceEdit(db, wfiles, sym, param.newName); + result = BuildWorkspaceEdit( + db, wfiles, sym, + LexIdentifierAroundPos(param.position, wf->buffer_content), + param.newName); break; } diff --git a/src/messages/textDocument_signatureHelp.cc b/src/messages/textDocument_signatureHelp.cc index 419bdbe8..68af2dcc 100644 --- a/src/messages/textDocument_signatureHelp.cc +++ b/src/messages/textDocument_signatureHelp.cc @@ -159,7 +159,7 @@ void MessageHandler::textDocument_signatureHelp( } { std::string filter; - Position end_pos = param.position; + Position end_pos; begin_pos = wf->GetCompletionPosition(param.position, &filter, &end_pos); }