Skip to content

Commit 02771d3

Browse files
committed
The binaryPath option was added to the rescript.settings
1 parent 4f8d3f9 commit 02771d3

File tree

4 files changed

+89
-15
lines changed

4 files changed

+89
-15
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@
131131
"type": "boolean",
132132
"default": false,
133133
"description": "Automatically start ReScript's code analysis."
134+
},
135+
"rescript.settings.binaryPath": {
136+
"type": "string",
137+
"default": "",
138+
"description": "Path to the ReScript binary. You can use it if you haven't or don't want to use the installed ReScript binary from node_modules in your project."
134139
}
135140
}
136141
},

server/src/constants.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,19 @@ export let analysisProdPath = path.join(
3232
"rescript-editor-analysis.exe"
3333
);
3434

35+
export let rescriptBinName = "rescript";
36+
37+
export let bsbBinName = "bsb";
38+
39+
export let bscBinName = "bsc";
40+
3541
// can't use the native bsb/rescript since we might need the watcher -w flag, which is only in the JS wrapper
3642
export let rescriptNodePartialPath = path.join(
3743
"node_modules",
3844
".bin",
39-
"rescript"
45+
rescriptBinName,
4046
);
41-
export let bsbNodePartialPath = path.join("node_modules", ".bin", "bsb");
47+
export let bsbNodePartialPath = path.join("node_modules", ".bin", bsbBinName);
4248

4349
export let bsbLock = ".bsb.lock";
4450
export let bsconfigPartialPath = "bsconfig.json";

