@@ -36,6 +36,9 @@ module.exports = {
36
36
} ,
37
37
38
38
create : Components . detect ( ( context , components , utils ) => {
39
+ let propTypesPackageName = null ;
40
+ let reactPackageName = null ;
41
+
39
42
function checkValidPropTypeQualfier ( node ) {
40
43
if ( node . name !== 'isRequired' ) {
41
44
context . report ( {
@@ -54,38 +57,66 @@ module.exports = {
54
57
}
55
58
}
56
59
60
+ function isPropTypesPackage ( node ) {
61
+ return (
62
+ node . type === 'Identifier' &&
63
+ node . name === propTypesPackageName
64
+ ) || (
65
+ node . type === 'MemberExpression' &&
66
+ node . property . name === 'PropTypes' &&
67
+ node . object . name === reactPackageName
68
+ ) ;
69
+ }
70
+
57
71
/* eslint-disable no-use-before-define */
72
+
73
+ function checkValidCallExpression ( node ) {
74
+ const callee = node . callee ;
75
+ if ( callee . type === 'MemberExpression' && callee . property . name === 'shape' ) {
76
+ checkValidPropObject ( node . arguments [ 0 ] ) ;
77
+ } else if ( callee . type === 'MemberExpression' && callee . property . name === 'oneOfType' ) {
78
+ const args = node . arguments [ 0 ] ;
79
+ if ( args && args . type === 'ArrayExpression' ) {
80
+ args . elements . forEach ( el => {
81
+ checkValidProp ( el ) ;
82
+ } ) ;
83
+ }
84
+ }
85
+ }
86
+
58
87
function checkValidProp ( node ) {
59
- if ( node && node . type === 'MemberExpression' && node . object . type === 'MemberExpression' ) {
60
- checkValidPropType ( node . object . property ) ;
61
- checkValidPropTypeQualfier ( node . property ) ;
62
- } else if ( node && node . type === 'MemberExpression' && node . object . type === 'Identifier' && node . property . name !== 'isRequired' ) {
63
- checkValidPropType ( node . property ) ;
64
- } else if ( node && (
65
- node . type === 'MemberExpression' && node . object . type === 'CallExpression' || node . type === 'CallExpression'
66
- ) ) {
67
- if ( node . type === 'MemberExpression' ) {
88
+ if ( ( ! propTypesPackageName && ! reactPackageName ) || ! node ) {
89
+ return ;
90
+ }
91
+
92
+ if ( node . type === 'MemberExpression' ) {
93
+ if (
94
+ node . object . type === 'MemberExpression' &&
95
+ isPropTypesPackage ( node . object . object )
96
+ ) { // PropTypes.myProp.isRequired
97
+ checkValidPropType ( node . object . property ) ;
68
98
checkValidPropTypeQualfier ( node . property ) ;
69
- node = node . object ;
70
- }
71
- const callee = node . callee ;
72
- if ( callee . type === 'MemberExpression' && callee . property . name === 'shape' ) {
73
- checkValidPropObject ( node . arguments [ 0 ] ) ;
74
- } else if ( callee . type === 'MemberExpression' && callee . property . name === 'oneOfType' ) {
75
- const args = node . arguments [ 0 ] ;
76
- if ( args && args . type === 'ArrayExpression' ) {
77
- args . elements . forEach ( el => checkValidProp ( el ) ) ;
78
- }
99
+ } else if (
100
+ isPropTypesPackage ( node . object ) &&
101
+ node . property . name !== 'isRequired'
102
+ ) { // PropTypes.myProp
103
+ checkValidPropType ( node . property ) ;
104
+ } else if ( node . object . type === 'CallExpression' ) {
105
+ checkValidPropTypeQualfier ( node . property ) ;
106
+ checkValidCallExpression ( node . object ) ;
79
107
}
108
+ } else if ( node . type === 'CallExpression' ) {
109
+ checkValidCallExpression ( node ) ;
80
110
}
81
111
}
82
112
113
+ /* eslint-enable no-use-before-define */
114
+
83
115
function checkValidPropObject ( node ) {
84
116
if ( node && node . type === 'ObjectExpression' ) {
85
117
node . properties . forEach ( prop => checkValidProp ( prop . value ) ) ;
86
118
}
87
119
}
88
- /* eslint-enable no-use-before-define */
89
120
90
121
function reportErrorIfClassPropertyCasingTypo ( node , propertyName ) {
91
122
if ( propertyName === 'propTypes' || propertyName === 'contextTypes' || propertyName === 'childContextTypes' ) {
@@ -114,6 +145,23 @@ module.exports = {
114
145
}
115
146
116
147
return {
148
+ ImportDeclaration : function ( node ) {
149
+ if ( node . source && node . source . value === 'prop-types' ) { // import PropType from "prop-types"
150
+ propTypesPackageName = node . specifiers [ 0 ] . local . name ;
151
+ } else if ( node . source && node . source . value === 'react' ) { // import { PropTypes } from "react"
152
+ reactPackageName = node . specifiers [ 0 ] . local . name ;
153
+
154
+ if ( node . specifiers . length >= 1 ) {
155
+ const propTypesSpecifier = node . specifiers . find ( specifier => (
156
+ specifier . imported && specifier . imported . name === 'PropTypes'
157
+ ) ) ;
158
+ if ( propTypesSpecifier ) {
159
+ propTypesPackageName = propTypesSpecifier . local . name ;
160
+ }
161
+ }
162
+ }
163
+ } ,
164
+
117
165
ClassProperty : function ( node ) {
118
166
if ( ! node . static || ! utils . isES6Component ( node . parent . parent ) ) {
119
167
return ;
0 commit comments