clang-tools  7.0.0
JSONRPCDispatcher.h
Go to the documentation of this file.
1 //===--- JSONRPCDispatcher.h - Main JSON parser entry point -----*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
11 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
12 
13 #include "Logger.h"
14 #include "Protocol.h"
15 #include "Trace.h"
16 #include "clang/Basic/LLVM.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/Support/JSON.h"
20 #include <iosfwd>
21 #include <mutex>
22 
23 namespace clang {
24 namespace clangd {
25 
26 /// Encapsulates output and logs streams and provides thread-safe access to
27 /// them.
28 class JSONOutput : public Logger {
29  // FIXME(ibiryukov): figure out if we can shrink the public interface of
30  // JSONOutput now that we pass Context everywhere.
31 public:
32  JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
33  Logger::Level MinLevel, llvm::raw_ostream *InputMirror = nullptr,
34  bool Pretty = false)
35  : Pretty(Pretty), MinLevel(MinLevel), Outs(Outs), Logs(Logs),
36  InputMirror(InputMirror) {}
37 
38  /// Emit a JSONRPC message.
39  void writeMessage(const llvm::json::Value &Result);
40 
41  /// Write a line to the logging stream.
42  void log(Level, const llvm::formatv_object_base &Message) override;
43 
44  /// Mirror \p Message into InputMirror stream. Does nothing if InputMirror is
45  /// null.
46  /// Unlike other methods of JSONOutput, mirrorInput is not thread-safe.
47  void mirrorInput(const Twine &Message);
48 
49  // Whether output should be pretty-printed.
50  const bool Pretty;
51 
52 private:
53  Logger::Level MinLevel;
54  llvm::raw_ostream &Outs;
55  llvm::raw_ostream &Logs;
56  llvm::raw_ostream *InputMirror;
57 
58  std::mutex StreamMutex;
59 };
60 
61 /// Sends a successful reply.
62 /// Current context must derive from JSONRPCDispatcher::Handler.
63 void reply(llvm::json::Value &&Result);
64 /// Sends an error response to the client, and logs it.
65 /// Current context must derive from JSONRPCDispatcher::Handler.
66 void replyError(ErrorCode Code, const llvm::StringRef &Message);
67 /// Sends a request to the client.
68 /// Current context must derive from JSONRPCDispatcher::Handler.
69 void call(llvm::StringRef Method, llvm::json::Value &&Params);
70 
71 /// Main JSONRPC entry point. This parses the JSONRPC "header" and calls the
72 /// registered Handler for the method received.
74 public:
75  // A handler responds to requests for a particular method name.
76  using Handler = std::function<void(const llvm::json::Value &)>;
77 
78  /// Create a new JSONRPCDispatcher. UnknownHandler is called when an unknown
79  /// method is received.
80  JSONRPCDispatcher(Handler UnknownHandler)
81  : UnknownHandler(std::move(UnknownHandler)) {}
82 
83  /// Registers a Handler for the specified Method.
84  void registerHandler(StringRef Method, Handler H);
85 
86  /// Parses a JSONRPC message and calls the Handler for it.
87  bool call(const llvm::json::Value &Message, JSONOutput &Out) const;
88 
89 private:
90  llvm::StringMap<Handler> Handlers;
91  Handler UnknownHandler;
92 };
93 
94 /// Controls the way JSON-RPC messages are encoded (both input and output).
96  /// Encoding per the LSP specification, with mandatory Content-Length header.
98  /// Messages are delimited by a '---' line. Comment lines start with #.
100 };
101 
102 /// Parses input queries from LSP client (coming from \p In) and runs call
103 /// method of \p Dispatcher for each query.
104 /// After handling each query checks if \p IsDone is set true and exits the loop
105 /// if it is.
106 /// Input stream(\p In) must be opened in binary mode to avoid preliminary
107 /// replacements of \r\n with \n.
108 /// We use C-style FILE* for reading as std::istream has unclear interaction
109 /// with signals, which are sent by debuggers on some OSs.
110 void runLanguageServerLoop(std::FILE *In, JSONOutput &Out,
112  JSONRPCDispatcher &Dispatcher, bool &IsDone);
113 
114 } // namespace clangd
115 } // namespace clang
116 
117 #endif
JSONStreamStyle
Controls the way JSON-RPC messages are encoded (both input and output).
Encapsulates output and logs streams and provides thread-safe access to them.
void log(Level, const llvm::formatv_object_base &Message) override
Write a line to the logging stream.
JSONRPCDispatcher(Handler UnknownHandler)
Create a new JSONRPCDispatcher.
JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs, Logger::Level MinLevel, llvm::raw_ostream *InputMirror=nullptr, bool Pretty=false)
void replyError(ErrorCode Code, const llvm::StringRef &Message)
Sends an error response to the client, and logs it.
Interface to allow custom logging in clangd.
Definition: Logger.h:23
void mirrorInput(const Twine &Message)
Mirror Message into InputMirror stream.
Messages are delimited by a &#39;—&#39; line. Comment lines start with #.
Main JSONRPC entry point.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::function< void(const llvm::json::Value &)> Handler
Encoding per the LSP specification, with mandatory Content-Length header.
void call(llvm::StringRef Method, llvm::json::Value &&Params)
Sends a request to the client.
void writeMessage(const llvm::json::Value &Result)
Emit a JSONRPC message.
void reply(llvm::json::Value &&Result)
Sends a successful reply.
void runLanguageServerLoop(std::FILE *In, JSONOutput &Out, JSONStreamStyle InputStyle, JSONRPCDispatcher &Dispatcher, bool &IsDone)
Parses input queries from LSP client (coming from In) and runs call method of Dispatcher for each que...
static llvm::cl::opt< JSONStreamStyle > InputStyle("input-style", llvm::cl::desc("Input JSON stream encoding"), llvm::cl::values(clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"), clEnumValN(JSONStreamStyle::Delimited, "delimited", "messages delimited by --- lines, with # comment support")), llvm::cl::init(JSONStreamStyle::Standard))