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