diff --git a/lib/rules/no-attrs-in-components.js b/lib/rules/no-attrs-in-components.js index 0f3c2974f7..f6be9a56bc 100644 --- a/lib/rules/no-attrs-in-components.js +++ b/lib/rules/no-attrs-in-components.js @@ -1,6 +1,7 @@ 'use strict'; const types = require('../utils/types'); +const { isEmberComponent, isGlimmerComponent } = require('../utils/ember'); const ERROR_MESSAGE = 'Do not use `this.attrs`'; @@ -25,9 +26,35 @@ module.exports = { ERROR_MESSAGE, create(context) { + let currentEmberComponent = null; + return { + ClassDeclaration(node) { + if (isEmberComponent(context, node) || isGlimmerComponent(context, node)) { + currentEmberComponent = node; + } + }, + + CallExpression(node) { + if (isEmberComponent(context, node)) { + currentEmberComponent = node; + } + }, + + 'ClassDeclaration:exit'(node) { + if (currentEmberComponent === node) { + currentEmberComponent = null; + } + }, + + 'CallExpression:exit'(node) { + if (currentEmberComponent === node) { + currentEmberComponent = null; + } + }, + MemberExpression(node) { - if (isThisAttrsExpression(node)) { + if (currentEmberComponent && isThisAttrsExpression(node)) { context.report(node.property, ERROR_MESSAGE); } }, diff --git a/tests/lib/rules/no-attrs-in-components.js b/tests/lib/rules/no-attrs-in-components.js index aedabda226..78726346a5 100644 --- a/tests/lib/rules/no-attrs-in-components.js +++ b/tests/lib/rules/no-attrs-in-components.js @@ -19,26 +19,37 @@ const ruleTester = new RuleTester({ ruleTester.run('no-attrs-in-components', rule, { valid: [ - `Component.extend({ - init() { - const newName = get(this, '_name'); - } - });`, + "import Component from '@ember/component'; Component.extend({ init() { this.foo.bar; } });", + "import Component from '@ember/component'; class MyComponent extends Component { init() { this.foo.bar; } }", + "import Component from '@glimmer/component'; class MyComponent extends Component { constructor() { this.foo.bar; } }", + + // After a component: + "import Component from '@ember/component'; Component.extend({}); this.attrs.foo;", + "import Component from '@ember/component'; class MyComponent extends Component {} this.attrs.foo;", + + // Not a component: + 'Random.extend({ init() { this.attrs.foo; } });', + "import Component from 'not-a-component'; class MyComponent extends Component { init() { this.attrs.foo; } }", ], invalid: [ { - code: `Component.extend({ - init() { - const newName = this.attrs.name; - } - });`, + code: + "import Component from '@ember/component'; Component.extend({ init() { this.attrs.foo; } });", + output: null, + errors: [{ message: ERROR_MESSAGE, type: 'Identifier' }], + }, + { + code: + "import Component from '@ember/component'; class MyComponent extends Component { init() { this.attrs.foo; } }", + output: null, + errors: [{ message: ERROR_MESSAGE, type: 'Identifier' }], + }, + { + code: + "import Component from '@glimmer/component'; class MyComponent extends Component { constructor() { this.attrs.foo; } }", output: null, - errors: [ - { - message: ERROR_MESSAGE, - }, - ], + errors: [{ message: ERROR_MESSAGE, type: 'Identifier' }], }, ], });