Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes a few false positive failures in the no-unused-prop-types rule #792

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fixes a few false positive failures in the no-unused-prop-types rule
Evgueni Naverniouk committed Aug 30, 2016
commit 3d090754929d4d518d542b96182abf3f98b5adfe
71 changes: 68 additions & 3 deletions lib/rules/no-unused-prop-types.js
Original file line number Diff line number Diff line change
@@ -174,6 +174,53 @@ module.exports = {
);
}

/**
* Returns true if the given node is a React Component lifecycle method
* @param {ASTNode} node The AST node being checked.
* @return {Boolean} True if the node is a lifecycle method
*/
function isNodeALifeCycleMethod(node) {
var nodeKeyName = (node.key || {}).name;
return (
node.kind === 'constructor' ||
nodeKeyName === 'componentWillReceiveProps' ||
nodeKeyName === 'shouldComponentUpdate' ||
nodeKeyName === 'componentWillUpdate' ||
nodeKeyName === 'componentDidUpdate'
);
}

/**
* Returns true if the given node is inside a React Component lifecycle
* method.
* @param {ASTNode} node The AST node being checked.
* @return {Boolean} True if the node is inside a lifecycle method
*/
function isInLifeCycleMethod(node) {
if (node.type === 'MethodDefinition' && isNodeALifeCycleMethod(node)) {
return true;
}

if (node.parent) {
return isInLifeCycleMethod(node.parent);
}

return false;
}

/**
* Checks if a prop init name matches common naming patterns
* @param {ASTNode} node The AST node being checked.
* @returns {Boolean} True if the prop name matches
*/
function isPropAttributeName (node) {
return (
node.init.name === 'props' ||
node.init.name === 'nextProps' ||
node.init.name === 'prevProps'
);
}

/**
* Checks if a prop is used
* @param {ASTNode} node The AST node being checked.
@@ -536,11 +583,14 @@ module.exports = {
node.id.properties[i].value.type === 'ObjectPattern'
);
// let {firstname} = props
var statelessDestructuring = node.init.name === 'props' && utils.getParentStatelessComponent();
var genericDestructuring = isPropAttributeName(node) && (
utils.getParentStatelessComponent() ||
isInLifeCycleMethod(node)
);

if (thisDestructuring) {
properties = node.id.properties[i].value.properties;
} else if (statelessDestructuring) {
} else if (genericDestructuring) {
properties = node.id.properties;
} else {
continue;
@@ -776,7 +826,10 @@ module.exports = {
// let {props: {firstname}} = this
var thisDestructuring = destructuring && node.init.type === 'ThisExpression';
// let {firstname} = props
var statelessDestructuring = destructuring && node.init.name === 'props' && utils.getParentStatelessComponent();
var statelessDestructuring = destructuring && isPropAttributeName(node) && (
utils.getParentStatelessComponent() ||
isInLifeCycleMethod(node)
);

if (!thisDestructuring && !statelessDestructuring) {
return;
@@ -831,6 +884,18 @@ module.exports = {
}
},

ObjectPattern: function(node) {
// If the object pattern is a destructured props object in a lifecycle
// method -- mark it for used props.
if (isNodeALifeCycleMethod(node.parent.parent)) {
node.properties.forEach(function(property, i) {
if (i === 0) {
markPropTypesAsUsed(node.parent);
}
});
}
},

ObjectExpression: function(node) {
// Search for the proptypes declaration
node.properties.forEach(function(property) {
Loading