[clangd] Add rename support.
Summary:
Make clangd handle "textDocument/rename" request. The rename
functionality comes from the "local-rename" sub-tool of clang-refactor.
Currently clangd only supports local rename (only symbol occurrences in
the main file will be renamed).
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: cfe-commits, ioeric, arphaman, mgorny
Differential Revision: https://reviews.llvm.org/D39676
llvm-svn: 317780
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index 8fa23bf..7d53134 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -1073,3 +1073,51 @@
{"signatures", json::ary(SH.signatures)},
};
}
+
+llvm::Optional<RenameParams>
+RenameParams::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) {
+ RenameParams Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+
+ if (KeyValue == "textDocument") {
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
+ if (!Value)
+ continue;
+ auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
+ if (!Map)
+ return llvm::None;
+ auto Parsed = TextDocumentIdentifier::parse(Map, Logger);
+ if (!Parsed)
+ return llvm::None;
+ Result.textDocument = std::move(*Parsed);
+ } else if (KeyValue == "position") {
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
+ if (!Value)
+ continue;
+ auto Parsed = Position::parse(Value, Logger);
+ if (!Parsed)
+ return llvm::None;
+ Result.position = std::move(*Parsed);
+ } else if (KeyValue == "newName") {
+ auto *Value = NextKeyValue.getValue();
+ if (!Value)
+ continue;
+ auto *Node = dyn_cast<llvm::yaml::ScalarNode>(Value);
+ if (!Node)
+ return llvm::None;
+ llvm::SmallString<10> Storage;
+ Result.newName = Node->getValue(Storage);
+ } else {
+ logIgnoredField(KeyValue, Logger);
+ }
+ }
+ return Result;
+}