Skip to content

feat(oxfmt/lsp): support untitled:// schema#19287

Merged
graphite-app[bot] merged 1 commit intomainfrom
02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_
Feb 17, 2026
Merged

feat(oxfmt/lsp): support untitled:// schema#19287
graphite-app[bot] merged 1 commit intomainfrom
02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_

Conversation

@Sysix
Copy link
Member

@Sysix Sysix commented Feb 11, 2026

related oxc-project/oxc-vscode#25

This PR adds support for formatting unsaved documents using the untitled:// URI scheme in the oxfmt LSP server. This enables VS Code and other LSP clients to format in-memory documents that haven't been saved to disk yet.

Angular is not supported for the moment, could not find a VS Code extension which defines a language ID for it :/

Copy link
Member Author

Sysix commented Feb 11, 2026


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.

@github-actions github-actions bot added A-cli Area - CLI A-formatter Area - Formatter C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior labels Feb 11, 2026
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from f04a325 to 10b4f0b Compare February 12, 2026 22:05
@Sysix Sysix force-pushed the 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ branch from c51ddcb to a9b1aca Compare February 12, 2026 22:05
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from 10b4f0b to 3e478df Compare February 12, 2026 22:08
@Sysix Sysix changed the title refactor(oxfmt/lsp): split run_format to format_in_memory and format_file feat(oxfmt/lsp): support untitled:// schema Feb 12, 2026
@github-actions github-actions bot added the C-enhancement Category - New feature or request label Feb 12, 2026
@Sysix Sysix force-pushed the 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ branch from a9b1aca to 10b8c79 Compare February 12, 2026 22:44
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from 3e478df to 6d8842d Compare February 12, 2026 22:44
@Sysix Sysix force-pushed the 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ branch from 10b8c79 to bfe263c Compare February 12, 2026 23:24
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch 2 times, most recently from 0554ae2 to 2b3f78d Compare February 12, 2026 23:26
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from 2b3f78d to 100f135 Compare February 12, 2026 23:37
Copy link
Member

@leaysgur leaysgur left a comment

Choose a reason for hiding this comment

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

Instead of duplicating the strategy/options mapping from LanguageId (the large match blocks in mod.rs)..., you could generate a fake path from the language ID (e.g. "untitled.tsx" for "typescriptreact") and feed it into the existing FormatFileStrategy::try_from(path) + config_resolver.resolve(&strategy) pipeline.

This would eliminate many lines with keeping support.rs as the single source of truth.


And for the fake path, it would be better to use {workspace_root}/untitled.{ext} rather than just untitled.{ext}.

There is a FormatFileStrategy::resolve_relative_path() (which may be needed to tailwind plugin work correctly).
It isn't called in the LSP path, but LSP already using absolute path, so that's not a concern though.

But config_resolver.resolve() and the external formatter's options.filepath both use the path — a workspace-rooted path ensures editorconfig/oxfmtrc overrides and Prettier plugin config resolution work
correctly.

@Sysix
Copy link
Member Author

Sysix commented Feb 13, 2026

And for the fake path, it would be better to use {workspace_root}/untitled.{ext} rather than just untitled.{ext}.

This will be a problem because there is no real path. We do not know to which config is really should resolve. This why I did go with the "default" way :)
I agree the solution is not the nicest one. Will think about a better solution which could work with oxlint too. See backlog oxc-project/backlog#171

@Sysix Sysix force-pushed the 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ branch from bfe263c to e4fa5ef Compare February 14, 2026 13:16
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from 100f135 to b54b409 Compare February 14, 2026 13:16
@github-actions github-actions bot added A-editor Area - Editor and Language Server labels Feb 14, 2026
@codspeed-hq
Copy link

codspeed-hq bot commented Feb 14, 2026

Merging this PR will not alter performance

✅ 47 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ (85e51f8) with 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ (5d5aa58)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch 3 times, most recently from 13b0123 to 30e4e0c Compare February 14, 2026 14:10
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch 2 times, most recently from 0000f48 to 293cc7c Compare February 14, 2026 14:53
@Sysix Sysix requested a review from Copilot February 14, 2026 15:23
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 adds support for formatting unsaved documents using the untitled:// URI scheme in the oxfmt LSP server. This enables VS Code and other LSP clients to format in-memory documents that haven't been saved to disk yet.

