15 #include "llvm/Support/Path.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include "gtest/gtest.h"
18 #include <condition_variable>
25 std::unique_lock<std::mutex> Lock(Mu);
27 [
this] {
return Value.hasValue(); })) {
28 ADD_FAILURE() <<
"No result from call after 10 seconds!";
31 auto Res = std::move(*Value);
37 auto ExpValue =
take();
39 ADD_FAILURE() <<
"takeValue(): " <<
llvm::toString(ExpValue.takeError());
42 return std::move(*ExpValue);
45 void LSPClient::CallResult::set(llvm::Expected<llvm::json::Value> V) {
46 std::lock_guard<std::mutex> Lock(Mu);
48 ADD_FAILURE() <<
"Multiple replies";
49 llvm::consumeError(V.takeError());
57 if (Value && !*Value) {
64 vlog(
"{0} {1}: {2:2}", Send ?
"<<<" :
">>>",
Method, V);
70 std::lock_guard<std::mutex> Lock(Mu);
71 unsigned ID = CallResults.size();
72 CallResults.emplace_back();
73 return {
ID, &CallResults.back()};
78 std::lock_guard<std::mutex> Lock(Mu);
79 Actions.push(std::move(
Action));
84 std::vector<llvm::json::Value> Result;
86 std::lock_guard<std::mutex> Lock(Mu);
87 std::swap(Result, Notifications[
Method]);
94 llvm::Expected<llvm::json::Value> V)
override {
97 std::lock_guard<std::mutex> Lock(Mu);
98 if (
auto I =
ID.getAsInteger()) {
99 if (*I >= 0 && *I <
static_cast<int64_t
>(CallResults.size())) {
100 CallResults[*I].set(std::move(V));
104 ADD_FAILURE() <<
"Invalid reply to ID " <<
ID;
105 llvm::consumeError(std::move(V).takeError());
110 std::lock_guard<std::mutex> Lock(Mu);
111 Notifications[Method].push_back(std::move(V));
116 logBody(Method, Params,
false);
117 ADD_FAILURE() <<
"Unexpected server->client call " <<
Method;
120 llvm::Error loop(MessageHandler &H)
override {
121 std::unique_lock<std::mutex> Lock(Mu);
123 CV.wait(Lock, [&] {
return !Actions.empty(); });
124 if (!Actions.front())
125 return llvm::Error::success();
126 auto Action = std::move(Actions.front());
135 std::deque<CallResult> CallResults;
136 std::queue<std::function<void(Transport::MessageHandler &)>> Actions;
137 std::condition_variable CV;
138 llvm::StringMap<std::vector<llvm::json::Value>> Notifications;
146 auto Slot = T->addCallSlot();
150 H.onCall(
Method, std::move(Params),
ID);
159 H.onNotify(
Method, std::move(Params));
163 std::vector<llvm::json::Value>
165 return T->takeNotifications(
Method);
172 using Obj = llvm::json::Object;
176 if (!llvm::sys::path::is_absolute(
Path))
186 "textDocument/didOpen",
188 Obj{{
"uri",
uri(
Path)}, {
"text", Content}, {
"languageId",
"cpp"}}}});
191 notify(
"textDocument/didChange",
193 {
"contentChanges", llvm::json::Array{
Obj{{
"text", Content}}}}});
201 llvm::Optional<std::vector<llvm::json::Value>>
205 for (
const auto &
Notification : llvm::reverse(Notifications)) {
206 if (
const auto *PubDiagsParams =
Notification.getAsObject()) {
207 auto U = PubDiagsParams->getString(
"uri");
208 auto *
D = PubDiagsParams->getArray(
"diagnostics");
210 ADD_FAILURE() <<
"Bad PublishDiagnosticsParams: " << PubDiagsParams;
214 return std::vector<llvm::json::Value>(
D->begin(),
D->end());