server/src/server.ts

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as v from "vscode-languageserver";
44
import * as rpc from "vscode-jsonrpc/node";
55
import * as path from "path";
66
import fs from "fs";
7+
import os from "os";
78
// TODO: check DidChangeWatchedFilesNotification.
89
import {
910
DidOpenTextDocumentNotification,
@@ -23,9 +24,11 @@ import { WorkspaceEdit } from "vscode-languageserver";
2324

2425
interface extensionConfiguration {
2526
askToStartBuild: boolean;
27+
binaryPath: string;
2628
}
2729
let extensionConfiguration: extensionConfiguration = {
2830
askToStartBuild: true,
31+
binaryPath: "",
2932
};
3033
let pullConfigurationPeriodically: NodeJS.Timeout | null = null;
3134

@@ -209,7 +212,12 @@ let openedFile = (fileUri: string, fileContent: string) => {
209212
// TODO: sometime stale .bsb.lock dangling. bsb -w knows .bsb.lock is
210213
// stale. Use that logic
211214
// TODO: close watcher when lang-server shuts down
212-
if (utils.findNodeBuildOfProjectRoot(projectRootPath) != null) {
215+
if (
216+
utils.findNodeBuildOfProjectRoot(
217+
projectRootPath,
218+
extensionConfiguration.binaryPath
219+
) != null
220+
) {
213221
let payload: clientSentBuildAction = {
214222
title: c.startBuildAction,
215223
projectRootPath: projectRootPath,
@@ -231,7 +239,19 @@ let openedFile = (fileUri: string, fileContent: string) => {
231239
// handle in the isResponseMessage check in the message handling way
232240
// below
233241
} else {
234-
// we should send something to say that we can't find bsb.exe. But right now we'll silently not do anything
242+
let binaryPath = extensionConfiguration.binaryPath === ""
243+
? path.join(projectRootPath, "node_modules", ".bin")
244+
: extensionConfiguration.binaryPath;
245+
246+
let request: p.NotificationMessage = {
247+
jsonrpc: c.jsonrpcVersion,
248+
method: "window/showMessage",
249+
params: {
250+
type: p.MessageType.Error,
251+
message: `Can't find ReScript binary on path ${binaryPath}`,
252+
},
253+
};
254+
send(request);
235255
}
236256
}
237257

@@ -570,7 +590,11 @@ function format(msg: p.RequestMessage): Array<p.Message> {
570590
} else {
571591
// code will always be defined here, even though technically it can be undefined
572592
let code = getOpenedFileContent(params.textDocument.uri);
573-
let formattedResult = utils.formatCode(filePath, code);
593+
let formattedResult = utils.formatCode(
594+
extensionConfiguration.binaryPath,
595+
filePath,
596+
code
597+
);
574598
if (formattedResult.kind === "success") {
575599
let max = code.length;
576600
let result: p.TextEdit[] = [
@@ -905,6 +929,17 @@ function onMessage(msg: p.Message) {
905929

906930
if (initialConfiguration != null) {
907931
extensionConfiguration = initialConfiguration;
932+
if (
933+
extensionConfiguration.binaryPath !== "" &&
934+
extensionConfiguration.binaryPath[0] === "~"
935+
) {
936+
// What should happen if the path contains the home directory symbol?
937+
// This situation is handled below, but maybe it isn't the best option.
938+
extensionConfiguration.binaryPath = path.join(
939+
os.homedir(),
940+
extensionConfiguration.binaryPath.slice(1)
941+
);
942+
}
908943
}
909944

910945
send(response);
@@ -1013,7 +1048,10 @@ function onMessage(msg: p.Message) {
10131048
// TODO: close watcher when lang-server shuts down. However, by Node's
10141049
// default, these subprocesses are automatically killed when this
10151050
// language-server process exits
1016-
let found = utils.findNodeBuildOfProjectRoot(projectRootPath);
1051+
let found = utils.findNodeBuildOfProjectRoot(
1052+
projectRootPath,
1053+
extensionConfiguration.binaryPath
1054+
);
10171055
if (found != null) {
10181056
let bsbProcess = utils.runBuildWatcherUsingValidBuildPath(
10191057
found.buildPath,

server/src/utils.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,29 @@ export let findBscNativeOfFile = (
7070
}
7171
};
7272

73+
let findBscBinFromConfig = (
74+
pathToBinFromConfig: p.DocumentUri
75+
): null | p.DocumentUri => {
76+
let bscPath = path.join(pathToBinFromConfig, c.bscBinName);
77+
if (fs.existsSync(bscPath)) {
78+
return bscPath;
79+
}
80+
return null;
81+
};
82+
7383
// TODO: this doesn't handle file:/// scheme
7484
export let findNodeBuildOfProjectRoot = (
75-
projectRootPath: p.DocumentUri
85+
projectRootPath: p.DocumentUri,
86+
pathToBinFromConfig: p.DocumentUri
7687
): null | { buildPath: p.DocumentUri; isReScript: boolean } => {
77-
let rescriptNodePath = path.join(projectRootPath, c.rescriptNodePartialPath);
78-
let bsbNodePath = path.join(projectRootPath, c.bsbNodePartialPath);
88+
let rescriptNodePath =
89+
pathToBinFromConfig === ""
90+
? path.join(projectRootPath, c.rescriptNodePartialPath)
91+
: path.join(pathToBinFromConfig, c.rescriptBinName);
92+
let bsbNodePath =
93+
pathToBinFromConfig === ""
94+
? path.join(projectRootPath, c.bsbNodePartialPath)
95+
: path.join(pathToBinFromConfig, c.bsbBinName);
7996

8097
if (fs.existsSync(rescriptNodePath)) {
8198
return { buildPath: rescriptNodePath, isReScript: true };
@@ -94,21 +111,29 @@ type execResult =
94111
kind: "error";
95112
error: string;
96113
};
97-
export let formatCode = (filePath: string, code: string): execResult => {
114+
export let formatCode = (
115+
pathToBinFromConfig: p.DocumentUri,
116+
filePath: string,
117+
code: string
118+
): execResult => {
98119
let extension = path.extname(filePath);
99120
let formatTempFileFullPath = createFileInTempDir(extension);
100121
fs.writeFileSync(formatTempFileFullPath, code, {
101122
encoding: "utf-8",
102123
});
103124
try {
125+
// Try to find the bsc bin from the binaryPath setting from the configuration.
126+
let bscPath = findBscBinFromConfig(pathToBinFromConfig);
127+
104128
// See comment on findBscNativeDirOfFile for why we need
105129
// to recursively search for bsc.exe upward
106-
let bscNativePath = findBscNativeOfFile(filePath);
130+
bscPath = bscPath == null ? findBscNativeOfFile(filePath) : bscPath;
107131

108-
// Default to using the project formatter. If not, use the one we ship with
109-
// the analysis binary in the extension itself.
110-
if (bscNativePath != null) {
111-
let result = childProcess.execFileSync(bscNativePath, [
132+
// Default to using the formatter from the binaryPath setting from the configuration
133+
// or the project formatter.
134+
// If not, use the one we ship with the analysis binary in the extension itself.
135+
if (bscPath != null) {
136+
let result = childProcess.execFileSync(bscPath, [
112137
"-color",
113138
"never",
114139
"-format",

0 commit comments

Comments
 (0)