diff --git a/server/src/RescriptEditorSupport.ts b/server/src/RescriptEditorSupport.ts index d4d36f58a..cdc559e8f 100644 --- a/server/src/RescriptEditorSupport.ts +++ b/server/src/RescriptEditorSupport.ts @@ -2,7 +2,7 @@ import { fileURLToPath } from "url"; import { RequestMessage } from "vscode-languageserver"; import * as utils from "./utils"; import * as path from "path"; -import { exec } from "child_process"; +import { execSync } from "child_process"; import fs from "fs"; let binaryPath = path.join( @@ -27,67 +27,74 @@ let findExecutable = (uri: string) => { } }; -export function runDumpCommand( - msg: RequestMessage, - onResult: ( - result: { hover?: string; definition?: { uri?: string; range: any } } | null - ) => void -) { +type dumpCommandResult = { + hover?: string; + definition?: { uri?: string; range: any }; +}; +export function runDumpCommand(msg: RequestMessage): dumpCommandResult | null { let executable = findExecutable(msg.params.textDocument.uri); if (executable == null) { - onResult(null); - } else { - let command = - executable.binaryPathQuoted + - " dump " + - executable.filePathQuoted + - ":" + - msg.params.position.line + - ":" + - msg.params.position.character; - exec(command, { cwd: executable.cwd }, function (_error, stdout, _stderr) { - let result = JSON.parse(stdout); - if (result && result[0]) { - onResult(result[0]); - } else { - onResult(null); - } - }); + return null; + } + + let command = + executable.binaryPathQuoted + + " dump " + + executable.filePathQuoted + + ":" + + msg.params.position.line + + ":" + + msg.params.position.character; + + try { + let stdout = execSync(command, { cwd: executable.cwd }); + let parsed = JSON.parse(stdout.toString()); + if (parsed && parsed[0]) { + return parsed[0]; + } else { + return null; + } + } catch (error) { + // TODO: @cristianoc any exception possible? + return null; } } +type completionCommandResult = [{ label: string }]; export function runCompletionCommand( msg: RequestMessage, - code: string, - onResult: (result: [{ label: string }] | null) => void -) { + code: string +): completionCommandResult | null { let executable = findExecutable(msg.params.textDocument.uri); if (executable == null) { - onResult(null); - } else { - let tmpname = utils.createFileInTempDir(); - fs.writeFileSync(tmpname, code, { encoding: "utf-8" }); + return null; + } + let tmpname = utils.createFileInTempDir(); + fs.writeFileSync(tmpname, code, { encoding: "utf-8" }); - let command = - executable.binaryPathQuoted + - " complete " + - executable.filePathQuoted + - ":" + - msg.params.position.line + - ":" + - msg.params.position.character + - " " + - tmpname; + let command = + executable.binaryPathQuoted + + " complete " + + executable.filePathQuoted + + ":" + + msg.params.position.line + + ":" + + msg.params.position.character + + " " + + tmpname; - exec(command, { cwd: executable.cwd }, function (_error, stdout, _stderr) { - // async close is fine. We don't use this file name again - fs.unlink(tmpname, () => null); - let result = JSON.parse(stdout); - if (result && result[0]) { - onResult(result); - } else { - onResult(null); - } - }); + try { + let stdout = execSync(command, { cwd: executable.cwd }); + let parsed = JSON.parse(stdout.toString()); + if (parsed && parsed[0]) { + return parsed; + } else { + return null; + } + } catch (error) { + // TODO: @cristianoc any exception possible? + return null; + } finally { + fs.unlink(tmpname, () => null); } } diff --git a/server/src/server.ts b/server/src/server.ts index 3d3cf899e..7af63880a 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -332,19 +332,16 @@ process.on("message", (msg: m.Message) => { // type Hover = {contents: MarkedString | MarkedString[] | MarkupContent, range?: Range} result: null, }; - runDumpCommand(msg, (result) => { - if (result && result.hover) { - let hoverResponse: m.ResponseMessage = { - ...emptyHoverResponse, - result: { - contents: result.hover, - }, - }; - process.send!(hoverResponse); - } else { - process.send!(emptyHoverResponse); - } - }); + let result = runDumpCommand(msg); + if (result !== null && result.hover != null) { + let hoverResponse: m.ResponseMessage = { + ...emptyHoverResponse, + result: { contents: result.hover }, + }; + process.send!(hoverResponse); + } else { + process.send!(emptyHoverResponse); + } } else if (msg.method === p.DefinitionRequest.method) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition let emptyDefinitionResponse: m.ResponseMessage = { @@ -355,20 +352,19 @@ process.on("message", (msg: m.Message) => { // error: code and message set in case an exception happens during the definition request. }; - runDumpCommand(msg, (result) => { - if (result && result.definition) { - let definitionResponse: m.ResponseMessage = { - ...emptyDefinitionResponse, - result: { - uri: result.definition.uri || msg.params.textDocument.uri, - range: result.definition.range, - }, - }; - process.send!(definitionResponse); - } else { - process.send!(emptyDefinitionResponse); - } - }); + let result = runDumpCommand(msg); + if (result !== null && result.definition != null) { + let definitionResponse: m.ResponseMessage = { + ...emptyDefinitionResponse, + result: { + uri: result.definition.uri || msg.params.textDocument.uri, + range: result.definition.range, + }, + }; + process.send!(definitionResponse); + } else { + process.send!(emptyDefinitionResponse); + } } else if (msg.method === p.CompletionRequest.method) { let emptyCompletionResponse: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, @@ -376,17 +372,16 @@ process.on("message", (msg: m.Message) => { result: null, }; let code = getOpenedFileContent(msg.params.textDocument.uri); - runCompletionCommand(msg, code, (result) => { - if (result) { - let definitionResponse: m.ResponseMessage = { - ...emptyCompletionResponse, - result: result, - }; - process.send!(definitionResponse); - } else { - process.send!(emptyCompletionResponse); - } - }); + let result = runCompletionCommand(msg, code); + if (result === null) { + process.send!(emptyCompletionResponse); + } else { + let definitionResponse: m.ResponseMessage = { + ...emptyCompletionResponse, + result: result, + }; + process.send!(definitionResponse); + } } else if (msg.method === p.DocumentFormattingRequest.method) { // technically, a formatting failure should reply with the error. Sadly // the LSP alert box for these error replies sucks (e.g. doesn't actually