fix: add test for failing regression and fix program.comments not sorted by range#198
Merged
NullVoxPopuli merged 2 commits intoember-tooling:mainfrom Apr 24, 2026
Conversation
ce0502a to
b46414f
Compare
ESLint's SourceCode builds both `tokensAndComments = sortedMerge(tokens,
comments)` and the token-store's `createIndexMap(tokens, comments)`
assuming each input array is sorted by `range[0]`. Every standard JS
parser (espree, @babel/eslint-parser, @typescript-eslint/parser) honors
that invariant.
When a .gts file has a JS /* */ comment interleaved between templates,
TS-parser comments are spread into program.comments first and Glimmer
template comments get appended — producing an array whose order doesn't
match range order:
const X = <template>{{! glimmer at 22 }}</template>;
/* js at 56 */
const Y = 1;
ast.comments: [[65,87] js, [23,51] glimmer] ← unsorted
The downstream effect is that `sourceCode.getTokenBefore(glimmer)` /
`getTokenAfter(glimmer)` return wrong tokens:
before: ";" @ [63,64] (wrong — that's *after* the comment)
after: "const" @ [88,93] (skips </template>)
Adds two tests:
1. ast.comments is sorted by range[0] — direct structural assertion.
2. getTokenBefore / getTokenAfter on a Glimmer comment return
source-adjacent tokens — end-to-end through Linter.
Both currently fail; they'll pass once program.comments is sorted.
ESLint's SourceCode.tokensAndComments merge and createIndexMap both assume comments are sorted by range[0]; appending Glimmer comments after the TS-parser comments breaks that invariant when a JS block comment sits between templates, producing wrong results from getTokenBefore/getTokenAfter on template comments.
b46414f to
20410ac
Compare
NullVoxPopuli
approved these changes
Apr 24, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #196.
Observed
With #196 applied,
program.commentscomes out unsorted whenever a JS/* */comment sits between two templates:ESLint's
SourceCodebuildstokensAndComments = sortedMerge(ast.tokens, ast.comments)and the token-store'screateIndexMap(tokens, comments)— both assume each input array is sorted byrange[0](espree,@typescript-eslint/parser,@babel/eslint-parserall honor that invariant). With unsorted comments, the index map points at the wrong token indices for positions whose nearest comment was iterated out of order, which surfaces as wrong answers fromsourceCode.getTokenBefore(commentNode)/getTokenAfter(commentNode):getTokenBefore(glimmer@[23,51])getTokenAfter(glimmer@[23,51]);@ [63,64] (wrong — after the comment)const@ [88,93] (skips</template>)<template>@ [10,20]</template>@ [52,63]Commits
test:—tests/program-comments-sort-order.test.js, two tests that pin the invariant:ast.comments.map(c => c.range[0])equals its sorted copy.Linter: for the{{! }}comment,getTokenBefore/getTokenAfterreturn tokens that bracket the comment (before-end ≤ comment-start, after-start ≥ comment-end).fix:— sort the concatenated array after appending Glimmer comments ingjs-gts-parser.js(programNode.comments = […TS, …glimmer].sort((a, b) => a.range[0] - b.range[0])).Verification
test:commit alone, pass afterfix:.npm run lintandprettier --checkclean.Review comment companion
I also ran eslint-plugin-ember#2733's five-test directive suite against #196 + this fix — all 5 pass.