12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/CommandLine.h"
14 #include "llvm/Support/Path.h"
15 #include "llvm/Support/Signals.h"
17 #include <grpc++/grpc++.h>
18 #include <grpc++/health_check_service_interface.h>
20 #include "Index.grpc.pb.h"
27 static constexpr
char Overview[] = R
"(
28 This is an experimental remote index implementation. The server opens Dex and
29 awaits gRPC lookup requests from the client.
32 llvm::cl::opt<std::string> IndexPath(llvm::cl::desc("<INDEX FILE>"),
33 llvm::cl::Positional, llvm::cl::Required);
35 llvm::cl::opt<std::string> IndexRoot(llvm::cl::desc(
"<PROJECT ROOT>"),
36 llvm::cl::Positional, llvm::cl::Required);
38 llvm::cl::opt<std::string> ServerAddress(
39 "server-address", llvm::cl::init(
"0.0.0.0:50051"),
40 llvm::cl::desc(
"Address of the invoked server. Defaults to 0.0.0.0:50051"));
42 std::unique_ptr<clangd::SymbolIndex> openIndex(llvm::StringRef
Index) {
46 class RemoteIndexServer final :
public SymbolIndex::Service {
48 RemoteIndexServer(std::unique_ptr<clangd::SymbolIndex>
Index,
49 llvm::StringRef IndexRoot)
51 llvm::SmallString<256> NativePath = IndexRoot;
52 llvm::sys::path::native(NativePath);
53 IndexedProjectRoot = std::string(NativePath);
57 grpc::Status Lookup(grpc::ServerContext *Context,
58 const LookupRequest *Request,
59 grpc::ServerWriter<LookupReply> *Reply)
override {
60 clangd::LookupRequest Req;
61 for (
const auto &ID : Request->ids()) {
64 return grpc::Status::CANCELLED;
67 Index->lookup(Req, [&](
const clangd::Symbol &Sym) {
68 LookupReply NextMessage;
69 *NextMessage.mutable_stream_result() =
71 Reply->Write(NextMessage);
73 LookupReply LastMessage;
74 LastMessage.set_final_result(
true);
75 Reply->Write(LastMessage);
76 return grpc::Status::OK;
79 grpc::Status FuzzyFind(grpc::ServerContext *Context,
80 const FuzzyFindRequest *Request,
81 grpc::ServerWriter<FuzzyFindReply> *Reply)
override {
82 const auto Req =
fromProtobuf(Request, IndexedProjectRoot);
83 bool HasMore =
Index->fuzzyFind(Req, [&](
const clangd::Symbol &Sym) {
84 FuzzyFindReply NextMessage;
85 *NextMessage.mutable_stream_result() =
87 Reply->Write(NextMessage);
89 FuzzyFindReply LastMessage;
90 LastMessage.set_final_result(HasMore);
91 Reply->Write(LastMessage);
92 return grpc::Status::OK;
95 grpc::Status
Refs(grpc::ServerContext *Context,
const RefsRequest *Request,
96 grpc::ServerWriter<RefsReply> *Reply)
override {
97 clangd::RefsRequest Req;
98 for (
const auto &ID : Request->ids()) {
101 return grpc::Status::CANCELLED;
102 Req.IDs.insert(*SID);
104 bool HasMore =
Index->refs(Req, [&](
const clangd::Ref &Reference) {
105 RefsReply NextMessage;
106 *NextMessage.mutable_stream_result() =
toProtobuf(Reference, IndexRoot);
107 Reply->Write(NextMessage);
109 RefsReply LastMessage;
110 LastMessage.set_final_result(HasMore);
111 Reply->Write(LastMessage);
112 return grpc::Status::OK;
115 std::unique_ptr<clangd::SymbolIndex>
Index;
116 std::string IndexedProjectRoot;
119 void runServer(std::unique_ptr<clangd::SymbolIndex>
Index,
120 const std::string &ServerAddress) {
121 RemoteIndexServer Service(std::move(
Index), IndexRoot);
123 grpc::EnableDefaultHealthCheckService(
true);
125 Builder.AddListeningPort(ServerAddress, grpc::InsecureServerCredentials());
126 Builder.RegisterService(&Service);
127 std::unique_ptr<grpc::Server> Server(
Builder.BuildAndStart());
128 llvm::outs() <<
"Server listening on " << ServerAddress <<
'\n';
138 int main(
int argc,
char *argv[]) {
140 llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
141 llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
143 if (!llvm::sys::path::is_absolute(IndexRoot)) {
144 llvm::outs() <<
"Index root should be an absolute path.\n";
148 std::unique_ptr<clang::clangd::SymbolIndex>
Index = openIndex(IndexPath);
151 llvm::outs() <<
"Failed to open the index.\n";
155 runServer(std::move(
Index), ServerAddress);