Extract rule: template-no-this-in-template-only-components#2575
Conversation
NullVoxPopuli-ai-agent
left a comment
There was a problem hiding this comment.
Review: template-no-this-in-template-only-components
Compared against the original ember-template-lint rule at lib/rules/no-this-in-template-only-components.js.
What's done well
- Core detection logic using
GlimmerPathExpressionwithnode.head?.type === 'ThisHead'is clean and correct. - The auto-fix from
this.footo@foois properly implemented. - Built-in properties that shouldn't be auto-fixed are handled correctly (reported but not fixed).
- Tests cover the key cases from the original: basic
this.foo, subexpressions, action helpers, and theelementIdnon-fixable case. - Both
ember-eslint-parserandember-eslint-parser/hbsmodes are tested. - The
originallyFrommetadata is a nice touch for traceability.
Differences from the original worth noting
-
Reduced
BUILTIN_PROPERTIESlist: The original ember-template-lint rule has a larger set of built-in properties that are excluded from auto-fix:action,actionContext,actionContextObject,concatenatedProperties,element,parentView,target-- in addition to the ones included here (elementId,tagName,ariaRole,class,classNames,classNameBindings,attributeBindings,isVisible). Some of these (likeaction,element,parentView) could cause incorrect fixes if auto-replaced with@actionetc. Consider aligning the list with the original, or documenting why the reduced set is intentional. -
No file-path-based detection: The original rule has sophisticated logic to determine whether a template is actually template-only by checking for a co-located component class file on disk (
isTemplateOnlyComponent()). The ESLint version skips this entirely and flags allthisusage in<template>tags. This is a significant behavioral difference. In gjs/gts, the ESLint rule can rely on AST context (class body vs module level) -- but the rule as written doesn't distinguish between<template>inside a class body vs at module level. This meansthis.fooinside a class component's<template>would be incorrectly flagged. This seems like a bug -- the rule should check whether the<template>is inside a class body (similar to what PR 2580 does withisInsideClassOrFunction). -
validComponentExtensionsconfig option: The original supports avalidComponentExtensionsconfig option (defaulting to['.js', '.ts']). The ESLint version hasschema: [](no options). This is fine for a first pass but worth noting. -
Error message: The original includes "...or create a component.js for this component" in the message. The ESLint version omits this, which is reasonable since gjs/gts files are self-contained.
Potential bug
The rule uses GlimmerPathExpression which fires for all <template> tags in the file, including those inside class bodies. A class component like:
class MyComponent extends Component {
<template>{{this.name}}</template>
}would be incorrectly flagged. The rule should check that the <template> is at module level (not inside a class or function) before reporting. Consider reusing the isInsideClassOrFunction helper from PR #2580.
Test coverage
- The valid case
{{@foo}}is good. Consider adding a valid test forthisinside a class body<template>to verify it's not flagged (once the bug above is fixed). - Missing a test for
this.foo.bar(nested property access) -- the fix should produce@foo.bar.
🤖 Automated review comparing with ember-template-lint source
The rule was incorrectly flagging `this` usage in ALL `<template>` tags, including those inside class bodies (class components). It should only flag `this` in template-only components (standalone `<template>` tags). Also adds missing BUILTIN_PROPERTIES from the original ember-template-lint rule: action, element, parentView, attrs, isDestroying, isDestroyed. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
41758b1 to
c23fa18
Compare
Split from #2371.