blob: 62b68caef1f8e7eb1b434c64b10e5811da42dc46 [file] [log] [blame]
Ilya Biryukovcd5eb002018-02-12 11:37:28 +00001//===--- SyncAPI.cpp - Sync version of ClangdServer's API --------*- C++-*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===---------------------------------------------------------------------===//
9#include "SyncAPI.h"
10
11namespace clang {
12namespace clangd {
13
Sam McCall7363a2f2018-03-05 17:28:54 +000014void runAddDocument(ClangdServer &Server, PathRef File, StringRef Contents) {
15 Server.addDocument(File, Contents);
16 if (!Server.blockUntilIdleForTest())
17 llvm_unreachable("not idle after addDocument");
18}
19
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000020namespace {
21/// A helper that waits for async callbacks to fire and exposes their result in
22/// the output variable. Intended to be used in the following way:
23/// T Result;
24/// someAsyncFunc(Param1, Param2, /*Callback=*/capture(Result));
25template <typename T> struct CaptureProxy {
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000026 CaptureProxy(llvm::Optional<T> &Target) : Target(&Target) {
27 assert(!Target.hasValue());
28 }
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000029
30 CaptureProxy(const CaptureProxy &) = delete;
31 CaptureProxy &operator=(const CaptureProxy &) = delete;
32 // We need move ctor to return a value from the 'capture' helper.
33 CaptureProxy(CaptureProxy &&Other) : Target(Other.Target) {
34 Other.Target = nullptr;
35 }
36 CaptureProxy &operator=(CaptureProxy &&) = delete;
37
38 operator UniqueFunction<void(T)>() && {
39 assert(!Future.valid() && "conversion to callback called multiple times");
40 Future = Promise.get_future();
Sam McCall091557d2018-02-23 07:54:17 +000041 return Bind(
Ilya Biryukov40bf17c2018-02-15 15:41:49 +000042 [](std::promise<std::shared_ptr<T>> Promise, T Value) {
43 Promise.set_value(std::make_shared<T>(std::move(Value)));
44 },
45 std::move(Promise));
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000046 }
47
48 ~CaptureProxy() {
49 if (!Target)
50 return;
51 assert(Future.valid() && "conversion to callback was not called");
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000052 assert(!Target->hasValue());
Ilya Biryukov40bf17c2018-02-15 15:41:49 +000053 Target->emplace(std::move(*Future.get()));
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000054 }
55
56private:
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000057 llvm::Optional<T> *Target;
Ilya Biryukov40bf17c2018-02-15 15:41:49 +000058 // Using shared_ptr to workaround compilation errors with MSVC.
59 // MSVC only allows default-construcitble and copyable objects as future<>
60 // arguments.
61 std::promise<std::shared_ptr<T>> Promise;
62 std::future<std::shared_ptr<T>> Future;
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000063};
64
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000065template <typename T> CaptureProxy<T> capture(llvm::Optional<T> &Target) {
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000066 return CaptureProxy<T>(Target);
67}
68} // namespace
69
Sam McCalldb3ea4c2018-02-27 17:15:50 +000070Tagged<CompletionList> runCodeComplete(ClangdServer &Server, PathRef File,
71 Position Pos,
72 clangd::CodeCompleteOptions Opts) {
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000073 llvm::Optional<Tagged<CompletionList>> Result;
Sam McCalldb3ea4c2018-02-27 17:15:50 +000074 Server.codeComplete(File, Pos, Opts, capture(Result));
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000075 return std::move(*Result);
76}
77
78llvm::Expected<Tagged<SignatureHelp>>
Sam McCalldb3ea4c2018-02-27 17:15:50 +000079runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos) {
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000080 llvm::Optional<llvm::Expected<Tagged<SignatureHelp>>> Result;
Sam McCalldb3ea4c2018-02-27 17:15:50 +000081 Server.signatureHelp(File, Pos, capture(Result));
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000082 return std::move(*Result);
83}
84
85llvm::Expected<Tagged<std::vector<Location>>>
86runFindDefinitions(ClangdServer &Server, PathRef File, Position Pos) {
87 llvm::Optional<llvm::Expected<Tagged<std::vector<Location>>>> Result;
88 Server.findDefinitions(File, Pos, capture(Result));
89 return std::move(*Result);
90}
91
92llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
93runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
94 llvm::Optional<llvm::Expected<Tagged<std::vector<DocumentHighlight>>>> Result;
95 Server.findDocumentHighlights(File, Pos, capture(Result));
96 return std::move(*Result);
97}
98
99llvm::Expected<std::vector<tooling::Replacement>>
100runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName) {
101 llvm::Optional<llvm::Expected<std::vector<tooling::Replacement>>> Result;
102 Server.rename(File, Pos, NewName, capture(Result));
103 return std::move(*Result);
104}
105
106std::string runDumpAST(ClangdServer &Server, PathRef File) {
107 llvm::Optional<std::string> Result;
108 Server.dumpAST(File, capture(Result));
109 return std::move(*Result);
Ilya Biryukovcd5eb002018-02-12 11:37:28 +0000110}
111
112} // namespace clangd
113} // namespace clang