blob: 0816f540b047b0a2b5861d819d8b714b9eb4e455 [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//
Kirill Bobyrev8e35f1e2018-08-14 16:03:32 +00008//===----------------------------------------------------------------------===//
9
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000010#include "SyncAPI.h"
11
Sam McCallc008af62018-10-20 15:30:37 +000012using namespace llvm;
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000013namespace clang {
14namespace clangd {
15
Ilya Biryukovbec5df22018-03-14 17:08:41 +000016void runAddDocument(ClangdServer &Server, PathRef File, StringRef Contents,
Ilya Biryukovb10ef472018-06-13 09:20:41 +000017 WantDiagnostics WantDiags) {
18 Server.addDocument(File, Contents, WantDiags);
Sam McCall7363a2f2018-03-05 17:28:54 +000019 if (!Server.blockUntilIdleForTest())
20 llvm_unreachable("not idle after addDocument");
21}
22
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000023namespace {
24/// A helper that waits for async callbacks to fire and exposes their result in
25/// the output variable. Intended to be used in the following way:
26/// T Result;
27/// someAsyncFunc(Param1, Param2, /*Callback=*/capture(Result));
28template <typename T> struct CaptureProxy {
Sam McCallc008af62018-10-20 15:30:37 +000029 CaptureProxy(Optional<T> &Target) : Target(&Target) {
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000030 assert(!Target.hasValue());
31 }
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000032
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
Sam McCallc008af62018-10-20 15:30:37 +000041 operator unique_function<void(T)>() && {
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000042 assert(!Future.valid() && "conversion to callback called multiple times");
43 Future = Promise.get_future();
Sam McCall091557d2018-02-23 07:54:17 +000044 return Bind(
Ilya Biryukov40bf17c2018-02-15 15:41:49 +000045 [](std::promise<std::shared_ptr<T>> Promise, T Value) {
46 Promise.set_value(std::make_shared<T>(std::move(Value)));
47 },
48 std::move(Promise));
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000049 }
50
51 ~CaptureProxy() {
52 if (!Target)
53 return;
54 assert(Future.valid() && "conversion to callback was not called");
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000055 assert(!Target->hasValue());
Ilya Biryukov40bf17c2018-02-15 15:41:49 +000056 Target->emplace(std::move(*Future.get()));
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000057 }
58
59private:
Sam McCallc008af62018-10-20 15:30:37 +000060 Optional<T> *Target;
Ilya Biryukov40bf17c2018-02-15 15:41:49 +000061 // Using shared_ptr to workaround compilation errors with MSVC.
62 // MSVC only allows default-construcitble and copyable objects as future<>
63 // arguments.
64 std::promise<std::shared_ptr<T>> Promise;
65 std::future<std::shared_ptr<T>> Future;
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000066};
67
Sam McCallc008af62018-10-20 15:30:37 +000068template <typename T> CaptureProxy<T> capture(Optional<T> &Target) {
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000069 return CaptureProxy<T>(Target);
70}
71} // namespace
72
Sam McCallc008af62018-10-20 15:30:37 +000073Expected<CodeCompleteResult> runCodeComplete(ClangdServer &Server, PathRef File,
74 Position Pos,
75 clangd::CodeCompleteOptions Opts) {
76 Optional<Expected<CodeCompleteResult>> Result;
Sam McCalldb3ea4c2018-02-27 17:15:50 +000077 Server.codeComplete(File, Pos, Opts, capture(Result));
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000078 return std::move(*Result);
79}
80
Sam McCallc008af62018-10-20 15:30:37 +000081Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server, PathRef File,
82 Position Pos) {
83 Optional<Expected<SignatureHelp>> Result;
Sam McCalldb3ea4c2018-02-27 17:15:50 +000084 Server.signatureHelp(File, Pos, capture(Result));
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000085 return std::move(*Result);
86}
87
Sam McCallc008af62018-10-20 15:30:37 +000088Expected<std::vector<Location>> runFindDefinitions(ClangdServer &Server,
89 PathRef File, Position Pos) {
90 Optional<Expected<std::vector<Location>>> Result;
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000091 Server.findDefinitions(File, Pos, capture(Result));
92 return std::move(*Result);
93}
94
Sam McCallc008af62018-10-20 15:30:37 +000095Expected<std::vector<DocumentHighlight>>
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000096runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
Sam McCallc008af62018-10-20 15:30:37 +000097 Optional<Expected<std::vector<DocumentHighlight>>> Result;
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +000098 Server.findDocumentHighlights(File, Pos, capture(Result));
99 return std::move(*Result);
100}
101
Sam McCallc008af62018-10-20 15:30:37 +0000102Expected<std::vector<tooling::Replacement>>
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +0000103runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName) {
Sam McCallc008af62018-10-20 15:30:37 +0000104 Optional<Expected<std::vector<tooling::Replacement>>> Result;
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +0000105 Server.rename(File, Pos, NewName, capture(Result));
106 return std::move(*Result);
107}
108
109std::string runDumpAST(ClangdServer &Server, PathRef File) {
Sam McCallc008af62018-10-20 15:30:37 +0000110 Optional<std::string> Result;
Ilya Biryukov2c5e8e82018-02-15 13:15:47 +0000111 Server.dumpAST(File, capture(Result));
112 return std::move(*Result);
Ilya Biryukovcd5eb002018-02-12 11:37:28 +0000113}
114
Sam McCallc008af62018-10-20 15:30:37 +0000115Expected<std::vector<SymbolInformation>>
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000116runWorkspaceSymbols(ClangdServer &Server, StringRef Query, int Limit) {
Sam McCallc008af62018-10-20 15:30:37 +0000117 Optional<Expected<std::vector<SymbolInformation>>> Result;
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000118 Server.workspaceSymbols(Query, Limit, capture(Result));
119 return std::move(*Result);
120}
121
Sam McCallc008af62018-10-20 15:30:37 +0000122Expected<std::vector<SymbolInformation>>
Marc-Andre Laperle1be69702018-07-05 19:35:01 +0000123runDocumentSymbols(ClangdServer &Server, PathRef File) {
Sam McCallc008af62018-10-20 15:30:37 +0000124 Optional<Expected<std::vector<SymbolInformation>>> Result;
Marc-Andre Laperle1be69702018-07-05 19:35:01 +0000125 Server.documentSymbols(File, capture(Result));
126 return std::move(*Result);
127}
128
Sam McCall8dc9dbb2018-10-15 13:34:10 +0000129SymbolSlab runFuzzyFind(const SymbolIndex &Index, StringRef Query) {
130 FuzzyFindRequest Req;
131 Req.Query = Query;
132 return runFuzzyFind(Index, Req);
133}
134
135SymbolSlab runFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req) {
136 SymbolSlab::Builder Builder;
137 Index.fuzzyFind(Req, [&](const Symbol &Sym) { Builder.insert(Sym); });
138 return std::move(Builder).build();
139}
140
Ilya Biryukovcd5eb002018-02-12 11:37:28 +0000141} // namespace clangd
142} // namespace clang