Skip to content

Commit d75c664

Browse files
committed
Improve monorepo/workspace bsc
1 parent ce3970e commit d75c664

File tree

3 files changed

+35
-23
lines changed

3 files changed

+35
-23
lines changed

server/src/constants.ts

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ export let bscExePartialPath = path.join(
99
process.platform,
1010
"bsc.exe"
1111
);
12-
export let bscNodePartialPath = path.join("node_modules", ".bin", "bsc");
1312

1413
// can't use the native bsb since we might need the watcher -w flag, which is only in the js wrapper
1514
// export let bsbPartialPath = path.join('node_modules', 'bs-platform', process.platform, 'bsb.exe');

server/src/server.ts

+8-22
Original file line numberDiff line numberDiff line change
@@ -431,30 +431,15 @@ process.on("message", (msg: m.Message) => {
431431
process.send!(fakeSuccessResponse);
432432
process.send!(response);
433433
} else {
434-
let bscExePath = path.join(projectRootPath, c.bscExePartialPath);
435-
let bscNodePath = path.join(projectRootPath, c.bscNodePartialPath);
436-
// There are the native bsc.exe binaries the bs-platform package, and
437-
// the javascript bsc wrapper within node_modules/.bin. The JS wrapper
438-
// starts and finds the right platform-specific native binary to call.
439-
// This has nontrivial overhead each formatting, so we try to directly
440-
// invoke the platform-specific native binary (inside bs-platform).
441-
442-
// However, we won't always be able to find the bs-platform package;
443-
// for example yarn workspace lifts up the dependencies packages to a
444-
// directory higher (grumbles); that setup only leaves us to find
445-
// node_modules/.bin (which it doesn't touch, thankfully). So for
446-
// quirky npm setups, we need to have a graceful degradation and find
447-
// the JS bsc wrapper. If we can't even find node_modules/.bin then we
448-
// give up
449-
let resolvedBscPath = fs.existsSync(bscExePath)
450-
? bscExePath
451-
: fs.existsSync(bscNodePath)
452-
? bscNodePath
453-
: null;
454-
if (resolvedBscPath === null) {
434+
// See comment on findBscExeDirUpwardFromProjectRoot for why we need
435+
// to recursively search for bsc.exe upward
436+
let bscExeDir = utils.findBscExeDirUpwardFromProjectRoot(
437+
projectRootPath
438+
);
439+
if (bscExeDir === null) {
455440
let params: p.ShowMessageParams = {
456441
type: p.MessageType.Error,
457-
message: `Cannot find a nearby ${c.bscExePartialPath} nor ${c.bscNodePartialPath}. It's needed for formatting.`,
442+
message: `Cannot find a nearby ${c.bscExePartialPath}. It's needed for formatting.`,
458443
};
459444
let response: m.NotificationMessage = {
460445
jsonrpc: c.jsonrpcVersion,
@@ -464,6 +449,7 @@ process.on("message", (msg: m.Message) => {
464449
process.send!(fakeSuccessResponse);
465450
process.send!(response);
466451
} else {
452+
let resolvedBscPath = path.join(bscExeDir, c.bscExePartialPath);
467453
// code will always be defined here, even though technically it can be undefined
468454
let code = getOpenedFileContent(params.textDocument.uri);
469455
let formattedResult = utils.formatUsingValidBscPath(

server/src/utils.ts

+27
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,33 @@ export let findProjectRootOfFile = (
3434
}
3535
};
3636

37+
// TODO: races here?
38+
// TODO: this doesn't handle file:/// scheme
39+
40+
// We need to recursively search for bs-platform/{platform}/bsc.exe upward from
41+
// the project's root, because in some setups, such as yarn workspace/monorepo,
42+
// the node_modules/bs-platform package might be hoisted up instead of alongside
43+
// the project root.
44+
// Also, if someone's ever formatting a regular project setup's dependency
45+
// (which is weird but whatever), they'll at least find an upward bs-platform
46+
// from the dependent.
47+
export let findBscExeDirUpwardFromProjectRoot = (
48+
dir: p.DocumentUri
49+
): null | p.DocumentUri => {
50+
let bscPath = path.join(dir, c.bscExePartialPath);
51+
if (fs.existsSync(bscPath)) {
52+
return dir;
53+
} else {
54+
let parentDir = path.dirname(dir);
55+
if (parentDir === dir) {
56+
// reached the top
57+
return null;
58+
} else {
59+
return findBscExeDirUpwardFromProjectRoot(parentDir);
60+
}
61+
}
62+
};
63+
3764
type execResult =
3865
| {
3966
kind: "success";

0 commit comments

Comments
 (0)