//===--- JSONTransport.cpp - sending and receiving LSP messages over JSON -===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Tools/lsp-server-support/Transport.h" #include "mlir/Support/ToolUtilities.h" #include "mlir/Tools/lsp-server-support/Logging.h" #include "mlir/Tools/lsp-server-support/Protocol.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Errno.h" #include "llvm/Support/Error.h" #include <optional> #include <system_error> #include <utility> usingnamespacemlir; usingnamespacemlir::lsp; //===----------------------------------------------------------------------===// // Reply //===----------------------------------------------------------------------===// namespace { /// Function object to reply to an LSP call. /// Each instance must be called exactly once, otherwise: /// - if there was no reply, an error reply is sent /// - if there were multiple replies, only the first is sent class Reply { … }; } // namespace Reply::Reply(const llvm::json::Value &id, llvm::StringRef method, JSONTransport &transport, std::mutex &transportOutputMutex) : … { … } Reply::Reply(Reply &&other) : … { … } void Reply::operator()(llvm::Expected<llvm::json::Value> reply) { … } //===----------------------------------------------------------------------===// // MessageHandler //===----------------------------------------------------------------------===// bool MessageHandler::onNotify(llvm::StringRef method, llvm::json::Value value) { … } bool MessageHandler::onCall(llvm::StringRef method, llvm::json::Value params, llvm::json::Value id) { … } bool MessageHandler::onReply(llvm::json::Value id, llvm::Expected<llvm::json::Value> result) { … } //===----------------------------------------------------------------------===// // JSONTransport //===----------------------------------------------------------------------===// /// Encode the given error as a JSON object. static llvm::json::Object encodeError(llvm::Error error) { … } /// Decode the given JSON object into an error. llvm::Error decodeError(const llvm::json::Object &o) { … } void JSONTransport::notify(StringRef method, llvm::json::Value params) { … } void JSONTransport::call(StringRef method, llvm::json::Value params, llvm::json::Value id) { … } void JSONTransport::reply(llvm::json::Value id, llvm::Expected<llvm::json::Value> result) { … } llvm::Error JSONTransport::run(MessageHandler &handler) { … } void JSONTransport::sendMessage(llvm::json::Value msg) { … } bool JSONTransport::handleMessage(llvm::json::Value msg, MessageHandler &handler) { … } /// Tries to read a line up to and including \n. /// If failing, feof(), ferror(), or shutdownRequested() will be set. LogicalResult readLine(std::FILE *in, SmallVectorImpl<char> &out) { … } // Returns std::nullopt when: // - ferror(), feof(), or shutdownRequested() are set. // - Content-Length is missing or empty (protocol error) LogicalResult JSONTransport::readStandardMessage(std::string &json) { … } /// For lit tests we support a simplified syntax: /// - messages are delimited by '// -----' on a line by itself /// - lines starting with // are ignored. /// This is a testing path, so favor simplicity over performance here. /// When returning failure: feof(), ferror(), or shutdownRequested() will be /// set. LogicalResult JSONTransport::readDelimitedMessage(std::string &json) { … }