Skip to content

Conversation

@Sysix
Copy link
Member

@Sysix Sysix commented Dec 12, 2025

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.

@github-actions github-actions bot added A-editor Area - Editor and Language Server C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior labels Dec 12, 2025
Copy link
Member Author

Sysix commented Dec 12, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

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.

@Sysix Sysix force-pushed the 12-12-refactor_vscode_use_node_module_.bin_oxlint_by_default_fallback_to_internal_language_server branch from 6cd0669 to 9cfdd3e Compare December 12, 2025 21:55
@Sysix Sysix requested a review from Copilot December 12, 2025 21:56
Copy link
Contributor

Copilot AI left a 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 ConfigService to introduce a unified searchBinaryPath() method that searches for binaries in node_modules/.bin when 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.ts to the main extension.ts activation 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.

@Sysix Sysix force-pushed the 12-12-refactor_vscode_use_node_module_.bin_oxlint_by_default_fallback_to_internal_language_server branch from 9cfdd3e to 2ad7e14 Compare December 12, 2025 22:27
@nrayburn-tech
Copy link
Collaborator

@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).

@camc314 camc314 self-assigned this Dec 13, 2025
@Sysix
Copy link
Member Author

Sysix commented Dec 13, 2025

@nrayburn-tech yes, this will become a problem too for VS Code :)
oxc-zed has something similar already: https://github.com/oxc-project/oxc-zed/blob/5d031d2000355c1767b595372f43461d2e20570b/src/oxc.rs#L72-L111

@Sysix Sysix force-pushed the 12-12-refactor_vscode_use_node_module_.bin_oxlint_by_default_fallback_to_internal_language_server branch from 2ad7e14 to f4453e4 Compare December 13, 2025 16:04
@Sysix Sysix requested a review from Copilot December 13, 2025 16:11
Copy link
Contributor

Copilot AI left a 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.

@Sysix Sysix force-pushed the 12-12-refactor_vscode_use_node_module_.bin_oxlint_by_default_fallback_to_internal_language_server branch from f4453e4 to fb4fecf Compare December 13, 2025 16:16
@Sysix Sysix marked this pull request as ready for review December 13, 2025 16:16
@Sysix Sysix requested a review from camc314 as a code owner December 13, 2025 16:16
Copy link

@charliecreates charliecreates bot left a 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 from node_modules/.bin when 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.isTrusted for user-provided paths, but still searches node_modules/.bin when settingsBinary is 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 nested node_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 to binaryPaths[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 of tools or 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 async getOxlintServerBinPath().
    • 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
  • Updated tools:
    • linter.ts now awaits configService.getOxlintServerBinPath() and no longer hardcodes fallback to oxc_language_server.
    • formatter.ts now relies on ConfigService for trust checks and just uses returned bin.
  • Moved fallback logic for the internal server to extension activation:
    • If the linter binary is missing, extension.ts now sets binaryPaths[0] to SERVER_PATH_DEV or ./target/release/oxc_language_server(.exe).
  • Updated tests to use the new getOxlintServerBinPath() API.

@charliecreates charliecreates bot removed the request for review from CharlieHelps December 13, 2025 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-editor Area - Editor and Language Server C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants