Skip to content

Commit

Permalink
Fix props detection when used in an object (fixes #41)
Browse files Browse the repository at this point in the history
  • Loading branch information
yannickcr committed Mar 29, 2015
1 parent 2d9004b commit 8b7b848
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 15 deletions.
44 changes: 29 additions & 15 deletions lib/util/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,42 @@ function isReactComponent(context, node) {
return Boolean(isEmptyComponentRender || isComponentRender);
}

/**
* Detect if the node is a component definition
* @param {ASTNode} node The AST node being checked.
* @returns {Boolean} True the node is a component definition, false if not.
*/
function isComponentDefinition(node) {
var isES6Component = node.type === 'ClassDeclaration';
var isES5Component = Boolean(
node.type === 'ObjectExpression' &&
node.parent &&
node.parent.callee &&
node.parent.callee.object &&
node.parent.callee.property &&
node.parent.callee.object.name === 'React' &&
node.parent.callee.property.name === 'createClass'
);
return isES5Component || isES6Component;
}

/**
* Get the React component ASTNode from any child ASTNode
* @param {Object} context The current rule context.
* @param {ASTNode} node The AST node being checked.
* @returns {ASTNode} The ASTNode of the React component.
*/
function getNode(context, node) {
var componentNode;

if (node.type === 'ClassDeclaration' || node.type === 'ObjectExpression') {
componentNode = node;
} else {
var ancestors = context.getAncestors().reverse();
for (var i = 0, j = ancestors.length; i < j; i++) {
if (ancestors[i].type === 'ClassDeclaration' || ancestors[i].type === 'ObjectExpression') {
componentNode = ancestors[i];
break;
}
}
}
var componentNode = null;
var ancestors = context.getAncestors().reverse();

if (!componentNode) {
return null;
ancestors.unshift(node);

for (var i = 0, j = ancestors.length; i < j; i++) {
if (isComponentDefinition(ancestors[i])) {
componentNode = ancestors[i];
break;
}
}

return componentNode;
Expand Down Expand Up @@ -188,6 +201,7 @@ module.exports = {
DEFAULT_COMPONENT_NAME: DEFAULT_COMPONENT_NAME,
isReactComponent: isReactComponent,
getNode: getNode,
isComponentDefinition: isComponentDefinition,
getIdentifiers: getIdentifiers,
List: List
};
17 changes: 17 additions & 0 deletions tests/lib/rules/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,23 @@ eslintTester.addRuleTest('lib/rules/prop-types', {
classes: true,
jsx: true
}
}, {
code: [
'var Hello = React.createClass({',
' propTypes: {',
' name: React.PropTypes.object.isRequired',
' },',
' render: function() {',
' var user = {',
' name: this.props.name',
' };',
' return <div>Hello {user.name}</div>;',
' }',
'});'
].join('\n'),
ecmaFeatures: {
jsx: true
}
}
],

Expand Down

0 comments on commit 8b7b848

Please sign in to comment.