@@ -651,24 +651,75 @@ function isMemoCallback(path: NodePath<t.Expression>): boolean {
651
651
) ;
652
652
}
653
653
654
+ function isValidPropsAnnotation (
655
+ annot : t . TypeAnnotation | t . TSTypeAnnotation | t . Noop | null | undefined
656
+ ) : boolean {
657
+ if ( annot == null ) {
658
+ return true ;
659
+ } else if ( annot . type === "TSTypeAnnotation" ) {
660
+ switch ( annot . typeAnnotation . type ) {
661
+ case "TSArrayType" :
662
+ case "TSBigIntKeyword" :
663
+ case "TSBooleanKeyword" :
664
+ case "TSConstructorType" :
665
+ case "TSFunctionType" :
666
+ case "TSLiteralType" :
667
+ case "TSNeverKeyword" :
668
+ case "TSNumberKeyword" :
669
+ case "TSStringKeyword" :
670
+ case "TSSymbolKeyword" :
671
+ case "TSTupleType" :
672
+ return false ;
673
+ }
674
+ return true ;
675
+ } else if ( annot . type === "TypeAnnotation" ) {
676
+ switch ( annot . typeAnnotation . type ) {
677
+ case "ArrayTypeAnnotation" :
678
+ case "BooleanLiteralTypeAnnotation" :
679
+ case "BooleanTypeAnnotation" :
680
+ case "EmptyTypeAnnotation" :
681
+ case "FunctionTypeAnnotation" :
682
+ case "NumberLiteralTypeAnnotation" :
683
+ case "NumberTypeAnnotation" :
684
+ case "StringLiteralTypeAnnotation" :
685
+ case "StringTypeAnnotation" :
686
+ case "SymbolTypeAnnotation" :
687
+ case "ThisTypeAnnotation" :
688
+ case "TupleTypeAnnotation" :
689
+ return false ;
690
+ }
691
+ return true ;
692
+ } else if ( annot . type === "Noop" ) {
693
+ return true ;
694
+ } else {
695
+ assertExhaustive ( annot , `Unexpected annotation node \`${ annot } \`` ) ;
696
+ }
697
+ }
698
+
654
699
function isValidComponentParams (
655
700
params : Array < NodePath < t . Identifier | t . Pattern | t . RestElement > >
656
701
) : boolean {
657
702
if ( params . length === 0 ) {
658
703
return true ;
659
- } else if ( params . length === 1 ) {
660
- return ! params [ 0 ] . isRestElement ( ) ;
661
- } else if ( params . length === 2 ) {
662
- // check if second param might be a ref
663
- if ( params [ 1 ] . isIdentifier ( ) ) {
704
+ } else if ( params . length > 0 && params . length <= 2 ) {
705
+ if ( ! isValidPropsAnnotation ( params [ 0 ] . node . typeAnnotation ) ) {
706
+ return false ;
707
+ }
708
+
709
+ if ( params . length === 1 ) {
710
+ return ! params [ 0 ] . isRestElement ( ) ;
711
+ } else if ( params [ 1 ] . isIdentifier ( ) ) {
712
+ // check if second param might be a ref
664
713
const { name } = params [ 1 ] . node ;
665
714
return name . includes ( "ref" ) || name . includes ( "Ref" ) ;
715
+ } else {
716
+ /**
717
+ * Otherwise, avoid helper functions that take more than one argument.
718
+ * Helpers are _usually_ named with lowercase, but some code may
719
+ * violate this rule
720
+ */
721
+ return false ;
666
722
}
667
- /**
668
- * Otherwise, avoid helper functions that take more than one argument.
669
- * Helpers are _usually_ named with lowercase, but some code may
670
- * violate this rule
671
- */
672
723
}
673
724
return false ;
674
725
}
0 commit comments