@@ -15,7 +15,8 @@ var annotations = require('../util/annotations');
1515// Constants
1616// ------------------------------------------------------------------------------
1717
18- var DIRECT_PROPS_REGEX = / ^ p r o p s \s * ( \. | \[ ) / ;
18+ var PROPS_REGEX = / ^ ( p r o p s | n e x t P r o p s ) $ / ;
19+ var DIRECT_PROPS_REGEX = / ^ ( p r o p s | n e x t P r o p s ) \s * ( \. | \[ ) / ;
1920
2021// ------------------------------------------------------------------------------
2122// Rule Definition
@@ -81,6 +82,39 @@ module.exports = {
8182 return value ;
8283 }
8384
85+ /**
86+ * Check if we are in a class constructor
87+ * @return {boolean } true if we are in a class constructor, false if not
88+ */
89+ function inConstructor ( ) {
90+ var scope = context . getScope ( ) ;
91+ while ( scope ) {
92+ if ( scope . block && scope . block . parent && scope . block . parent . kind === 'constructor' ) {
93+ return true ;
94+ }
95+ scope = scope . upper ;
96+ }
97+ return false ;
98+ }
99+
100+ /**
101+ * Check if we are in a class constructor
102+ * @return {boolean } true if we are in a class constructor, false if not
103+ */
104+ function inComponentWillReceiveProps ( ) {
105+ var scope = context . getScope ( ) ;
106+ while ( scope ) {
107+ if (
108+ scope . block && scope . block . parent &&
109+ scope . block . parent . key && scope . block . parent . key . name === 'componentWillReceiveProps'
110+ ) {
111+ return true ;
112+ }
113+ scope = scope . upper ;
114+ }
115+ return false ;
116+ }
117+
84118 /**
85119 * Checks if we are using a prop
86120 * @param {ASTNode } node The AST node being checked.
@@ -92,7 +126,8 @@ module.exports = {
92126 node . object . type === 'ThisExpression' && node . property . name === 'props'
93127 ) ;
94128 var isStatelessFunctionUsage = node . object . name === 'props' ;
95- return isClassUsage || isStatelessFunctionUsage ;
129+ var isNextPropsUsage = node . object . name === 'nextProps' && inComponentWillReceiveProps ( ) ;
130+ return isClassUsage || isStatelessFunctionUsage || isNextPropsUsage ;
96131 }
97132
98133 /**
@@ -464,21 +499,6 @@ module.exports = {
464499 }
465500 }
466501
467- /**
468- * Check if we are in a class constructor
469- * @return {boolean } true if we are in a class constructor, false if not
470- */
471- function inConstructor ( ) {
472- var scope = context . getScope ( ) ;
473- while ( scope ) {
474- if ( scope . block && scope . block . parent && scope . block . parent . kind === 'constructor' ) {
475- return true ;
476- }
477- scope = scope . upper ;
478- }
479- return false ;
480- }
481-
482502 /**
483503 * Retrieve the name of a property node
484504 * @param {ASTNode } node The AST node with the property.
@@ -487,8 +507,9 @@ module.exports = {
487507 function getPropertyName ( node ) {
488508 var isDirectProp = DIRECT_PROPS_REGEX . test ( sourceCode . getText ( node ) ) ;
489509 var isInClassComponent = utils . getParentES6Component ( ) || utils . getParentES5Component ( ) ;
490- var isNotInConstructor = ! inConstructor ( node ) ;
491- if ( isDirectProp && isInClassComponent && isNotInConstructor ) {
510+ var isNotInConstructor = ! inConstructor ( ) ;
511+ var isNotInComponentWillReceiveProps = ! inComponentWillReceiveProps ( ) ;
512+ if ( isDirectProp && isInClassComponent && isNotInConstructor && isNotInComponentWillReceiveProps ) {
492513 return void 0 ;
493514 }
494515 if ( ! isDirectProp ) {
@@ -561,13 +582,13 @@ module.exports = {
561582 // let {props: {firstname}} = this
562583 var thisDestructuring = (
563584 ! hasSpreadOperator ( node . id . properties [ i ] ) &&
564- ( node . id . properties [ i ] . key . name === 'props' || node . id . properties [ i ] . key . value === 'props' ) &&
585+ ( PROPS_REGEX . test ( node . id . properties [ i ] . key . name ) || PROPS_REGEX . test ( node . id . properties [ i ] . key . value ) ) &&
565586 node . id . properties [ i ] . value . type === 'ObjectPattern'
566587 ) ;
567588 // let {firstname} = props
568589 var directDestructuring =
569- node . init . name === 'props' &&
570- ( utils . getParentStatelessComponent ( ) || inConstructor ( ) )
590+ PROPS_REGEX . test ( node . init . name ) &&
591+ ( utils . getParentStatelessComponent ( ) || inConstructor ( ) || inComponentWillReceiveProps ( ) )
571592 ;
572593
573594 if ( thisDestructuring ) {
@@ -600,7 +621,10 @@ module.exports = {
600621 usedPropTypes . push ( {
601622 name : name ,
602623 allNames : allNames ,
603- node : ! isDirectProp && ! inConstructor ( node ) ? node . parent . property : node . property
624+ node : (
625+ ! isDirectProp && ! inConstructor ( ) && ! inComponentWillReceiveProps ( ) ? node . parent . property :
626+ node . property
627+ )
604628 } ) ;
605629 break ;
606630 case 'destructuring' :
@@ -612,7 +636,7 @@ module.exports = {
612636
613637 var currentNode = node ;
614638 allNames = [ ] ;
615- while ( currentNode . property && currentNode . property . name !== 'props' ) {
639+ while ( currentNode . property && ! PROPS_REGEX . test ( currentNode . property . name ) ) {
616640 allNames . unshift ( currentNode . property . name ) ;
617641 currentNode = currentNode . object ;
618642 }
@@ -813,8 +837,8 @@ module.exports = {
813837 // let {firstname} = props
814838 var directDestructuring =
815839 destructuring &&
816- node . init . name === 'props' &&
817- ( utils . getParentStatelessComponent ( ) || inConstructor ( ) )
840+ PROPS_REGEX . test ( node . init . name ) &&
841+ ( utils . getParentStatelessComponent ( ) || inConstructor ( ) || inComponentWillReceiveProps ( ) )
818842 ;
819843
820844 if ( ! thisDestructuring && ! directDestructuring ) {
0 commit comments