Skip to content

Commit

Permalink
Add class properties support to require-render-return (fixes #564)
Browse files Browse the repository at this point in the history
  • Loading branch information
yannickcr committed May 3, 2016
1 parent 04d9b17 commit 01af82d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
31 changes: 27 additions & 4 deletions lib/rules/require-render-return.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ module.exports = Components.detect(function(context, components, utils) {
}
}

/**
* Get properties name
* @param {Object} node - Property.
* @returns {String} Property name.
*/
function getPropertyName(node) {
// Special case for class properties
// (babel-eslint does not expose property name so we have to rely on tokens)
if (node.type === 'ClassProperty') {
var tokens = context.getFirstTokens(node, 2);
return tokens[1] && tokens[1].type === 'Identifier' ? tokens[1].value : tokens[0].value;
}

return node.key.name;
}

/**
* Check if a given AST node has a render method
* @param {ASTNode} node The AST node being checked.
Expand All @@ -46,10 +62,10 @@ module.exports = Components.detect(function(context, components, utils) {
function hasRenderMethod(node) {
var properties = getComponentProperties(node);
for (var i = 0, j = properties.length; i < j; i++) {
if (properties[i].key.name !== 'render') {
if (getPropertyName(properties[i]) !== 'render') {
continue;
}
return properties[i].value.type === 'FunctionExpression';
return /FunctionExpression$/.test(properties[i].value.type);
}
return false;
}
Expand All @@ -63,8 +79,8 @@ module.exports = Components.detect(function(context, components, utils) {
depth++;
}
if (
(ancestors[i].type !== 'Property' && ancestors[i].type !== 'MethodDefinition') ||
ancestors[i].key.name !== 'render' ||
!/(MethodDefinition|(Class)?Property)$/.test(ancestors[i].type) ||
getPropertyName(ancestors[i]) !== 'render' ||
depth > 1
) {
continue;
Expand All @@ -73,6 +89,13 @@ module.exports = Components.detect(function(context, components, utils) {
}
},

ArrowFunctionExpression: function(node) {
if (node.expression === false || getPropertyName(node.parent) !== 'render') {
return;
}
markReturnStatementPresent(node);
},

'Program:exit': function() {
var list = components.list();
for (var component in list) {
Expand Down
36 changes: 36 additions & 0 deletions tests/lib/rules/require-render-return.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,28 @@ ruleTester.run('require-render-return', rule, {
'}'
].join('\n'),
parserOptions: parserOptions
}, {
// ES6 class with render property
code: [
'class Hello extends React.Component {',
' render = () => {',
' return <div>Hello {this.props.name}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
parserOptions: parserOptions
}, {
// ES6 class with render property (implicit return)
code: [
'class Hello extends React.Component {',
' render = () => (',
' <div>Hello {this.props.name}</div>',
' )',
'}'
].join('\n'),
parser: 'babel-eslint',
parserOptions: parserOptions
}, {
// ES5 class
code: [
Expand Down Expand Up @@ -150,5 +172,19 @@ ruleTester.run('require-render-return', rule, {
errors: [{
message: 'Your render method should have return statement'
}]
}, {
// Missing return ES6 class render property
code: [
'class Hello extends React.Component {',
' render = () => {',
' <div>Hello {this.props.name}</div>',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
parserOptions: parserOptions,
errors: [{
message: 'Your render method should have return statement'
}]
}
]});

0 comments on commit 01af82d

Please sign in to comment.