Skip to content

Commit 9bbacb4

Browse files
Merge pull request #14 from rescript-lang/runDumpCommand
Hook up command from rescript-editor-support.
2 parents 63b37a0 + c42f6e2 commit 9bbacb4

5 files changed

+149
-15
lines changed
13.8 MB
Binary file not shown.
20.6 MB
Binary file not shown.

server/src/RescriptEditorSupport.ts

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { fileURLToPath } from "url";
2+
import { RequestMessage } from "vscode-languageserver";
3+
import * as utils from "./utils";
4+
import * as path from "path";
5+
import { exec } from "child_process";
6+
import * as tmp from "tmp";
7+
import fs from "fs";
8+
9+
let binaryPath = path.join(
10+
path.dirname(__dirname),
11+
process.platform,
12+
"rescript-editor-support.exe"
13+
);
14+
15+
export let binaryExists = fs.existsSync(binaryPath);
16+
17+
let findExecutable = (uri: string) => {
18+
let filePath = fileURLToPath(uri);
19+
let projectRootPath = utils.findProjectRootOfFile(filePath);
20+
if (projectRootPath == null || !binaryExists) {
21+
return null;
22+
} else {
23+
return { binaryPath, filePath, cwd: projectRootPath };
24+
}
25+
};
26+
27+
export function runDumpCommand(
28+
msg: RequestMessage,
29+
onResult: (
30+
result: { hover?: string; definition?: { uri?: string; range: any } } | null
31+
) => void
32+
) {
33+
let executable = findExecutable(msg.params.textDocument.uri);
34+
if (executable == null) {
35+
onResult(null);
36+
} else {
37+
let command =
38+
executable.binaryPath +
39+
" dump " +
40+
executable.filePath +
41+
":" +
42+
msg.params.position.line +
43+
":" +
44+
msg.params.position.character;
45+
exec(command, { cwd: executable.cwd }, function (_error, stdout, _stderr) {
46+
let result = JSON.parse(stdout);
47+
if (result && result[0]) {
48+
onResult(result[0]);
49+
} else {
50+
onResult(null);
51+
}
52+
});
53+
}
54+
}
55+
56+
export function runCompletionCommand(
57+
msg: RequestMessage,
58+
code: string,
59+
onResult: (result: [{ label: string }] | null) => void
60+
) {
61+
let executable = findExecutable(msg.params.textDocument.uri);
62+
if (executable == null) {
63+
onResult(null);
64+
} else {
65+
let tmpobj = tmp.fileSync();
66+
let tmpname = tmpobj.name;
67+
fs.writeFileSync(tmpname, code, { encoding: "utf-8" });
68+
69+
let command =
70+
executable.binaryPath +
71+
" complete " +
72+
executable.filePath +
73+
":" +
74+
msg.params.position.line +
75+
":" +
76+
msg.params.position.character +
77+
" " +
78+
tmpname;
79+
80+
exec(command, { cwd: executable.cwd }, function (_error, stdout, _stderr) {
81+
tmpobj.removeCallback();
82+
let result = JSON.parse(stdout);
83+
if (result && result[0]) {
84+
onResult(result);
85+
} else {
86+
onResult(null);
87+
}
88+
});
89+
}
90+
}

server/src/server.ts

+59-15
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ import * as chokidar from "chokidar";
2020
import { assert } from "console";
2121
import { fileURLToPath } from "url";
2222
import { ChildProcess } from "child_process";
23+
import {
24+
binaryExists,
25+
runDumpCommand,
26+
runCompletionCommand,
27+
} from "./RescriptEditorSupport";
2328

2429
// https://microsoft.github.io/language-server-protocol/specification#initialize
2530
// According to the spec, there could be requests before the 'initialize' request. Link in comment tells how to handle them.
@@ -270,8 +275,11 @@ process.on("message", (msg: m.Message) => {
270275
// TODO: incremental sync?
271276
textDocumentSync: v.TextDocumentSyncKind.Full,
272277
documentFormattingProvider: true,
273-
hoverProvider: true,
274-
definitionProvider: true,
278+
hoverProvider: binaryExists,
279+
definitionProvider: binaryExists,
280+
completionProvider: binaryExists
281+
? { triggerCharacters: ["."] }
282+
: undefined,
275283
},
276284
};
277285
let response: m.ResponseMessage = {
@@ -315,32 +323,68 @@ process.on("message", (msg: m.Message) => {
315323
process.send!(response);
316324
}
317325
} else if (msg.method === p.HoverRequest.method) {
318-
let dummyHoverResponse: m.ResponseMessage = {
326+
let emptyHoverResponse: m.ResponseMessage = {
319327
jsonrpc: c.jsonrpcVersion,
320328
id: msg.id,
321329
// type result = Hover | null
322330
// type Hover = {contents: MarkedString | MarkedString[] | MarkupContent, range?: Range}
323-
result: { contents: "Time to go for a 20k run!" },
331+
result: null,
324332
};
325-
326-
process.send!(dummyHoverResponse);
333+
runDumpCommand(msg, (result) => {
334+
if (result && result.hover) {
335+
let hoverResponse: m.ResponseMessage = {
336+
...emptyHoverResponse,
337+
result: {
338+
contents: result.hover,
339+
},
340+
};
341+
process.send!(hoverResponse);
342+
} else {
343+
process.send!(emptyHoverResponse);
344+
}
345+
});
327346
} else if (msg.method === p.DefinitionRequest.method) {
328347
// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition
329-
let dummyDefinitionResponse: m.ResponseMessage = {
348+
let emptyDefinitionResponse: m.ResponseMessage = {
330349
jsonrpc: c.jsonrpcVersion,
331350
id: msg.id,
332351
// result should be: Location | Array<Location> | Array<LocationLink> | null
333-
result: {
334-
uri: msg.params.textDocument.uri,
335-
range: {
336-
start: { line: 2, character: 4 },
337-
end: { line: 2, character: 12 },
338-
},
339-
},
352+
result: null,
340353
// error: code and message set in case an exception happens during the definition request.
341354
};
342355

343-
process.send!(dummyDefinitionResponse);
356+
runDumpCommand(msg, (result) => {
357+
if (result && result.definition) {
358+
let definitionResponse: m.ResponseMessage = {
359+
...emptyDefinitionResponse,
360+
result: {
361+
uri: result.definition.uri || msg.params.textDocument.uri,
362+
range: result.definition.range,
363+
},
364+
};
365+
process.send!(definitionResponse);
366+
} else {
367+
process.send!(emptyDefinitionResponse);
368+
}
369+
});
370+
} else if (msg.method === p.CompletionRequest.method) {
371+
let emptyCompletionResponse: m.ResponseMessage = {
372+
jsonrpc: c.jsonrpcVersion,
373+
id: msg.id,
374+
result: null,
375+
};
376+
let code = getOpenedFileContent(msg.params.textDocument.uri);
377+
runCompletionCommand(msg, code, (result) => {
378+
if (result) {
379+
let definitionResponse: m.ResponseMessage = {
380+
...emptyCompletionResponse,
381+
result: result,
382+
};
383+
process.send!(definitionResponse);
384+
} else {
385+
process.send!(emptyCompletionResponse);
386+
}
387+
});
344388
} else if (msg.method === p.DocumentFormattingRequest.method) {
345389
// technically, a formatting failure should reply with the error. Sadly
346390
// the LSP alert box for these error replies sucks (e.g. doesn't actually
16.2 MB
Binary file not shown.

0 commit comments

Comments
 (0)