Skip to content

Add no-legacy-helper-imports rule for Ember 7.1+ with safe autofix#2820

Open
NullVoxPopuli with Copilot wants to merge 3 commits into
masterfrom
copilot/lint-ember-imports
Open

Add no-legacy-helper-imports rule for Ember 7.1+ with safe autofix#2820
NullVoxPopuli with Copilot wants to merge 3 commits into
masterfrom
copilot/lint-ember-imports

Conversation

Copilot AI commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Ember 7.1+ provides built-in equivalents for helpers/modifiers commonly imported from ember-truth-helpers, ember-element-helper, and parts of @ember/helper / @ember/modifier. This PR adds a dedicated lint rule to flag those legacy imports and autofix them when alias/name conflicts are not introduced.

  • New rule: ember/no-legacy-helper-imports

    • Flags legacy imports that should be replaced by Ember built-ins in 7.1+.
    • Covers:
      • ember-truth-helpers (and helper subpaths)
      • ember-element-helper (and helper subpath)
      • @ember/helper (array, hash, fn)
      • @ember/modifier (on)
    • Rule is gated to ember-source >= 7.1.
  • Autofix behavior

    • Removes now-unnecessary imports.
    • Renames aliased local bindings to canonical built-in names when needed (e.g. notEqneq, aliased element_element).
    • Skips autofix when import-specifier/name conflicts would make changes unsafe.
  • Docs and rule surface

    • Added rule documentation page.
    • Updated generated rules table in README.md.
// before
import { notEq as isDifferent } from 'ember-truth-helpers';
import element_ from 'ember-element-helper';

const a = isDifferent(x, y);
const el = element_(this.id);

// after (autofix, when conflict-free)
const a = neq(x, y);
const el = element(this.id);

Copilot AI changed the title [WIP] Lint against imports from ember-element-helper and ember-truth-helpers Add no-legacy-helper-imports rule for Ember 7.1+ with safe autofix Jul 1, 2026
Copilot AI requested a review from NullVoxPopuli July 1, 2026 19:36
…itives

The initial implementation reported any import from @ember/helper /
@ember/modifier (including non-superseded exports like `helper` and
`setModifierManager`) and its autofix removed imports whose bindings were
used in plain JavaScript, where the Ember 7.1 built-in template keywords
do not exist — producing broken code.

Now the rule:

- only reports imports that bind a specifier superseded by an Ember 7.1
  built-in template keyword (eq, neq, not, and, or, gt, gte, lt, lte,
  element, array, hash, fn, on)
- only autofixes when every reference to the binding is inside a
  <template> tag (Glimmer scope references from ember-eslint-parser),
  renaming usages to the keyword name where it differs (notEq -> neq,
  aliased locals, default imports)
- partially fixes mixed imports, keeping non-superseded specifiers
  (import { fn, helper } from '@ember/helper' -> import { helper } ...)
- bails on renames whenever the keyword name is shadowed by a binding in
  any scope enclosing the usage, not just at module scope
- skips type-only imports and preserves kept specifiers verbatim

Tests now run against ember-eslint-parser with real gjs templates and
cover the < 7.1 version gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🏎️ Benchmark Comparison

Benchmark Control (p50) Experiment (p50) Δ
🟢 js small 15.93 ms 15.43 ms -3.1%
🟢 js medium 7.78 ms 7.52 ms -3.4%
🟢 js large 2.97 ms 2.82 ms -5.1%
🟢 gjs small 1.30 ms 1.26 ms -3.1%
gjs medium 632.00 µs 638.73 µs +1.1%
gjs large 252.52 µs 249.58 µs -1.2%
gts small 1.27 ms 1.26 ms -1.1%
gts medium 628.19 µs 628.60 µs +0.1%
gts large 249.44 µs 249.11 µs -0.1%

🟢 faster · 🔴 slower · 🟠 slightly slower · ⚪ within 2%

Full mitata output
clk: ~3.10 GHz
cpu: AMD EPYC 7763 64-Core Processor
runtime: node 24.16.0 (x64-linux)

benchmark                   avg (min … max) p75 / p99    (min … top 1%)
------------------------------------------- -------------------------------
js small (control)            18.46 ms/iter  19.76 ms ▅ █                  
                      (13.57 ms … 32.47 ms)  29.41 ms █ █    ▂             
                    (  5.32 mb …  10.66 mb)   7.32 mb █▄█▄▁▇▇█▄▁▁▄▄▄▁▁▁▇▁▄▄

