Skip to content

fix(parser): don't emit TS1477 for parenthesized instantiation expression#23147

Merged
graphite-app[bot] merged 1 commit into
mainfrom
fix-ts1477-parenthesized-instantiation
Jun 9, 2026
Merged

fix(parser): don't emit TS1477 for parenthesized instantiation expression#23147
graphite-app[bot] merged 1 commit into
mainfrom
fix-ts1477-parenthesized-instantiation

Conversation

@Boshen

@Boshen Boshen commented Jun 9, 2026

Copy link
Copy Markdown
Member

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

@github-actions github-actions Bot added the A-parser Area - Parser label Jun 9, 2026
@codspeed-hq

codspeed-hq Bot commented Jun 9, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 57 untouched benchmarks
⏩ 14 skipped benchmarks1


Comparing fix-ts1477-parenthesized-instantiation (b20c584) with main (e78e75b)2

Open in CodSpeed

Footnotes

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

  2. No successful run was found on main (8ab6ee1) during the generation of this report, so e78e75b was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@Boshen Boshen force-pushed the fix-ts1477-parenthesized-instantiation branch from 9cabfd6 to 5c78c0c Compare June 9, 2026 09:36

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread crates/oxc_parser/src/js/expression.rs
@Boshen Boshen force-pushed the fix-ts1477-parenthesized-instantiation branch 3 times, most recently from 0a97c77 to b20c584 Compare June 9, 2026 10:29
@Boshen Boshen added the 0-merge Merge with Graphite Merge Queue label Jun 9, 2026

Boshen commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

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)
@graphite-app graphite-app Bot force-pushed the fix-ts1477-parenthesized-instantiation branch from b20c584 to e89f81d Compare June 9, 2026 10:34
@graphite-app graphite-app Bot merged commit e89f81d into main Jun 9, 2026
30 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label Jun 9, 2026
@graphite-app graphite-app Bot deleted the fix-ts1477-parenthesized-instantiation branch June 9, 2026 10:38
Boshen added a commit that referenced this pull request Jun 15, 2026
### 💥 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-parser Area - Parser

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parser: false-positive TS1477 on parenthesized instantiation expression

1 participant