Repository: ember-cli/eslint-plugin-ember (js)

Issue:
New Rule: no-computed-arrows
```js
// BAD
const myObject = Ember.Object.extend({
  dependentKey: 'hello',

  myComputed: Ember.computed('dependentKey', () => {
    this.get('dependentKey'); // Whoops.
  })
});

// GOOD
const myObject = Ember.Object.extend({
  dependentKey: 'hello',

  myComputed: Ember.computed('dependentKey', function() {
    this.get('dependentKey'); // No problem.
  })
});
```

This is not typically a problem in the first pass (if the code doesn't work the user will not commit it), but it can create a surprising refactoring hazard that is not easy to identify in code review.

Pull request:
Add new rule `no-arrow-function-computed-properties`
Fixes #263.

Patch:
diff --git a/README.md b/README.md
index a96c9c49..4f4d2f40 100644
--- a/README.md
+++ b/README.md
@@ -111,6 +111,7 @@ The `--fix` option on the command line automatically fixes problems reported by
 |    | Rule ID | Description |
 |:---|:--------|:------------|
 | :white_check_mark: | [jquery-ember-run](./docs/rules/jquery-ember-run.md) | Prevents usage of jQuery without Ember Run Loop |
+|  | [no-arrow-function-computed-properties](./docs/rules/no-arrow-function-computed-properties.md) | Disallows arrow functions in computed properties |
 | :white_check_mark: | [no-attrs-in-components](./docs/rules/no-attrs-in-components.md) | Disallow usage of this.attrs in components |
 | :white_check_mark: | [no-attrs-snapshot](./docs/rules/no-attrs-snapshot.md) | Disallow use of attrs snapshot in `didReceiveAttrs` and `didUpdateAttrs` |
 | :white_check_mark: | [no-capital-letters-in-routes](./docs/rules/no-capital-letters-in-routes.md) | Raise an error when there is a route with uppercased letters in router.js |
diff --git a/docs/rules/no-arrow-function-computed-properties.md b/docs/rules/no-arrow-function-computed-properties.md
new file mode 100644
index 00000000..49285418
--- /dev/null
+++ b/docs/rules/no-arrow-function-computed-properties.md
@@ -0,0 +1,38 @@
+# no-arrow-function-computed-properties
+
+Arrow functions should not be used in computed properties because they are unable to access other properties (using `this.property`) of the same object. Accidental usage can thus lead to bugs.
+
+## Rule Details
+
+This rule disallows using arrow functions in computed properties.
+
+## Examples
+
+Examples of **incorrect** code for this rule:
+
+```js
+import EmberObject, { computed } from '@ember/object';
+
+const Person = EmberObject.extend({
+  fullName: computed('firstName', 'lastName', () => {
+    return `${this.firstName} ${this.lastName}`;
+  })
+});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+import EmberObject, { computed } from '@ember/object';
+
+const Person = EmberObject.extend({
+  fullName: computed('firstName', 'lastName', function() {
+    return `${this.firstName} ${this.lastName}`;
+  })
+});
+```
+
+## References
+
+* [Arrow function spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
+* [Computed property spec](https://api.emberjs.com/ember/release/classes/ComputedProperty)
diff --git a/lib/index.js b/lib/index.js
index cd4427c8..66e085a2 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -14,6 +14,7 @@ module.exports = {
     'local-modules': require('./rules/local-modules'),
     'named-functions-in-promises': require('./rules/named-functions-in-promises'),
     'new-module-imports': require('./rules/new-module-imports'),
+    'no-arrow-function-computed-properties': require('./rules/no-arrow-function-computed-properties'),
     'no-attrs-in-components': require('./rules/no-attrs-in-components'),
     'no-attrs-snapshot': require('./rules/no-attrs-snapshot'),
     'no-capital-letters-in-routes': require('./rules/no-capital-letters-in-routes'),
diff --git a/lib/recommended-rules.js b/lib/recommended-rules.js
index 934f760c..ba07e2a4 100644
--- a/lib/recommended-rules.js
+++ b/lib/recommended-rules.js
@@ -17,6 +17,7 @@ module.exports = {
   "ember/local-modules": "off",
   "ember/named-functions-in-promises": "off",
   "ember/new-module-imports": "error",
+  "ember/no-arrow-function-computed-properties": "off",
   "ember/no-attrs-in-components": "error",
   "ember/no-attrs-snapshot": "error",
   "ember/no-capital-letters-in-routes": "error",
diff --git a/lib/rules/no-arrow-function-computed-properties.js b/lib/rules/no-arrow-function-computed-properties.js
new file mode 100644
index 00000000..710cb891
--- /dev/null
+++ b/lib/rules/no-arrow-function-computed-properties.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const utils = require('../utils/utils');
+const emberUtils = require('../utils/ember');
+
+const ERROR_MESSAGE = 'Do not use arrow functions in computed properties';
+
+module.exports = {
+  ERROR_MESSAGE,
+
+  meta: {
+    docs: {
+      description: 'Disallows arrow functions in computed properties',
+      category: 'Possible Errors',
+      recommended: false,
+    },
+  },
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (
+          emberUtils.isComputedProp(node) &&
+          node.arguments.length > 0 &&
+          utils.isArrowFunctionExpression(node.arguments[node.arguments.length - 1])
+        ) {
+          context.report(node.arguments[node.arguments.length - 1], ERROR_MESSAGE);
+        }
+      },
+    };
+  },
+};


Test patch:
diff --git a/tests/lib/rules/no-arrow-function-computed-properties.js b/tests/lib/rules/no-arrow-function-computed-properties.js
new file mode 100644
index 00000000..e457a148
--- /dev/null
+++ b/tests/lib/rules/no-arrow-function-computed-properties.js
@@ -0,0 +1,51 @@
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require('../../../lib/rules/no-arrow-function-computed-properties');
+const RuleTester = require('eslint').RuleTester;
+
+const { ERROR_MESSAGE } = rule;
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({
+  parserOptions: {
+    ecmaVersion: 6,
+    sourceType: 'module',
+  },
+});
+ruleTester.run('no-arrow-function-computed-properties', rule, {
+  valid: [
+    'computed()',
+    'computed(function() { return 123; })',
+    "computed('prop', function() { return this.prop; })",
+    "computed('prop', function() { return this.prop; }).volatile()",
+    "computed.map('products', function(product) { return someFunction(product); })",
+    'other(() => {})',
+    'other.computed(() => {})',
+  ],
+  invalid: [
+    {
+      code: 'computed(() => { return 123; })',
+      errors: [{ message: ERROR_MESSAGE, type: 'ArrowFunctionExpression' }],
+    },
+
+    {
+      code: "computed('prop', () => { return this.prop; })",
+      errors: [{ message: ERROR_MESSAGE, type: 'ArrowFunctionExpression' }],
+    },
+
+    {
+      code: "computed('prop', () => { return this.prop; }).volatile()",
+      errors: [{ message: ERROR_MESSAGE, type: 'ArrowFunctionExpression' }],
+    },
+
+    {
+      code: "computed.map('products', product => { return someFunction(product); })",
+      errors: [{ message: ERROR_MESSAGE, type: 'ArrowFunctionExpression' }],
+    },
+  ],
+});