Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions editors/vscode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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` | - | `<string>` | Path to Oxc language server binary. Mostly for testing the language server. |
| `oxc.path.node` | - | `<string>` | Path to a Node.js binary. Will be added to the language server `PATH` environment. |

### Workspace Configuration

Expand Down
19 changes: 19 additions & 0 deletions editors/vscode/client/VSCodeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -19,6 +20,7 @@ export class VSCodeConfig implements VSCodeConfigInterface {
this._enable = this.configuration.get<boolean>('enable') ?? true;
this._trace = this.configuration.get<TraceLevel>('trace.server') || 'off';
this._binPath = this.configuration.get<string>('path.server');
this._nodePath = this.configuration.get<string>('path.node');
this._requireConfig = this.configuration.get<boolean>('requireConfig') ?? false;
}

Expand Down Expand Up @@ -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<void> {
this._nodePath = value;
return this.configuration.update('path.node', value);
}

get requireConfig(): boolean {
return this._requireConfig;
}
Expand Down Expand Up @@ -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`
Expand Down
18 changes: 13 additions & 5 deletions editors/vscode/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -143,13 +145,19 @@ export async function activate(context: ExtensionContext) {
}

const command = await findBinary();

const nodePath = configService.vsCodeConfig.nodePath;
const serverEnv: Record<string, string> = {
...process.env,
RUST_LOG: process.env.RUST_LOG || 'info',
};
if (nodePath) {
serverEnv.PATH = `${nodePath}${process.platform === 'win32' ? ';' : ':'}${process.env.PATH ?? ''}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states nodePath is a "Path to a Node.js binary" (e.g., /usr/local/bin/node), but the code adds it directly to PATH without extracting the directory. PATH environment variables should contain directories, not file paths. This will cause the PATH to be malformed if users follow the documentation.

Fix: Extract the directory from the binary path:

if (nodePath) {
  const nodeDir = require('path').dirname(nodePath);
  serverEnv.PATH = `${nodeDir}${process.platform === 'win32' ? ';' : ':'}${process.env.PATH ?? ''}`;
}

Alternatively, update the documentation to clarify that users should provide the directory path, not the binary path.

Suggested change
serverEnv.PATH = `${nodePath}${process.platform === 'win32' ? ';' : ':'}${process.env.PATH ?? ''}`;
if (nodePath) {
const nodeDir = require('path').dirname(nodePath);
serverEnv.PATH = `${nodeDir}${process.platform === 'win32' ? ';' : ':'}${process.env.PATH ?? ''}`;
}

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

}
const run: Executable = {
command: command!,
options: {
env: {
...process.env,
RUST_LOG: process.env.RUST_LOG || 'info',
},
env: serverEnv,
},
};
const serverOptions: ServerOptions = {
Expand Down
15 changes: 10 additions & 5 deletions editors/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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."
}
}
},
Expand Down
8 changes: 4 additions & 4 deletions editors/vscode/tests/VSCodeConfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
});

Expand All @@ -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 () => {
Expand All @@ -35,6 +33,7 @@ suite('VSCodeConfig', () => {
config.updateRequireConfig(true),
config.updateTrace('messages'),
config.updateBinPath('./binary'),
config.updateNodePath('./node'),
]);

const wsConfig = workspace.getConfiguration('oxc');
Expand All @@ -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');
});
});
Loading