-
-
Notifications
You must be signed in to change notification settings - Fork 739
refactor(vscode)!: use node_module/.bin/oxlint by default, fallback to internal language server
#16784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
6cd0669 to
9cfdd3e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors the VSCode extension to prefer using oxlint and oxfmt binaries from node_modules/.bin by default, with a fallback to the internal oxc_language_server when no binaries are found.
Key Changes:
- Refactored
ConfigServiceto introduce a unifiedsearchBinaryPath()method that searches for binaries innode_modules/.binwhen no explicit path is configured - Made binary path resolution async to support file system operations for searching binaries
- Moved the fallback logic for the internal language server from
linter.tsto the mainextension.tsactivation function
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| editors/vscode/client/ConfigService.ts | Refactored getUserServerBinPath() to getOxlintServerBinPath() and introduced unified searchBinaryPath() method; both oxlint and oxfmt methods now search node_modules/.bin by default |
| editors/vscode/client/tools/linter.ts | Updated to call async getOxlintServerBinPath() method; removed internal fallback logic and join import |
| editors/vscode/client/extension.ts | Added fallback logic for internal language server when no binaries are found; added join import |
| editors/vscode/tests/ConfigService.spec.ts | Updated test method calls to use renamed getOxlintServerBinPath() method |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
9cfdd3e to
2ad7e14
Compare
|
@Sysix by making this change, is oxc-project/oxc-intellij-plugin#239 going to become a more common issue for the VS Code plugin as well? Given both oxfmt/oxlint have mostly shifted to requiring JavaScript, maybe your suggestion of how NX solved this issue should be revisited as something to change in core oxc-project/oxc-intellij-plugin#239 (comment). |
|
@nrayburn-tech yes, this will become a problem too for VS Code :) |
2ad7e14 to
f4453e4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… to internal language server
f4453e4 to
fb4fecf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The refactor introduces a useful unified binary resolver, but it currently trusts node_modules/.bin discovery more than user-provided paths and can still discover workspace executables even when the workspace is untrusted. Activation fallback logic in extension.ts is brittle due to its reliance on binaryPaths[0] ordering rather than tool identity. Finally, findFiles(..., 1) can pick a non-deterministic binary in monorepos, which can cause surprising behavior.
Additional notes (4)
- Security |
editors/vscode/client/ConfigService.ts:102-102
searchBinaryPath()returns a path fromnode_modules/.binwhen the user did not configure a path, but it doesn’t validate/verify that path at all (unlike user-provided paths). This creates an inconsistency: a workspace-controlled binary is trusted more than a user-configured one.
Even if you “need to trust node_modules”, you should at least ensure the resolved path is inside the current workspace folder and points to an executable file (or at minimum exists). That reduces the risk of weird resolutions via symlinks/out-of-workspace matches and makes behavior more predictable across multi-root setups.
- Security |
editors/vscode/client/ConfigService.ts:111-111
searchBinaryPath()returns early when!workspace.isTrustedfor user-provided paths, but still searchesnode_modules/.binwhensettingsBinaryis empty. In an untrusted workspace, you likely should not scan the workspace filesystem for executables at all.
Right now the behavior is: untrusted workspace + no setting => you may still discover and later run a workspace-provided binary; untrusted workspace + explicit setting => you refuse. That’s backwards from a safety standpoint.
- Readability |
editors/vscode/client/ConfigService.ts:111-111
workspace.findFiles(new RelativePattern(cwd, "**/node_modules/.bin/<binary>"), ..., 1)returns the first match, but the “first” is not necessarily deterministic across platforms/filesystems and can pick an unexpected nestednode_modules(e.g., in a monorepo).
This can lead to running a different package’s binary than the user expects.
- Maintainability |
editors/vscode/client/extension.ts:76-87
The fallback decision is hard-coded tobinaryPaths[0]with the comment “when no oxlint binary path are provided”. This assumes tool ordering (linter first) and makes the activation logic brittle—any future reordering oftoolsor insertion of another tool before the linter will silently break the fallback.
It also couples extension.ts to an implicit binaryPaths index instead of making the decision based on tool identity.
Summary of changes
Summary of changes
- Refactored VS Code client config to resolve tool binaries via a unified async helper:
- Replaced
getUserServerBinPath()with asyncgetOxlintServerBinPath(). - Added
searchBinaryPath(settingsBinary, defaultPattern)to:- search
**/node_modules/.bin/<binary>when no explicit setting is provided - validate user-provided paths via
validateSafeBinaryPath() - resolve relative paths against the first workspace folder
- search
- Replaced
- Updated tools:
linter.tsnow awaitsconfigService.getOxlintServerBinPath()and no longer hardcodes fallback tooxc_language_server.formatter.tsnow relies onConfigServicefor trust checks and just uses returnedbin.
- Moved fallback logic for the internal server to extension activation:
- If the linter binary is missing,
extension.tsnow setsbinaryPaths[0]toSERVER_PATH_DEVor./target/release/oxc_language_server(.exe).
- If the linter binary is missing,
- Updated tests to use the new
getOxlintServerBinPath()API.

This PR refactors the VSCode extension to prefer using oxlint and oxfmt binaries from node_modules/.bin by default, with a fallback to the internal oxc_language_server when no binaries are found.