Changes:

  • Added inner() method to LanguageId for accessing the underlying string value
  • Implemented in-memory formatting for untitled:// URIs using language ID to determine format strategy
  • Refactored test utilities to support both file-based and in-memory formatting tests
  • Added comprehensive test coverage for unsaved documents across multiple file types

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
crates/oxc_language_server/src/language_id.rs Added inner() accessor method to expose the underlying language ID string
apps/oxfmt/src/lsp/mod.rs Added language ID conversion functions to map language IDs to file extensions, parser names, and format strategies
apps/oxfmt/src/lsp/server_formatter.rs Split formatting logic into format_file() and format_in_memory() methods to handle both file-based and untitled URIs
apps/oxfmt/test/lsp/utils.ts Extracted formatFixtureContent() function to support testing with custom URIs
apps/oxfmt/test/lsp/format/format.test.ts Added test suite for unsaved documents covering TypeScript, JSON, Vue, TOML, and plaintext files
apps/oxfmt/test/lsp/format/__snapshots__/format.test.ts.snap Added expected output snapshots for all unsaved document test cases

@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from 293cc7c to ce9f087 Compare February 14, 2026 16:23
@Sysix Sysix force-pushed the 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ branch from e4fa5ef to 001e002 Compare February 14, 2026 16:23
@Sysix Sysix marked this pull request as ready for review February 14, 2026 16:23
@Sysix Sysix requested a review from camc314 as a code owner February 14, 2026 16:23
@Sysix Sysix requested a review from leaysgur February 14, 2026 16:23
Copy link
Member

@leaysgur leaysgur left a comment

Choose a reason for hiding this comment

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

👀

@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from ce9f087 to 46a0b1a Compare February 16, 2026 18:37
@Sysix Sysix force-pushed the 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ branch from 001e002 to 5d5aa58 Compare February 16, 2026 18:37
@Sysix Sysix force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from 46a0b1a to 85e51f8 Compare February 16, 2026 22:19
@Sysix Sysix requested a review from leaysgur February 16, 2026 22:23
Copy link
Member

@leaysgur leaysgur left a comment

Choose a reason for hiding this comment

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

Thanks as always~ 👍🏻

@leaysgur leaysgur added the 0-merge Merge with Graphite Merge Queue label Feb 17, 2026
Copy link
Member

leaysgur commented Feb 17, 2026

Merge activity

related oxc-project/oxc-vscode#25

> This PR adds support for formatting unsaved documents using the untitled:// URI scheme in the oxfmt LSP server. This enables VS Code and other LSP clients to format in-memory documents that haven't been saved to disk yet.

Angular is not supported for the moment, could not find a VS Code extension which defines a language ID for it  :/
@graphite-app graphite-app bot force-pushed the 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ branch from 5d5aa58 to 0eb9a2d Compare February 17, 2026 01:50
@graphite-app graphite-app bot force-pushed the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch from 85e51f8 to 652c346 Compare February 17, 2026 01:50
Base automatically changed from 02-11-refacor_oxfmt_lsp_pass_languageid_to_run_format_ to main February 17, 2026 02:13
@graphite-app graphite-app bot removed 0-merge Merge with Graphite Merge Queue labels Feb 17, 2026
@graphite-app graphite-app bot merged commit 652c346 into main Feb 17, 2026
22 checks passed
@graphite-app graphite-app bot deleted the 02-11-refactor_oxfmt_lsp_split_run_format_to_format_in_memory_and_format_file_ branch February 17, 2026 02:13
OskarLebuda pushed a commit to OskarLebuda/oxc that referenced this pull request Feb 17, 2026
related oxc-project/oxc-vscode#25

> This PR adds support for formatting unsaved documents using the untitled:// URI scheme in the oxfmt LSP server. This enables VS Code and other LSP clients to format in-memory documents that haven't been saved to disk yet.

Angular is not supported for the moment, could not find a VS Code extension which defines a language ID for it  :/
camc314 added a commit that referenced this pull request Feb 19, 2026
# Oxlint
### 💥 BREAKING CHANGES