js small (experiment)         16.38 ms/iter  17.15 ms  █▂                  
                      (14.29 ms … 24.68 ms)  22.99 ms ▂██▅ ▇               
                    (  6.60 mb …   8.40 mb)   6.89 mb ████▄█▁▇▇▄▄▄▁▁▁▁▁▄▁▁▄

                             ┌                                            ┐
                             ╷   ┌─────────┬───┐                          ╷
          js small (control) ├───┤         │   ├──────────────────────────┤
                             ╵   └─────────┴───┘                          ╵
                               ╷┌────┬─┐                ╷
       js small (experiment)   ├┤    │ ├────────────────┤
                               ╵└────┴─┘                ╵
                             └                                            ┘
                             13.57 ms           21.49 ms           29.41 ms

summary
  js small (experiment)
   1.13x faster than js small (control)

------------------------------------------- -------------------------------
js medium (control)            8.54 ms/iter   8.81 ms ▃█▂                  
                       (7.20 ms … 14.94 ms)  14.39 ms ███                  
                    (  2.46 mb …   4.62 mb)   3.56 mb ████▃▂▃▅▅▂▂▃▁▂▁▂▁▃▁▁▂

js medium (experiment)         8.06 ms/iter   8.39 ms ▂ █                  
                       (6.96 ms … 15.13 ms)  13.63 ms █▇█                  
                    (  2.52 mb …   4.50 mb)   3.54 mb ███▇▅▄▅▃▁▅▂▂▁▁▁▁▁▁▂▁▂

                             ┌                                            ┐
                              ╷ ┌──────┬┐                                 ╷
         js medium (control)  ├─┤      │├─────────────────────────────────┤
                              ╵ └──────┴┘                                 ╵
                             ╷┌─────┬─┐                              ╷
      js medium (experiment) ├┤     │ ├──────────────────────────────┤
                             ╵└─────┴─┘                              ╵
                             └                                            ┘
                             6.96 ms           10.67 ms            14.39 ms

summary
  js medium (experiment)
   1.06x faster than js medium (control)

------------------------------------------- -------------------------------
js large (control)             3.26 ms/iter   3.09 ms  █                   
                        (2.80 ms … 8.00 ms)   7.41 ms ▆█                   
                    (692.38 kb …   2.09 mb)   1.44 mb ██▃▂▂▂▁▂▁▁▁▁▂▁▁▁▁▁▁▁▁

js large (experiment)          3.38 ms/iter   3.28 ms █                    
                       (2.70 ms … 11.05 ms)   8.13 ms █▃                   
                    (315.05 kb …   3.57 mb)   1.45 mb ██▄▃▂▂▂▁▂▁▁▁▂▂▁▁▁▁▁▁▁

                             ┌                                            ┐
                              ╷┌──┬                                 ╷
          js large (control)  ├┤  │─────────────────────────────────┤
                              ╵└──┴                                 ╵
                             ╷┌────┬                                      ╷
       js large (experiment) ├┤    │──────────────────────────────────────┤
                             ╵└────┴                                      ╵
                             └                                            ┘
                             2.70 ms            5.42 ms             8.13 ms

summary
  js large (control)
   1.04x faster than js large (experiment)

------------------------------------------- -------------------------------
gjs small (control)            1.44 ms/iter   1.39 ms █                    
                        (1.23 ms … 6.31 ms)   5.60 ms █▃                   
                    (240.86 kb …   1.66 mb)   1.06 mb ██▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs small (experiment)         1.39 ms/iter   1.29 ms █                    
                        (1.21 ms … 6.82 ms)   5.79 ms █                    
                    (306.23 kb …   1.59 mb)   1.06 mb █▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌┬                                        ╷
         gjs small (control) ├┤│────────────────────────────────────────┤
                             ╵└┴                                        ╵
                             ┌─┬                                          ╷
      gjs small (experiment) │ │──────────────────────────────────────────┤
                             └─┴                                          ╵
                             └                                            ┘
                             1.21 ms            3.50 ms             5.79 ms

summary
  gjs small (experiment)
   1.04x faster than gjs small (control)

------------------------------------------- -------------------------------
gjs medium (control)         692.34 µs/iter 653.58 µs █                    
                      (597.50 µs … 6.30 ms)   3.40 ms █                    
                    (124.66 kb …   1.09 mb) 541.19 kb █▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs medium (experiment)      688.28 µs/iter 653.21 µs  █                   
                      (604.75 µs … 5.74 ms)   1.28 ms  █                   
                    (107.07 kb …   1.04 mb) 540.16 kb ██▇▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ┌─┬                                          ╷
        gjs medium (control) │ │──────────────────────────────────────────┤
                             └─┴                                          ╵
                             ┌┬         ╷
     gjs medium (experiment) ││─────────┤
                             └┴         ╵
                             └                                            ┘
                             597.50 µs           2.00 ms            3.40 ms

