1 //===-- LSPClient.h - Helper for ClangdLSPServer tests ----------*- 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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_LSPCLIENT_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_LSPCLIENT_H
11 
12 #include <llvm/ADT/Optional.h>
13 #include <llvm/Support/Error.h>
14 #include <llvm/Support/JSON.h>
15 #include <condition_variable>
16 #include <deque>
17 #include <mutex>
18 
19 namespace clang {
20 namespace clangd {
21 class Transport;
22 
23 // A client library for talking to ClangdLSPServer in tests.
24 // Manages serialization of messages, pairing requests/repsonses, and implements
25 // the Transport abstraction.
26 class LSPClient {
27   class TransportImpl;
28   std::unique_ptr<TransportImpl> T;
29 
30 public:
31   // Represents the result of an LSP call: a promise for a result or error.
32   class CallResult {
33   public:
34     ~CallResult();
35     // Blocks up to 10 seconds for the result to be ready.
36     // Records a test failure if there was no reply.
37     llvm::Expected<llvm::json::Value> take();
38     // Like take(), but records a test failure if the result was an error.
39     llvm::json::Value takeValue();
40 
41   private:
42     // Should be called once to provide the value.
43     void set(llvm::Expected<llvm::json::Value> V);
44 
45     llvm::Optional<llvm::Expected<llvm::json::Value>> Value;
46     std::mutex Mu;
47     std::condition_variable CV;
48 
49     friend TransportImpl; // Calls set().
50   };
51 
52   LSPClient();
53   ~LSPClient();
54   LSPClient(LSPClient &&) = delete;
55   LSPClient &operator=(LSPClient &&) = delete;
56 
57   // Enqueue an LSP method call, returns a promise for the reply. Threadsafe.
58   CallResult &call(llvm::StringRef Method, llvm::json::Value Params);
59   // Enqueue an LSP notification. Threadsafe.
60   void notify(llvm::StringRef Method, llvm::json::Value Params);
61   // Returns matching notifications since the last call to takeNotifications.
62   std::vector<llvm::json::Value> takeNotifications(llvm::StringRef Method);
63   // The transport is shut down after all pending messages are sent.
64   void stop();
65 
66   // Shorthand for common LSP methods. Relative paths are passed to testPath().
67   static llvm::json::Value uri(llvm::StringRef Path);
68   static llvm::json::Value documentID(llvm::StringRef Path);
69   void didOpen(llvm::StringRef Path, llvm::StringRef Content);
70   void didChange(llvm::StringRef Path, llvm::StringRef Content);
71   void didClose(llvm::StringRef Path);
72   // Blocks until the server is idle (using the 'sync' protocol extension).
73   void sync();
74   // sync()s to ensure pending diagnostics arrive, and returns the newest set.
75   llvm::Optional<std::vector<llvm::json::Value>>
76   diagnostics(llvm::StringRef Path);
77 
78   // Get the transport used to connect this client to a ClangdLSPServer.
79   Transport &transport();
80 
81 private:
82 };
83 
84 } // namespace clangd
85 } // namespace clang
86 
87 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_LSPCLIENT_H
88