[clang-tools-extra] 67b2dbd - [clangd] Extend dexp to support remote index

Kirill Bobyrev via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 24 04:59:33 PDT 2020


Author: Kirill Bobyrev
Date: 2020-04-24T13:59:21+02:00
New Revision: 67b2dbd5a33583fe148fd12f141e15301cfe99d1

URL: https://github.com/llvm/llvm-project/commit/67b2dbd5a33583fe148fd12f141e15301cfe99d1
DIFF: https://github.com/llvm/llvm-project/commit/67b2dbd5a33583fe148fd12f141e15301cfe99d1.diff

LOG: [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

Added: 
    clang-tools-extra/clangd/index/remote/Client.cpp
    clang-tools-extra/clangd/index/remote/Client.h
    clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt
    clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
    clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h
    clang-tools-extra/clangd/index/remote/unimplemented/CMakeLists.txt
    clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp

Modified: 
    clang-tools-extra/clangd/CMakeLists.txt
    clang-tools-extra/clangd/Features.inc.in
    clang-tools-extra/clangd/index/Serialization.h
    clang-tools-extra/clangd/index/YAMLSerialization.cpp
    clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt
    clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
    clang-tools-extra/clangd/index/remote/CMakeLists.txt
    clang-tools-extra/clangd/index/remote/Index.proto
    clang-tools-extra/clangd/index/remote/server/CMakeLists.txt
    clang-tools-extra/clangd/index/remote/server/Server.cpp

Removed: 
    clang-tools-extra/clangd/index/remote/client/CMakeLists.txt
    clang-tools-extra/clangd/index/remote/client/Client.cpp


################################################################################
diff  --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt
index 1c2cbf398b77..124f087589d6 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -140,7 +140,6 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
 endif()
 add_subdirectory(tool)
 add_subdirectory(indexer)
-add_subdirectory(index/dex/dexp)
 
 if (LLVM_INCLUDE_BENCHMARKS)
   add_subdirectory(benchmarks)
@@ -160,5 +159,6 @@ set(GRPC_INSTALL_PATH "" CACHE PATH "Path to gRPC library manual installation.")
 
 if (CLANGD_ENABLE_REMOTE)
   include(FindGRPC)
-  add_subdirectory(index/remote)
 endif()
+add_subdirectory(index/remote)
+add_subdirectory(index/dex/dexp)

diff  --git a/clang-tools-extra/clangd/Features.inc.in b/clang-tools-extra/clangd/Features.inc.in
index da75aa67a65b..6797232ddac7 100644
--- a/clang-tools-extra/clangd/Features.inc.in
+++ b/clang-tools-extra/clangd/Features.inc.in
@@ -1 +1,2 @@
 #define CLANGD_BUILD_XPC @CLANGD_BUILD_XPC@
+#define CLANGD_ENABLE_REMOTE @CLANGD_ENABLE_REMOTE@

diff  --git a/clang-tools-extra/clangd/index/Serialization.h b/clang-tools-extra/clangd/index/Serialization.h
index 47317c0401fc..99510630f1ca 100644
--- a/clang-tools-extra/clangd/index/Serialization.h
+++ b/clang-tools-extra/clangd/index/Serialization.h
@@ -77,6 +77,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const IndexFileOut &O);
 std::string toYAML(const Symbol &);
 std::string toYAML(const std::pair<SymbolID, ArrayRef<Ref>> &);
 std::string toYAML(const Relation &);
+std::string toYAML(const Ref &);
+
+// Deserialize a single symbol from YAML.
+llvm::Expected<clangd::Symbol> symbolFromYAML(StringRef YAML,
+                                              llvm::UniqueStringSaver *Strings);
+llvm::Expected<clangd::Ref> refFromYAML(StringRef YAML,
+                                        llvm::UniqueStringSaver *Strings);
 
 // Build an in-memory static index from an index file.
 // The size should be relatively small, so data can be managed in memory.

diff  --git a/clang-tools-extra/clangd/index/YAMLSerialization.cpp b/clang-tools-extra/clangd/index/YAMLSerialization.cpp
index 79965ceb1634..fc515a17d100 100644
--- a/clang-tools-extra/clangd/index/YAMLSerialization.cpp
+++ b/clang-tools-extra/clangd/index/YAMLSerialization.cpp
@@ -517,5 +517,40 @@ std::string toYAML(const Relation &R) {
   return Buf;
 }
 
