From fd28773ea149c0b192b591be81f874769ee32926 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger <649677+nhedger@users.noreply.github.com> Date: Fri, 6 Oct 2023 18:25:40 +0200 Subject: [PATCH] fix(vscode): biome resolution (#492) --- editors/vscode/src/main.ts | 40 +++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/editors/vscode/src/main.ts b/editors/vscode/src/main.ts index bbcbc2405541..6c2489d3ce51 100644 --- a/editors/vscode/src/main.ts +++ b/editors/vscode/src/main.ts @@ -1,6 +1,6 @@ import { type ChildProcess, spawn } from "child_process"; import { type Socket, connect } from "net"; -import { isAbsolute } from "path"; +import { dirname, isAbsolute } from "path"; import { TextDecoder, promisify } from "util"; import { ExtensionContext, @@ -25,6 +25,7 @@ import { StatusBar } from "./statusBar"; import { setContextValue } from "./utils"; import resolveImpl = require("resolve/async"); +import { createRequire } from "module"; import type * as resolve from "resolve"; const resolveAsync = promisify( @@ -243,16 +244,34 @@ async function getWorkspaceDependency( outputChannel: OutputChannel, ): Promise { for (const workspaceFolder of workspace.workspaceFolders) { - const path = Uri.joinPath( - workspaceFolder.uri, - "node_modules", - ".bin", - "biome", - ); + // To resolve the @biomejs/cli-*, which is a transitive dependency of the + // @biomejs/biome package, we need to create a custom require function that + // is scoped to @biomejs/biome. This allows us to reliably resolve the + // package regardless of the package manager used by the user. + try { + const requireFromBiome = createRequire( + require.resolve("@biomejs/biome/package.json", { + paths: [workspaceFolder.uri.fsPath], + }), + ); + const binaryPackage = dirname( + requireFromBiome.resolve( + `@biomejs/cli-${process.platform}-${process.arch}/package.json`, + ), + ); - if (await fileExists(path)) { - return path.fsPath; + const biomePath = Uri.file( + `${binaryPackage}/biome${process.platform === "win32" ? ".exe" : ""}`, + ); + + if (await fileExists(biomePath)) { + return biomePath.fsPath; + } + } catch { + return undefined; } + + return undefined; } window.showWarningMessage( @@ -351,9 +370,8 @@ async function getSocket( outputChannel: OutputChannel, command: string, ): Promise { - const process = spawn(`"${command}"`, ["__print_socket"], { + const process = spawn(command, ["__print_socket"], { stdio: [null, "pipe", "pipe"], - shell: true, }); const stdout = { content: "" };