Skip to content

fix(formatter): handle comments after pipe in single-member union types#21487

Merged
leaysgur merged 4 commits intooxc-project:mainfrom
costajohnt:fix/formatter-union-comment
Apr 17, 2026
Merged

fix(formatter): handle comments after pipe in single-member union types#21487
leaysgur merged 4 commits intooxc-project:mainfrom
costajohnt:fix/formatter-union-comment

Conversation

@costajohnt
Copy link
Copy Markdown
Contributor

Summary

  • Extend the hug-shortcut guard and leading comment collection to detect own-line comments between | and the first member in single-member union types
  • Add test fixture covering line comments, block comments, and multiple comments

Why

The formatter's single-member union "hug" optimization (type A = | "VALUE"type A = "VALUE") was incorrectly triggered when own-line comments appeared after the | pipe. The comment detection only checked comments_before(self.span().start) (before the |), missing comments between | and the member.

Before:

type A = // comment
B;

After (matches Prettier):

type A =
  // comment
  | B;

Verification

  • All 270 formatter tests pass (zero regressions)
  • New fixture covers: line comments, block comments, multiple comments after pipe

Closes #21399

When a single-member union type has own-line comments between the
pipe and the first member, the formatter's hug shortcut incorrectly
activates because it only checked for comments before the union's
span start, missing comments between | and the member.

Extend both the hug-shortcut guard and the leading comment collection
to detect comments at the first member's span start for single-member
unions at the alias level. Guard against parenthesized and nested
union types to avoid regressions in complex cases.

Closes oxc-project#21399
@github-actions github-actions Bot added A-formatter Area - Formatter C-bug Category - Bug labels Apr 16, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 16, 2026

Merging this PR will not alter performance

✅ 44 untouched benchmarks
⏩ 7 skipped benchmarks1


Comparing costajohnt:fix/formatter-union-comment (ea9fff6) with main (836fe9d)

Open in CodSpeed

Footnotes

  1. 7 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.

@leaysgur
Copy link
Copy Markdown
Member

/oxfmt-ecosys

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 16, 2026

Oxfmt Ecosystem CI

suite oxfmt@latest refs/pull/21487/head branch
formatjs/formatjs
eggjs/egg
cnpm/cnpmcore
monkeytypegame/monkeytype
fuma-nama/fumadocs
actualbudget/actual
vuejs/pinia
tale/headplane
AmanVarshney01/create-better-t-stack
vercel/turborepo
cloudflare/agents
lichess-org/lila
dyad-sh/dyad
mastodon/mastodon
openclaw/openclaw
Comfy-Org/ComfyUI_frontend
getsentry/sentry-javascript
aidenybai/react-grab
npmx-dev/npmx.dev
huggingface/huggingface.js
rolldown/rolldown
vuejs/core
fastify/fastify-vite

@leaysgur
Copy link
Copy Markdown
Member

(I may update the comment and do some refactoring later but,) Thank you very much!

@leaysgur leaysgur merged commit a501a53 into oxc-project:main Apr 17, 2026
33 checks passed
graphite-app Bot pushed a commit that referenced this pull request Apr 17, 2026
@costajohnt costajohnt deleted the fix/formatter-union-comment branch April 17, 2026 03:51
camc314 added a commit that referenced this pull request Apr 20, 2026
# Oxlint
### 💥 BREAKING CHANGES

- 24fb7eb allocator: [**BREAKING**] Rename `Box` and `Vec` methods
(#21395) (overlookmotel)

### 🚀 Features

- 38d8090 linter/jest: Implemented jest `version` settings in config
file. (#21522) (Said Atrahouch)
- 7dbbb99 linter/eslint: Implement suggestion for `no-case-declarations`
rule (#21508) (Mikhail Baev)
- 9b4d9f6 linter/prefer-template: Implement autofix (#21502) (François)
- daa64ed linter/no-empty-pattern: Add `allowObjectPatternsAsParameters`
option (#21474) (camc314)
- cf2d281 linter/typescript: Implement explicit-member-accessibility
(#21447) (Hunter Tunnicliff)
- d48de6f linter/unicorn: Add help messages to 3 rule diagnostics
(#21459) (Mukunda Rao Katta)
- cffdc2e linter: Backfill rule version metadata (#21391) (Old Autumn)

### 🐛 Bug Fixes

- 1e69b91 linter/no-useless-assignment: Improve diagnostic spans
(#21581) (camc314)
- f272594 linter/plugins: Align `RuleMeta.replacedBy` type with ESLint
(#21544) (bab)
- 4d57851 linter/eslint: Enhance `no-empty-function` rule to support
async and generator functions in VariableDeclarator (#21542) (Mikhail
Baev)
- 00fc136 codegen: Preserve coverage comments before object properties
(#21312) (bab)
- a56b7b9 oxlint: Dont enable gitlab formatter by default (#21501)
(camc314)
- 9c9b6a2 linter/array-callback-return: Ignore non-exit CFG dead ends
(#21497) (camc314)
- 61088e0 linter/unicorn: Handle computed property access in
`prefer-dom-node-remove` rule (#21470) (Mikhail Baev)
- eab5934 linter: Report an error on unsupported `extends` values
(#21406) (John Costa)
- 3289ba0 linter/valid-expect-in-promise: Check a jest fn to be `test`
instead of `describe` (#21422) (Said Atrahouch)
- 4417fe3 linter/prefer-ending-with-an-expect: Ignore vi.mock factory
callbacks (#21414) (Cédric Exbrayat)
- a904883 linter/consistent-type-imports: Ignore vue/svelte/astro files
(#21415) (bab)
- 2498fe6 linter/no-unused-vars: Allow segments of dotted namespace
declarations (#21416) (bab)
- 44b5b35 linter: Preserve vitest-compatible jest rules when applying
overrides (#21389) (Cameron)
- 7bd8331 linter/prefer-ending-with-an-expect: Add missing `version`
docs (#21390) (Said Atrahouch)
- 43d8f0d linter/no-useless-assignment: Ignore writes read by closures
(#21380) (camc314)

### 📚 Documentation

- c1eeae3 linter: Add version to `rule.json` (#21547) (camchenry)
- 0ec6ab2 linter: Improve the `vitest/no-importing-vitest-globals` rule
documentation. (#21557) (connorshea)
# Oxfmt
### 💥 BREAKING CHANGES

- 24fb7eb allocator: [**BREAKING**] Rename `Box` and `Vec` methods
(#21395) (overlookmotel)

### 🚀 Features

- 5aa7fe1 oxfmt: Add `--disable-nested-config` CLI flag (#21514)
(leaysgur)
- b5cb8d1 oxfmt: Update prettier to 3.8.3 (#21451) (leaysgur)
- 16713d5 oxfmt/cli: Support per-directory config (#21103) (leaysgur)
- 952de06 oxfmt/lsp: Support per-directory config (#21081) (leaysgur)

### 🐛 Bug Fixes

- a501a53 formatter: Handle comments after pipe in single-member union
types (#21487) (John Costa)
- 6f49fad oxfmt: Respect nested config.`ignorePatterns` (#21489)
(leaysgur)
- 7c98d52 oxfmt: Do not panic on finding invalid nested config (#21461)
(leaysgur)
- 41bb2d5 formatter: Preserve more `intrinsic` parens (#21449)
(leaysgur)
- f894750 formatter: Preserve parens around `intrinsic` in type alias
annotation (#21410) (Dunqing)

### ⚡ Performance

- df27b48 oxfmt: Skip ancestors check when no nested config found
(#21517) (leaysgur)
- 5e1522a oxfmt: Do not occupy the rayon thread solely for handover
(#21408) (leaysgur)

Co-authored-by: camc314 <18101008+camc314@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-formatter Area - Formatter C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

formatter: Diff with Prettier on single member union type with comment after pipe

3 participants