+std::string toYAML(const Ref &R) {
+  std::string Buf;
+  {
+    llvm::raw_string_ostream OS(Buf);
+    llvm::yaml::Output Yout(OS);
+    Ref Reference = R; // copy: Yout<< requires mutability.
+    Yout << Reference;
+  }
+  return Buf;
+}
+
+llvm::Expected<clangd::Symbol>
+symbolFromYAML(StringRef YAML, llvm::UniqueStringSaver *Strings) {
+  clangd::Symbol Deserialized;
+  llvm::yaml::Input YAMLInput(YAML, Strings);
+  if (YAMLInput.error())
+    return llvm::make_error<llvm::StringError>(
+        llvm::formatv("Unable to deserialize Symbol from YAML: {0}", YAML),
+        llvm::inconvertibleErrorCode());
+  YAMLInput >> Deserialized;
+  return Deserialized;
+}
+
+llvm::Expected<clangd::Ref> refFromYAML(StringRef YAML,
+                                        llvm::UniqueStringSaver *Strings) {
+  clangd::Ref Deserialized;
+  llvm::yaml::Input YAMLInput(YAML, Strings);
+  if (YAMLInput.error())
+    return llvm::make_error<llvm::StringError>(
+        llvm::formatv("Unable to deserialize Symbol from YAML: {0}", YAML),
+        llvm::inconvertibleErrorCode());
+  YAMLInput >> Deserialized;
+  return Deserialized;
+}
+
 } // namespace clangd
 } // namespace clang

