fix(linter/no-else-return): preserve statement boundary in fixer#22687
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
222b26e to
3fd1c8b
Compare
3fd1c8b to
a6188ca
Compare
Merge activity
|
) ## Summary `eslint/no-else-return` could remove an `else` block in a way that glued the moved statement to the next token. In minified code, this turned a valid pattern like: ```js if (foo) { return bar } else { baz = qux } while (baz) {} ``` into invalid syntax because the moved assignment and following `while` were no longer separated. This fixes that by adding an explicit semicolon only when the moved statement needs a boundary before the next token. The check uses the existing line-terminator utility and is limited to the expression/return statement shapes that can run into the following token. I also added a focused regression case for the minified shape that triggered the bug. ## Ecosystem CI This came from the failing `vercel/next.js` ecosystem CI job: https://github.com/oxc-project/oxc-ecosystem-ci/actions/runs/26298001101/job/77416984230 The job panicked while running `oxlint --fix ... -D all` because the fixer produced invalid syntax after applying `no-else-return`.
8786840 to
71d2a3b
Compare
There was a problem hiding this comment.
Pull request overview
Fixes an eslint/no-else-return autofix edge case where removing an else block could concatenate the moved statement with the next token (notably in minified code), producing invalid JavaScript.
Changes:
- Adds logic to optionally append a trailing semicolon when moving
elsecontents out of anifand a statement boundary is required. - Introduces helper functions to determine whether a separator is needed and to fetch the last statement of an
elsebranch. - Adds a regression fix test covering the minified
...}while(...)...shape that previously broke.
) ## Summary `eslint/no-else-return` could remove an `else` block in a way that glued the moved statement to the next token. In minified code, this turned a valid pattern like: ```js if (foo) { return bar } else { baz = qux } while (baz) {} ``` into invalid syntax because the moved assignment and following `while` were no longer separated. This fixes that by adding an explicit semicolon only when the moved statement needs a boundary before the next token. The check uses the existing line-terminator utility and is limited to the expression/return statement shapes that can run into the following token. I also added a focused regression case for the minified shape that triggered the bug. ## Ecosystem CI This came from the failing `vercel/next.js` ecosystem CI job: https://github.com/oxc-project/oxc-ecosystem-ci/actions/runs/26298001101/job/77416984230 The job panicked while running `oxlint --fix ... -D all` because the fixer produced invalid syntax after applying `no-else-return`.
1f71ba9 to
27268a0
Compare
# Oxlint ### 🚀 Features - e4b1f46 linter/typescript: Implement `method-signature-style` rule (#22679) (Mikhail Baev) - bc462ca linter/vue: Implement no-reserved-component-names rule (#22741) (bab) - ef9e751 linter/vue: Implement component-definition-name-casing rule (#22818) (bab) - d67f51a linter/vue: Implement require-prop-type-constructor rule (#22708) (bab) - 1444f82 linter/promise/spec-only: Add `Promise.try` to `Promise` static methods (#22812) (Ben Saufley) - 8422e8b linter/jsdoc: Implement `require-yields-description` rule (#22805) (Mikhail Baev) - fe93f97 linter/eslint: Implement `prefer-named-capture-group` rule (#22759) (Sebastian Poxhofer) - 1a7798b linter: Add suggestion for `unicorn/no-new-array` (#22682) (Sysix) ### 🐛 Bug Fixes - 760a9f9 linter: Report errors when writing to the filesystem (#22881) (camc314) - e5a2748 linter: Avoid no-unreachable false positive after conditional loop (#22869) (camc314) - 39d92d6 linter/arrow-body-style: Preserve comments within function (#22854) (Sysix) - 3d13e29 parser: Reject `declare` in an already-ambient context (TS1038) (#22850) (Boshen) - 5152854 parser: Reject statements in ambient contexts (TS1036) (#22849) (Boshen) - 2eafea6 parser: Reject function implementations in ambient contexts (TS1183) (#22845) (Boshen) - c645615 parser: Reject incompatible class member modifiers (#22843) (Boshen) - 4a1ca4a linter/export: Detect duplicate explicit exports (#22798) (camc314) - 0a9a735 linter/no-loop-func: Allow safe let closures (#22811) (camc314) - 1599f11 linter: Align lsp extends default plugins (#22788) (camc314) - db32ec9 linter/no-accumulating-spread: Use loop as primary span (#22800) (camc314) - 33ec6b4 linter/consistent-test-it: Avoid adjacent describe leakage (#22796) (camc314) - 2606069 linter/no-array-sort: Unwrap parenthesized sort args (#22794) (camc314) - 9f2f709 linter/no-array-sort: Skip non compare fn sort arguments (#22752) (Gaurav Dubey) - 27268a0 linter/no-else-return: Preserve statement boundary in fixer (#22687) (camc314) - d9cb6d8 linter/no-empty-function: Allow functions callbacks with `allow: functions` (#22764) (camc314) - a40a314 linter/no-shadow-restricted-names: Ignore enum members (#22762) (camc314) - 82366d9 linter/no-cond-assign: Align ternary handling (#22761) (camc314) ### 📚 Documentation - 5e113ba linter: Add license notices for ported ESLint plugins (#22768) (Boshen) # Oxfmt ### 🚀 Features - d75cbbf oxfmt: Format `parser:json` files by `oxc_formatter_json` (#22709) (leaysgur) - 49db054 formatter_json: Implement `oxc_formatter_json` (json variant only) (#22641) (leaysgur) - 9c71f2e ast, codegen, formatter: Add `WithClauseKeyword::as_str` helper and use it (#22791) (camc314) ### 🐛 Bug Fixes - d3cdd62 oxfmt: Skip formatting for whitespace-only file (#22780) (leaysgur) - 23f0cc8 formatter: Don't move comments inside variable declaration in for in loop (#22776) (leaysgur) - f200c40 formatter: Don't move comments inside variable declaration in for of loop (#22773) (Leonabcd123) ### 📚 Documentation - 845f393 oxfmt,formatter,formatter_json,formatter_core: Add/update AGENTS.md (#22873) (leaysgur)
Summary
eslint/no-else-returncould remove anelseblock in a way that glued the moved statement to the next token. In minified code, this turned a valid pattern like:into invalid syntax because the moved assignment and following
whilewere no longer separated.This fixes that by adding an explicit semicolon only when the moved statement needs a boundary before the next token. The check uses the existing line-terminator utility and is limited to the expression/return statement shapes that can run into the following token. I also added a focused regression case for the minified shape that triggered the bug.
Ecosystem CI
This came from the failing
vercel/next.jsecosystem CI job:https://github.com/oxc-project/oxc-ecosystem-ci/actions/runs/26298001101/job/77416984230
The job panicked while running
oxlint --fix ... -D allbecause the fixer produced invalid syntax after applyingno-else-return.