Description
Which packages would you like to change?
-
espree
-
eslint-scope
-
eslint-visitor-keys
What problem do you want to solve?
The source range for Program
is surprising when source code starts or ends with comments.
e.g.:
// foo
x
// bar
Espree (like Esprima) produces an AST where range
of Program
node excludes whitespace and comments from start and end of file. In example above, the range of Program
node is [ 8, 9 ]
i.e. the range of the sole statement.
This differs from Acorn, which produces a range of [0, 17]
i.e. the whole of the source code.
What is particularly surprising is that with option comment: true
you get comments which are outside the range of the program that contains them:
{
type: 'Program',
start: 8,
end: 9,
body: [
{
type: 'ExpressionStatement',
start: 8,
end: 9,
expression: { type: 'Identifier', start: 8, end: 9, name: 'x' }
}
],
sourceType: 'script',
comments: [
{ type: 'Line', value: ' foo', start: 0, end: 6, range: [ 0, 6 ] },
{ type: 'Line', value: ' bar', start: 11, end: 17, range: [ 11, 17 ] }
]
}
As a further surprise, if the file contains only comments, then the behavior changes:
// foo
This produces a range of [ 0, 8 ]
. This does not align with Esprima, which produces range of [ 8, 8 ]
.
What do you think is the correct solution?
Espree's docs state that:
The primary goal is to produce the exact same AST structure and tokens as Esprima, and that takes precedence over anything else.
Given that Esprima has not received updates for 7 years, and is essentially defunct, I'm not sure whether the maintainers of Espree consider alignment with Esprima still to be the primary goal. I'm also not sure whether that aim, if it still holds, extends to source ranges, or just the AST shape.
What's the correct behavior?
This is arguable. But, in my opinion, it's unintuitive that comments which are part of a program exist in ranges outside of the Program
.
The example where the program consists of only comments I think is illustrative. What's the logical range for Program
to have in this case, if comments are excluded? [0, 0]
or [8, 8]
?
The fact that there isn't a clear answer I feel reveals there's a problem with the mental model.
[0, 8]
(as Espree currently does) makes most sense to me. But this is inconsistent with Esprima, and also inconsistent with Espree's behavior when there are statements in the program.
Others may feel differently.
Why does this matter?
In addition to the difference from Acorn, @typescript-eslint/parser
is also different again - for the first example, it gives a range of [8, 18]
! Though the maintainers seem to think Acorn's behavior would be preferable.
Personally, I think it's unfortunate that the 3 most depended-on ESTree-compatible parsers Espree, Acorn, and TS-ESLint differ in this respect.
What to do?
One way or another, in my opinion Espree's current behavior is incorrect.
- In the case which program is only comments, output differs from Esprima, violating Espree's stated goal.
- Or, if alignment with Esprima is not an aim as far as ranges are concerned, it would make more sense to have a less surprising behavior.
Changing behavior to match Acorn (which personally I'd advocate for) would be a breaking change. Though, given that the 3 most popular ESTree-compatible parsers differ from each in this regard and I'm not aware of anyone complaining about it before, probably not a big one!
Participation
- I am willing to submit a pull request for this change.
Additional comments
No response
Metadata
Metadata
Assignees
Type
Projects
Status