Created
November 29, 2021 11:48
-
-
Save christianparpart/e300b2c67353811fe1141f641633213c to your computer and use it in GitHub Desktop.
Patch for reviving LSP TCP listener.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 6cccca59014f49c52faaf19f8f2e9f102f519884 | |
Author: Christian Parpart <[email protected]> | |
Date: Mon Nov 29 12:46:52 2021 +0100 | |
Revert "Drop LSP TCP listener." | |
This reverts commit 5b61209d11fe046dfc57e4c74762c3da9dfc0e3d. | |
diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt | |
index 3e3594766..51b77d29b 100644 | |
--- a/solc/CMakeLists.txt | |
+++ b/solc/CMakeLists.txt | |
@@ -5,6 +5,19 @@ set(libsolcli_sources | |
set(libsolcli_libs solidity Boost::boost Boost::program_options) | |
+if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") | |
+ # Since we do not want to depend on networking code on production binaries, | |
+ # this feature is only available when creating a debug build. | |
+ # the LSP's TCP listener is exclusively used more convenient debugging. | |
+ option(SOLC_LSP_TCP "Solidity LSP: Enables TCP listener support (should only be eanbled for debugging purposes)." OFF) | |
+ if(SOLC_LSP_TCP) | |
+ set(libsolcli_defines SOLC_LSP_TCP=1) | |
+ list(APPEND libsolcli_sources LSPTCPTransport.cpp LSPTCPTransport.h) | |
+ find_package(Threads REQUIRED) | |
+ list(APPEND libsolcli_libs Threads::Threads) | |
+ endif() | |
+endif() | |
+ | |
add_library(solcli ${libsolcli_sources}) | |
target_compile_definitions(solcli PUBLIC ${libsolcli_defines}) | |
target_link_libraries(solcli PUBLIC ${libsolcli_libs}) | |
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp | |
index ba1140f98..1bfa60f95 100644 | |
--- a/solc/CommandLineInterface.cpp | |
+++ b/solc/CommandLineInterface.cpp | |
@@ -25,6 +25,10 @@ | |
#include "license.h" | |
+#if defined(SOLC_LSP_TCP) | |
+#include <solc/LSPTCPTransport.h> | |
+#endif | |
+ | |
#include "solidity/BuildInfo.h" | |
#include <libsolidity/interface/Version.h> | |
@@ -902,6 +906,15 @@ void CommandLineInterface::handleAst() | |
void CommandLineInterface::serveLSP() | |
{ | |
+#if defined(SOLC_LSP_TCP) | |
+ if (m_options.lsp.port.has_value()) | |
+ { | |
+ lsp::LSPTCPTransport transport(m_options.lsp.port.value()); | |
+ lsp::LanguageServer{transport}.run(); | |
+ return; | |
+ } | |
+#endif | |
+ | |
lsp::JSONTransport transport; | |
lsp::LanguageServer{transport}.run(); | |
} | |
diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp | |
index 73f6a1e3a..caa1fdfbd 100644 | |
--- a/solc/CommandLineParser.cpp | |
+++ b/solc/CommandLineParser.cpp | |
@@ -1261,6 +1261,19 @@ bool CommandLineParser::processArgs() | |
} | |
} | |
+#if defined(SOLC_LSP_TCP) | |
+ if (m_args.count("lsp-port")) | |
+ { | |
+ unsigned const port = m_args.at("lsp-port").as<unsigned>(); | |
+ if (port > 0xFFFF) | |
+ { | |
+ serr() << "LSP port number not in valid port range " << port << '.' << endl; | |
+ return false; | |
+ } | |
+ m_options.lsp.port = port; | |
+ } | |
+#endif | |
+ | |
if (m_args.count(g_strModelCheckerContracts)) | |
{ | |
string contractsStr = m_args[g_strModelCheckerContracts].as<string>(); | |
diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h | |
index d4909a109..4bf0be764 100644 | |
--- a/solc/CommandLineParser.h | |
+++ b/solc/CommandLineParser.h | |
@@ -227,6 +227,13 @@ struct CommandLineOptions | |
std::optional<std::string> yulSteps; | |
} optimizer; | |
+#if defined(SOLC_LSP_TCP) | |
+ struct | |
+ { | |
+ std::optional<unsigned short> port; | |
+ } lsp; | |
+#endif | |
+ | |
struct | |
{ | |
bool initialize = false; | |
diff --git a/solc/LSPTCPTransport.cpp b/solc/LSPTCPTransport.cpp | |
new file mode 100644 | |
index 000000000..9c765fa0c | |
--- /dev/null | |
+++ b/solc/LSPTCPTransport.cpp | |
@@ -0,0 +1,96 @@ | |
+/* | |
+ 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 <http://www.gnu.org/licenses/>. | |
+*/ | |
+// SPDX-License-Identifier: GPL-3.0 | |
+#include <solc/LSPTCPTransport.h> | |
+ | |
+#include <libsolutil/JSON.h> | |
+#include <fmt/format.h> | |
+ | |
+#include <optional> | |
+#include <string> | |
+#include <iostream> | |
+ | |
+namespace solidity::lsp | |
+{ | |
+ | |
+using std::nullopt; | |
+using std::optional; | |
+using std::string_view; | |
+ | |
+using namespace std::string_literals; | |
+ | |
+LSPTCPTransport::LSPTCPTransport(unsigned short _port, std::string const& _address): | |
+ m_io_service(), | |
+ m_endpoint(boost::asio::ip::make_address(_address), _port), | |
+ m_acceptor(m_io_service), | |
+ m_stream(), | |
+ m_jsonTransport() | |
+{ | |
+ m_acceptor.open(m_endpoint.protocol()); | |
+ m_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); | |
+ m_acceptor.bind(m_endpoint); | |
+ m_acceptor.listen(); | |
+} | |
+ | |
+bool LSPTCPTransport::closed() const noexcept | |
+{ | |
+ return !m_acceptor.is_open(); | |
+} | |
+ | |
+optional<Json::Value> LSPTCPTransport::receive() | |
+{ | |
+ auto const clientClosed = [&]() { return !m_stream || !m_stream.value().good() || m_stream.value().eof(); }; | |
+ | |
+ if (clientClosed()) | |
+ { | |
+ m_stream.emplace(m_acceptor.accept()); | |
+ if (clientClosed()) | |
+ return nullopt; | |
+ | |
+ m_jsonTransport.emplace(m_stream.value(), m_stream.value()); | |
+ } | |
+ | |
+ if (auto value = m_jsonTransport.value().receive(); value.has_value()) | |
+ return value; | |
+ | |
+ if (clientClosed()) | |
+ { | |
+ m_jsonTransport.reset(); | |
+ m_stream.reset(); | |
+ } | |
+ return nullopt; | |
+} | |
+ | |
+void LSPTCPTransport::notify(std::string _method, Json::Value _params) | |
+{ | |
+ if (m_jsonTransport.has_value()) | |
+ m_jsonTransport.value().notify(move(_method), _params); | |
+} | |
+ | |
+void LSPTCPTransport::reply(MessageID _id, Json::Value _result) | |
+{ | |
+ if (m_jsonTransport.has_value()) | |
+ m_jsonTransport.value().reply(_id, _result); | |
+} | |
+ | |
+void LSPTCPTransport::error(MessageID _id, ErrorCode _code, std::string _message) | |
+{ | |
+ if (m_jsonTransport.has_value()) | |
+ m_jsonTransport.value().error(_id, _code, move(_message)); | |
+} | |
+ | |
+} | |
diff --git a/solc/LSPTCPTransport.h b/solc/LSPTCPTransport.h | |
new file mode 100644 | |
index 000000000..485849906 | |
--- /dev/null | |
+++ b/solc/LSPTCPTransport.h | |
@@ -0,0 +1,46 @@ | |
+/* | |
+ 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 <http://www.gnu.org/licenses/>. | |
+*/ | |
+// SPDX-License-Identifier: GPL-3.0 | |
+#pragma once | |
+ | |
+#include <libsolidity/lsp/Transport.h> | |
+ | |
+#include <boost/asio.hpp> | |
+#include <optional> | |
+ | |
+namespace solidity::lsp | |
+{ | |
+ | |
+class LSPTCPTransport: public lsp::Transport { | |
+public: | |
+ explicit LSPTCPTransport(unsigned short _port, std::string const& _address = "127.0.0.1"); | |
+ | |
+ bool closed() const noexcept override; | |
+ std::optional<Json::Value> receive() override; | |
+ void notify(std::string _method, Json::Value _params) override; | |
+ void reply(lsp::MessageID _id, Json::Value _result) override; | |
+ void error(lsp::MessageID _id, lsp::ErrorCode _code, std::string _message) override; | |
+ | |
+private: | |
+ boost::asio::io_service m_io_service; | |
+ boost::asio::ip::tcp::endpoint m_endpoint; | |
+ boost::asio::ip::tcp::acceptor m_acceptor; | |
+ std::optional<boost::asio::ip::tcp::iostream> m_stream; | |
+ std::optional<lsp::JSONTransport> m_jsonTransport; | |
+}; | |
+ | |
+} // end namespace |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment