LSP for solcjs

This commit is contained in:
chriseth
2022-03-15 11:48:28 +01:00
committed by Christian Parpart
parent c6ac1625bd
commit e1947faa1a
7 changed files with 245 additions and 30 deletions
+3
View File
@@ -7,6 +7,9 @@ if (EMSCRIPTEN)
solidity_alloc
solidity_free
solidity_reset
solidity_lsp_start
solidity_lsp_send
solidity_lsp_send_receive
)
# Specify which functions to export in soljson.js.
# Note that additional Emscripten-generated methods needed by solc-js are
+57
View File
@@ -24,6 +24,8 @@
#include <libsolc/libsolc.h>
#include <libsolidity/interface/StandardCompiler.h>
#include <libsolidity/interface/Version.h>
#include <libsolidity/lsp/LanguageServer.h>
#include <libsolidity/lsp/Transport.h>
#include <libyul/YulString.h>
#include <cstdlib>
@@ -112,6 +114,9 @@ string compile(string _input, CStyleReadFileCallback _readCallback, void* _readC
return compiler.compile(move(_input));
}
unique_ptr<lsp::MockTransport> languageServerTransport;
unique_ptr<lsp::LanguageServer> languageServer;
}
extern "C"
@@ -132,6 +137,56 @@ extern char* solidity_compile(char const* _input, CStyleReadFileCallback _readCa
return solidityAllocations.emplace_back(compile(_input, _readCallback, _readContext)).data();
}
extern int solidity_lsp_start(CStyleReadFileCallback /*TODO(pr) _readCallback*/, void* /*_readContext*/) noexcept
{
if (languageServer || languageServerTransport)
return -1;
languageServerTransport = make_unique<lsp::MockTransport>();
languageServer = make_unique<lsp::LanguageServer>(*languageServerTransport);
return 0;
}
extern int solidity_lsp_send(char const* _input) noexcept
{
if (!languageServer)
return -1;
if (languageServer->isRunning())
return -2;
solAssert(languageServerTransport, "");
std::string errors{};
Json::Value jsonMessage{};
if (!jsonParseStrict(_input, jsonMessage, &errors))
return -3;
languageServerTransport->appendInput(jsonMessage);
languageServer->runIteration();
return 0;
}
extern char const* solidity_try_receive() noexcept
{
if (!languageServerTransport)
return "";
optional<Json::Value> messageJson = languageServerTransport->popOutput();
if (!messageJson)
return "";
return solidityAllocations.emplace_back(jsonPrettyPrint(messageJson.value())).data();
}
extern char const* solidity_lsp_send_receive(char const* _input) noexcept
{
if (solidity_lsp_send(_input) < 0)
return "";
return solidity_try_receive();
}
extern char* solidity_alloc(size_t _size) noexcept
{
try
@@ -156,5 +211,7 @@ extern void solidity_reset() noexcept
// can be freed here.
yul::YulStringRepository::reset();
solidityAllocations.clear();
languageServer.reset();
languageServerTransport.reset();
}
}
+34
View File
@@ -90,6 +90,40 @@ void solidity_free(char* _data) SOLC_NOEXCEPT;
/// @returns A pointer to the result. The pointer returned must be freed by the caller using solidity_free() or solidity_reset().
char* solidity_compile(char const* _input, CStyleReadFileCallback _readCallback, void* _readContext) SOLC_NOEXCEPT;
/// @TODO the biggest problem here is that the callback has to be synchronous.
/// With "compile" we would just record requested files and trigger a recompile later,
/// so we might need a way to trigger a recompile.
/// Switch into LSP mode. Can be undone using solidity_reset().
///
/// @returns 0 on success and -1 on failure. A failure can only happen due to mis-use of the API,
/// such as, the LSP mode has been already initiated.
int solidity_lsp_start(CStyleReadFileCallback _readCallback, void* _readContext) SOLC_NOEXCEPT;
/// Sends a single JSON-RPC message to the LSP server.
/// This message must not include any HTTP headers but only hold the payload.
///
/// @retval 0 Success.
/// @retval -1 Server not initialized.
/// @retval -2 Server not running (e.g. termination initiated).
/// @retval -3 Could not parse JSON RPC message.
int solidity_lsp_send(char const* _input) SOLC_NOEXCEPT;
/// Tries to pop a pending message from the LSP server.
/// @returns either an empty string if not possible
/// (e.g. no message available or server shut down) or a stringified JSON response message.
char const* solidity_try_receive() SOLC_NOEXCEPT;
/// Send one or more JSON-RPC messages to the LSP (including the HTTP headers),
/// expecting a response.
/// If the input is empty, just checks for a pending response.
/// @returns JSON-RPC message (inculding HTTP headers), can be empty (or nullptr).
/// If the result is not null, it has to be freed by the caller using solidity_free.
///
/// This can cause the callback provided in solidity_lsp to be invoked.
/// Should only be called after having called solidity_lsp.
char const *solidity_lsp_send_receive(char const* _input) SOLC_NOEXCEPT;
/// Frees up any allocated memory.
///
/// NOTE: the pointer returned by solidity_compile as well as any other pointer retrieved via solidity_alloc()