brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · 7e8c8e2 Raw
179 lines · cpp
1//===--- SyncAPI.cpp - Sync version of ClangdServer's API --------*- 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 "SyncAPI.h"10#include "Protocol.h"11#include "index/Index.h"12#include <optional>13 14namespace clang {15namespace clangd {16 17void runAddDocument(ClangdServer &Server, PathRef File,18                    llvm::StringRef Contents, llvm::StringRef Version,19                    WantDiagnostics WantDiags, bool ForceRebuild) {20  Server.addDocument(File, Contents, Version, WantDiags, ForceRebuild);21  if (!Server.blockUntilIdleForTest())22    llvm_unreachable("not idle after addDocument");23}24 25namespace {26/// A helper that waits for async callbacks to fire and exposes their result in27/// the output variable. Intended to be used in the following way:28///    T Result;29///    someAsyncFunc(Param1, Param2, /*Callback=*/capture(Result));30template <typename T> struct CaptureProxy {31  CaptureProxy(std::optional<T> &Target) : Target(&Target) { assert(!Target); }32 33  CaptureProxy(const CaptureProxy &) = delete;34  CaptureProxy &operator=(const CaptureProxy &) = delete;35  // We need move ctor to return a value from the 'capture' helper.36  CaptureProxy(CaptureProxy &&Other) : Target(Other.Target) {37    Other.Target = nullptr;38  }39  CaptureProxy &operator=(CaptureProxy &&) = delete;40 41  operator llvm::unique_function<void(T)>() && {42    assert(!Future.valid() && "conversion to callback called multiple times");43    Future = Promise.get_future();44    return [Promise = std::move(Promise)](T Value) mutable {45      Promise.set_value(std::make_shared<T>(std::move(Value)));46    };47  }48 49  ~CaptureProxy() {50    if (!Target)51      return;52    assert(Future.valid() && "conversion to callback was not called");53    assert(!Target->has_value());54    Target->emplace(std::move(*Future.get()));55  }56 57private:58  std::optional<T> *Target;59  // Using shared_ptr to workaround compilation errors with MSVC.60  // MSVC only allows default-constructible and copyable objects as future<>61  // arguments.62  std::promise<std::shared_ptr<T>> Promise;63  std::future<std::shared_ptr<T>> Future;64};65 66template <typename T> CaptureProxy<T> capture(std::optional<T> &Target) {67  return CaptureProxy<T>(Target);68}69} // namespace70 71llvm::Expected<CodeCompleteResult>72runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,73                clangd::CodeCompleteOptions Opts) {74  std::optional<llvm::Expected<CodeCompleteResult>> Result;75  Server.codeComplete(File, Pos, Opts, capture(Result));76  return std::move(*Result);77}78 79llvm::Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server,80                                               PathRef File, Position Pos,81                                               MarkupKind DocumentationFormat) {82  std::optional<llvm::Expected<SignatureHelp>> Result;83  Server.signatureHelp(File, Pos, DocumentationFormat, capture(Result));84  return std::move(*Result);85}86 87llvm::Expected<std::vector<LocatedSymbol>>88runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos) {89  std::optional<llvm::Expected<std::vector<LocatedSymbol>>> Result;90  Server.locateSymbolAt(File, Pos, capture(Result));91  return std::move(*Result);92}93 94llvm::Expected<std::vector<DocumentHighlight>>95runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {96  std::optional<llvm::Expected<std::vector<DocumentHighlight>>> Result;97  Server.findDocumentHighlights(File, Pos, capture(Result));98  return std::move(*Result);99}100 101llvm::Expected<RenameResult> runRename(ClangdServer &Server, PathRef File,102                                       Position Pos, llvm::StringRef NewName,103                                       const RenameOptions &RenameOpts) {104  std::optional<llvm::Expected<RenameResult>> Result;105  Server.rename(File, Pos, NewName, RenameOpts, capture(Result));106  return std::move(*Result);107}108 109llvm::Expected<RenameResult>110runPrepareRename(ClangdServer &Server, PathRef File, Position Pos,111                 std::optional<std::string> NewName,112                 const RenameOptions &RenameOpts) {113  std::optional<llvm::Expected<RenameResult>> Result;114  Server.prepareRename(File, Pos, NewName, RenameOpts, capture(Result));115  return std::move(*Result);116}117 118llvm::Expected<tooling::Replacements>119runFormatFile(ClangdServer &Server, PathRef File,120              const std::vector<Range> &Rngs) {121  std::optional<llvm::Expected<tooling::Replacements>> Result;122  Server.formatFile(File, Rngs, capture(Result));123  return std::move(*Result);124}125 126SymbolSlab runFuzzyFind(const SymbolIndex &Index, llvm::StringRef Query) {127  FuzzyFindRequest Req;128  Req.Query = std::string(Query);129  Req.AnyScope = true;130  return runFuzzyFind(Index, Req);131}132 133SymbolSlab runFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req) {134  SymbolSlab::Builder Builder;135  Index.fuzzyFind(Req, [&](const Symbol &Sym) { Builder.insert(Sym); });136  return std::move(Builder).build();137}138 139RefSlab getRefs(const SymbolIndex &Index, SymbolID ID) {140  RefsRequest Req;141  Req.IDs = {ID};142  RefSlab::Builder Slab;143  Index.refs(Req, [&](const Ref &S) { Slab.insert(ID, S); });144  return std::move(Slab).build();145}146 147llvm::Expected<std::vector<SelectionRange>>148runSemanticRanges(ClangdServer &Server, PathRef File,149                  const std::vector<Position> &Pos) {150  std::optional<llvm::Expected<std::vector<SelectionRange>>> Result;151  Server.semanticRanges(File, Pos, capture(Result));152  return std::move(*Result);153}154 155llvm::Expected<std::optional<clangd::Path>>156runSwitchHeaderSource(ClangdServer &Server, PathRef File) {157  std::optional<llvm::Expected<std::optional<clangd::Path>>> Result;158  Server.switchSourceHeader(File, capture(Result));159  return std::move(*Result);160}161 162llvm::Error runCustomAction(ClangdServer &Server, PathRef File,163                            llvm::function_ref<void(InputsAndAST)> Action) {164  llvm::Error Result = llvm::Error::success();165  Notification Done;166  Server.customAction(File, "Custom", [&](llvm::Expected<InputsAndAST> AST) {167    if (!AST)168      Result = AST.takeError();169    else170      Action(*AST);171    Done.notify();172  });173  Done.wait();174  return Result;175}176 177} // namespace clangd178} // namespace clang179