Repository: ember-cli/eslint-plugin-ember
Pull request #165 (2017-11-08 16:05:44)

Allow member expressions and unary expression for `avoid-leaking-state-in-ember-objects` rule
Currently rule is not allowing following case

```js
import abc from 'xyz';
export default foo.extend({ 
 someProp: abc.something;
});
```

```js
import abc from 'xyz';
export default foo.extend({
  someProp: !true;
});
```


Patch:
diff --git a/README.md b/README.md
index 1e5ee1c0..aa719324 100644
--- a/README.md
+++ b/README.md
@@ -26,9 +26,6 @@
 ```javascript
 // .eslintrc.js
 module.exports = {
-  plugins: [
-    'ember'
-  ],
   extends: [
     'eslint:recommended',
     'plugin:ember/recommended'
@@ -49,12 +46,12 @@ If you don't want to use predefined settings, you can use it as a plain plugin a
 
 ```javascript
 module.exports = {
-  plugins: [
-    'ember'
-  ],
   extends: [
     'eslint:recommended'
   ],
+  plugins: [
+    'ember'
+  ],
   rules: {
     // add rules' settings here, eg.:
     'ember/local-modules': 2
diff --git a/lib/rules/avoid-leaking-state-in-ember-objects.js b/lib/rules/avoid-leaking-state-in-ember-objects.js
index 13c0be38..dde58b90 100644
--- a/lib/rules/avoid-leaking-state-in-ember-objects.js
+++ b/lib/rules/avoid-leaking-state-in-ember-objects.js
@@ -23,7 +23,9 @@ const isAllowed = function (property) {
     utils.isCallExpression(value) ||
     utils.isBinaryExpression(value) ||
     utils.isTemplateLiteral(value) ||
-    utils.isTaggedTemplateExpression(value);
+    utils.isTaggedTemplateExpression(value) ||
+    utils.isMemberExpression(value) ||
+    utils.isUnaryExpression(value);
 };
 
 
diff --git a/lib/rules/no-empty-attrs.js b/lib/rules/no-empty-attrs.js
index 45d80573..1434186c 100644
--- a/lib/rules/no-empty-attrs.js
+++ b/lib/rules/no-empty-attrs.js
@@ -18,7 +18,6 @@ module.exports = {
 
   create(context) {
     const message = 'Supply proper attribute type';
-    const filePath = context.getFilename();
 
     const report = function (node) {
       context.report(node, message);
@@ -26,7 +25,7 @@ module.exports = {
 
     return {
       CallExpression(node) {
-        if (!ember.isDSModel(node, filePath)) return;
+        if (!ember.isDSModel(node)) return;
 
         const allProperties = ember.getModuleProperties(node);
         const isDSAttr = allProperties.filter(property => ember.isModule(property.value, 'attr', 'DS'));
diff --git a/lib/rules/order-in-models.js b/lib/rules/order-in-models.js
index 20d74b01..e07fc1e4 100644
--- a/lib/rules/order-in-models.js
+++ b/lib/rules/order-in-models.js
@@ -31,11 +31,10 @@ module.exports = {
   create(context) {
     const options = context.options[0] || {};
     const order = options.order ? addBackwardsPosition(options.order, 'empty-method', 'method') : ORDER;
-    const filePath = context.getFilename();
 
     return {
       CallExpression(node) {
-        if (!ember.isDSModel(node, filePath)) return;
+        if (!ember.isDSModel(node)) return;
 
         reportUnorderedProperties(node, context, 'model', order);
       },
diff --git a/lib/utils/ember.js b/lib/utils/ember.js
index 888a23ed..a4f1cbdf 100644
--- a/lib/utils/ember.js
+++ b/lib/utils/ember.js
@@ -92,15 +92,8 @@ function isModule(node, element, module) {
     (isLocalModule(node.callee, element) || isEmberModule(node.callee, element, moduleName));
 }
 
-function isDSModel(node, filePath) {
-  const isExtended = isEmberObject(node);
-  let isModuleByPath = false;
-
-  if (filePath && isExtended) {
-    isModuleByPath = isModuleByFilePath(filePath, 'model');
-  }
-
-  return isModule(node, 'Model', 'DS') || isModuleByPath;
+function isDSModel(node) {
+  return isModule(node, 'Model', 'DS');
 }
 
 function isModuleByFilePath(filePath, module) {


Test patch:
diff --git a/tests/lib/rules/avoid-leaking-state-in-ember-objects.js b/tests/lib/rules/avoid-leaking-state-in-ember-objects.js
index 7c90d8d1..d6097fe1 100644
--- a/tests/lib/rules/avoid-leaking-state-in-ember-objects.js
+++ b/tests/lib/rules/avoid-leaking-state-in-ember-objects.js
@@ -94,7 +94,16 @@ eslintTester.run('avoid-leaking-state-in-ember-objects', rule, {
     },
     {
       code: 'export default Foo.extend({ test: `lorem ipsum` });'
-    }
+    },
+    {
+      code: 'export default Foo.extend({ fullName: abc.dgc });'
+    },
+    {
+      code: 'export default Foo.extend({ foo: abc.something() });'
+    },
+    {
+      code: 'export default Foo.extend({ foo: !true });'
+    },
   ],
   invalid: [
     {
diff --git a/tests/lib/rules/no-empty-attrs.js b/tests/lib/rules/no-empty-attrs.js
index 2334ef7a..670c0a84 100644
--- a/tests/lib/rules/no-empty-attrs.js
+++ b/tests/lib/rules/no-empty-attrs.js
@@ -88,11 +88,5 @@ eslintTester.run('no-empty-attrs', rule, {
       parserOptions: { ecmaVersion: 6, sourceType: 'module' },
       errors: [{ message, line: 2 }, { message, line: 3 }, { message, line: 4 }],
     },
-    {
-      filename: 'example-app/models/some-model.js',
-      code: 'export default CustomModel.extend({name: attr()});',
-      parserOptions: { ecmaVersion: 6, sourceType: 'module' },
-      errors: [{ message, line: 1 }]
-    },
   ],
 });
diff --git a/tests/lib/utils/ember-test.js b/tests/lib/utils/ember-test.js
index e0b28e1a..15c72ca2 100644
--- a/tests/lib/utils/ember-test.js
+++ b/tests/lib/utils/ember-test.js
@@ -30,26 +30,11 @@ describe('isModule', () => {
 });
 
 describe('isDSModel', () => {
-  it('should check if it\'s a DS Model', () => {
-    const node = parse('DS.Model()');
+  const node = parse('DS.Model()');
 
+  it('should check if it\'s a DS Model', () => {
     expect(emberUtils.isDSModel(node)).toBeTruthy();
   });
-
-  it('should check if it\'s a DS Model even if it uses custom name', () => {
-    const node = parse('CustomModel.extend()');
-    const filePath = 'example-app/models/path/to/some-model.js';
-
-    expect(
-      emberUtils.isDSModel(node),
-      'it shouldn\'t detect Model when no file path is provided'
-    ).toBeFalsy();
-
-    expect(
-      emberUtils.isDSModel(node, filePath),
-      'it should detect Model when file path is provided'
-    ).toBeTruthy();
-  });
 });
 
 describe('isModuleByFilePath', () => {