Skip to content

Post-merge-review: Fix template-no-implicit-this: callee detection, block-param scoping, bare {{this}}#2659

Open
johanrd wants to merge 1 commit intoember-cli:masterfrom
johanrd:night_fix/template-no-implicit-this
Open

Post-merge-review: Fix template-no-implicit-this: callee detection, block-param scoping, bare {{this}}#2659
johanrd wants to merge 1 commit intoember-cli:masterfrom
johanrd:night_fix/template-no-implicit-this

Conversation

@johanrd
Copy link
Copy Markdown
Contributor

@johanrd johanrd commented Apr 13, 2026

What's broken on master

Four independent false positives:

  1. SubExpression / ElementModifier / BlockStatement callees flagged. {{echo (my-helper)}}, <div {{my-modifier}}>, and {{#my-component}}…{{/my-component}} are all flagged as ambiguous this.* candidates. Upstream whitelists all callee positions via a nextPathIsCallee flag (no-implicit-this.js L104–151).
  2. Block-param scope tracking only checks direct parent. {{#each @items as |item|}}{{item.name}}{{/each}} flags item.name because the scope walker stops at the direct parent. Fix walks the ancestor chain.
  3. JS scope bindings flagged in GJS/GTS. import x from '…'; <template>{{x}}</template> or const cond = false; <template>{{if cond "y" "n"}}</template> produce false positives because the port doesn't check whether the identifier resolves to a JavaScript binding. The existing CONTROL_FLOW_HELPERS blanket-skip is a coarse workaround (it exempts all positional args of if/unless/each/etc., even truly-ambiguous ones).
  4. Bare {{this}} flagged. Master's startsWith-check doesn't catch the exact string "this".

Fix

  • Unified isCalleePosition that treats SubExpression / BlockStatement / ElementModifierStatement callees as always-valid, and MustacheStatement callees as valid only when the mustache has arguments.
  • isLocalBlockParam walks up the ancestor chain collecting GlimmerBlockStatement.program.blockParams.
  • isJsScopeVariable uses sourceCode.getScope() to detect JS bindings. Replaces the coarse CONTROL_FLOW_HELPERS workaround with precise detection: truly-ambiguous paths like {{if condition "y" "n"}} (no binding for condition) are now correctly flagged again. Pattern matches template-no-redundant-fn and template-no-restricted-invocations (isJsScopeVariable).
  • Skip reporting when path === 'this'.

Test plan

  • 84/84 tests pass on the branch
  • 10 new valid tests covering SubExpression/ElementModifier/BlockStatement callees (HBS + GTS), 4 new valid tests for nested block params, 2 new valid tests for bare {{this}}, and 3 new valid tests for JS-scope bindings (const, import, const with {{#each}}). All fail on master.
  • 1 new invalid test ({{if condition "yes" "no"}} with no JS binding) confirms control-flow args are correctly flagged when truly ambiguous. Fails on master (master silently allowed via CONTROL_FLOW_HELPERS).

Co-written by Claude.

… JS scope, bare {{this}}

Four false positives in the port:

1. SubExpression, ElementModifier, and BlockStatement callees were
   incorrectly flagged as ambiguous paths. Upstream whitelists all
   callee positions via a `nextPathIsCallee` flag.

2. Block-param scope tracking only checked the direct parent, so
   `{{#each @Items as |item|}}{{item.name}}{{/each}}` falsely flagged
   `item.name`. Fix walks the ancestor chain.

3. Bare JS scope bindings (imports, const, function params) in GJS/GTS
   strict mode were flagged as ambiguous — `const x = 1; <template>{{x}}</template>`
   would report `x` as needing `@x` or `this.x`. Fix uses
   `sourceCode.getScope()` to detect legitimate JS bindings. Pattern
   already used by `template-no-restricted-invocations`,
   `template-no-redundant-fn`, and `template-no-let-reference`.

4. Bare `{{this}}` was flagged because the startsWith-check didn't
   catch the exact string "this".

This also replaces the previous `CONTROL_FLOW_HELPERS` workaround (which
blanket-skipped positional args of if/unless/each/etc) with the more
precise JS scope check. `{{if condition "y" "n"}}` without any binding
for `condition` is now correctly flagged as ambiguous.
@johanrd johanrd marked this pull request as ready for review April 13, 2026 10:29
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.

1 participant