Skip to content

perf(span): faster conversion of path/extension to SourceType#10996

Merged
graphite-app[bot] merged 1 commit intomainfrom
05-13-perf_span_faster_conversion_of_path_extension_to_sourcetype_
May 13, 2025
Merged

perf(span): faster conversion of path/extension to SourceType#10996
graphite-app[bot] merged 1 commit intomainfrom
05-13-perf_span_faster_conversion_of_path_extension_to_sourcetype_

Conversation

@overlookmotel
Copy link
Member

@overlookmotel overlookmotel commented May 13, 2025

In SourceType::from_path and SourceType::from_extension, remove expensive string matching and branches by converting extension string to an enum FileExtension only once, and then performing all further operations on that enum.

@github-actions github-actions bot added the C-performance Category - Solution not expected to change functional behavior, only performance label May 13, 2025
Copy link
Member Author


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

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.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@overlookmotel overlookmotel marked this pull request as ready for review May 13, 2025 10:28
@codspeed-hq
Copy link

codspeed-hq bot commented May 13, 2025

CodSpeed Instrumentation Performance Report

Merging #10996 will not alter performance

Comparing 05-13-perf_span_faster_conversion_of_path_extension_to_sourcetype_ (c50b1a5) with main (1673ffb)

Summary

✅ 36 untouched benchmarks

@overlookmotel overlookmotel force-pushed the 05-13-perf_span_faster_conversion_of_path_extension_to_sourcetype_ branch from 7a562ee to 04934e8 Compare May 13, 2025 10:36
@Boshen Boshen added the 0-merge Merge with Graphite Merge Queue label May 13, 2025
Copy link
Member

Boshen commented May 13, 2025

Merge activity

In `SourceType::from_path` and `SourceType::from_extension`, remove expensive string matching and branches by converting extension string to an enum `FileExtension` only once, and then performing all further operations on that enum.
@graphite-app graphite-app bot force-pushed the 05-13-perf_span_faster_conversion_of_path_extension_to_sourcetype_ branch from 04934e8 to c50b1a5 Compare May 13, 2025 11:26
@graphite-app graphite-app bot merged commit c50b1a5 into main May 13, 2025
25 checks passed
@graphite-app graphite-app bot deleted the 05-13-perf_span_faster_conversion_of_path_extension_to_sourcetype_ branch May 13, 2025 11:33
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label May 13, 2025
Dunqing added a commit that referenced this pull request Dec 1, 2025
…with same name is referenced in implements clause (#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 #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 #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 #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>
taearls pushed a commit to taearls/oxc that referenced this pull request Dec 11, 2025
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-performance Category - Solution not expected to change functional behavior, only performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants