From af96b7197c9b9d7f0a1e5e625988f32fcacee446 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 15 Mar 2016 23:29:13 +0200 Subject: [PATCH 1/3] Require return value in render function. Tests and rule. --- lib/rules/require-render-return.js | 55 ++++++++++++++++++ tests/lib/rules/require-render-return.js | 73 ++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 lib/rules/require-render-return.js create mode 100644 tests/lib/rules/require-render-return.js diff --git a/lib/rules/require-render-return.js b/lib/rules/require-render-return.js new file mode 100644 index 0000000000..84c6ec7e0f --- /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 = [{}]; diff --git a/tests/lib/rules/require-render-return.js b/tests/lib/rules/require-render-return.js new file mode 100644 index 0000000000..8eb388dd4f --- /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
Hello {this.props.name}
;', + ' }', + '}' + ].join('\n'), + parserOptions: parserOptions + }, { + code: [ + 'var Hello = React.createClass({', + ' displayName: \'Hello\',', + ' render: function() {', + ' return
', + ' }', + '});' + ].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' + }] + } +]}); From 625e28e9a053d6d71a04b1eaddd96b34217d04b6 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 15 Mar 2016 23:38:21 +0200 Subject: [PATCH 2/3] Fix: lint checking for tests --- tests/lib/rules/require-render-return.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/rules/require-render-return.js b/tests/lib/rules/require-render-return.js index 8eb388dd4f..8010b5732d 100644 --- a/tests/lib/rules/require-render-return.js +++ b/tests/lib/rules/require-render-return.js @@ -37,7 +37,7 @@ ruleTester.run('require-render-return', rule, { ].join('\n'), parserOptions: parserOptions }, { - code: [ + code: [ 'var Hello = React.createClass({', ' displayName: \'Hello\',', ' render: function() {', From 08800fec6ca35bc948ddd97af918dcd85098c828 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 15 Mar 2016 23:43:09 +0200 Subject: [PATCH 3/3] Added rule require-render-return to Library --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 38b655040d..effb5ae9c4 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: {