- 4315594 oxlint: [**BREAKING**] Deprecate `"always"` and `"as-needed"`
options of the radix rule (#19408) (Sysix)
- d4c7af3 linter: [**BREAKING**] Remove
`allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing` option (#19451)
(camc314)

### 🚀 Features

- 82ca5c3 linter: Add typescript/dot-notation rule (#19442) (camc314)
- 6db0811 linter: Implement
eslint-plugin-vitest/no-importing-vitest-globals (#18694) (Said
Atrahouch)
- c7fe8ae linter: Implement eslint-plugin-vitest/prefer-import-in-mock
(#17966) (Said Atrahouch)
- 0abb39a linter: Implement
eslint-vitest-jest-plugin/prefer-mock-return-shorthand (#18002) (Said
Atrahouch)
- 2b95537 linter: Implement `n/no-path-concat` rule (#19502) (Mikhail
Baev)
- 735d0e4 linter: Implement typescript/no-useless-default-assignment
(#19488) (camc314)
- 31c3a93 linter: Add typescript/no-unnecessary-type-parameters rule
(#19450) (camc314)
- c948090 linter: Add typescript/consistent-return rule (#19449)
(camc314)
- 9f87df0 linter: Add typescript/prefer-string-starts-ends-with rule
(#19448) (camc314)
- 04536be linter: Add typescript/prefer-regexp-exec rule (#19447)
(camc314)
- 56a7feb linter: Add typescript/prefer-readonly rule (#19446) (camc314)
- a1cea63 linter: Add typescript/no-unnecessary-qualifier rule (#19445)
(camc314)
- e3144d2 linter: Add typescript/prefer-find rule (#19444) (camc314)
- 13c7408 linter: Add typescript/prefer-readonly-parameter-types rule
(#19443) (camc314)
- 9b17d44 linter: Add typescript/strict-void-return rule (#19441)
(camc314)
- ed821b4 linter: Add typescript/consistent-type-exports rule (#19440)
(camc314)

### 🐛 Bug Fixes

- daad7bc linter/array-callback-return: Check `allowVoid` option
(#19506) (Said Atrahouch)
- 638cf94 linter: Add help text to eslint rule diagnostics (#19508)
(Kyle Tse)
- 79fc6d7 linter: Move no-use-before-define to eslint plugin (#19438)
(camc314)
- c832a9f linter: Add `onScrollEnd` and `onScrollEndCapture` to
`react/no-unknown-property`. (#19536) (connorshea)
- 999a0db linter: Add help text to `symbol-description` diagnostics
(#19538) (Anthony Amaro)
- f064482 linter: Add help text to eslint rule diagnostics (#19539)
(Anthony Amaro)
- fd11073 linter/react/no-unknown-property: Add missing `fetchPriority`
prop (#19525) (João Pedro Schmitz)
- a9bb604 linter/no-shadow: Align initializer shadow handling with
typescript-eslint (#19462) (camc314)
- 32e6eb9 linter: Handle typed arrays/array buffers in `prefer-spread`
rule. (#19478) (connorshea)
- e309f84 linter: Handle additional cases in
`typescript/consistent-generic-constructors` rule. (#19477) (connorshea)
- 71db91a linter/array-callback-return: Check `fromAsync`, update test
cases (#19483) (Said Atrahouch)
- 2a12d74 linter: Handle optional chaining in
`no-array-method-this-argument` rule. (#19476) (connorshea)
- f65310b linter: Handle optional chaining in
`prefer-object-from-entries` rule. (#19475) (connorshea)
- 840acf4 linter: Handle optional chain in
`no-unnecessary-array-flat-depth` rule. (#19471) (connorshea)
- 85a19e9 linter: Skip string literal imports in `consistent-assert`
rule. (#19474) (connorshea)

### ⚡ Performance

- 6155ac4 linter/constructor-super: Use node_id over nodes loop (#19489)
(camc314)
- a02496d linter/consistent-index-object-style: Resolve circular type
refs semantically (#19490) (camc314)
# Oxfmt
### 🚀 Features

- 652c346 oxfmt/lsp: Support `untitled://` schema (#19287) (Sysix)

### 🐛 Bug Fixes

- 6c61b70 oxfmt: Fix outdated `sortImports.groups` doc comments (#19513)
(leaysgur)

Co-authored-by: camc314 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-editor Area - Editor and Language Server A-formatter Area - Formatter C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments