Skip to content

Commit 01af82d

Browse files
committed
Add class properties support to require-render-return (fixes #564)
1 parent 04d9b17 commit 01af82d

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

lib/rules/require-render-return.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ module.exports = Components.detect(function(context, components, utils) {
3838
}
3939
}
4040

41+
/**
42+
* Get properties name
43+
* @param {Object} node - Property.
44+
* @returns {String} Property name.
45+
*/
46+
function getPropertyName(node) {
47+
// Special case for class properties
48+
// (babel-eslint does not expose property name so we have to rely on tokens)
49+
if (node.type === 'ClassProperty') {
50+
var tokens = context.getFirstTokens(node, 2);
51+
return tokens[1] && tokens[1].type === 'Identifier' ? tokens[1].value : tokens[0].value;
52+
}
53+
54+
return node.key.name;
55+
}
56+
4157
/**
4258
* Check if a given AST node has a render method
4359
* @param {ASTNode} node The AST node being checked.
@@ -46,10 +62,10 @@ module.exports = Components.detect(function(context, components, utils) {
4662
function hasRenderMethod(node) {
4763
var properties = getComponentProperties(node);
4864
for (var i = 0, j = properties.length; i < j; i++) {
49-
if (properties[i].key.name !== 'render') {
65+
if (getPropertyName(properties[i]) !== 'render') {
5066
continue;
5167
}
52-
return properties[i].value.type === 'FunctionExpression';
68+
return /FunctionExpression$/.test(properties[i].value.type);
5369
}
5470
return false;
5571
}
@@ -63,8 +79,8 @@ module.exports = Components.detect(function(context, components, utils) {
6379
depth++;
6480
}
6581
if (
66-
(ancestors[i].type !== 'Property' && ancestors[i].type !== 'MethodDefinition') ||
67-
ancestors[i].key.name !== 'render' ||
82+
!/(MethodDefinition|(Class)?Property)$/.test(ancestors[i].type) ||
83+
getPropertyName(ancestors[i]) !== 'render' ||
6884
depth > 1
6985
) {
7086
continue;
@@ -73,6 +89,13 @@ module.exports = Components.detect(function(context, components, utils) {
7389
}
7490
},
7591

92+
ArrowFunctionExpression: function(node) {
93+
if (node.expression === false || getPropertyName(node.parent) !== 'render') {
94+
return;
95+
}
96+
markReturnStatementPresent(node);
97+
},
98+
7699
'Program:exit': function() {
77100
var list = components.list();
78101
for (var component in list) {

tests/lib/rules/require-render-return.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,28 @@ ruleTester.run('require-render-return', rule, {
3737
'}'
3838
].join('\n'),
3939
parserOptions: parserOptions
40+
}, {
41+
// ES6 class with render property
42+
code: [
43+
'class Hello extends React.Component {',
44+
' render = () => {',
45+
' return <div>Hello {this.props.name}</div>;',
46+
' }',
47+
'}'
48+
].join('\n'),
49+
parser: 'babel-eslint',
50+
parserOptions: parserOptions
51+
}, {
52+
// ES6 class with render property (implicit return)
53+
code: [
54+
'class Hello extends React.Component {',
55+
' render = () => (',
56+
' <div>Hello {this.props.name}</div>',
57+
' )',
58+
'}'
59+
].join('\n'),
60+
parser: 'babel-eslint',
61+
parserOptions: parserOptions
4062
}, {
4163
// ES5 class
4264
code: [
@@ -150,5 +172,19 @@ ruleTester.run('require-render-return', rule, {
150172
errors: [{
151173
message: 'Your render method should have return statement'
152174
}]
175+
}, {
176+
// Missing return ES6 class render property
177+
code: [
178+
'class Hello extends React.Component {',
179+
' render = () => {',
180+
' <div>Hello {this.props.name}</div>',
181+
' }',
182+
'}'
183+
].join('\n'),
184+
parser: 'babel-eslint',
185+
parserOptions: parserOptions,
186+
errors: [{
187+
message: 'Your render method should have return statement'
188+
}]
153189
}
154190
]});

0 commit comments

Comments
 (0)