Repository: yannickcr/eslint-plugin-react
Pull request #502 (2016-03-15 21:32:06)

Require return value in render function. Tests and rule.
Hello react rules writers!
I have tried to make this feature #482. Hope this rule will be suitable for your repository.
The code is linted and tested. 
Waiting for your response.


Patch:
diff --git a/index.js b/index.js
index 38b65504..effb5ae9 100644
--- a/index.js
+++ b/index.js
@@ -41,7 +41,8 @@ module.exports = {
     'prefer-es6-class': require('./lib/rules/prefer-es6-class'),
     'jsx-key': require('./lib/rules/jsx-key'),
     'no-string-refs': require('./lib/rules/no-string-refs'),
-    'prefer-stateless-function': require('./lib/rules/prefer-stateless-function')
+    'prefer-stateless-function': require('./lib/rules/prefer-stateless-function'),
+    'require-render-return': require('./lib/rules/require-render-return')
   },
   configs: {
     recommended: {
diff --git a/lib/rules/require-render-return.js b/lib/rules/require-render-return.js
new file mode 100644
index 00000000..84c6ec7e
--- /dev/null
+++ b/lib/rules/require-render-return.js
@@ -0,0 +1,55 @@
+/**
+ * @fileoverview Enforce ES5 or ES6 class for returning value in render function.
+ * @author Mark Orel
+ */
+'use strict';
+
+var Components = require('../util/Components');
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+module.exports = Components.detect(function(context) {
+  /**
+   * Helper for checking if parent node is render method.
+   * @param {ASTNode} node to check
+   * @returns {boolean} If previous node is method and name is render returns true, otherwise false;
+   */
+  function checkParent(node) {
+    return (node.parent.type === 'Property' || node.parent.type === 'MethodDefinition')
+        && node.parent.key
+        && node.parent.key.name === 'render';
+  }
+
+  /**
+   * Helper for checking if child node exists and if it's ReturnStatement
+   * @param {ASTNode} node to check
+   * @returns {boolean} True if ReturnStatement exists, otherwise false
+   */
+  function checkReturnStatementExistence(node) {
+    if (!node.body && !node.body.body && !node.body.body.length) {
+      return false;
+    }
+
+    var hasReturnStatement = node.body.body.some(function(elem) {
+      return elem.type === 'ReturnStatement';
+    });
+
+    return hasReturnStatement;
+  }
+
+
+  return {
+    FunctionExpression: function(node) {
+      if (checkParent(node) && !checkReturnStatementExistence(node)) {
+        context.report({
+          node: node,
+          message: 'Your render method should have return statement'
+        });
+      }
+    }
+  };
+});
+
+module.exports.schema = [{}];


Test patch:
diff --git a/tests/lib/rules/require-render-return.js b/tests/lib/rules/require-render-return.js
new file mode 100644
index 00000000..8010b573
--- /dev/null
+++ b/tests/lib/rules/require-render-return.js
@@ -0,0 +1,73 @@
+/**
+ * @fileoverview Enforce ES5 or ES6 class for returning value in render function.
+ * @author Mark Orel
+ */
+'use strict';
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require('../../../lib/rules/require-render-return');
+var RuleTester = require('eslint').RuleTester;
+
+var parserOptions = {
+  ecmaVersion: 6,
+  ecmaFeatures: {
+    jsx: true
+  }
+};
+
+require('babel-eslint');
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+var ruleTester = new RuleTester();
+ruleTester.run('require-render-return', rule, {
+
+  valid: [{
+    code: [
+      'class Hello extends React.Component {',
+      '  render() {',
+      '    return <div>Hello {this.props.name}</div>;',
+      '  }',
+      '}'
+    ].join('\n'),
+    parserOptions: parserOptions
+  }, {
+    code: [
+      'var Hello = React.createClass({',
+      '  displayName: \'Hello\',',
+      '  render: function() {',
+      '    return <div></div>',
+      '  }',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions
+  }],
+
+  invalid: [{
+    code: [
+      'var Hello = React.createClass({',
+      '  displayName: \'Hello\',',
+      '  render: function() {}',
+      '});'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{
+      message: 'Your render method should have return statement'
+    }]
+  }, {
+    code: [
+      'class Hello extends React.Component {',
+      '  render() {} ',
+      '}'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{
+      message: 'Your render method should have return statement'
+    }]
+  }
+]});