diff  --git a/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt b/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt
index a4edbb372a76..7b4b6e53a4ad 100644
--- a/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt
+++ b/clang-tools-extra/clangd/index/dex/dexp/CMakeLists.txt
@@ -1,4 +1,5 @@
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../)
+include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../)
 
 set(LLVM_LINK_COMPONENTS
   LineEditor
@@ -16,4 +17,5 @@ clang_target_link_libraries(dexp
 target_link_libraries(dexp
   PRIVATE
   clangDaemon
+  clangdRemoteIndex
   )

diff  --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
index 015246d1a82f..101367ce7c67 100644
--- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
+++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
@@ -11,9 +11,11 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "Features.inc"
 #include "SourceCode.h"
 #include "index/Serialization.h"
 #include "index/dex/Dex.h"
+#include "index/remote/Client.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -26,8 +28,9 @@ namespace clang {
 namespace clangd {
 namespace {
 
-llvm::cl::opt<std::string> IndexPath(llvm::cl::desc("<INDEX FILE>"),
-                                     llvm::cl::Positional, llvm::cl::Required);
+llvm::cl::opt<std::string> IndexLocation(
+    llvm::cl::desc("<path to index file | remote:server.address>"),
+    llvm::cl::Positional);
 
 llvm::cl::opt<std::string>
     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
 tool can be used to evaluate search quality of existing index implementations
 and manually construct non-trivial test cases.
 
+You can connect to remote index by passing remote:address to dexp. Example:
+
+$ dexp remote:0.0.0.0:9000
+
 Type use "help" request to get information about the details.
 )";
 
@@ -150,7 +157,7 @@ class FuzzyFind : public Command {
     }
     Request.AnyScope = Request.Scopes.empty();
     // FIXME(kbobyrev): Print symbol final scores to see the distribution.
-    static const auto OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n";
+    static const auto *OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n";
     llvm::outs() << llvm::formatv(OutputFormat, "Rank", "Symbol ID",
                                   "Symbol Name");
     size_t Rank = 0;
@@ -316,13 +323,14 @@ struct {
     {"find", "Search for symbols with fuzzyFind", std::make_unique<FuzzyFind>},
     {"lookup", "Dump symbol details by ID or qualified name",
      std::make_unique<Lookup>},
-    {"refs", "Find references by ID or qualified name",
-     std::make_unique<Refs>},
+    {"refs", "Find references by ID or qualified name", std::make_unique<Refs>},
     {"export", "Export index", std::make_unique<Export>},
 };
 
 std::unique_ptr<SymbolIndex> openIndex(llvm::StringRef Index) {
-  return loadIndex(Index, /*UseDex=*/true);
+  return Index.startswith("remote:")
+             ? remote::getClient(Index.drop_front(strlen("remote:")))
+             : loadIndex(Index, /*UseDex=*/true);
 }
 
 bool runCommand(std::string Request, const SymbolIndex &Index) {
@@ -365,9 +373,10 @@ int main(int argc, const char *argv[]) {
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
 
   std::unique_ptr<SymbolIndex> Index;
-  reportTime("Dex build", [&]() {
-    Index = openIndex(IndexPath);
-  });
+  reportTime(llvm::StringRef(IndexLocation).startswith("remote:")
+                 ? "Remote index client creation"
+                 : "Dex build",
+             [&]() { Index = openIndex(IndexLocation); });
 
   if (!Index) {
     llvm::outs() << "Failed to open the index.\n";

diff  --git a/clang-tools-extra/clangd/index/remote/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/CMakeLists.txt
index b946958f3c5f..1bd336e626d9 100644
--- a/clang-tools-extra/clangd/index/remote/CMakeLists.txt
+++ b/clang-tools-extra/clangd/index/remote/CMakeLists.txt
@@ -1,7 +1,28 @@
-generate_grpc_protos(RemoteIndexProtos "Index.proto")
+if (CLANGD_ENABLE_REMOTE)
+  generate_grpc_protos(RemoteIndexProtos "Index.proto")
+  include_directories(${CMAKE_CURRENT_BINARY_DIR})
+  include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../)
 
-include_directories("${CMAKE_CURRENT_BINARY_DIR}")
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../)
+  # FIXME(kirillbobyrev): target_compile_definitions is not working with
+  # add_clang_library for some reason. Is there any way to make this
+  # target-local?
+  add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=1)
 
-add_subdirectory(client)
-add_subdirectory(server)
+  add_clang_library(clangdRemoteIndex
+    Client.cpp
+
+    LINK_LIBS
+    RemoteIndexProtos
+    clangdRemoteMarshalling
+
+    protobuf
+    grpc++
+    clangDaemon
+    )
+
+  add_subdirectory(marshalling)
+  add_subdirectory(server)
+else()
+  # Provides a dummy implementation of clangdRemoteIndex.
+  add_subdirectory(unimplemented)
+endif()

diff  --git a/clang-tools-extra/clangd/index/remote/Client.cpp b/clang-tools-extra/clangd/index/remote/Client.cpp
new file mode 100644
index 000000000000..79f303978c31
--- /dev/null
+++ b/clang-tools-extra/clangd/index/remote/Client.cpp
@@ -0,0 +1,105 @@
+//===--- Client.cpp ----------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <grpcpp/grpcpp.h>
+
+#include "Client.h"
+#include "Index.grpc.pb.h"
+#include "Logger.h"
+#include "Trace.h"
+#include "index/Serialization.h"
+#include "marshalling/Marshalling.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace clang {
+namespace clangd {
+namespace remote {
+namespace {
+
+class IndexClient : public clangd::SymbolIndex {
+  template <typename RequestT, typename ReplyT>
+  using StreamingCall = std::unique_ptr<grpc::ClientReader<ReplyT>> (
+      remote::SymbolIndex::Stub::*)(grpc::ClientContext *, const RequestT &);
+
+  // FIXME(kirillbobyrev): Set deadlines for requests.
+  template <typename RequestT, typename ReplyT, typename ClangdRequestT,
+            typename CallbackT>
+  bool streamRPC(ClangdRequestT Request,
+                 StreamingCall<RequestT, ReplyT> RPCCall,
+                 CallbackT Callback) const {
+    bool FinalResult = false;
+    trace::Span Tracer(RequestT::descriptor()->name());
+    const auto RPCRequest = toProtobuf(Request);
+    grpc::ClientContext Context;
+    auto Reader = (Stub.get()->*RPCCall)(&Context, RPCRequest);
+    llvm::BumpPtrAllocator Arena;
+    llvm::UniqueStringSaver Strings(Arena);
+    ReplyT Reply;
+    while (Reader->Read(&Reply)) {
+      if (!Reply.has_stream_result()) {
+        FinalResult = Reply.final_result();
+        continue;
+      }
+      auto Sym = fromProtobuf(Reply.stream_result(), &Strings);
+      if (!Sym)
+        elog("Received invalid {0}: {1}", ReplyT::descriptor()->name(),
+             Reply.stream_result().yaml_serialization());
+      Callback(*Sym);
+    }
+    SPAN_ATTACH(Tracer, "status", Reader->Finish().ok());
+    return FinalResult;
+  }
+
+public:
+  IndexClient(std::shared_ptr<grpc::Channel> Channel)
+      : Stub(remote::SymbolIndex::NewStub(Channel)) {}
+
+  void lookup(const clangd::LookupRequest &Request,
+              llvm::function_ref<void(const clangd::Symbol &)> Callback) const {
+    streamRPC<LookupRequest, LookupReply>(
+        Request, &remote::SymbolIndex::Stub::Lookup, Callback);
+  }
+
+  bool
+  fuzzyFind(const clangd::FuzzyFindRequest &Request,
+            llvm::function_ref<void(const clangd::Symbol &)> Callback) const {
+    return streamRPC<FuzzyFindRequest, FuzzyFindReply>(
+        Request, &remote::SymbolIndex::Stub::FuzzyFind, Callback);
+  }
+
+  bool refs(const clangd::RefsRequest &Request,
+            llvm::function_ref<void(const clangd::Ref &)> Callback) const {
+    return streamRPC<RefsRequest, RefsReply>(
+        Request, &remote::SymbolIndex::Stub::Refs, Callback);
+  }
+
+  // FIXME(kirillbobyrev): Implement this.
+  void
+  relations(const clangd::RelationsRequest &,
+            llvm::function_ref<void(const SymbolID &, const clangd::Symbol &)>)
+      const {}
+
+  // IndexClient does not take any space since the data is stored on the server.
+  size_t estimateMemoryUsage() const { return 0; }
+
+private:
+  std::unique_ptr<remote::SymbolIndex::Stub> Stub;
+};
+
+} // namespace
+
+std::unique_ptr<clangd::SymbolIndex> getClient(llvm::StringRef Address) {
+  const auto Channel =
+      grpc::CreateChannel(Address.str(), grpc::InsecureChannelCredentials());
+  Channel->GetState(true);
+  return std::unique_ptr<clangd::SymbolIndex>(new IndexClient(Channel));
+}
+
+} // namespace remote
+} // namespace clangd
+} // namespace clang

diff  --git a/clang-tools-extra/clangd/index/remote/Client.h b/clang-tools-extra/clangd/index/remote/Client.h
new file mode 100644
index 000000000000..9708fdbe851a
--- /dev/null
+++ b/clang-tools-extra/clangd/index/remote/Client.h
@@ -0,0 +1,31 @@
+//===--- Client.h - Connect to a remote index via gRPC -----------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H
+
+#include "index/Index.h"
+
+namespace clang {
+namespace clangd {
+namespace remote {
+
+/// Returns an SymbolIndex client that passes requests to remote index located
+/// at \p Address. The client allows synchronous RPC calls.
+///
+/// This method attempts to resolve the address and establish the connection.
+///
+/// \returns nullptr if the address is not resolved during the function call or
+/// if the project was compiled without Remote Index support.
+std::unique_ptr<clangd::SymbolIndex> getClient(llvm::StringRef Address);
+
+} // namespace remote
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_INDEX_H

diff  --git a/clang-tools-extra/clangd/index/remote/Index.proto b/clang-tools-extra/clangd/index/remote/Index.proto
index 399036ed72b7..0cd9738db58c 100644
--- a/clang-tools-extra/clangd/index/remote/Index.proto
+++ b/clang-tools-extra/clangd/index/remote/Index.proto
@@ -10,10 +10,60 @@ syntax = "proto3";
 
 package clang.clangd.remote;
 
-service Index {
+service SymbolIndex {
   rpc Lookup(LookupRequest) returns (stream LookupReply) {}
+
+  rpc FuzzyFind(FuzzyFindRequest) returns (stream FuzzyFindReply) {}
+
+  rpc Refs(RefsRequest) returns (stream RefsReply) {}
+}
+
+message LookupRequest { repeated string ids = 1; }
+
+// The response is a stream of symbol messages and the terminating message
+// indicating the end of stream.
+message LookupReply {
+  oneof kind {
+    Symbol stream_result = 1;
+    bool final_result = 2;
+  }
+}
+
+message FuzzyFindRequest {
+  string query = 1;
+  repeated string scopes = 2;
+  bool any_scope = 3;
+  uint32 limit = 4;
+  bool resricted_for_code_completion = 5;
+  repeated string proximity_paths = 6;
+  repeated string preferred_types = 7;
+}
+
+// The response is a stream of symbol messages, and one terminating has_more
+// message.
+message FuzzyFindReply {
+  oneof kind {
+    Symbol stream_result = 1;
+    bool final_result = 2; // HasMore
+  }
 }
 
-message LookupRequest { string id = 1; }
+message RefsRequest {
+  repeated string ids = 1;
+  uint32 filter = 2;
+  uint32 limit = 3;
+}
+
+// The response is a stream of reference messages, and one terminating has_more
+// message.
+message RefsReply {
+  oneof kind {
+    Ref stream_result = 1;
+    bool final_result = 2; // HasMore
+  }
+}
 
-message LookupReply { string symbol_yaml = 1; }
+// FIXME(kirillbobyrev): Properly serialize symbols and refs instead of passing
+// YAML.
+message Ref { string yaml_serialization = 1; }
+message Symbol { string yaml_serialization = 1; }

diff  --git a/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt
deleted file mode 100644
index 18bca1b04436..000000000000
--- a/clang-tools-extra/clangd/index/remote/client/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  LineEditor
-  Support
-  )
-add_clang_executable(clangd-index-client
-  Client.cpp
-  )
-target_compile_definitions(clangd-index-client PRIVATE -DGOOGLE_PROTOBUF_NO_RTTI=1)
-clang_target_link_libraries(clangd-index-client
-  PRIVATE
-  clangDaemon
-  )
-target_link_libraries(clangd-index-client
-  PRIVATE
-  RemoteIndexProtos
-
-  protobuf
-  grpc++
-  )

diff  --git a/clang-tools-extra/clangd/index/remote/client/Client.cpp b/clang-tools-extra/clangd/index/remote/client/Client.cpp
deleted file mode 100644
index 5e888c5e0fa7..000000000000
--- a/clang-tools-extra/clangd/index/remote/client/Client.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//===--- Client.cpp - Remote Index Client -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a simple interactive tool which can be used to manually
-// evaluate symbol search quality of Clangd index.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SourceCode.h"
-#include "index/Serialization.h"
-#include "index/dex/Dex.h"
-#include "llvm/ADT/ScopeExit.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/LineEditor/LineEditor.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Signals.h"
-
-#include "grpcpp/grpcpp.h"
-
-#include "Index.grpc.pb.h"
-
-namespace clang {
-namespace clangd {
-namespace {
-
-llvm::cl::opt<std::string>
-    ServerAddress("server-address",
-                  llvm::cl::desc("Address of remote index server to use."),
-                  llvm::cl::init("0.0.0.0:50051"));
-
-static const std::string Overview = R"(
-This is an **experimental** interactive tool to process user-provided search
-queries over given symbol collection obtained via clangd-indexer with the help
-of remote index server. The client will connect to remote index server and pass
-it lookup queries.
-)";
-
-class RemoteIndexClient {
-public:
-  RemoteIndexClient(std::shared_ptr<grpc::Channel> Channel)
-      : Stub(remote::Index::NewStub(Channel)) {}
-
-  void lookup(llvm::StringRef ID) {
-    llvm::outs() << "Lookup of symbol with ID " << ID << '\n';
-    remote::LookupRequest Proto;
-    Proto.set_id(ID.str());
-
-    grpc::ClientContext Context;
-    remote::LookupReply Reply;
-    std::unique_ptr<grpc::ClientReader<remote::LookupReply>> Reader(
-        Stub->Lookup(&Context, Proto));
-    while (Reader->Read(&Reply)) {
-      llvm::outs() << Reply.symbol_yaml();
-    }
-    grpc::Status Status = Reader->Finish();
-    if (Status.ok()) {
-      llvm::outs() << "lookupRequest rpc succeeded.\n";
-    } else {
-      llvm::outs() << "lookupRequest rpc failed.\n";
-    }
-  }
-
-private:
-  std::unique_ptr<remote::Index::Stub> Stub;
-};
-
-} // namespace
-} // namespace clangd
-} // namespace clang
-
-int main(int argc, const char *argv[]) {
-  using namespace clang::clangd;
-
-  llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
-  llvm::cl::ResetCommandLineParser(); // We reuse it for REPL commands.
-  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
-
-  RemoteIndexClient IndexClient(
-      grpc::CreateChannel(ServerAddress, grpc::InsecureChannelCredentials()));
-
-  llvm::LineEditor LE("remote-index-client");
-  while (llvm::Optional<std::string> Request = LE.readLine())
-    IndexClient.lookup(std::move(*Request));
-}

diff  --git a/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt
new file mode 100644
index 000000000000..4789a728951c
--- /dev/null
+++ b/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_clang_library(clangdRemoteMarshalling
+  Marshalling.cpp
+
+  LINK_LIBS
+  RemoteIndexProtos
+
+  protobuf
+  clangDaemon
+  )

diff  --git a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
new file mode 100644
index 000000000000..d2ec07136fa5
--- /dev/null
+++ b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
@@ -0,0 +1,99 @@
+//===--- Marshalling.cpp -----------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Marshalling.h"
+#include "Logger.h"
+#include "index/Serialization.h"
+
+namespace clang {
+namespace clangd {
+namespace remote {
+
+clangd::FuzzyFindRequest fromProtobuf(const FuzzyFindRequest *Request) {
+  clangd::FuzzyFindRequest Result;
+  Result.Query = Request->query();
+  for (const auto &Scope : Request->scopes())
+    Result.Scopes.push_back(Scope);
+  Result.AnyScope = Request->any_scope();
+  if (Request->limit())
+    Result.Limit = Request->limit();
+  Result.RestrictForCodeCompletion = Request->resricted_for_code_completion();
+  for (const auto &Path : Request->proximity_paths())
+    Result.ProximityPaths.push_back(Path);
+  for (const auto &Type : Request->preferred_types())
+    Result.ProximityPaths.push_back(Type);
+  return Result;
+}
+
+llvm::Optional<clangd::Symbol> fromProtobuf(const Symbol &Message,
+                                            llvm::UniqueStringSaver *Strings) {
+  auto Result = symbolFromYAML(Message.yaml_serialization(), Strings);
+  if (!Result) {
+    elog("Cannot convert Symbol from Protobuf: {}", Result.takeError());
+    return llvm::None;
+  }
+  return *Result;
+}
+llvm::Optional<clangd::Ref> fromProtobuf(const Ref &Message,
+                                         llvm::UniqueStringSaver *Strings) {
+  auto Result = refFromYAML(Message.yaml_serialization(), Strings);
+  if (!Result) {
+    elog("Cannot convert Ref from Protobuf: {}", Result.takeError());
+    return llvm::None;
+  }
+  return *Result;
+}
+
+LookupRequest toProtobuf(const clangd::LookupRequest &From) {
+  LookupRequest RPCRequest;
+  for (const auto &SymbolID : From.IDs)
+    RPCRequest.add_ids(SymbolID.str());
+  return RPCRequest;
+}
+
+FuzzyFindRequest toProtobuf(const clangd::FuzzyFindRequest &From) {
+  FuzzyFindRequest RPCRequest;
+  RPCRequest.set_query(From.Query);
+  for (const auto &Scope : From.Scopes)
+    RPCRequest.add_scopes(Scope);
+  RPCRequest.set_any_scope(From.AnyScope);
+  if (From.Limit)
+    RPCRequest.set_limit(*From.Limit);
+  RPCRequest.set_resricted_for_code_completion(From.RestrictForCodeCompletion);
+  for (const auto &Path : From.ProximityPaths)
+    RPCRequest.add_proximity_paths(Path);
+  for (const auto &Type : From.PreferredTypes)
+    RPCRequest.add_preferred_types(Type);
+  return RPCRequest;
+}
+
+RefsRequest toProtobuf(const clangd::RefsRequest &From) {
+  RefsRequest RPCRequest;
+  for (const auto &ID : From.IDs)
+    RPCRequest.add_ids(ID.str());
+  RPCRequest.set_filter(static_cast<uint32_t>(From.Filter));
+  if (From.Limit)
+    RPCRequest.set_limit(*From.Limit);
+  return RPCRequest;
+}
+
+Symbol toProtobuf(const clangd::Symbol &From) {
+  Symbol Result;
+  Result.set_yaml_serialization(toYAML(From));
+  return Result;
+}
+
+Ref toProtobuf(const clangd::Ref &From) {
+  Ref Result;
+  Result.set_yaml_serialization(toYAML(From));
+  return Result;
+}
+
+} // namespace remote
+} // namespace clangd
+} // namespace clang

diff  --git a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h
new file mode 100644
index 000000000000..ae58318e3dbb
--- /dev/null
+++ b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h
@@ -0,0 +1,41 @@
+//===--- Marshalling.h -------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Transformations between native Clangd types and Protobuf-generated classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H
+
+#include "Index.grpc.pb.h"
+#include "index/Index.h"
+#include "llvm/Support/StringSaver.h"
+
+namespace clang {
+namespace clangd {
+namespace remote {
+
+clangd::FuzzyFindRequest fromProtobuf(const FuzzyFindRequest *Request);
+llvm::Optional<clangd::Symbol> fromProtobuf(const Symbol &Message,
+                                            llvm::UniqueStringSaver *Strings);
+llvm::Optional<clangd::Ref> fromProtobuf(const Ref &Message,
+                                         llvm::UniqueStringSaver *Strings);
+
+LookupRequest toProtobuf(const clangd::LookupRequest &From);
+FuzzyFindRequest toProtobuf(const clangd::FuzzyFindRequest &From);
+RefsRequest toProtobuf(const clangd::RefsRequest &From);
+
+Ref toProtobuf(const clangd::Ref &From);
+Symbol toProtobuf(const clangd::Symbol &From);
+
+} // namespace remote
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H

diff  --git a/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt
index 7493be1a444f..378ea2946839 100644
--- a/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt
+++ b/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt
@@ -5,7 +5,7 @@ set(LLVM_LINK_COMPONENTS
 add_clang_executable(clangd-index-server
   Server.cpp
   )
-target_compile_definitions(clangd-index-server PRIVATE -DGOOGLE_PROTOBUF_NO_RTTI=1)
+target_compile_definitions(clangd-index-server PRIVATE -D GOOGLE_PROTOBUF_NO_RTTI=1)
 clang_target_link_libraries(clangd-index-server
   PRIVATE
   clangDaemon
@@ -14,7 +14,5 @@ target_link_libraries(clangd-index-server
   PRIVATE
   RemoteIndexProtos
 
-  protobuf
-  grpc++
-  clangDaemon
+  clangdRemoteMarshalling
   )

diff  --git a/clang-tools-extra/clangd/index/remote/server/Server.cpp b/clang-tools-extra/clangd/index/remote/server/Server.cpp
index b7a54b79b6c3..ca35ff7715f0 100644
--- a/clang-tools-extra/clangd/index/remote/server/Server.cpp
+++ b/clang-tools-extra/clangd/index/remote/server/Server.cpp
@@ -8,6 +8,7 @@
 
 #include "index/Index.h"
 #include "index/Serialization.h"
+#include "index/remote/marshalling/Marshalling.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/LineEditor/LineEditor.h"
@@ -16,13 +17,14 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Signals.h"
 
-#include "grpcpp/grpcpp.h"
-#include "grpcpp/health_check_service_interface.h"
+#include <grpcpp/grpcpp.h>
+#include <grpcpp/health_check_service_interface.h>
 
 #include "Index.grpc.pb.h"
 
 namespace clang {
 namespace clangd {
+namespace remote {
 namespace {
 
 static const std::string Overview = R"(
@@ -33,42 +35,80 @@ awaits gRPC lookup requests from the client.
 llvm::cl::opt<std::string> IndexPath(llvm::cl::desc("<INDEX FILE>"),
                                      llvm::cl::Positional, llvm::cl::Required);
 
-llvm::cl::opt<std::string> ServerAddress("server-address",
-                                         llvm::cl::init("0.0.0.0:50051"));
+llvm::cl::opt<std::string> ServerAddress(
+    "server-address", llvm::cl::init("0.0.0.0:50051"),
+    llvm::cl::desc("Address of the invoked server. Defaults to 0.0.0.0:50051"));
 
-std::unique_ptr<SymbolIndex> openIndex(llvm::StringRef Index) {
+std::unique_ptr<clangd::SymbolIndex> openIndex(llvm::StringRef Index) {
   return loadIndex(Index, /*UseIndex=*/true);
 }
 
-class RemoteIndexServer final : public remote::Index::Service {
+class RemoteIndexServer final : public SymbolIndex::Service {
 public:
-  RemoteIndexServer(std::unique_ptr<SymbolIndex> Index)
+  RemoteIndexServer(std::unique_ptr<clangd::SymbolIndex> Index)
       : Index(std::move(Index)) {}
 
 private:
   grpc::Status Lookup(grpc::ServerContext *Context,
-                      const remote::LookupRequest *Request,
-                      grpc::ServerWriter<remote::LookupReply> *Reply) override {
-    llvm::outs() << "Lookup of symbol with ID " << Request->id() << '\n';
-    LookupRequest Req;
-    auto SID = SymbolID::fromStr(Request->id());
-    if (!SID) {
-      llvm::outs() << llvm::toString(SID.takeError()) << "\n";
-      return grpc::Status::CANCELLED;
+                      const LookupRequest *Request,
+                      grpc::ServerWriter<LookupReply> *Reply) override {
+    clangd::LookupRequest Req;
+    for (const auto &ID : Request->ids()) {
+      auto SID = SymbolID::fromStr(StringRef(ID));
+      if (!SID)
+        return grpc::Status::CANCELLED;
+      Req.IDs.insert(*SID);
     }
-    Req.IDs.insert(*SID);
-    Index->lookup(Req, [&](const Symbol &Sym) {
-      remote::LookupReply NextSymbol;
-      NextSymbol.set_symbol_yaml(toYAML(Sym));
-      Reply->Write(NextSymbol);
+    Index->lookup(Req, [&](const clangd::Symbol &Sym) {
+      LookupReply NextMessage;
+      *NextMessage.mutable_stream_result() = toProtobuf(Sym);
+      Reply->Write(NextMessage);
     });
+    LookupReply LastMessage;
+    LastMessage.set_final_result(true);
+    Reply->Write(LastMessage);
     return grpc::Status::OK;
   }
 
-  std::unique_ptr<SymbolIndex> Index;
+  grpc::Status FuzzyFind(grpc::ServerContext *Context,
+                         const FuzzyFindRequest *Request,
+                         grpc::ServerWriter<FuzzyFindReply> *Reply) override {
+    const auto Req = fromProtobuf(Request);
+    bool HasMore = Index->fuzzyFind(Req, [&](const clangd::Symbol &Sym) {
+      FuzzyFindReply NextMessage;
+      *NextMessage.mutable_stream_result() = toProtobuf(Sym);
+      Reply->Write(NextMessage);
+    });
+    FuzzyFindReply LastMessage;
+    LastMessage.set_final_result(HasMore);
+    Reply->Write(LastMessage);
+    return grpc::Status::OK;
+  }
+
+  grpc::Status Refs(grpc::ServerContext *Context, const RefsRequest *Request,
+                    grpc::ServerWriter<RefsReply> *Reply) override {
+    clangd::RefsRequest Req;
+    for (const auto &ID : Request->ids()) {
+      auto SID = SymbolID::fromStr(StringRef(ID));
+      if (!SID)
+        return grpc::Status::CANCELLED;
+      Req.IDs.insert(*SID);
+    }
+    bool HasMore = Index->refs(Req, [&](const clangd::Ref &Reference) {
+      RefsReply NextMessage;
+      *NextMessage.mutable_stream_result() = toProtobuf(Reference);
+      Reply->Write(NextMessage);
+    });
+    RefsReply LastMessage;
+    LastMessage.set_final_result(HasMore);
+    Reply->Write(LastMessage);
+    return grpc::Status::OK;
+  }
+
+  std::unique_ptr<clangd::SymbolIndex> Index;
 };
 
-void runServer(std::unique_ptr<SymbolIndex> Index,
+void runServer(std::unique_ptr<clangd::SymbolIndex> Index,
                const std::string &ServerAddress) {
   RemoteIndexServer Service(std::move(Index));
 
@@ -83,15 +123,16 @@ void runServer(std::unique_ptr<SymbolIndex> Index,
 }
 
 } // namespace
+} // namespace remote
 } // namespace clangd
 } // namespace clang
 
 int main(int argc, char *argv[]) {
-  using namespace clang::clangd;
-  llvm::cl::ParseCommandLineOptions(argc, argv, clang::clangd::Overview);
+  using namespace clang::clangd::remote;
+  llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
 
-  std::unique_ptr<SymbolIndex> Index = openIndex(IndexPath);
+  std::unique_ptr<clang::clangd::SymbolIndex> Index = openIndex(IndexPath);
 
   if (!Index) {
     llvm::outs() << "Failed to open the index.\n";

diff  --git a/clang-tools-extra/clangd/index/remote/unimplemented/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/unimplemented/CMakeLists.txt
new file mode 100644
index 000000000000..aebe4e674ab7
--- /dev/null
+++ b/clang-tools-extra/clangd/index/remote/unimplemented/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../)
+# When compiled without Remote Index support, the real implementation index
+# client is not present. Users will get a notification about this when trying
+# to connect to remote index server instance.
+add_clang_library(clangdRemoteIndex
+  UnimplementedClient.cpp
+
+  LINK_LIBS
+  clangDaemon
+  )

diff  --git a/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp b/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp
new file mode 100644
index 000000000000..725f0e472c3a
--- /dev/null
+++ b/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp
@@ -0,0 +1,23 @@
+//===--- UnimplementedClient.cpp ---------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Logger.h"
+#include "index/remote/Client.h"
+
+namespace clang {
+namespace clangd {
+namespace remote {
+
+std::unique_ptr<clangd::SymbolIndex> getClient(llvm::StringRef Address) {
+  elog("Can't create SymbolIndex client without Remote Index support.");
+  return nullptr;
+}
+
+} // namespace remote
+} // namespace clangd
+} // namespace clang


        


More information about the cfe-commits mailing list