diff --git a/README.md b/README.md index b1378a57..46e9f7a6 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,71 @@ The low-level API is as follows: For examples how to use them, please refer to the README of the above mentioned solc-js releases. +#### Language Server Mode + +Since version 0.8.11, the solidity compiler natively supports the +language server protocol. With solc-js, you can now use it as follows: + +```javascript +var solc = require('solc'); + +// Callback to be invoked when additional files have to be opened during +// source code analysis stage. +// +// This function behaves similar to the compilation file reader callback. +function fileReadCallback(path) +{ + if ('path' === 'file:///project/lib.sol') { + return { + contents: 'library L { function f() internal returns (uint) { return 7; } }'; + }; + } + else + return { error: 'File not found' }; +} + +// Put solcjs into LSP mode. +// Needs to be called only once before the actual LSP I/O calls. +solc.lspStart(fileReadCallback); + +// Send some LSP JSON-RPC message and optionally receive a reply. +var lspInitializationMessage = { + 'jsonrpc': '2.0', + 'method': 'initialize', + 'params': { + 'rootUri': 'file:///project/', + 'capabilities': { + 'textDocument': { + 'publishDiagnostics': {'relatedInformation': true} + }, + 'workspace': { + 'applyEdit': true, + 'configuration': true, + 'didChangeConfiguration': {'dynamicRegistration': true}, + 'workspaceEdit': {'documentChanges': true}, + 'workspaceFolders': true + } + } + } +}; +solc.lspSendReceive(JSON.stringify(lspInitializationMessage))); +solc.lspSendReceive(JSON.stringify({'jsonrpc': '2.0', 'method': 'initialized'})); + +// Now, with the LSP server, being set up the following +// can be called as often as needed. +function lspRoundtrip(jsonRpcInputObject) +{ + return JSON.parse(solc.lspSendReceive(JSON.stringify(jsonRpcInputObject))); +} +``` + +This is a low level API endpoint for use by language server clients, +such as Visual Studio Code, or any other editor. +In order to know what you can pass in and what can come out, +it is highly recommended to have a look at: + + https://microsoft.github.io/language-server-protocol/specification + ### Using with Electron **Note:** diff --git a/wrapper.ts b/wrapper.ts index 36c18d74..691832df 100755 --- a/wrapper.ts +++ b/wrapper.ts @@ -92,6 +92,25 @@ function setupMethods (soljson) { }; }; + let lspStart = null; + if ('_solidity_lsp_start' in soljson) { + const wrappedLspStart = soljson.cwrap('solidity_lsp_start', 'int', []); + lspStart = function (callbacks) { + return runWithCallbacks(callbacks, wrappedLspStart, []); + }; + } + + let lspSendReceive = null; + if ('_solidity_lsp_send_receive' in soljson) { + const wrappedLspSendReceive = soljson.cwrap('solidity_lsp_send_receive', 'string', ['string']); + lspSendReceive = function (input: String, callbacks) { + // We are reusing the `runWithCallbacks` function that was supposed to + // only receive _solidity_compile as second parameter. + // I may be wrong, but that should work analogous. + return runWithCallbacks(callbacks, wrappedLspSendReceive, [input]); + }; + } + // This calls compile() with args || cb const runWithCallbacks = function (callbacks, compile, args) { if (callbacks) { @@ -324,6 +343,8 @@ function setupMethods (soljson) { importCallback: compileJSONCallback !== null || compileStandard !== null, nativeStandardJSON: compileStandard !== null }, + lspStart: lspStart, + lspSendReceive: lspSendReceive, compile: compileStandardWrapper, // Loads the compiler of the given version from the github repository // instead of from the local filesystem.