@@ -32,13 +32,19 @@ function isSuperTypeParameterPropsDeclaration(node) {
32
32
* @param {Object[] } properties Array of properties to iterate.
33
33
* @param {Function } fn Function to call on each property, receives property key
34
34
and property value. (key, value) => void
35
+ * @param {Function } [handleSpreadFn] Function to call on each ObjectTypeSpreadProperty, receives the
36
+ argument
35
37
*/
36
- function iterateProperties ( context , properties , fn ) {
38
+ function iterateProperties ( context , properties , fn , handleSpreadFn ) {
37
39
if ( properties && properties . length && typeof fn === 'function' ) {
38
40
for ( let i = 0 , j = properties . length ; i < j ; i ++ ) {
39
41
const node = properties [ i ] ;
40
42
const key = getKeyValue ( context , node ) ;
41
43
44
+ if ( node . type === 'ObjectTypeSpreadProperty' && typeof handleSpreadFn === 'function' ) {
45
+ handleSpreadFn ( node . argument ) ;
46
+ }
47
+
42
48
const value = node . value ;
43
49
fn ( key , value , node ) ;
44
50
}
@@ -121,30 +127,41 @@ module.exports = function propTypesInstructions(context, components, utils) {
121
127
} ,
122
128
123
129
ObjectTypeAnnotation ( annotation , parentName , seen ) {
124
- let containsObjectTypeSpread = false ;
130
+ let containsUnresolvedObjectTypeSpread = false ;
131
+ let containsSpread = false ;
125
132
const containsIndexers = Boolean ( annotation . indexers && annotation . indexers . length ) ;
126
133
const shapeTypeDefinition = {
127
134
type : 'shape' ,
128
135
children : { }
129
136
} ;
130
137
iterateProperties ( context , annotation . properties , ( childKey , childValue , propNode ) => {
131
138
const fullName = [ parentName , childKey ] . join ( '.' ) ;
132
- if ( ! childKey && ! childValue ) {
133
- containsObjectTypeSpread = true ;
134
- } else {
139
+ if ( childKey || childValue ) {
135
140
const types = buildTypeAnnotationDeclarationTypes ( childValue , fullName , seen ) ;
136
141
types . fullName = fullName ;
137
142
types . name = childKey ;
138
143
types . node = propNode ;
139
144
types . isRequired = ! childValue . optional ;
140
145
shapeTypeDefinition . children [ childKey ] = types ;
141
146
}
147
+ } ,
148
+ ( spreadNode ) => {
149
+ const key = getKeyValue ( context , spreadNode ) ;
150
+ const types = buildTypeAnnotationDeclarationTypes ( spreadNode , key , seen ) ;
151
+ if ( ! types . children ) {
152
+ containsUnresolvedObjectTypeSpread = true ;
153
+ } else {
154
+ Object . assign ( shapeTypeDefinition , types . children ) ;
155
+ }
156
+ containsSpread = true ;
142
157
} ) ;
143
158
144
159
// Mark if this shape has spread or an indexer. We will know to consider all props from this shape as having propTypes,
145
160
// but still have the ability to detect unused children of this shape.
146
- shapeTypeDefinition . containsSpread = containsObjectTypeSpread ;
161
+ shapeTypeDefinition . containsUnresolvedSpread = containsUnresolvedObjectTypeSpread ;
147
162
shapeTypeDefinition . containsIndexers = containsIndexers ;
163
+ // Deprecated: containsSpread is not used anymore in the codebase, ensure to keep API backward compatibility
164
+ shapeTypeDefinition . containsSpread = containsSpread ;
148
165
149
166
return shapeTypeDefinition ;
150
167
} ,
@@ -241,7 +258,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
241
258
}
242
259
243
260
/**
244
- * Marks all props found inside ObjectTypeAnnotaiton as declared.
261
+ * Marks all props found inside ObjectTypeAnnotation as declared.
245
262
*
246
263
* Modifies the declaredProperties object
247
264
* @param {ASTNode } propTypes
@@ -253,7 +270,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
253
270
254
271
iterateProperties ( context , propTypes . properties , ( key , value , propNode ) => {
255
272
if ( ! value ) {
256
- ignorePropsValidation = true ;
273
+ ignorePropsValidation = ignorePropsValidation || propNode . type !== 'ObjectTypeSpreadProperty' ;
257
274
return ;
258
275
}
259
276
@@ -263,6 +280,15 @@ module.exports = function propTypesInstructions(context, components, utils) {
263
280
types . node = propNode ;
264
281
types . isRequired = ! propNode . optional ;
265
282
declaredPropTypes [ key ] = types ;
283
+ } , ( spreadNode ) => {
284
+ const key = getKeyValue ( context , spreadNode ) ;
285
+ const spreadAnnotation = getInTypeScope ( key ) ;
286
+ if ( ! spreadAnnotation ) {
287
+ ignorePropsValidation = true ;
288
+ } else {
289
+ const spreadIgnoreValidation = declarePropTypesForObjectTypeAnnotation ( spreadAnnotation , declaredPropTypes ) ;
290
+ ignorePropsValidation = ignorePropsValidation || spreadIgnoreValidation ;
291
+ }
266
292
} ) ;
267
293
268
294
return ignorePropsValidation ;
0 commit comments