Extract to ember-estree#181
Merged
NullVoxPopuli merged 35 commits intoember-tooling:mainfrom Mar 19, 2026
Merged
Conversation
b4e535b to
53c651f
Compare
Closed
- Use toTree({ templateOnly: true }) instead of processGlimmerTemplate
- Pass inner content (not full <template> tags) fixing 10-col offset
- Removes spurious GlimmerElementNode(tag: "template") wrapper
- Keep local traverse for convertAst scope management
- blockParamNodes now have parent refs (fixes template-no-let-reference)
- Update snapshots for corrected AST structure
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- ember-estree now uses VarHead nodes for accurate block param positions - Guard against undefined result.ast.comments (pre-existing bug) - Update snapshots for corrected AST structure Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
preprocessGlimmerTemplates now extracts contentRange and passes inner template content (without <template>/<template> tags) to toTree. Fixes the 10-column position offset that caused eslint-plugin-ember test failures. Template root range is fixed up to cover the full <template>...</template> range afterward. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Two fixes for ESLint autofix compatibility: 1. When replacing JS nodes (TemplateLiteral/StaticBlock) with GlimmerTemplate via Object.assign, delete leftover properties (quasis, expressions, etc.) that confuse ESLint rules. 2. Add tokens for <template> and </template> tags to the token stream so ESLint's SourceCode has full token coverage over the template range. Without these, autofixes like arrow-body-style produced mangled output. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
ember-estree uses GlimmerBlockParam (not BlockParam) for consistency with all other Glimmer-prefixed node types. Patch the downstream assertion in the integration test until eslint-plugin-ember updates. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1f2214e to
3b6c70a
Compare
Avoids shell quoting issues with execaCommand by using fse.readFile/writeFile for the string replacement. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Clone from NullVoxPopuli-ai-agent/eslint-plugin-ember#update-blockparam-nodetype which has the nodeType assertion updated. Revert to upstream once ember-cli/eslint-plugin-ember#2577 merges. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
|
This isn't toooo different, i suppose from normal PRs:
Full mitata output |
Member
|
second run:
Full mitata output |
- gjs-gts-parser uses toTree({ parser }) instead of separate
transformForLint + preprocessGlimmerTemplates + convertAst pipeline
- transforms.js reduced to registerGlimmerScopes + transformForLint
(transformForLint still needed for ts-patch.js and TS placeholder format)
- @babel/eslint-parser no longer used in the parsing pipeline
(JS files use ember-estree's default oxc parser + eslint-scope)
Still TODO: token stream tests fail due to TS placeholder format
mismatch — the TS parser produces backtick tokens but toTree adds
<template> tag tokens. Need to bridge token formats.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Major refactor of gjs-gts-parser to use ember-estree's toTree with a custom parser option: - toTree handles template extraction, placeholder JS, and AST splicing - gjs-gts-parser provides TS parser as callback; JS uses oxc default - Eliminated preprocessGlimmerTemplates and convertAst's splicing logic - transforms.js reduced to registerGlimmerScopes + transformForLint (transformForLint still needed for ts-patch.js virtual FS) - toTSPlaceholderJS builds TS-compatible placeholders from parseResults without calling content-tag twice - @babel/eslint-parser no longer used in the parsing pipeline - Error formatting for content-tag parse errors Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…holderJS - TS path uses toTree's visitor API for scope registration during traversal, eliminating the second registerGlimmerScopes pass - buildGlimmerVisitors() creates visitors that close over scopeManager - toTSPlaceholderJS removed — ember-estree's backtick placeholders work directly with @typescript-eslint/parser - transformForLint simplified to use ember-estree's toPlaceholderJS - JS/oxc path still uses registerGlimmerScopes as fallback - Benchmark: ~9% regression from baseline (improved from ~15%) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
Full mitata output |
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…olderJS - Import glimmerVisitorKeys (const) instead of buildGlimmerVisitorKeys (fn) - transformForLint builds placeholders inline instead of importing toPlaceholderJS - Fewer imports from ember-estree = cleaner dependency surface Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
Full mitata output |
Replace toBeLessThanOrEqual with exact toBe check to verify all traversed nodes are covered by snapshot assertions. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Consumer now owns the visitor key merge before returning to ESLint. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Both TS and JS paths now create scopeManager inside the parser callback (before visitors run), enabling single-pass scope registration via buildGlimmerVisitors for all file types. - JS path uses oxc-parser + eslint-scope in the parser callback - Remove registerGlimmerScopes import (no longer used) - Drop @babel/eslint-parser dependency and @babel/core peer dep - Add oxc-parser as direct dependency Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
These test projects use babelParser for plain .js files in their ESLint configs. Previously resolved through the root dependency which was removed. Now listed as direct devDependencies. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
Full mitata output |
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
Full mitata output |
…ntReferences) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
Full mitata output |
- JS path passes no parser to toTree (falsey = use ember-estree's oxc) - scopeManager created after toTree returns via eslint-scope.analyze - registerGlimmerScopes handles Glimmer scope registration for JS path - TS path unchanged (parser callback + visitors for single-pass scoping) - Remove oxc-parser from direct dependencies Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
eslint-scope's esrecurse traverses all enumerable properties, which crashes on Glimmer nodes' getter chains. Use the fallback option to return [] for Glimmer-prefixed types, skipping them during JS scope analysis. Glimmer scopes are registered separately via registerGlimmerScopes. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
🏎️ Benchmark Comparison
Full mitata output``` clk: ~3.10 GHz cpu: AMD EPYC 7763 64-Core Processor runtime: node 24.14.0 (x64-linux) benchmark avg (min … max) p75 / p99 (min … top 1%) ------------------------------------------- ------------------------------- gts small (control) 2.15 ms/iter 2.44 ms █▃ (1.10 ms … 20.38 ms) 5.54 ms ██▇ ( 30.91 kb … 2.05 mb) 639.39 kb ████▇▆▇▄▂▂▄▄▂▃▇▂▂▁▂▂▂ gts small (experiment) 1.91 ms/iter 1.96 ms █ (1.04 ms … 22.10 ms) 7.23 ms ██▄ ( 34.99 kb … 1.74 mb) 575.53 kb ████▄▃▃▂▂▃▂▂▁▂▁▁▁▁▁▁▁ ┌ ┐ ╷┌──────┬─┐ ╷ gts small (control) ├┤ │ ├──────────────────────┤ ╵└──────┴─┘ ╵ ╷┌────┬┐ ╷ gts small (experiment) ├┤ │├─────────────────────────────────────┤ ╵└────┴┘ ╵ └ ┘ 1.04 ms 4.14 ms 7.23 ms summary gts small (experiment) 1.13x faster than gts small (control) ------------------------------------------- ------------------------------- gts medium (control) 6.90 ms/iter 7.56 ms ▂██ (3.73 ms … 28.50 ms) 28.37 ms ███▂ (889.77 kb … 8.57 mb) 2.61 mb ████▇▄▄▄▃▁▁▁▁▁▁▁▁▁▁▁▂ gts medium (experiment) 6.94 ms/iter 7.69 ms █ (3.68 ms … 28.19 ms) 23.38 ms ▄█▇▄▂ (498.00 kb … 12.73 mb) 2.70 mb █████▇▆▅▂▁▂▂▂▁▁▁▁▁▁▁▂ ┌ ┐ ╷ ┌───┬┐ ╷ gts medium (control) ├─┤ │├─────────────────────────────────────┤ ╵ └───┴┘ ╵ ╷ ┌───┬┐ ╷ gts medium (experiment) ├─┤ │├────────────────────────────┤ ╵ └───┴┘ ╵ └ ┘ 3.68 ms 16.02 ms 28.37 ms summary gts medium (control) 1.01x faster than gts medium (experiment) ------------------------------------------- ------------------------------- gts large (control) 19.87 ms/iter 21.85 ms █ █ (10.95 ms … 40.77 ms) 40.64 ms ▇▇▂ █ █▇▇ ▂ ( 4.80 mb … 18.11 mb) 7.28 mb ███▆█▆███▁▁█▁▁▁▁▆▁▁▁▆ gts large (experiment) 17.52 ms/iter 18.73 ms ▄ █ (10.52 ms … 39.32 ms) 38.52 ms █▅██ █▅ ( 4.37 mb … 17.11 mb) 6.69 mb ████▅██▅▅▅▅▅▁▁▅▁▁▁▁▁▅ ┌ ┐ ╷ ┌────────┬──┐ ╷ gts large (control) ├───┤ │ ├───────────────────────────┤ ╵ └────────┴──┘ ╵ ╷ ┌──────┬─┐ ╷ gts large (experiment) ├──┤ │ ├─────────────────────────────┤ ╵ └──────┴─┘ ╵ └ ┘ 10.52 ms 25.58 ms 40.64 ms summary gts large (experiment) 1.13x faster than gts large (control) ------------------------------------------- ------------------------------- gjs small (control) 1.59 ms/iter 1.48 ms █▆ (864.10 µs … 20.12 ms) 5.30 ms ██ ( 70.60 kb … 7.52 mb) 579.66 kb ██▅▆▃▂▂▂▂▁▂▂▃▂▃▁▁▁▁▁▁ gjs small (experiment) 1.48 ms/iter 1.24 ms █ (842.35 µs … 19.56 ms) 6.09 ms █▄ ( 21.48 kb … 5.94 mb) 521.53 kb ██▄▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁ ┌ ┐ ╷┌────┬ ╷ gjs small (control) ├┤ │───────────────────────────────┤ ╵└────┴ ╵ ┌────┬ ╷ gjs small (experiment) │ │───────────────────────────────────────┤ └────┴ ╵ └ ┘ 842.35 µs 3.47 ms 6.09 ms summary gjs small (experiment) 1.08x faster than gjs small (control) ------------------------------------------- ------------------------------- gjs medium (control) 5.96 ms/iter 6.11 ms ▆█ (3.26 ms … 32.34 ms) 23.35 ms ██▇ (730.70 kb … 8.71 mb) 2.35 mb ███▆▃▆▄▅▁▂▂▁▁▁▁▁▁▁▁▁▂ gjs medium (experiment) 5.62 ms/iter 5.95 ms █▅ (3.12 ms … 31.28 ms) 25.51 ms ██▅▂ (577.51 kb … 4.53 mb) 2.07 mb ████▄▅▄▂▁▁▁▁▁▁▁▁▁▁▁▁▂ ┌ ┐ ╷┌────┬ ╷ gjs medium (control) ├┤ │──────────────────────────────────┤ ╵└────┴ ╵ ╷┌───┬┐ ╷ gjs medium (experiment) ├┤ │├──────────────────────────────────────┤ ╵└───┴┘ ╵ └ ┘ 3.12 ms 14.32 ms 25.51 ms summary gjs medium (experiment) 1.06x faster than gjs medium (control) ------------------------------------------- ------------------------------- gjs large (control) 14.23 ms/iter 15.49 ms ▅ ▂█ (7.46 ms … 38.68 ms) 35.89 ms ▇█▅██ ▂▂ ( 4.69 mb … 7.63 mb) 6.17 mb █████▇██▇▁▁▁▁▁▁▁▁▄▁▄▄ gjs large (experiment) 12.97 ms/iter 12.65 ms █▂ (7.65 ms … 39.43 ms) 39.04 ms ▆██▅ ( 4.43 mb … 15.57 mb) 5.86 mb █████▅▁▃▃▃▁▁▁▁▁▁▁▃▁▁▃ ┌ ┐ ╷ ┌───────┬┐ ╷ gjs large (control) ├─┤ │├─────────────────────────────┤ ╵ └───────┴┘ ╵ ╷ ┌─────┬ ╷ gjs large (experiment) ├─┤ │────────────────────────────────────┤ ╵ └─────┴ ╵ └ ┘ 7.46 ms 23.25 ms 39.04 ms summary gjs large (experiment) 1.1x faster than gjs large (control) ------------------------------------------- ------------------------------- hbs small (control) 217.69 µs/iter 136.44 µs █ (96.15 µs … 23.11 ms) 2.90 ms █ ( 3.81 kb … 2.58 mb) 139.50 kb █▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ hbs small (experiment) 196.78 µs/iter 134.12 µs █ (93.58 µs … 22.22 ms) 2.11 ms █ ( 21.20 kb … 2.87 mb) 128.57 kb █▅▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ┌ ┐ ┌─┬ ╷ hbs small (control) │ │──────────────────────────────────────────┤ └─┴ ╵ ┌─┬ ╷ hbs small (experiment) │ │─────────────────────────────┤ └─┴ ╵ └ ┘ 93.58 µs 1.49 ms 2.90 ms summary hbs small (experiment) 1.11x faster than hbs small (control) ------------------------------------------- ------------------------------- hbs medium (control) 2.68 ms/iter 2.16 ms █ (1.37 ms … 20.39 ms) 19.14 ms █ (374.17 kb … 4.58 mb) 1.97 mb █▅▃▂▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ hbs medium (experiment) 2.68 ms/iter 2.16 ms █ (1.46 ms … 20.70 ms) 19.81 ms █ ( 87.51 kb … 3.96 mb) 1.82 mb █▅▂▃▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ┌ ┐ ┌──┬ ╷ hbs medium (control) │ │───────────────────────────────────────┤ └──┴ ╵ ┌──┬ ╷ hbs medium (experiment) │ │─────────────────────────────────────────┤ └──┴ ╵ └ ┘ 1.37 ms 10.59 ms 19.81 ms summary hbs medium (experiment) 1x faster than hbs medium (control) ------------------------------------------- ------------------------------- hbs large (control) 14.65 ms/iter 20.03 ms █ ▂ (8.17 ms … 29.76 ms) 27.97 ms █▇█▅ ▂ ▂ ▂ ( 7.23 mb … 10.73 mb) 9.07 mb ████▄▇▄▄▁▄▄▁▇█▁▁▁▁█▁█ hbs large (experiment) 12.48 ms/iter 13.05 ms █ (7.99 ms … 29.70 ms) 27.42 ms █▅ ( 6.47 mb … 9.83 mb) 8.14 mb ██▅▄▇▅▁▄▁▁▂▄▁▂▁▂▁▁▄▂▂ ┌ ┐ ╷ ┌────────────┬───────────┐ ╷ hbs large (control) ├─┤ │ ├─────────────────┤ ╵ └────────────┴───────────┘ ╵ ┌─────────┬┐ ╷ hbs large (experiment) │ │├────────────────────────────────┤ └─────────┴┘ ╵ └ ┘ 7.99 ms 17.98 ms 27.97 ms summary hbs large (experiment) 1.17x faster than hbs large (control) ``` |
ember-estree now produces plain objects for all Glimmer nodes, so eslint-scope's esrecurse can traverse them safely. Remove the fallback workaround that skipped Glimmer nodes during scope analysis. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Use templateNode.loc.end for Program end position instead of creating a duplicate DocumentLines. Only create it for error formatting (rare path). Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Replace git reference with published npm version. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
JS path now also passes a parser callback (oxc + eslint-scope) so scopeManager is available when toTree invokes visitors during splice. Eliminates the separate registerGlimmerScopes traversal. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Member
Full mitata output |
eslint-plugin-ember now handles GlimmerBlockParam nodeType natively. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This reverts commit d82c51b.
Member
Full mitata output |
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.
No description provided.