Skip to content

Commit 67b2dbd

Browse files
committed
[clangd] Extend dexp to support remote index
Summary: * Merge clangd-remote-client into dexp * Implement `clangd::remote::IndexClient` that is derived from `SymbolIndex` * Upgrade remote mode-related CMake infrastructure Reviewers: sammccall Reviewed By: sammccall Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D78521
1 parent 7631af3 commit 67b2dbd

File tree

19 files changed

+530
-158
lines changed

19 files changed

+530
-158
lines changed

clang-tools-extra/clangd/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
140140
endif()
141141
add_subdirectory(tool)
142142
add_subdirectory(indexer)
143-
add_subdirectory(index/dex/dexp)
144143

145144
if (LLVM_INCLUDE_BENCHMARKS)
146145
add_subdirectory(benchmarks)
@@ -160,5 +159,6 @@ set(GRPC_INSTALL_PATH "" CACHE PATH "Path to gRPC library manual installation.")
160159

161160
if (CLANGD_ENABLE_REMOTE)
162161
include(FindGRPC)
163-
add_subdirectory(index/remote)
164162
endif()
163+
add_subdirectory(index/remote)
164+
add_subdirectory(index/dex/dexp)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
#define CLANGD_BUILD_XPC @CLANGD_BUILD_XPC@
2+
#define CLANGD_ENABLE_REMOTE @CLANGD_ENABLE_REMOTE@

clang-tools-extra/clangd/index/Serialization.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const IndexFileOut &O);
7777
std::string toYAML(const Symbol &);
7878
std::string toYAML(const std::pair<SymbolID, ArrayRef<Ref>> &);
7979
std::string toYAML(const Relation &);
80+
std::string toYAML(const Ref &);
81+
82+
// Deserialize a single symbol from YAML.
83+
llvm::Expected<clangd::Symbol> symbolFromYAML(StringRef YAML,
84+
llvm::UniqueStringSaver *Strings);
85+
llvm::Expected<clangd::Ref> refFromYAML(StringRef YAML,
86+
llvm::UniqueStringSaver *Strings);
8087

8188
// Build an in-memory static index from an index file.
8289
// The size should be relatively small, so data can be managed in memory.

clang-tools-extra/clangd/index/YAMLSerialization.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,5 +517,40 @@ std::string toYAML(const Relation &R) {
517517
return Buf;
518518
}
519519

520+
std::string toYAML(const Ref &R) {
521+
std::string Buf;
522+
{
523+
llvm::raw_string_ostream OS(Buf);
524+
llvm::yaml::Output Yout(OS);
525+
Ref Reference = R; // copy: Yout<< requires mutability.
526+
Yout << Reference;
527+
}
528+
return Buf;
529+
}
530+
531+
llvm::Expected<clangd::Symbol>
532+
symbolFromYAML(StringRef YAML, llvm::UniqueStringSaver *Strings) {
533+
clangd::Symbol Deserialized;
534+
llvm::yaml::Input YAMLInput(YAML, Strings);
535+
if (YAMLInput.error())
536+
return llvm::make_error<llvm::StringError>(
537+
llvm::formatv("Unable to deserialize Symbol from YAML: {0}", YAML),
538+
llvm::inconvertibleErrorCode());
539+
YAMLInput >> Deserialized;
540+
return Deserialized;
541+
}
542+
543+
llvm::Expected<clangd::Ref> refFromYAML(StringRef YAML,
544+
llvm::UniqueStringSaver *Strings) {
545+
clangd::Ref Deserialized;
546+
llvm::yaml::Input YAMLInput(YAML, Strings);
547+
if (YAMLInput.error())
548+
return llvm::make_error<llvm::StringError>(
549+
llvm::formatv("Unable to deserialize Symbol from YAML: {0}", YAML),
550+
llvm::inconvertibleErrorCode());
551+
YAMLInput >> Deserialized;
552+
return Deserialized;
553+
}
554+
520555
} // namespace clangd
521556
} // namespace clang

clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../)
2+
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../)
23

