15#include "llvm/Support/Path.h"
16#include "llvm/Support/raw_ostream.h"
17#include "gtest/gtest.h"
18#include <condition_variable>
26 std::unique_lock<std::mutex> Lock(Mu);
28 [
this] {
return Value.has_value(); })) {
29 ADD_FAILURE() <<
"No result from call after 10 seconds!";
30 return llvm::json::Value(
nullptr);
32 auto Res = std::move(*
Value);
38 auto ExpValue =
take();
40 ADD_FAILURE() <<
"takeValue(): " << llvm::toString(ExpValue.takeError());
41 return llvm::json::Value(
nullptr);
43 return std::move(*ExpValue);
46void LSPClient::CallResult::set(llvm::Expected<llvm::json::Value> V) {
47 std::lock_guard<std::mutex> Lock(Mu);
49 ADD_FAILURE() <<
"Multiple replies";
50 llvm::consumeError(V.takeError());
59 ADD_FAILURE() << llvm::toString(
Value->takeError());
63static void logBody(llvm::StringRef
Method, llvm::json::Value V,
bool Send) {
65 vlog(
"{0} {1}: {2:2}", Send ?
"<<<" :
">>>",
Method, V);
71 std::lock_guard<std::mutex> Lock(Mu);
72 unsigned ID = CallResults.size();
73 CallResults.emplace_back();
74 return {ID, &CallResults.back()};
79 std::lock_guard<std::mutex> Lock(Mu);
80 Actions.push(std::move(
Action));
85 std::vector<llvm::json::Value> Result;
87 std::lock_guard<std::mutex> Lock(Mu);
88 std::swap(Result, Notifications[
Method]);
94 void reply(llvm::json::Value ID,
95 llvm::Expected<llvm::json::Value> V)
override {
98 std::lock_guard<std::mutex> Lock(Mu);
99 if (
auto I = ID.getAsInteger()) {
100 if (*I >= 0 && *I <
static_cast<int64_t
>(CallResults.size())) {
101 CallResults[*I].set(std::move(V));
105 ADD_FAILURE() <<
"Invalid reply to ID " << ID;
106 llvm::consumeError(std::move(V).takeError());
109 void notify(llvm::StringRef Method, llvm::json::Value V)
override {
110 logBody(Method, V,
false);
111 std::lock_guard<std::mutex> Lock(Mu);
112 Notifications[Method].push_back(std::move(V));
115 void call(llvm::StringRef Method, llvm::json::Value Params,
116 llvm::json::Value ID)
override {
117 logBody(Method, Params,
false);
118 ADD_FAILURE() <<
"Unexpected server->client call " <<
Method;
121 llvm::Error loop(MessageHandler &H)
override {
122 std::unique_lock<std::mutex> Lock(Mu);
124 CV.wait(Lock, [&] {
return !Actions.empty(); });
125 if (!Actions.front())
126 return llvm::Error::success();
127 auto Action = std::move(Actions.front());
136 std::deque<CallResult> CallResults;
137 std::queue<std::function<void(Transport::MessageHandler &)>> Actions;
138 std::condition_variable CV;
139 llvm::StringMap<std::vector<llvm::json::Value>> Notifications;
146 llvm::json::Value Params) {
147 auto Slot = T->addCallSlot();
151 H.onCall(
Method, std::move(Params), ID);
160 H.onNotify(
Method, std::move(Params));
164std::vector<llvm::json::Value>
166 return T->takeNotifications(
Method);
173using Obj = llvm::json::Object;
177 if (!llvm::sys::path::is_absolute(
Path))
187 "textDocument/didOpen",
189 Obj{{
"uri",
uri(
Path)}, {
"text", Content}, {
"languageId",
"cpp"}}}});
192 notify(
"textDocument/didChange",
194 {
"contentChanges", llvm::json::Array{
Obj{{
"text", Content}}}}});
202std::optional<std::vector<llvm::json::Value>>
206 for (
const auto &
Notification : llvm::reverse(Notifications)) {
207 if (
const auto *PubDiagsParams =
Notification.getAsObject()) {
208 auto U = PubDiagsParams->getString(
"uri");
209 auto *D = PubDiagsParams->getArray(
"diagnostics");
211 ADD_FAILURE() <<
"Bad PublishDiagnosticsParams: " << PubDiagsParams;
215 return std::vector<llvm::json::Value>(D->begin(), D->end());
llvm::Expected< llvm::json::Value > take()
llvm::json::Value takeValue()
std::vector< llvm::json::Value > takeNotifications(llvm::StringRef Method)
void enqueue(std::function< void(MessageHandler &)> Action)
std::pair< llvm::json::Value, CallResult * > addCallSlot()
CallResult & call(llvm::StringRef Method, llvm::json::Value Params)
std::vector< llvm::json::Value > takeNotifications(llvm::StringRef Method)
static llvm::json::Value uri(llvm::StringRef Path)
static llvm::json::Value documentID(llvm::StringRef Path)
void didClose(llvm::StringRef Path)
void notify(llvm::StringRef Method, llvm::json::Value Params)
void didOpen(llvm::StringRef Path, llvm::StringRef Content)
void didChange(llvm::StringRef Path, llvm::StringRef Content)
std::optional< std::vector< llvm::json::Value > > diagnostics(llvm::StringRef Path)
A threadsafe flag that is initially clear.
std::string Path
A typedef to represent a file path.
void vlog(const char *Fmt, Ts &&... Vals)
static void logBody(llvm::StringRef Method, llvm::json::Value V, bool Send)
std::string testPath(PathRef File, llvm::sys::path::Style Style)
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
Deadline timeoutSeconds(std::optional< double > Seconds)
Makes a deadline from a timeout in seconds. None means wait forever.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.