diff --git a/editors/vscode/README.md b/editors/vscode/README.md index e4274ad729894..97f34f7933c4b 100644 --- a/editors/vscode/README.md +++ b/editors/vscode/README.md @@ -52,6 +52,7 @@ Following configuration are supported via `settings.json` and effect the window | `oxc.requireConfig` | `false` | `true` \| `false` | Start the language server only when a `.oxlintrc.json` file exists in one of the workspaces. | | `oxc.trace.server` | `off` | `off` \| `messages` \| `verbose` | Traces the communication between VS Code and the language server. | | `oxc.path.server` | - | `` | Path to Oxc language server binary. Mostly for testing the language server. | +| `oxc.path.node` | - | `` | Path to a Node.js binary. Will be added to the language server `PATH` environment. | ### Workspace Configuration diff --git a/editors/vscode/client/VSCodeConfig.ts b/editors/vscode/client/VSCodeConfig.ts index 47618d197fd0d..23deb88e955b4 100644 --- a/editors/vscode/client/VSCodeConfig.ts +++ b/editors/vscode/client/VSCodeConfig.ts @@ -5,6 +5,7 @@ export class VSCodeConfig implements VSCodeConfigInterface { private _enable!: boolean; private _trace!: TraceLevel; private _binPath: string | undefined; + private _nodePath: string | undefined; private _requireConfig!: boolean; constructor() { @@ -19,6 +20,7 @@ export class VSCodeConfig implements VSCodeConfigInterface { this._enable = this.configuration.get('enable') ?? true; this._trace = this.configuration.get('trace.server') || 'off'; this._binPath = this.configuration.get('path.server'); + this._nodePath = this.configuration.get('path.node'); this._requireConfig = this.configuration.get('requireConfig') ?? false; } @@ -49,6 +51,15 @@ export class VSCodeConfig implements VSCodeConfigInterface { return this.configuration.update('path.server', value); } + get nodePath(): string | undefined { + return this._nodePath; + } + + updateNodePath(value: string | undefined): PromiseLike { + this._nodePath = value; + return this.configuration.update('path.node', value); + } + get requireConfig(): boolean { return this._requireConfig; } @@ -84,6 +95,14 @@ interface VSCodeConfigInterface { * @default undefined */ binPath: string | undefined; + + /** + * Path to Node.js + * `oxc.path.node` + * @default undefined + */ + nodePath: string | undefined; + /** * Start the language server only when a `.oxlintrc.json` file exists in one of the workspaces. * `oxc.requireConfig` diff --git a/editors/vscode/client/extension.ts b/editors/vscode/client/extension.ts index 082f56bb506a0..748f62ba754ee 100644 --- a/editors/vscode/client/extension.ts +++ b/editors/vscode/client/extension.ts @@ -116,7 +116,9 @@ export async function activate(context: ExtensionContext) { await client.sendRequest(ExecuteCommandRequest.type, params); }); - const outputChannel = window.createOutputChannel(outputChannelName, { log: true }); + const outputChannel = window.createOutputChannel(outputChannelName, { + log: true, + }); context.subscriptions.push( applyAllFixesFile, @@ -143,13 +145,19 @@ export async function activate(context: ExtensionContext) { } const command = await findBinary(); + + const nodePath = configService.vsCodeConfig.nodePath; + const serverEnv: Record = { + ...process.env, + RUST_LOG: process.env.RUST_LOG || 'info', + }; + if (nodePath) { + serverEnv.PATH = `${nodePath}${process.platform === 'win32' ? ';' : ':'}${process.env.PATH ?? ''}`; + } const run: Executable = { command: command!, options: { - env: { - ...process.env, - RUST_LOG: process.env.RUST_LOG || 'info', - }, + env: serverEnv, }, }; const serverOptions: ServerOptions = { diff --git a/editors/vscode/package.json b/editors/vscode/package.json index 002c9622e91fb..ad0bdfbf4bee5 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -102,11 +102,6 @@ "default": "off", "description": "Traces the communication between VS Code and the language server." }, - "oxc.path.server": { - "type": "string", - "scope": "window", - "description": "Path to Oxc language server binary. Mostly for testing the language server." - }, "oxc.configPath": { "type": [ "string", @@ -196,6 +191,16 @@ "scope": "resource", "default": null, "description": "Path to an oxfmt configuration file" + }, + "oxc.path.server": { + "type": "string", + "scope": "window", + "description": "Path to Oxc language server binary. Mostly for testing the language server." + }, + "oxc.path.node": { + "type": "string", + "scope": "window", + "description": "Path to a Node.js binary. Will be added to the language server `PATH` environment." } } }, diff --git a/editors/vscode/tests/VSCodeConfig.spec.ts b/editors/vscode/tests/VSCodeConfig.spec.ts index fedccf549554f..e48c4fe004ab2 100644 --- a/editors/vscode/tests/VSCodeConfig.spec.ts +++ b/editors/vscode/tests/VSCodeConfig.spec.ts @@ -6,15 +6,12 @@ import { testSingleFolderMode } from './test-helpers.js'; const conf = workspace.getConfiguration('oxc'); suite('VSCodeConfig', () => { + const keys = ['enable', 'requireConfig', 'trace.server', 'path.server', 'path.node']; setup(async () => { - const keys = ['enable', 'requireConfig', 'trace.server', 'path.server']; - await Promise.all(keys.map(key => conf.update(key, undefined))); }); teardown(async () => { - const keys = ['enable', 'requireConfig', 'trace.server', 'path.server']; - await Promise.all(keys.map(key => conf.update(key, undefined))); }); @@ -25,6 +22,7 @@ suite('VSCodeConfig', () => { strictEqual(config.requireConfig, false); strictEqual(config.trace, 'off'); strictEqual(config.binPath, ''); + strictEqual(config.nodePath, ''); }); testSingleFolderMode('updating values updates the workspace configuration', async () => { @@ -35,6 +33,7 @@ suite('VSCodeConfig', () => { config.updateRequireConfig(true), config.updateTrace('messages'), config.updateBinPath('./binary'), + config.updateNodePath('./node'), ]); const wsConfig = workspace.getConfiguration('oxc'); @@ -43,5 +42,6 @@ suite('VSCodeConfig', () => { strictEqual(wsConfig.get('requireConfig'), true); strictEqual(wsConfig.get('trace.server'), 'messages'); strictEqual(wsConfig.get('path.server'), './binary'); + strictEqual(wsConfig.get('path.node'), './node'); }); });