Skip to content

Commit af96b71

Browse files
committed
Require return value in render function. Tests and rule.
1 parent f24d0cb commit af96b71

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

lib/rules/require-render-return.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @fileoverview Enforce ES5 or ES6 class for returning value in render function.
3+
* @author Mark Orel
4+
*/
5+
'use strict';
6+
7+
var Components = require('../util/Components');
8+
9+
// ------------------------------------------------------------------------------
10+
// Rule Definition
11+
// ------------------------------------------------------------------------------
12+
13+
module.exports = Components.detect(function(context) {
14+
/**
15+
* Helper for checking if parent node is render method.
16+
* @param {ASTNode} node to check
17+
* @returns {boolean} If previous node is method and name is render returns true, otherwise false;
18+
*/
19+
function checkParent(node) {
20+
return (node.parent.type === 'Property' || node.parent.type === 'MethodDefinition')
21+
&& node.parent.key
22+
&& node.parent.key.name === 'render';
23+
}
24+
25+
/**
26+
* Helper for checking if child node exists and if it's ReturnStatement
27+
* @param {ASTNode} node to check
28+
* @returns {boolean} True if ReturnStatement exists, otherwise false
29+
*/
30+
function checkReturnStatementExistence(node) {
31+
if (!node.body && !node.body.body && !node.body.body.length) {
32+
return false;
33+
}
34+
35+
var hasReturnStatement = node.body.body.some(function(elem) {
36+
return elem.type === 'ReturnStatement';
37+
});
38+
39+
return hasReturnStatement;
40+
}
41+
42+
43+
return {
44+
FunctionExpression: function(node) {
45+
if (checkParent(node) && !checkReturnStatementExistence(node)) {
46+
context.report({
47+
node: node,
48+
message: 'Your render method should have return statement'
49+
});
50+
}
51+
}
52+
};
53+
});
54+
55+
module.exports.schema = [{}];
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* @fileoverview Enforce ES5 or ES6 class for returning value in render function.
3+
* @author Mark Orel
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var rule = require('../../../lib/rules/require-render-return');
12+
var RuleTester = require('eslint').RuleTester;
13+
14+
var parserOptions = {
15+
ecmaVersion: 6,
16+
ecmaFeatures: {
17+
jsx: true
18+
}
19+
};
20+
21+
require('babel-eslint');
22+
23+
// ------------------------------------------------------------------------------
24+
// Tests
25+
// ------------------------------------------------------------------------------
26+
27+
var ruleTester = new RuleTester();
28+
ruleTester.run('require-render-return', rule, {
29+
30+
valid: [{
31+
code: [
32+
'class Hello extends React.Component {',
33+
' render() {',
34+
' return <div>Hello {this.props.name}</div>;',
35+
' }',
36+
'}'
37+
].join('\n'),
38+
parserOptions: parserOptions
39+
}, {
40+
code: [
41+
'var Hello = React.createClass({',
42+
' displayName: \'Hello\',',
43+
' render: function() {',
44+
' return <div></div>',
45+
' }',
46+
'});'
47+
].join('\n'),
48+
parserOptions: parserOptions
49+
}],
50+
51+
invalid: [{
52+
code: [
53+
'var Hello = React.createClass({',
54+
' displayName: \'Hello\',',
55+
' render: function() {}',
56+
'});'
57+
].join('\n'),
58+
parserOptions: parserOptions,
59+
errors: [{
60+
message: 'Your render method should have return statement'
61+
}]
62+
}, {
63+
code: [
64+
'class Hello extends React.Component {',
65+
' render() {} ',
66+
'}'
67+
].join('\n'),
68+
parserOptions: parserOptions,
69+
errors: [{
70+
message: 'Your render method should have return statement'
71+
}]
72+
}
73+
]});

0 commit comments

Comments
 (0)