mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 15:45:08 +00:00
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
This commit is contained in:
parent
4047db2669
commit
beff1f6e89
@ -514,7 +514,7 @@ void MessageHandler::textDocument_completion(CompletionParam ¶m,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string filter;
|
std::string filter;
|
||||||
Position end_pos = param.position;
|
Position end_pos;
|
||||||
Position begin_pos =
|
Position begin_pos =
|
||||||
wf->GetCompletionPosition(param.position, &filter, &end_pos);
|
wf->GetCompletionPosition(param.position, &filter, &end_pos);
|
||||||
|
|
||||||
|
@ -4,54 +4,65 @@
|
|||||||
#include "message_handler.hh"
|
#include "message_handler.hh"
|
||||||
#include "query.hh"
|
#include "query.hh"
|
||||||
|
|
||||||
|
#include <clang/Basic/CharInfo.h>
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
using namespace clang;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
WorkspaceEdit BuildWorkspaceEdit(DB *db, WorkingFiles *wfiles, SymbolRef sym,
|
WorkspaceEdit BuildWorkspaceEdit(DB *db, WorkingFiles *wfiles, SymbolRef sym,
|
||||||
|
std::string_view old_text,
|
||||||
const std::string &new_text) {
|
const std::string &new_text) {
|
||||||
std::unordered_map<int, TextDocumentEdit> path_to_edit;
|
std::unordered_map<int, std::pair<WorkingFile *, TextDocumentEdit>> path2edit;
|
||||||
|
std::unordered_map<int, std::unordered_set<Range>> edited;
|
||||||
|
|
||||||
EachOccurrence(db, sym, true, [&](Use use) {
|
EachOccurrence(db, sym, true, [&](Use use) {
|
||||||
std::optional<Location> ls_location = GetLsLocation(db, wfiles, use);
|
|
||||||
if (!ls_location)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int file_id = use.file_id;
|
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];
|
QueryFile &file = db->files[file_id];
|
||||||
if (!file.def)
|
if (!file.def || !edited[file_id].insert(use.range).second)
|
||||||
|
return;
|
||||||
|
std::optional<Location> loc = GetLsLocation(db, wfiles, use);
|
||||||
|
if (!loc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto [it, inserted] = path2edit.try_emplace(file_id);
|
||||||
|
auto &edit = it->second.second;
|
||||||
|
if (inserted) {
|
||||||
const std::string &path = file.def->path;
|
const std::string &path = file.def->path;
|
||||||
path_to_edit[file_id].textDocument.uri = DocumentUri::FromPath(path);
|
edit.textDocument.uri = DocumentUri::FromPath(path);
|
||||||
|
if ((it->second.first = wfiles->GetFile(path)))
|
||||||
WorkingFile *wf = wfiles->GetFile(path);
|
edit.textDocument.version = it->second.first->version;
|
||||||
if (wf)
|
|
||||||
path_to_edit[file_id].textDocument.version = wf->version;
|
|
||||||
}
|
}
|
||||||
|
// TODO LoadIndexedContent if wf is nullptr.
|
||||||
TextEdit &edit = path_to_edit[file_id].edits.emplace_back();
|
if (WorkingFile *wf = it->second.first) {
|
||||||
edit.range = ls_location->range;
|
int start = GetOffsetForPosition(loc->range.start, wf->buffer_content),
|
||||||
edit.newText = new_text;
|
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;
|
WorkspaceEdit ret;
|
||||||
for (const auto &changes : path_to_edit)
|
for (auto &x : path2edit)
|
||||||
edit.documentChanges.push_back(changes.second);
|
ret.documentChanges.push_back(std::move(x.second.second));
|
||||||
return edit;
|
return ret;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void MessageHandler::textDocument_rename(RenameParam ¶m, ReplyOnce &reply) {
|
void MessageHandler::textDocument_rename(RenameParam ¶m, ReplyOnce &reply) {
|
||||||
auto [file, wf] = FindOrFail(param.textDocument.uri.GetPath(), reply);
|
auto [file, wf] = FindOrFail(param.textDocument.uri.GetPath(), reply);
|
||||||
if (!wf) {
|
if (!wf)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
WorkspaceEdit result;
|
WorkspaceEdit result;
|
||||||
|
|
||||||
for (SymbolRef sym : FindSymbolsAtLocation(wf, file, param.position)) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ void MessageHandler::textDocument_signatureHelp(
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::string filter;
|
std::string filter;
|
||||||
Position end_pos = param.position;
|
Position end_pos;
|
||||||
begin_pos = wf->GetCompletionPosition(param.position, &filter, &end_pos);
|
begin_pos = wf->GetCompletionPosition(param.position, &filter, &end_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user