/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 #pragma once #include #include #include #include #include #include #include #include #include namespace solidity::lsp { using MessageID = Json::Value; enum class TraceValue { Off, Messages, Verbose }; enum class ErrorCode { // Defined by JSON RPC ParseError = -32700, MethodNotFound = -32601, InvalidParams = -32602, InternalError = -32603, // Defined by the protocol. ServerNotInitialized = -32002, RequestFailed = -32803 }; /** * Error exception used to bail out on errors in the LSP function-call handlers. */ class RequestError: public util::Exception { public: explicit RequestError(ErrorCode _code): m_code{_code} { } ErrorCode code() const noexcept { return m_code; } private: ErrorCode m_code; }; #define lspAssert(condition, errorCode, errorMessage) \ if (!(condition)) \ { \ BOOST_THROW_EXCEPTION( \ RequestError(errorCode) << \ util::errinfo_comment(errorMessage) \ ); \ } /** * Transport layer API * * The transport layer API is abstracted to make LSP more testable as well as * this way it could be possible to support other transports (HTTP for example) easily. */ class Transport { public: virtual ~Transport() = default; virtual bool closed() const noexcept = 0; virtual std::optional receive() = 0; virtual void notify(std::string _method, Json::Value _params) = 0; virtual void reply(MessageID _id, Json::Value _result) = 0; virtual void error(MessageID _id, ErrorCode _code, std::string _message) = 0; void trace(std::string _message, Json::Value _extra = Json::nullValue); TraceValue traceValue() const noexcept { return m_logTrace; } void setTrace(TraceValue _value) noexcept { m_logTrace = _value; } private: TraceValue m_logTrace = TraceValue::Off; }; /** * LSP Transport using JSON-RPC over iostreams. */ class IOStreamTransport: public Transport { public: /// Constructs a standard stream transport layer. /// /// @param _in for example std::cin (stdin) /// @param _out for example std::cout (stdout) IOStreamTransport(std::istream& _in, std::ostream& _out); // Constructs a JSON transport using standard I/O streams. IOStreamTransport(); bool closed() const noexcept override; std::optional receive() override; void notify(std::string _method, Json::Value _params) override; void reply(MessageID _id, Json::Value _result) override; void error(MessageID _id, ErrorCode _code, std::string _message) override; protected: /// Sends an arbitrary raw message to the client. /// /// Used by the notify/reply/error function family. virtual void send(Json::Value _message, MessageID _id = Json::nullValue); /// Parses header section from the client including message-delimiting empty line. std::optional> parseHeaders(); private: std::istream& m_input; std::ostream& m_output; }; }