summary
  gjs medium (experiment)
   1.01x faster than gjs medium (control)

------------------------------------------- -------------------------------
gjs large (control)          280.76 µs/iter 270.28 µs  █                   
                      (240.73 µs … 5.32 ms) 399.72 µs  █▂                  
                    (216.10 kb … 960.98 kb) 217.54 kb ▆██▅█▅▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs large (experiment)       277.64 µs/iter 268.11 µs  █                   
                      (239.16 µs … 5.39 ms) 385.74 µs  █                   
                    (173.59 kb …   1.06 mb) 216.76 kb ▆██▃▇▆▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷ ┌─────────┬                                ╷
         gjs large (control) ├─┤         │────────────────────────────────┤
                             ╵ └─────────┴                                ╵
                             ╷ ┌────────┬                             ╷
      gjs large (experiment) ├─┤        │─────────────────────────────┤
                             ╵ └────────┴                             ╵
                             └                                            ┘
                             239.16 µs         319.44 µs          399.72 µs

summary
  gjs large (experiment)
   1.01x faster than gjs large (control)

------------------------------------------- -------------------------------
gts small (control)            1.49 ms/iter   1.30 ms █                    
                        (1.23 ms … 6.97 ms)   6.17 ms █                    
                    (228.62 kb …   1.50 mb)   1.06 mb █▃▂▁▁▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gts small (experiment)         1.34 ms/iter   1.28 ms █                    
                        (1.21 ms … 6.01 ms)   5.03 ms █                    
                    (444.22 kb …   2.15 mb)   1.05 mb █▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ┌─┬                                          ╷
         gts small (control) │ │──────────────────────────────────────────┤
                             └─┴                                          ╵
                             ┌┬                                 ╷
      gts small (experiment) ││─────────────────────────────────┤
                             └┴                                 ╵
                             └                                            ┘
                             1.21 ms            3.69 ms             6.17 ms

summary
  gts small (experiment)
   1.11x faster than gts small (control)

------------------------------------------- -------------------------------
gts medium (control)         680.53 µs/iter 647.79 µs █                    
                      (594.34 µs … 5.86 ms)   2.09 ms ██                   
                    (200.57 kb …   1.23 mb) 542.17 kb ██▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gts medium (experiment)      688.90 µs/iter 647.04 µs █                    
                      (591.24 µs … 5.85 ms)   3.47 ms █                    
                    (261.80 kb …   1.38 mb) 541.88 kb █▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ┌┬                     ╷
        gts medium (control) ││─────────────────────┤
                             └┴                     ╵
                             ┌─┬                                          ╷
     gts medium (experiment) │ │──────────────────────────────────────────┤
                             └─┴                                          ╵
                             └                                            ┘
                             591.24 µs           2.03 ms            3.47 ms

summary
  gts medium (control)
   1.01x faster than gts medium (experiment)

------------------------------------------- -------------------------------
gts large (control)          272.31 µs/iter 264.43 µs  █▂                  
                      (236.38 µs … 4.81 ms) 398.03 µs ▅██                  
                    (187.79 kb … 802.34 kb) 216.84 kb ██████▃▂▂▁▁▁▁▁▁▁▁▁▁▁▁

gts large (experiment)       272.40 µs/iter 265.11 µs  █▆                  
                      (236.67 µs … 5.15 ms) 350.42 µs  ██                  
                    (181.04 kb … 738.24 kb) 216.71 kb ▅███▄█▇▆▂▂▂▂▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷ ┌───────┬                                  ╷
         gts large (control) ├─┤       │──────────────────────────────────┤
                             ╵ └───────┴                                  ╵
                             ╷ ┌───────┬                     ╷
      gts large (experiment) ├─┤       │─────────────────────┤
                             ╵ └───────┴                     ╵
                             └                                            ┘
                             236.38 µs         317.21 µs          398.03 µs

summary
  gts large (control)
   1x faster than gts large (experiment)

@NullVoxPopuli NullVoxPopuli marked this pull request as ready for review July 2, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

If we are using ember 7.1 or newer, we should lint against imports from ember-element-helper, ember-truth-helpers, etc

2 participants