fix(parser): don't emit TS1477 for parenthesized instantiation expression#23147
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
9cabfd6 to
5c78c0c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c78c0c327
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0a97c77 to
b20c584
Compare
Merge activity
|
…sion (#23147) `oxc_parser` emitted TS1477 ("An instantiation expression cannot be followed by a property access") for parenthesized instantiation expressions such as `(a<b>).c` when `preserve_parens: false` (the mode oxfmt and oxlint use). tsc and Babel accept it — only the *unparenthesized* form is an error. The old check keyed off `lhs` being a `TSInstantiationExpression`, but the `ParenthesizedExpression` wrapper that distinguishes `(a<b>).c` from `a<b>.c` is dropped when `preserve_parens` is off, so the bare instantiation leaked through. ## Fix Emit TS1477 only when the instantiation expression is *not* parenthesized. Instead of relying on a `ParenthesizedExpression` node surviving the AST, detect it by span: an instantiation built in the member-expression loop starts at `lhs_span`, while one unwrapped from a stripped paren starts past the `(`. A shared helper covers both the property-access (`.`) and element-access (`[`) branches. | source | result | notes | | --- | --- | --- | | `a<b>.c` | TS1477 | | | `a<b>?.[c]` | TS1477 | element access on a bare instantiation | | `a?.b<c>.d` | TS1477 | | | `(a<b>).c` | ok | the fix | | `(a<b>)[c]` / `(a<b>)?.[c]` | ok | the fix | | `(a).b<c>.d` | TS1477 | parens wrap `a`, not the instantiation | Correct regardless of `preserve_parens`; under the default (`true`) behavior is unchanged, so no conformance snapshots move. Note: tsc only checks property access (`parsePropertyAccessExpressionRest`), so it does not flag `a<b>?.[c]` — an apparent oversight, since accessing a member of an instantiation expression is the same operation either way. Babel flags both, and this PR keeps oxc's existing behavior for the unparenthesized element-access case. Closes #23133. Alternative to #23135 (same issue, same resulting behavior). That PR records parenthesized instantiation expressions in a new `ParserState` set; this one derives the same fact from spans, needing no extra parser state. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
b20c584 to
e89f81d
Compare
### 💥 BREAKING CHANGES - 7a24911 codegen: [**BREAKING**] Borrow sourcemaps from codegen (#23422) (Boshen) - bb0ed44 transformer: [**BREAKING**] Disable styled-components transpileTemplateLiterals by default (#23171) (Boshen) ### 🚀 Features - 1490a0a linter/react: Implement react-compiler rule (#23202) (Boshen) - 6c0bdf0 transformer/react-refresh: Support `module.property.useHook()` (#23190) (Dunqing) - 47991bd semantic: Report TS1228 for invalid type predicates (#23174) (camc314) - 1d3af58 parser: Add TS2398 parameter property diagnostic (#23216) (camc314) - 44313da semantic: Add `scope_is_descendant_of` api (#22313) (camc314) - e5050c0 parser: Improve diagnostic for rest initializer (#23205) (camc314) - ec266bb transformer: Run React Compiler as a feature-gated transform pass (#23201) (Boshen) - e7374fe parser: Report error for `const` modifier on interface type parameter (#23173) (camc314) - a7c1c9b parser: Report ambient definite variable assertions (#23165) (camc314) - d169fcd parser: Report invalid class definite assertions (#23164) (camc314) - 00244d8 parser: Report definite property initializer errors (#23160) (camc314) ### 🐛 Bug Fixes - 52d0c31 transformer: Replace ambient dot defines (#23231) (camc314) - 2c28748 transformer/class: Parent generated constructors to class scope (#23222) (camc314) - 8edd234 parser: Report accessor definite assertion on token (#23203) (camc314) - de38a3f react_compiler: Keep imports referenced only by a local re-export (#23176) (Boshen) - f5721c2 codegen: Preserve parentheses around `intrinsic` type reference (#23156) (Boshen) - e89f81d parser: Don't emit TS1477 for parenthesized instantiation expression (#23147) (Boshen) - 8a04149 parser: Reject module-referencing imports/exports in a namespace body (#22829) (Boshen) ### ⚡ Performance - 2783295 parser: Table-driven operator precedence lookup (#23346) (Boshen) - 231d5de parser: Single-match member expression dispatch (#23347) (Boshen) - e89729b codegen: Accept one-shot wrap closures (#23265) (camc314) - a6c11fa parser: Force-inline read_non_decimal to fold per-digit number dispatch (#23157) (Boshen) - d74964c parser: Store class definite assertion offset (#23170) (camc314) - f0fda4d parser: Shrink-wrap cold diagnostic tails out of hot frames (#23159) (Boshen) - a082180 parser: Store definite assertion offset (#23167) (camc314) - 534f9c6 oxc: Conditionally rebuild semantic in compiler pipeline (#23153) (Boshen) - b435c6a parser: Skip checkpoint for `infer T extends U` constraint in disallow context (#23128) (Boshen) - 7464dce parser: Peek instead of checkpoint/rewind for `export default` modifier (#23124) (Boshen) - 80a9a32 parser: Fast-path single-keyword TS declarations (#23083) (Boshen) - da1a6c6 diagnostics: Migrate to allocation-optimized oxc-miette (#23094) (Boshen) - b7b08ce parser: Peek once for the static modifier disambiguation (#23079) (Boshen) - e7e07a3 parser: Fold unary dispatch into a single match (#23076) (Boshen) ### 📚 Documentation - d241add semantic: Add `AGENTS.md` test guidance for agents (#23441) (camc314) - 026f1ae parser: Add `AGENTS.md` test guidance for agents (#23440) (camc314) - 09755ac transformer: Add `AGENTS.md` test guidance for agents (#23439) (camc314) - e6bdfd4 lexer: Correct reference link for `byte_handlers!` (#23313) (Dunqing) - 65b6d7a allocator: Fix memory leaks in `Arena` examples (#23257) (overlookmotel) Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
oxc_parseremitted TS1477 ("An instantiation expression cannot be followed by a property access") for parenthesized instantiation expressions such as(a<b>).cwhenpreserve_parens: false(the mode oxfmt and oxlint use). tsc and Babel accept it — only the unparenthesized form is an error.The old check keyed off
lhsbeing aTSInstantiationExpression, but theParenthesizedExpressionwrapper that distinguishes(a<b>).cfroma<b>.cis dropped whenpreserve_parensis off, so the bare instantiation leaked through.Fix
Emit TS1477 only when the instantiation expression is not parenthesized. Instead of relying on a
ParenthesizedExpressionnode surviving the AST, detect it by span: an instantiation built in the member-expression loop starts atlhs_span, while one unwrapped from a stripped paren starts past the(. A shared helper covers both the property-access (.) and element-access ([) branches.a<b>.ca<b>?.[c]a?.b<c>.d(a<b>).c(a<b>)[c]/(a<b>)?.[c](a).b<c>.da, not the instantiationCorrect regardless of
preserve_parens; under the default (true) behavior is unchanged, so no conformance snapshots move.Note: tsc only checks property access (
parsePropertyAccessExpressionRest), so it does not flaga<b>?.[c]— an apparent oversight, since accessing a member of an instantiation expression is the same operation either way. Babel flags both, and this PR keeps oxc's existing behavior for the unparenthesized element-access case.Closes #23133.
Alternative to #23135 (same issue, same resulting behavior). That PR records parenthesized instantiation expressions in a new
ParserStateset; this one derives the same fact from spans, needing no extra parser state.🤖 Generated with Claude Code