6
6
7
7
const docsUrl = require ( '../util/docsUrl' ) ;
8
8
9
- // ------------------------------------------------------------------------------
10
- // Constants
11
- // ------------------------------------------------------------------------------
12
-
13
-
14
- // ------------------------------------------------------------------------------
15
- // Rule Definition
16
- // ------------------------------------------------------------------------------
17
-
18
9
module . exports = {
19
10
meta : {
20
11
docs : {
21
12
description : 'Forbid using another component\'s propTypes' ,
22
13
category : 'Best Practices' ,
23
14
recommended : false ,
24
15
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
+ ]
26
29
} ,
27
30
28
31
create : function ( context ) {
32
+ const config = context . options [ 0 ] || { } ;
33
+ const allowInPropTypes = config . allowInPropTypes || false ;
34
+
29
35
// --------------------------------------------------------------------------
30
36
// Helpers
31
37
// --------------------------------------------------------------------------
@@ -34,15 +40,56 @@ module.exports = {
34
40
return node . parent . type === 'AssignmentExpression' && node . parent . left === node ;
35
41
}
36
42
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
+
37
73
return {
38
74
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
+ ) {
43
90
context . report ( {
44
91
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 '
46
93
} ) ;
47
94
}
48
95
} ,
@@ -53,7 +100,7 @@ module.exports = {
53
100
if ( propTypesNode ) {
54
101
context . report ( {
55
102
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 '
57
104
} ) ;
58
105
}
59
106
}
0 commit comments