[clang-tools-extra] 0a4f99c - [clangd] Call hierarchy (ClangdLSPServer layer)
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 23 17:44:35 PST 2020
Author: Nathan Ridge
Date: 2020-11-23T20:44:07-05:00
New Revision: 0a4f99c494d007a21652b1b3939bde4753042c33
URL: https://github.com/llvm/llvm-project/commit/0a4f99c494d007a21652b1b3939bde4753042c33
DIFF: https://github.com/llvm/llvm-project/commit/0a4f99c494d007a21652b1b3939bde4753042c33.diff
LOG: [clangd] Call hierarchy (ClangdLSPServer layer)
Differential Revision: https://reviews.llvm.org/D91124
Added:
clang-tools-extra/clangd/test/call-hierarchy.test
Modified:
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/ClangdLSPServer.h
clang-tools-extra/clangd/test/initialize-params.test
clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 335a6fc9ad94..66dee68ec474 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -625,6 +625,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
}},
{"typeHierarchyProvider", true},
{"memoryUsageProvider", true}, // clangd extension.
+ {"callHierarchyProvider", true},
}}}};
if (Opts.Encoding)
Result["offsetEncoding"] = *Opts.Encoding;
@@ -1224,6 +1225,26 @@ void ClangdLSPServer::onResolveTypeHierarchy(
std::move(Reply));
}
+void ClangdLSPServer::onPrepareCallHierarchy(
+ const CallHierarchyPrepareParams &Params,
+ Callback<std::vector<CallHierarchyItem>> Reply) {
+ Server->prepareCallHierarchy(Params.textDocument.uri.file(), Params.position,
+ std::move(Reply));
+}
+
+void ClangdLSPServer::onCallHierarchyIncomingCalls(
+ const CallHierarchyIncomingCallsParams &Params,
+ Callback<std::vector<CallHierarchyIncomingCall>> Reply) {
+ Server->incomingCalls(Params.item, std::move(Reply));
+}
+
+void ClangdLSPServer::onCallHierarchyOutgoingCalls(
+ const CallHierarchyOutgoingCallsParams &Params,
+ Callback<std::vector<CallHierarchyOutgoingCall>> Reply) {
+ // FIXME: To be implemented.
+ Reply(std::vector<CallHierarchyOutgoingCall>{});
+}
+
void ClangdLSPServer::applyConfiguration(
const ConfigurationSettings &Settings) {
// Per-file update to the compilation database.
@@ -1468,6 +1489,9 @@ ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
MsgHandler->bind("textDocument/symbolInfo", &ClangdLSPServer::onSymbolInfo);
MsgHandler->bind("textDocument/typeHierarchy", &ClangdLSPServer::onTypeHierarchy);
MsgHandler->bind("typeHierarchy/resolve", &ClangdLSPServer::onResolveTypeHierarchy);
+ MsgHandler->bind("textDocument/prepareCallHierarchy", &ClangdLSPServer::onPrepareCallHierarchy);
+ MsgHandler->bind("callHierarchy/incomingCalls", &ClangdLSPServer::onCallHierarchyIncomingCalls);
+ MsgHandler->bind("callHierarchy/outgoingCalls", &ClangdLSPServer::onCallHierarchyOutgoingCalls);
MsgHandler->bind("textDocument/selectionRange", &ClangdLSPServer::onSelectionRange);
MsgHandler->bind("textDocument/documentLink", &ClangdLSPServer::onDocumentLink);
MsgHandler->bind("textDocument/semanticTokens/full", &ClangdLSPServer::onSemanticTokens);
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h
index 4d568bc13d8b..e65fc0e8a006 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -135,6 +135,14 @@ class ClangdLSPServer : private ClangdServer::Callbacks {
Callback<llvm::Optional<TypeHierarchyItem>>);
void onResolveTypeHierarchy(const ResolveTypeHierarchyItemParams &,
Callback<llvm::Optional<TypeHierarchyItem>>);
+ void onPrepareCallHierarchy(const CallHierarchyPrepareParams &,
+ Callback<std::vector<CallHierarchyItem>>);
+ void onCallHierarchyIncomingCalls(
+ const CallHierarchyIncomingCallsParams &,
+ Callback<std::vector<CallHierarchyIncomingCall>>);
+ void onCallHierarchyOutgoingCalls(
+ const CallHierarchyOutgoingCallsParams &,
+ Callback<std::vector<CallHierarchyOutgoingCall>>);
void onChangeConfiguration(const DidChangeConfigurationParams &);
void onSymbolInfo(const TextDocumentPositionParams &,
Callback<std::vector<SymbolDetails>>);
diff --git a/clang-tools-extra/clangd/test/call-hierarchy.test b/clang-tools-extra/clangd/test/call-hierarchy.test
new file mode 100644
index 000000000000..6548ea0068a8
--- /dev/null
+++ b/clang-tools-extra/clangd/test/call-hierarchy.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"cpp","text":"void callee(int);\nvoid caller1() {\n callee(42);\n}\nvoid caller2() {\n caller1();\n caller1();\n}\nvoid caller3() {\n caller1();\n caller2();\n}\n","uri":"test:///main.cpp","version":1}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/prepareCallHierarchy","params":{"position":{"character":8,"line":0},"textDocument":{"uri":"test:///main.cpp"}}}
+# CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "data": "{{.*}}",
+# CHECK-NEXT: "kind": 12,
+# CHECK-NEXT: "name": "callee",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 16,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "selectionRange": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 11,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test
index dbfe7d006c72..e4f4bf18dee4 100644
--- a/clang-tools-extra/clangd/test/initialize-params.test
+++ b/clang-tools-extra/clangd/test/initialize-params.test
@@ -6,6 +6,7 @@
# CHECK-NEXT: "result": {
# CHECK-NEXT: "capabilities": {
# CHECK-NEXT: "astProvider": true,
+# CHECK-NEXT: "callHierarchyProvider": true,
# CHECK-NEXT: "codeActionProvider": true,
# CHECK-NEXT: "completionProvider": {
# CHECK-NEXT: "allCommitCharacters": [
diff --git a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
index ff3b27d8cf99..8cd8764f3ef4 100644
--- a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
@@ -37,6 +37,8 @@ class LSPTest : public ::testing::Test, private clangd::Logger {
LSPTest() : LogSession(*this) {
ClangdServer::Options &Base = Opts;
Base = ClangdServer::optsForTest();
+ // This is needed to we can test index-based operations like call hierarchy.
+ Base.BuildDynamicSymbolIndex = true;
}
LSPClient &start() {
@@ -165,6 +167,33 @@ TEST_F(LSPTest, RecordsLatencies) {
stop();
EXPECT_THAT(Tracer.takeMetric("lsp_latency", MethodName), testing::SizeIs(1));
}
+
+TEST_F(LSPTest, IncomingCalls) {
+ Annotations Code(R"cpp(
+ void calle^e(int);
+ void caller1() {
+ [[callee]](42);
+ }
+ )cpp");
+ auto &Client = start();
+ Client.didOpen("foo.cpp", Code.code());
+ auto Items = Client
+ .call("textDocument/prepareCallHierarchy",
+ llvm::json::Object{
+ {"textDocument", Client.documentID("foo.cpp")},
+ {"position", Code.point()}})
+ .takeValue();
+ auto FirstItem = (*Items.getAsArray())[0];
+ auto Calls = Client
+ .call("callHierarchy/incomingCalls",
+ llvm::json::Object{{"item", FirstItem}})
+ .takeValue();
+ auto FirstCall = *(*Calls.getAsArray())[0].getAsObject();
+ EXPECT_EQ(FirstCall["fromRanges"], llvm::json::Value{Code.range()});
+ auto From = *FirstCall["from"].getAsObject();
+ EXPECT_EQ(From["name"], "caller1");
+}
+
} // namespace
} // namespace clangd
} // namespace clang
More information about the cfe-commits
mailing list