@@ -359,7 +359,7 @@ module.exports = {
359
359
value . callee . object &&
360
360
hasCustomValidator ( value . callee . object . name )
361
361
) {
362
- return true ;
362
+ return { } ;
363
363
}
364
364
365
365
if (
@@ -387,23 +387,20 @@ module.exports = {
387
387
switch ( callName ) {
388
388
case 'shape' :
389
389
if ( skipShapeProps ) {
390
- return true ;
390
+ return { } ;
391
391
}
392
392
393
393
if ( argument . type !== 'ObjectExpression' ) {
394
394
// Invalid proptype or cannot analyse statically
395
- return true ;
395
+ return { } ;
396
396
}
397
397
const shapeTypeDefinition = {
398
398
type : 'shape' ,
399
399
children : [ ]
400
400
} ;
401
401
iterateProperties ( argument . properties , ( childKey , childValue ) => {
402
402
const fullName = [ parentName , childKey ] . join ( '.' ) ;
403
- let types = buildReactDeclarationTypes ( childValue , fullName ) ;
404
- if ( types === true ) {
405
- types = { } ;
406
- }
403
+ const types = buildReactDeclarationTypes ( childValue , fullName ) ;
407
404
types . fullName = fullName ;
408
405
types . name = childKey ;
409
406
types . node = childValue ;
@@ -413,10 +410,7 @@ module.exports = {
413
410
case 'arrayOf' :
414
411
case 'objectOf' :
415
412
const fullName = [ parentName , '*' ] . join ( '.' ) ;
416
- let child = buildReactDeclarationTypes ( argument , fullName ) ;
417
- if ( child === true ) {
418
- child = { } ;
419
- }
413
+ const child = buildReactDeclarationTypes ( argument , fullName ) ;
420
414
child . fullName = fullName ;
421
415
child . name = '__ANY_KEY__' ;
422
416
child . node = argument ;
@@ -430,7 +424,7 @@ module.exports = {
430
424
! argument . elements . length
431
425
) {
432
426
// Invalid proptype or cannot analyse statically
433
- return true ;
427
+ return { } ;
434
428
}
435
429
const unionTypeDefinition = {
436
430
type : 'union' ,
@@ -439,7 +433,7 @@ module.exports = {
439
433
for ( let i = 0 , j = argument . elements . length ; i < j ; i ++ ) {
440
434
const type = buildReactDeclarationTypes ( argument . elements [ i ] , parentName ) ;
441
435
// keep only complex type
442
- if ( type !== true ) {
436
+ if ( Object . keys ( type ) . length > 0 ) {
443
437
if ( type . children === true ) {
444
438
// every child is accepted for one type, abort type analysis
445
439
unionTypeDefinition . children = true ;
@@ -451,7 +445,7 @@ module.exports = {
451
445
}
452
446
if ( unionTypeDefinition . length === 0 ) {
453
447
// no complex type found, simply accept everything
454
- return true ;
448
+ return { } ;
455
449
}
456
450
return unionTypeDefinition ;
457
451
case 'instanceOf' :
@@ -462,19 +456,19 @@ module.exports = {
462
456
} ;
463
457
case 'oneOf' :
464
458
default :
465
- return true ;
459
+ return { } ;
466
460
}
467
461
}
468
462
// Unknown property or accepts everything (any, object, ...)
469
- return true ;
463
+ return { } ;
470
464
}
471
465
472
466
/**
473
467
* Creates the representation of the React props type annotation for the component.
474
468
* The representation is used to verify nested used properties.
475
469
* @param {ASTNode } annotation Type annotation for the props class property.
476
470
* @param {String } parentName Name of the parent prop node.
477
- * @return {Object|Boolean } The representation of the declaration, true means
471
+ * @return {Object } The representation of the declaration, an empty object means
478
472
* the property is declared without the need for further analysis.
479
473
*/
480
474
function buildTypeAnnotationDeclarationTypes ( annotation , parentName ) {
@@ -483,21 +477,18 @@ module.exports = {
483
477
if ( typeScope ( annotation . id . name ) ) {
484
478
return buildTypeAnnotationDeclarationTypes ( typeScope ( annotation . id . name ) , parentName ) ;
485
479
}
486
- return true ;
480
+ return { } ;
487
481
case 'ObjectTypeAnnotation' :
488
482
if ( skipShapeProps ) {
489
- return true ;
483
+ return { } ;
490
484
}
491
485
const shapeTypeDefinition = {
492
486
type : 'shape' ,
493
487
children : [ ]
494
488
} ;
495
489
iterateProperties ( annotation . properties , ( childKey , childValue ) => {
496
490
const fullName = [ parentName , childKey ] . join ( '.' ) ;
497
- let types = buildTypeAnnotationDeclarationTypes ( childValue , fullName ) ;
498
- if ( types === true ) {
499
- types = { } ;
500
- }
491
+ const types = buildTypeAnnotationDeclarationTypes ( childValue , fullName ) ;
501
492
types . fullName = fullName ;
502
493
types . name = childKey ;
503
494
types . node = childValue ;
@@ -512,7 +503,7 @@ module.exports = {
512
503
for ( let i = 0 , j = annotation . types . length ; i < j ; i ++ ) {
513
504
const type = buildTypeAnnotationDeclarationTypes ( annotation . types [ i ] , parentName ) ;
514
505
// keep only complex type
515
- if ( type !== true ) {
506
+ if ( Object . keys ( type ) . length > 0 ) {
516
507
if ( type . children === true ) {
517
508
// every child is accepted for one type, abort type analysis
518
509
unionTypeDefinition . children = true ;
@@ -523,16 +514,13 @@ module.exports = {
523
514
unionTypeDefinition . children . push ( type ) ;
524
515
}
525
516
if ( unionTypeDefinition . children . length === 0 ) {
526
- // no complex type found, simply accept everything
527
- return true ;
517
+ // no complex type found
518
+ return { } ;
528
519
}
529
520
return unionTypeDefinition ;
530
521
case 'ArrayTypeAnnotation' :
531
522
const fullName = [ parentName , '*' ] . join ( '.' ) ;
532
- let child = buildTypeAnnotationDeclarationTypes ( annotation . elementType , fullName ) ;
533
- if ( child === true ) {
534
- child = { } ;
535
- }
523
+ const child = buildTypeAnnotationDeclarationTypes ( annotation . elementType , fullName ) ;
536
524
child . fullName = fullName ;
537
525
child . name = '__ANY_KEY__' ;
538
526
child . node = annotation ;
@@ -542,7 +530,7 @@ module.exports = {
542
530
} ;
543
531
default :
544
532
// Unknown or accepts everything.
545
- return true ;
533
+ return { } ;
546
534
}
547
535
}
548
536
@@ -724,6 +712,60 @@ module.exports = {
724
712
} ) ;
725
713
}
726
714
715
+ /**
716
+ * Marks all props found inside ObjectTypeAnnotaiton as declared.
717
+ *
718
+ * Modifies the declaredProperties object
719
+ * @param {ASTNode } propTypes
720
+ * @param {Object } declaredPropTypes
721
+ * @returns {Boolean } True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
722
+ */
723
+ function declarePropTypesForObjectTypeAnnotation ( propTypes , declaredPropTypes ) {
724
+ let ignorePropsValidation = false ;
725
+
726
+ iterateProperties ( propTypes . properties , ( key , value ) => {
727
+ if ( ! value ) {
728
+ ignorePropsValidation = true ;
729
+ return ;
730
+ }
731
+
732
+ const types = buildTypeAnnotationDeclarationTypes ( value , key ) ;
733
+ types . fullName = key ;
734
+ types . name = key ;
735
+ types . node = value ;
736
+ declaredPropTypes . push ( types ) ;
737
+ } ) ;
738
+
739
+ return ignorePropsValidation ;
740
+ }
741
+
742
+ /**
743
+ * Marks all props found inside IntersectionTypeAnnotation as declared.
744
+ * Since InterSectionTypeAnnotations can be nested, this handles recursively.
745
+ *
746
+ * Modifies the declaredPropTypes object
747
+ * @param {ASTNode } propTypes
748
+ * @param {Object } declaredPropTypes
749
+ * @returns {Boolean } True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
750
+ */
751
+ function declarePropTypesForIntersectionTypeAnnotation ( propTypes , declaredPropTypes ) {
752
+ return propTypes . types . some ( annotation => {
753
+ if ( annotation . type === 'ObjectTypeAnnotation' ) {
754
+ return declarePropTypesForObjectTypeAnnotation ( annotation , declaredPropTypes ) ;
755
+ }
756
+
757
+ const typeNode = typeScope ( annotation . id . name ) ;
758
+
759
+ if ( ! typeNode ) {
760
+ return true ;
761
+ } else if ( typeNode . type === 'IntersectionTypeAnnotation' ) {
762
+ return declarePropTypesForIntersectionTypeAnnotation ( typeNode , declaredPropTypes ) ;
763
+ }
764
+
765
+ return declarePropTypesForObjectTypeAnnotation ( typeNode , declaredPropTypes ) ;
766
+ } ) ;
767
+ }
768
+
727
769
/**
728
770
* Mark a prop type as declared
729
771
* @param {ASTNode } node The AST node being checked.
@@ -736,31 +778,15 @@ module.exports = {
736
778
737
779
switch ( propTypes && propTypes . type ) {
738
780
case 'ObjectTypeAnnotation' :
739
- iterateProperties ( propTypes . properties , ( key , value ) => {
740
- if ( ! value ) {
741
- ignorePropsValidation = true ;
742
- return ;
743
- }
744
- let types = buildTypeAnnotationDeclarationTypes ( value , key ) ;
745
- if ( types === true ) {
746
- types = { } ;
747
- }
748
- types . fullName = key ;
749
- types . name = key ;
750
- types . node = value ;
751
- declaredPropTypes . push ( types ) ;
752
- } ) ;
781
+ ignorePropsValidation = declarePropTypesForObjectTypeAnnotation ( propTypes , declaredPropTypes ) ;
753
782
break ;
754
783
case 'ObjectExpression' :
755
784
iterateProperties ( propTypes . properties , ( key , value ) => {
756
785
if ( ! value ) {
757
786
ignorePropsValidation = true ;
758
787
return ;
759
788
}
760
- let types = buildReactDeclarationTypes ( value , key ) ;
761
- if ( types === true ) {
762
- types = { } ;
763
- }
789
+ const types = buildReactDeclarationTypes ( value , key ) ;
764
790
types . fullName = key ;
765
791
types . name = key ;
766
792
types . node = value ;
@@ -791,24 +817,7 @@ module.exports = {
791
817
}
792
818
break ;
793
819
case 'IntersectionTypeAnnotation' :
794
- propTypes . types . forEach ( annotation => {
795
- const propsType = typeScope ( annotation . id . name ) ;
796
- iterateProperties ( propsType . properties , ( key , value ) => {
797
- if ( ! value ) {
798
- ignorePropsValidation = true ;
799
- return ;
800
- }
801
-
802
- let types = buildTypeAnnotationDeclarationTypes ( value , key ) ;
803
- if ( types === true ) {
804
- types = { } ;
805
- }
806
- types . fullName = key ;
807
- types . name = key ;
808
- types . node = value ;
809
- declaredPropTypes . push ( types ) ;
810
- } ) ;
811
- } ) ;
820
+ ignorePropsValidation = declarePropTypesForIntersectionTypeAnnotation ( propTypes , declaredPropTypes ) ;
812
821
break ;
813
822
case null :
814
823
break ;
0 commit comments