Skip to content

Post-merge-review: Fix template-no-obsolete-elements: track element-level block params#2676

Open
johanrd wants to merge 3 commits intoember-cli:masterfrom
johanrd:night_fix/template-no-obsolete-elements
Open

Post-merge-review: Fix template-no-obsolete-elements: track element-level block params#2676
johanrd wants to merge 3 commits intoember-cli:masterfrom
johanrd:night_fix/template-no-obsolete-elements

Conversation

@johanrd
Copy link
Copy Markdown
Contributor

@johanrd johanrd commented Apr 13, 2026

What's broken on master

The rule suppresses reports when the tag name shadows a block param from a GlimmerBlockStatement (e.g. {{#let (...) as |marquee|}}<marquee />). It does not track element-level block params (<Comp as |marquee|>), so angle-bracket shadowing is ignored and the inner <marquee /> is falsely reported.

Fix

Push element block params on GlimmerElementNode enter, pop on exit, mirroring the existing GlimmerBlockStatement handling.

Test plan

36/36 tests pass. 2 new valid tests (element-level shadowing of plaintext and marquee) fail on master.


Co-written by Claude.

The rule suppressed obsolete-element reports when the tag name shadows a
block param from a GlimmerBlockStatement (e.g. {{#let (...) as |marquee|}}).
It did not track element-level block params (<Comp as |marquee|>), so
inside an angle-bracket component the shadowing was ignored and the tag
was falsely reported. Push element block params on enter and pop on exit,
mirroring the existing GlimmerBlockStatement handling.
@johanrd johanrd force-pushed the night_fix/template-no-obsolete-elements branch from 511b615 to 029c2c0 Compare April 13, 2026 10:01
@johanrd johanrd marked this pull request as ready for review April 13, 2026 10:34
// Element-level block params (e.g. `<Comp as |param|>`) are scoped to
// the children, so push them after the obsolete check. Pop on exit.
const elementParams = node.blockParams || [];
blockParamsInScope.push(...elementParams);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

shouldn't this be the responsibility of the scope manager?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added a clarification above blockParamsInScope now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

kinda seems like we should fix that rather than add a work-around here, ya?

Copy link
Copy Markdown
Contributor Author

@johanrd johanrd Apr 14, 2026

Choose a reason for hiding this comment

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

yes, maybe, although I'm not sure how to approach that.

To my understanding, getScope() runs into two problems:

HBS mode: ember-eslint-parser's HBS path creates an intentionally empty scope manager — Glimmer block params from {{#let ... as |x|}} and <Comp as |x|> are not registered, so getScope() sees nothing.

GTS mode: at the GlimmerElementNode visitor, the element's own as |x| params are already visible in scope. So getScope() at <marquee as |marquee|> test would find marquee in scope and incorrectly suppress the flag. The push-after-check ordering handles this: the element is checked against outer params only, then its own are pushed for its children.

or were you thinking something else completely? upstream to ember-eslint-parser? thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants