Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ast/estree): Better align program span start #10134

Merged

Conversation

therewillbecode
Copy link
Contributor

@therewillbecode therewillbecode commented Mar 30, 2025

This PR adjusts the start span of the program node to the first token of the first statement in order to align with TS-EStree serialisation. Previously the program start span was always 0.

The diff removes many mismatches but also adds around 35 new ones. Seem to be mostly related to strict mode directives.

For the mismatches that are added to the snapshot, I wonder if they just happened to not be mismatches because of the fact our Program spans used to always be 0 and the conformance tester incorrectly expected it to also be 0. TS-eslint seems to ignore comments when calculating the Program start span whereas our conformance snapshot cases don't ignore them.

The below code serialises to TS-ESTree with a program start span of 16 (see playground).

// @target: ES5
if (true) {}

However our conformance tester works such that we expect start span to be 0 which doesn't line up with the playground example linked. So I think its actually our conformance test parser thats set up wrong for the ~35 mismatches that this PR adds to the snapshot.

Copy link

graphite-app bot commented Mar 30, 2025

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.

@github-actions github-actions bot added A-ast Area - AST C-bug Category - Bug labels Mar 30, 2025
Copy link

codspeed-hq bot commented Mar 30, 2025

CodSpeed Instrumentation Performance Report

Merging #10134 will not alter performance

Comparing therewillbecode:fix/fix-program-span-start (0b38c8c) with main (f547d76)

Summary

✅ 36 untouched benchmarks

@therewillbecode therewillbecode force-pushed the fix/fix-program-span-start branch from 120c924 to 608ffde Compare April 2, 2025 07:34
@overlookmotel
Copy link
Contributor

Hmm. This is really odd!

I've delved into it a bit more...

Further oddities

Acorn includes comments in the Program start span, but both Espree and TS-ESLint do not.

Espree and TS-ESLint also exclude whitespace (line breaks or spaces) from Program start span.

Babel also behaves the same as Acorn (span of the Program is the total length of the file). But Babel has its own AST shape which doesn't conform to ESTree, so that's not very relevant.

But... Espree also does not include any trailing comments or whitespace at end of the file in Program end span.

Espree is the default parser for ESLint, so TS-ESLint should be aiming to be compatible with it. The fact that TS-ESLint behaves differently for trailing comments/whitespace I think should be considered a bug in TS-ESLint.

But... should Espree and TS-ESLint be including comments/whitespace in Program span or not? ESTree spec doesn't seem to say anything about spans/ranges/locations. So there's no "spec" to conform to. So, who's right??

Comments:

Whitespace:

What to do?

We should raise an issue on TS-ESLint to point out the discrepancy between it and Espree. Personally, I'd like to see Program span include the whole file (Acorn style). It doesn't make much sense for Acorn and Espree be out of line with each other. But probably no-one will want to make a breaking change.

To fix our tests in meantime, I think doing what you've done in this PR is probably the best way forward. However, you could also take into account directives. That might pass a few more tests.

if let Some(first_directive) = self.directives.first() {
    self.span.start = first_directive.span.start;
} else if let Some(first_stmt) = self.body.first() {
    self.span.start = first_stmt.span.start;
}

As you say, there's likely something else going on the conformance runner, but it'll be easier to figure that out once directives are handled like TS-ESLint does.

@overlookmotel
Copy link
Contributor

Also, please add a comment where you change the start span as to why this is necessary, and a link to this PR (or one of the TS-ESLint AST explorer links above).

@therewillbecode therewillbecode force-pushed the fix/fix-program-span-start branch from 608ffde to 74ea52a Compare April 2, 2025 14:20
@therewillbecode
Copy link
Contributor Author

therewillbecode commented Apr 2, 2025

Also, please add a comment where you change the start span as to why this is necessary, and a link to this PR (or one of the TS-ESLint AST explorer links above).

Thanks @overlookmotel for looking into this! Yes odd indeed.

I have implemented your suggestions and hopefully my amendment to the comment gives sufficient rationale for the change.

@therewillbecode therewillbecode force-pushed the fix/fix-program-span-start branch from 74ea52a to 84ca9e9 Compare April 2, 2025 18:37
Copy link
Contributor

@overlookmotel overlookmotel left a comment

Choose a reason for hiding this comment

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

Great. No new failing tests now!

@overlookmotel overlookmotel force-pushed the fix/fix-program-span-start branch from 84ca9e9 to 0b38c8c Compare April 3, 2025 08:34
@overlookmotel overlookmotel merged commit abc9ea4 into oxc-project:main Apr 3, 2025
25 checks passed
graphite-app bot pushed a commit that referenced this pull request Apr 3, 2025
#10134 fixed the start span of `Program` in TS AST to align with TS-ESLint.

Change the method this is achieved by - use a custom converter instead of mutating the AST in `to_estree_ts_json` and `to_pretty_estree_ts_json`. This method is more convoluted, but I think it's preferable if serialization does not have side effect of mutating the AST.
@overlookmotel
Copy link
Contributor

I've opened an issue about TS-ESLint's non-alignment with Espree: typescript-eslint/typescript-eslint#11026

@therewillbecode therewillbecode deleted the fix/fix-program-span-start branch April 11, 2025 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ast Area - AST C-bug Category - Bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants