brintos

brintos / llvm-project-archived public Read only

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