Skip to content

Commit 557322a

Browse files
committed
Fix nextProps false positive in no-unused-prop-types
1 parent b646485 commit 557322a

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

lib/rules/no-unused-prop-types.js

+28-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var annotations = require('../util/annotations');
1818
// ------------------------------------------------------------------------------
1919

2020
var DIRECT_PROPS_REGEX = /^props\s*(\.|\[)/;
21+
var DIRECT_NEXT_PROPS_REGEX = /^nextProps\s*(\.|\[)/;
2122

2223
// ------------------------------------------------------------------------------
2324
// Rule Definition
@@ -77,6 +78,24 @@ module.exports = {
7778
return value;
7879
}
7980

81+
/**
82+
* Check if we are in a class constructor
83+
* @return {boolean} true if we are in a class constructor, false if not
84+
**/
85+
function inComponentWillReceiveProps() {
86+
var scope = context.getScope();
87+
while (scope) {
88+
if (
89+
scope.block && scope.block.parent &&
90+
scope.block.parent.key && scope.block.parent.key.name === 'componentWillReceiveProps'
91+
) {
92+
return true;
93+
}
94+
scope = scope.upper;
95+
}
96+
return false;
97+
}
98+
8099
/**
81100
* Checks if we are using a prop
82101
* @param {ASTNode} node The AST node being checked.
@@ -88,7 +107,8 @@ module.exports = {
88107
node.object.type === 'ThisExpression' && node.property.name === 'props'
89108
);
90109
var isStatelessFunctionUsage = node.object.name === 'props';
91-
return isClassUsage || isStatelessFunctionUsage;
110+
var isNextPropsUsage = node.object.name === 'nextProps' && inComponentWillReceiveProps();
111+
return isClassUsage || isStatelessFunctionUsage || isNextPropsUsage;
92112
}
93113

94114
/**
@@ -491,12 +511,17 @@ module.exports = {
491511
*/
492512
function getPropertyName(node) {
493513
var isDirectProp = DIRECT_PROPS_REGEX.test(sourceCode.getText(node));
514+
var isDirectNextProp = DIRECT_NEXT_PROPS_REGEX.test(sourceCode.getText(node));
494515
var isInClassComponent = utils.getParentES6Component() || utils.getParentES5Component();
495516
var isNotInConstructor = !inConstructor(node);
496-
if (isDirectProp && isInClassComponent && isNotInConstructor) {
517+
var isNotInComponentWillReceiveProps = !inComponentWillReceiveProps();
518+
if ((isDirectProp || isDirectNextProp)
519+
&& isInClassComponent
520+
&& isNotInConstructor
521+
&& isNotInComponentWillReceiveProps) {
497522
return void 0;
498523
}
499-
if (!isDirectProp) {
524+
if (!isDirectProp && !isDirectNextProp) {
500525
node = node.parent;
501526
}
502527
var property = node.property;

tests/lib/rules/no-unused-prop-types.js

+16
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,22 @@ ruleTester.run('no-unused-prop-types', rule, {
14611461
'};'
14621462
].join('\n'),
14631463
parserOptions: parserOptions
1464+
}, {
1465+
code: [
1466+
'class Hello extends Component {',
1467+
' componentWillReceiveProps (nextProps) {',
1468+
' if (nextProps.foo) {',
1469+
' doSomething(this.props.bar);',
1470+
' }',
1471+
' }',
1472+
'}',
1473+
1474+
'Hello.propTypes = {',
1475+
' foo: PropTypes.bool,',
1476+
' bar: PropTypes.bool',
1477+
'};'
1478+
].join('\n'),
1479+
parserOptions: parserOptions
14641480
}
14651481
],
14661482

0 commit comments

Comments
 (0)