34
set(LLVM_LINK_COMPONENTS
45
LineEditor
@@ -16,4 +17,5 @@ clang_target_link_libraries(dexp
1617
target_link_libraries(dexp
1718
PRIVATE
1819
clangDaemon
20+
clangdRemoteIndex
1921
)

clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14+
#include "Features.inc"
1415
#include "SourceCode.h"
1516
#include "index/Serialization.h"
1617
#include "index/dex/Dex.h"
18+
#include "index/remote/Client.h"
1719
#include "llvm/ADT/ScopeExit.h"
1820
#include "llvm/ADT/SmallVector.h"
1921
#include "llvm/ADT/StringRef.h"
@@ -26,8 +28,9 @@ namespace clang {
2628
namespace clangd {
2729
namespace {
2830

29-
llvm::cl::opt<std::string> IndexPath(llvm::cl::desc("<INDEX FILE>"),
30-
llvm::cl::Positional, llvm::cl::Required);
31+
llvm::cl::opt<std::string> IndexLocation(
32+
llvm::cl::desc("<path to index file | remote:server.address>"),
33+
llvm::cl::Positional);
3134

3235
llvm::cl::opt<std::string>
3336
ExecCommand("c", llvm::cl::desc("Command to execute and then exit"));
@@ -38,6 +41,10 @@ queries over given symbol collection obtained via clangd-indexer. The
3841
tool can be used to evaluate search quality of existing index implementations
3942
and manually construct non-trivial test cases.
4043
44+
You can connect to remote index by passing remote:address to dexp. Example:
45+
46+
$ dexp remote:0.0.0.0:9000
47+
4148
Type use "help" request to get information about the details.
4249
)";
4350

@@ -150,7 +157,7 @@ class FuzzyFind : public Command {
150157
}
151158
Request.AnyScope = Request.Scopes.empty();
152159
// FIXME(kbobyrev): Print symbol final scores to see the distribution.
153-
static const auto OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n";
160+
static const auto *OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n";
154161
llvm::outs() << llvm::formatv(OutputFormat, "Rank", "Symbol ID",
155162
"Symbol Name");
156163
size_t Rank = 0;
@@ -316,13 +323,14 @@ struct {
316323
{"find", "Search for symbols with fuzzyFind", std::make_unique<FuzzyFind>},
317324
{"lookup", "Dump symbol details by ID or qualified name",
318325
std::make_unique<Lookup>},
319-
{"refs", "Find references by ID or qualified name",
320-
std::make_unique<Refs>},
326+
{"refs", "Find references by ID or qualified name", std::make_unique<Refs>},
321327
{"export", "Export index", std::make_unique<Export>},
322328
};
323329

324330
std::unique_ptr<SymbolIndex> openIndex(llvm::StringRef Index) {
325-
return loadIndex(Index, /*UseDex=*/true);
331+
return Index.startswith("remote:")
332+
? remote::getClient(Index.drop_front(strlen("remote:")))
333+
: loadIndex(Index, /*UseDex=*/true);
326334
}
327335

328336
bool runCommand(std::string Request, const SymbolIndex &Index) {
@@ -365,9 +373,10 @@ int main(int argc, const char *argv[]) {
365373
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
366374

367375
std::unique_ptr<SymbolIndex> Index;
368-
reportTime("Dex build", [&]() {
369-
Index = openIndex(IndexPath);
370-
});
376+
reportTime(llvm::StringRef(IndexLocation).startswith("remote:")
377+
? "Remote index client creation"
378+
: "Dex build",
379+
[&]() { Index = openIndex(IndexLocation); });
371380

372381
if (!Index) {
373382
llvm::outs() << "Failed to open the index.\n";
Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
1-
generate_grpc_protos(RemoteIndexProtos "Index.proto")
1+
if (CLANGD_ENABLE_REMOTE)
2+
generate_grpc_protos(RemoteIndexProtos "Index.proto")
3+
include_directories(${CMAKE_CURRENT_BINARY_DIR})
4+
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../)
25

3-
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
4-
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../)
6+
# FIXME(kirillbobyrev): target_compile_definitions is not working with
7+
# add_clang_library for some reason. Is there any way to make this
8+
# target-local?
9+
add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=1)
510

6-
add_subdirectory(client)
7-
add_subdirectory(server)
11+
add_clang_library(clangdRemoteIndex
12+
Client.cpp
13+
14+
LINK_LIBS
15+
RemoteIndexProtos
16+
clangdRemoteMarshalling
17+
18+
protobuf
19+
grpc++
20+
clangDaemon
21+
)
22+
23+
add_subdirectory(marshalling)
24+
add_subdirectory(server)
25+
else()
26+
# Provides a dummy implementation of clangdRemoteIndex.
27+
add_subdirectory(unimplemented)
28+
endif()
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//===--- Client.cpp ----------------------------------------------*- C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <grpcpp/grpcpp.h>
10+
11+
#include "Client.h"
12+
#include "Index.grpc.pb.h"
13+
#include "Logger.h"
14+
#include "Trace.h"
15+
#include "index/Serialization.h"
16+
#include "marshalling/Marshalling.h"
17+
#include "llvm/Support/YAMLTraits.h"
18+
19+
namespace clang {
20+
namespace clangd {
21+
namespace remote {
22+
namespace {
23+
24+
class IndexClient : public clangd::SymbolIndex {
25+
template <typename RequestT, typename ReplyT>
26+
using StreamingCall = std::unique_ptr<grpc::ClientReader<ReplyT>> (
27+
remote::SymbolIndex::Stub::*)(grpc::ClientContext *, const RequestT &);
28+
29+
// FIXME(kirillbobyrev): Set deadlines for requests.
30+
template <typename RequestT, typename ReplyT, typename ClangdRequestT,
31+
typename CallbackT>
32+
bool streamRPC(ClangdRequestT Request,
33+
StreamingCall<RequestT, ReplyT> RPCCall,
34+
CallbackT Callback) const {
35+
bool FinalResult = false;
36+
trace::Span Tracer(RequestT::descriptor()->name());
37+
const auto RPCRequest = toProtobuf(Request);
38+
grpc::ClientContext Context;
39+
auto Reader = (Stub.get()->*RPCCall)(&Context, RPCRequest);
40+
llvm::BumpPtrAllocator Arena;
41+
llvm::UniqueStringSaver Strings(Arena);
42+
ReplyT Reply;
43+
while (Reader->Read(&Reply)) {
44+
if (!Reply.has_stream_result()) {
45+
FinalResult = Reply.final_result();
46+
continue;
47+
}
48+
auto Sym = fromProtobuf(Reply.stream_result(), &Strings);
49+
if (!Sym)
50+
elog("Received invalid {0}: {1}", ReplyT::descriptor()->name(),
51+
Reply.stream_result().yaml_serialization());
52+
Callback(*Sym);
53+
}
54+
SPAN_ATTACH(Tracer, "status", Reader->Finish().ok());
55+
return FinalResult;
56+
}
57+
58+
public:
59+
IndexClient(std::shared_ptr<grpc::Channel> Channel)
60+
: Stub(remote::SymbolIndex::NewStub(Channel)) {}
61+
62+
void lookup(const clangd::LookupRequest &Request,
63+
llvm::function_ref<void(const clangd::Symbol &)> Callback) const {
64+
streamRPC<LookupRequest, LookupReply>(
65+
Request, &remote::SymbolIndex::Stub::Lookup, Callback);
66+
}
67+
68+
bool
69+
fuzzyFind(const clangd::FuzzyFindRequest &Request,
70+
llvm::function_ref<void(const clangd::Symbol &)> Callback) const {
71+
return streamRPC<FuzzyFindRequest, FuzzyFindReply>(
72+
Request, &remote::SymbolIndex::Stub::FuzzyFind, Callback);
73+
}
74+
75+
bool refs(const clangd::RefsRequest &Request,
76+
llvm::function_ref<void(const clangd::Ref &)> Callback) const {
77+
return streamRPC<RefsRequest, RefsReply>(
78+
Request, &remote::SymbolIndex::Stub::Refs, Callback);
79+
}
80+
81+
// FIXME(kirillbobyrev): Implement this.
82+
void
83+
relations(const clangd::RelationsRequest &,
84+
llvm::function_ref<void(const SymbolID &, const clangd::Symbol &)>)
85+
const {}
86+
87+
// IndexClient does not take any space since the data is stored on the server.
88+
size_t estimateMemoryUsage() const { return 0; }
89+
90+
private:
91+
std::unique_ptr<remote::SymbolIndex::Stub> Stub;
92+
};
93+
94+
} // namespace
95+
96+
std::unique_ptr<clangd::SymbolIndex> getClient(llvm::StringRef Address) {
97+
const auto Channel =
98+
grpc::CreateChannel(Address.str(), grpc::InsecureChannelCredentials());
99+
Channel->GetState(true);
100+
return std::unique_ptr<clangd::SymbolIndex>(new IndexClient(Channel));
101+
}
102+
103+
} // namespace remote
104+
} // namespace clangd
105+
} // namespace clang
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===--- Client.h - Connect to a remote index via gRPC -----------*- C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H
11+
12+
#include "index/Index.h"
13+
14+
namespace clang {
15+
namespace clangd {
16+
namespace remote {
17+
18+
/// Returns an SymbolIndex client that passes requests to remote index located
19+
/// at \p Address. The client allows synchronous RPC calls.
20+
///
21+
/// This method attempts to resolve the address and establish the connection.
22+
///
23+
/// \returns nullptr if the address is not resolved during the function call or
24+
/// if the project was compiled without Remote Index support.
25+
std::unique_ptr<clangd::SymbolIndex> getClient(llvm::StringRef Address);
26+
27+
} // namespace remote
28+
} // namespace clangd
29+
} // namespace clang
30+
31+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H

clang-tools-extra/clangd/index/remote/Index.proto

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,60 @@ syntax = "proto3";
1010

1111
package clang.clangd.remote;
1212

13-
service Index {
13+
service SymbolIndex {
1414
rpc Lookup(LookupRequest) returns (stream LookupReply) {}
15+
16+
rpc FuzzyFind(FuzzyFindRequest) returns (stream FuzzyFindReply) {}
17+
18+
rpc Refs(RefsRequest) returns (stream RefsReply) {}
19+
}
20+
21+
message LookupRequest { repeated string ids = 1; }
22+
23+
// The response is a stream of symbol messages and the terminating message
24+
// indicating the end of stream.
25+
message LookupReply {
26+
oneof kind {
27+
Symbol stream_result = 1;
28+
bool final_result = 2;
29+
}
30+
}
31+
32+
message FuzzyFindRequest {
33+
string query = 1;
34+
repeated string scopes = 2;
35+
bool any_scope = 3;
36+
uint32 limit = 4;
37+
bool resricted_for_code_completion = 5;
38+
repeated string proximity_paths = 6;
39+
repeated string preferred_types = 7;
40+
}
41+
42+
// The response is a stream of symbol messages, and one terminating has_more
43+
// message.
44+
message FuzzyFindReply {
45+
oneof kind {
46+
Symbol stream_result = 1;
47+
bool final_result = 2; // HasMore
48+
}
1549
}
1650

17-
message LookupRequest { string id = 1; }
51+
message RefsRequest {
52+
repeated string ids = 1;
53+
uint32 filter = 2;
54+
uint32 limit = 3;
55+
}
56+
57+
// The response is a stream of reference messages, and one terminating has_more
58+
// message.
59+
message RefsReply {
60+
oneof kind {
61+
Ref stream_result = 1;
62+
bool final_result = 2; // HasMore
63+
}
64+
}
1865

19-
message LookupReply { string symbol_yaml = 1; }
66+
// FIXME(kirillbobyrev): Properly serialize symbols and refs instead of passing
67+
// YAML.
68+
message Ref { string yaml_serialization = 1; }
69+
message Symbol { string yaml_serialization = 1; }

0 commit comments

Comments
 (0)