clang-tools  8.0.0
ClangdXPCTestClient.cpp
Go to the documentation of this file.
1 #include "xpc/Conversion.h"
2 #include "clang/Basic/LLVM.h"
3 #include "llvm/ADT/SmallString.h"
4 #include "llvm/Support/LineIterator.h"
5 #include "llvm/Support/MemoryBuffer.h"
6 #include "llvm/Support/Path.h"
7 #include "llvm/Support/raw_ostream.h"
8 #include <dlfcn.h>
9 #include <stdio.h>
10 #include <string>
11 #include <xpc/xpc.h>
12 
13 typedef const char *(*clangd_xpc_get_bundle_identifier_t)(void);
14 
15 using namespace llvm;
16 using namespace clang;
17 
18 std::string getLibraryPath() {
19  Dl_info info;
20  if (dladdr((void *)(uintptr_t)getLibraryPath, &info) == 0)
21  llvm_unreachable("Call to dladdr() failed");
22  llvm::SmallString<128> LibClangPath;
23  LibClangPath = llvm::sys::path::parent_path(
24  llvm::sys::path::parent_path(info.dli_fname));
25  llvm::sys::path::append(LibClangPath, "lib", "ClangdXPC.framework",
26  "ClangdXPC");
27  return LibClangPath.str();
28 }
29 
30 static void dumpXPCObject(xpc_object_t Object, llvm::raw_ostream &OS) {
31  xpc_type_t Type = xpc_get_type(Object);
32  if (Type == XPC_TYPE_DICTIONARY) {
33  json::Value Json = clang::clangd::xpcToJson(Object);
34  OS << Json;
35  } else {
36  OS << "<UNKNOWN>";
37  }
38 }
39 
40 int main(int argc, char *argv[]) {
41  // Open the ClangdXPC dylib in the framework.
42  std::string LibPath = getLibraryPath();
43  void *dlHandle = dlopen(LibPath.c_str(), RTLD_LOCAL | RTLD_FIRST);
44  if (!dlHandle)
45  return 1;
46 
47  // Lookup the XPC service bundle name, and launch it.
50  dlHandle, "clangd_xpc_get_bundle_identifier");
51  xpc_connection_t conn = xpc_connection_create(
52  clangd_xpc_get_bundle_identifier(), dispatch_get_main_queue());
53 
54  // Dump the XPC events.
55  xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
56  if (event == XPC_ERROR_CONNECTION_INVALID) {
57  llvm::errs() << "Received XPC_ERROR_CONNECTION_INVALID.";
58  exit(EXIT_SUCCESS);
59  }
60  if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
61  llvm::errs() << "Received XPC_ERROR_CONNECTION_INTERRUPTED.";
62  exit(EXIT_SUCCESS);
63  }
64 
65  dumpXPCObject(event, llvm::outs());
66  llvm::outs() << "\n";
67  });
68 
69  xpc_connection_resume(conn);
70 
71  // Read the input to determine the things to send to clangd.
72  llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> Stdin =
73  llvm::MemoryBuffer::getSTDIN();
74  if (!Stdin) {
75  llvm::errs() << "Failed to get STDIN!\n";
76  return 1;
77  }
78  for (llvm::line_iterator It(**Stdin, /*SkipBlanks=*/true,
79  /*CommentMarker=*/'#');
80  !It.is_at_eof(); ++It) {
81  StringRef Line = *It;
82  if (auto Request = json::parse(Line)) {
83  xpc_object_t Object = clangd::jsonToXpc(*Request);
84  xpc_connection_send_message(conn, Object);
85  } else {
86  llvm::errs() << llvm::Twine("JSON parse error: ")
87  << llvm::toString(Request.takeError());
88  return 1;
89  }
90  }
91 
92  dispatch_main();
93 
94  // dispatch_main() doesn't return
95  return EXIT_FAILURE;
96 }
const char *(* clangd_xpc_get_bundle_identifier_t)(void)
const char * clangd_xpc_get_bundle_identifier()
Returns the bundle identifier of the Clangd XPC service.
Definition: ClangdXPC.cpp:3
Some operations such as code completion produce a set of candidates.
int main(int argc, char *argv[])
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
std::string getLibraryPath()
json::Value xpcToJson(const xpc_object_t &XPCObject)
Definition: Conversion.cpp:27
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static void dumpXPCObject(xpc_object_t Object, llvm::raw_ostream &OS)
xpc_object_t jsonToXpc(const json::Value &JSON)
Definition: Conversion.cpp:21