66
77const docsUrl = require ( '../util/docsUrl' ) ;
88
9- // ------------------------------------------------------------------------------
10- // Constants
11- // ------------------------------------------------------------------------------
12-
13-
14- // ------------------------------------------------------------------------------
15- // Rule Definition
16- // ------------------------------------------------------------------------------
17-
189module . exports = {
1910 meta : {
2011 docs : {
2112 description : 'Forbid using another component\'s propTypes' ,
2213 category : 'Best Practices' ,
2314 recommended : false ,
2415 url : docsUrl ( 'forbid-foreign-prop-types' )
25- }
16+ } ,
17+
18+ schema : [
19+ {
20+ type : 'object' ,
21+ properties : {
22+ allowInPropTypes : {
23+ type : 'boolean'
24+ }
25+ } ,
26+ additionalProperties : false
27+ }
28+ ]
2629 } ,
2730
2831 create : function ( context ) {
32+ const config = context . options [ 0 ] || { } ;
33+ const allowInPropTypes = config . allowInPropTypes || false ;
34+
2935 // --------------------------------------------------------------------------
3036 // Helpers
3137 // --------------------------------------------------------------------------
@@ -34,15 +40,56 @@ module.exports = {
3440 return node . parent . type === 'AssignmentExpression' && node . parent . left === node ;
3541 }
3642
43+ function findParentAssignmentExpression ( node ) {
44+ let parent = node . parent ;
45+
46+ while ( parent && parent . type !== 'Program' ) {
47+ if ( parent . type === 'AssignmentExpression' ) {
48+ return parent ;
49+ }
50+ parent = parent . parent ;
51+ }
52+ return null ;
53+ }
54+
55+ function isAllowedAssignment ( node ) {
56+ if ( ! allowInPropTypes ) {
57+ return false ;
58+ }
59+
60+ const assignmentExpression = findParentAssignmentExpression ( node ) ;
61+
62+ if (
63+ assignmentExpression &&
64+ assignmentExpression . left &&
65+ assignmentExpression . left . property &&
66+ assignmentExpression . left . property . name === 'propTypes'
67+ ) {
68+ return true ;
69+ }
70+ return false ;
71+ }
72+
3773 return {
3874 MemberExpression : function ( node ) {
39- if ( ! node . computed && node . property && node . property . type === 'Identifier' &&
40- node . property . name === 'propTypes' && ! isLeftSideOfAssignment ( node ) ||
41- node . property && node . property . type === 'Literal' &&
42- node . property . value === 'propTypes' && ! isLeftSideOfAssignment ( node ) ) {
75+ if (
76+ node . property &&
77+ (
78+ ! node . computed &&
79+ node . property . type === 'Identifier' &&
80+ node . property . name === 'propTypes' &&
81+ ! isLeftSideOfAssignment ( node ) &&
82+ ! isAllowedAssignment ( node )
83+ ) || (
84+ node . property . type === 'Literal' &&
85+ node . property . value === 'propTypes' &&
86+ ! isLeftSideOfAssignment ( node ) &&
87+ ! isAllowedAssignment ( node )
88+ )
89+ ) {
4390 context . report ( {
4491 node : node . property ,
45- message : 'Using another component\'s propTypes is forbidden '
92+ message : 'Using propTypes from another component is not safe because they may be removed in production builds '
4693 } ) ;
4794 }
4895 } ,
@@ -53,7 +100,7 @@ module.exports = {
53100 if ( propTypesNode ) {
54101 context . report ( {
55102 node : propTypesNode ,
56- message : 'Using another component\'s propTypes is forbidden '
103+ message : 'Using propTypes from another component is not safe because they may be removed in production builds '
57104 } ) ;
58105 }
59106 }
0 commit comments