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