Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
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. |
…iting Co-authored-by: Dunqing <29533304+Dunqing@users.noreply.github.com>
…mplements clause Co-authored-by: Dunqing <29533304+Dunqing@users.noreply.github.com>
Co-authored-by: Dunqing <29533304+Dunqing@users.noreply.github.com>
Co-authored-by: Dunqing <29533304+Dunqing@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a critical bug in the isolated declarations transformer where variable declarations were incorrectly dropped from .d.ts output. The issue occurred when a variable was shadowed by a type alias with the same name, and that type alias was referenced in a class implements clause.
Key Changes:
- Fixed
add_reference()to mergeKindFlagswith bitwise OR instead of overwriting - Fixed
resolve_references()to merge flags when propagating unresolved references to parent scopes - Added comprehensive test case demonstrating the fix
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
crates/oxc_isolated_declarations/src/scope.rs |
Fixed add_reference() and resolve_references() to merge KindFlags using bitwise OR (|=) instead of overwriting with HashMap::insert() |
crates/oxc_isolated_declarations/tests/fixtures/shadowed.ts |
Added test case for variable shadowed by type alias referenced in implements clause |
crates/oxc_isolated_declarations/tests/snapshots/shadowed.snap |
Updated snapshot showing correct emission of both const and type declarations |
.gitignore |
Added .serena/memories to ignored paths (unrelated maintenance change) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
CodSpeed Performance ReportMerging #16328 will not alter performanceComparing Summary
Footnotes
|
…with same name is referenced in implements clause (oxc-project#16328) - [x] Understand the issue: variable declarations with shadowed type names are dropped when the type is referenced in implements clause - [x] Identify root cause: `add_reference` and `resolve_references` were overwriting flags instead of combining them - [x] Implement fix: use bitwise OR to combine `KindFlags` when adding references and merging scopes - [x] Add test case to fixtures (extended shadowed.ts with issue oxc-project#10996 test case) - [x] Run tests and update snapshots - [x] Run code review - [x] Run CodeQL security check (no issues found) - [x] Verify fix manually with original issue example - [x] Reverted .gitignore change per reviewer feedback ## Summary This PR fixes issue oxc-project#10996 where variable declarations with shadowed type names were incorrectly dropped when the type was referenced in a class `implements` clause. ### Problem When a variable name is shadowed by a type alias and that type is referenced in `implements`, the variable declaration was missing from `.d.ts` output. ### Root Cause `ScopeTree` used `HashMap::insert()` which overwrites reference flags. When a name had both `KindFlags::Value` (from `typeof Test2`) and `KindFlags::Type` (from `implements Thing<Test2>`), only the last one was preserved. ### Fix Changed `add_reference()` and `resolve_references()` to combine flags using bitwise OR (`|=`) instead of overwriting. <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[isolatedDeclarations] variable emit is dropped if the variable is shadowed as a type name and the type is part of a class implements interface</issue_title> > <issue_description># Repo > > ```ts > export interface Thing<T> {} > > /** WORKS */ > > const Test1 = 'test1' as const; > export type Test1 = typeof Test1; > export class Class1 { > readonly id: 'test1' = Test1; > } > > /** DOES NOT WORK */ > > const Test2 = 'test2' as const; > export type Test2 = typeof Test2; > export class Class2 implements Thing<Test2> { > readonly id: 'test2' = Test2; > } > ``` > > # Expected > > ```ts > export interface Thing<T> { > } > /** WORKS */ > declare const Test1: "test1"; > export type Test1 = typeof Test1; > export declare class Class1 { > readonly id: 'test1'; > } > /** DOES NOT WORK */ > declare const Test2: "test2"; > export type Test2 = typeof Test2; > export declare class Class2 implements Thing<Test2> { > readonly id: 'test2'; > } > export {}; > ``` > [ts playground](https://www.typescriptlang.org/play/?#code/KYDwDg9gTgLgBASwHY2FAZgQwMbDgFQAtkBzAHnwD44BvAXwCgGB6AKlbgHUB5AJQGkAynFbMm2CEgDO8fMBkBGOAF44AclSK1cTFLgTpMANxxmzODGJ6SwGHuABbBDFQATBqEiwLATzB45RRVffwh0AnkYBSMPcGh4bAAbXT0AYWSpKSUaBjg4KGBMV0lEn0RXAC51TSjtVUComMYWdjgAEW4AUWEAOW58Lj5+ETEGAxkImQAmYI1Iqe1dfUkZEzM4Yvk4JAh4G3hHZzdYr3gYPwD54PPQ8IapmM94-Qy015mEBzBEx2AUPSIpAo82oOTyBSKJTKCEq1XmdUmMAeDGaQA) > > # Actual > > ```ts > export interface Thing<T> {} > /** WORKS */ > declare const Test1: "test1"; > export type Test1 = typeof Test1; > export declare class Class1 { > readonly id: "test1"; > } > export type Test2 = typeof Test2; > export declare class Class2 implements Thing<Test2> { > readonly id: "test2"; > } > export {}; > ``` > [oxc playground](https://playground.oxc.rs/#eNp1VE1PGzEQ/SuWL5UQVSBSJRRKpQqIVJUSSqJyycXZnU0MXntrzxKiKP+9z5u1idr0ktjz+ebN825lIUeS3hrnWWjL5CtVkJittF1+nn0R293czu3g5EQ8TR6/T8XJIN4LZwOLGQU+F1fiA8fDB6GC6ByXYjAQvNJBLImDoFozUzm3fRfeNGjQ58aLq/bXyxxSGBWCuI6/52I7t0J4UqWzZiN0OcoNr3JeRnkzuZ2K+8msg/sP2mFCO/wLbekoCOs4Iv4/4Jh+AHh4FPBQ6LoxVJPF7D2PMRhcHh8EWPaDxHrdIPJUOjnaSt/a+GewFzli39KprJyvFdB5OaqUCbCwVzZEc7bo4IzCADcEWF6xxpgpf73S6Nlgxzm8VnZp3q+FqxtPARm9IRSugXufHzb1wpl0K6plH7Y7lY3yIeLaQk5MNqAtpMXhDeMoY9z6kbj1dtJy0CWNW1tEZKlU7En+lR6UR26ydnm/Lr5Z9hoVi+wIBNisi1vvne+twBCp6jDgfEDVVraBZmrxPhSrxZMueSVHw1NJtpxUd9piSmkqwG3QjXv/xRm6YYuGfraO33l6Dm/TI+bf8fbgXYNeUoWPlqikEjWxJw14y2tX1yr6jIEVc+g8LGZZp/nhX6tNQMjCq+KFeIqlIT0FJ6uqaY+87+8Wz1Twk1cNaiRSY6MO61cGkYsWCMkfpIGtLKM9X6w8nkL8NITh2fknFACDN1QhZ+x8J/SxJlPmheAhkNdR9cpAeA66y4uBF08qW38Qq1IxSOi3dlywWxkAtsHuyVsFzSWohStpSd3TsHHHWY7PoXT4nPVsWrznrlayGFqm2K5K0nkUS3oEmNw1d/RKuegLUXMPlpN2ulTo0ZkxtBkzXskvXDjgUtu4g+jKpx3MZUdfNOfTLtojzWmm3R88D/Yg) > > Note the missing emit of `declare const Test2: "test2";`</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> - Fixes oxc-project#16314 <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/oxc-project/oxc/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Dunqing <29533304+Dunqing@users.noreply.github.com>
add_referenceandresolve_referenceswere overwriting flags instead of combining themKindFlagswhen adding references and merging scopesSourceType#10996 test case)Summary
This PR fixes issue #10996 where variable declarations with shadowed type names were incorrectly dropped when the type was referenced in a class
implementsclause.Problem
When a variable name is shadowed by a type alias and that type is referenced in
implements, the variable declaration was missing from.d.tsoutput.Root Cause
ScopeTreeusedHashMap::insert()which overwrites reference flags. When a name had bothKindFlags::Value(fromtypeof Test2) andKindFlags::Type(fromimplements Thing<Test2>), only the last one was preserved.Fix
Changed
add_reference()andresolve_references()to combine flags using bitwise OR (|=) instead of overwriting.Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.