1- /*eslint no-use-before-define: 0*/
21import type { NodePath } from '@babel/traverse' ;
32import { getDocblock } from '../utils/docblock.js' ;
43import getMembers from './getMembers.js' ;
@@ -8,13 +7,8 @@ import printValue from './printValue.js';
87import resolveToValue from './resolveToValue.js' ;
98import resolveObjectKeysToArray from './resolveObjectKeysToArray.js' ;
109import resolveObjectValuesToArray from './resolveObjectValuesToArray.js' ;
11- import type { PropTypeDescriptor , PropDescriptor } from '../Documentation.js' ;
12- import type {
13- ArrayExpression ,
14- Expression ,
15- ObjectProperty ,
16- SpreadElement ,
17- } from '@babel/types' ;
10+ import type { PropTypeDescriptor } from '../Documentation.js' ;
11+ import type { ArrayExpression , Expression , SpreadElement } from '@babel/types' ;
1812
1913function getEnumValuesFromArrayExpression (
2014 path : NodePath < ArrayExpression > ,
@@ -145,6 +139,29 @@ function getPropTypeObjectOf(argumentPath: NodePath) {
145139 return type ;
146140}
147141
142+ function getFirstArgument ( path : NodePath ) : NodePath | undefined {
143+ let argument : NodePath | undefined ;
144+
145+ if ( path . isCallExpression ( ) ) {
146+ argument = path . get ( 'arguments' ) [ 0 ] ;
147+ } else {
148+ const members = getMembers ( path , true ) ;
149+
150+ if ( members [ 0 ] && members [ 0 ] . argumentPaths [ 0 ] ) {
151+ argument = members [ 0 ] . argumentPaths [ 0 ] ;
152+ }
153+ }
154+
155+ return argument ;
156+ }
157+
158+ function isCyclicReference (
159+ argument : NodePath ,
160+ argumentPath : NodePath ,
161+ ) : boolean {
162+ return Boolean ( argument && resolveToValue ( argument ) === argumentPath ) ;
163+ }
164+
148165/**
149166 * Handles shape and exact prop types
150167 */
@@ -156,29 +173,36 @@ function getPropTypeShapish(name: 'exact' | 'shape', argumentPath: NodePath) {
156173 }
157174
158175 if ( argumentPath . isObjectExpression ( ) ) {
159- const value = { } ;
176+ let value : Record < string , PropTypeDescriptor > | string = { } ;
160177
161178 argumentPath . get ( 'properties' ) . forEach ( ( propertyPath ) => {
162- if ( propertyPath . isSpreadElement ( ) || propertyPath . isObjectMethod ( ) ) {
163- // It is impossible to resolve a name for a spread element
164- return ;
165- }
179+ // We only handle ObjectProperty as there is nothing to handle for
180+ // SpreadElements and ObjectMethods
181+ if ( propertyPath . isObjectProperty ( ) ) {
182+ const propertyName = getPropertyName ( propertyPath ) ;
166183
167- const propertyName = getPropertyName ( propertyPath ) ;
184+ if ( ! propertyName ) return ;
168185
169- if ( ! propertyName ) return ;
186+ const valuePath = propertyPath . get ( 'value' ) ;
187+ const argument = getFirstArgument ( valuePath ) ;
170188
171- const valuePath = ( propertyPath as NodePath < ObjectProperty > ) . get ( 'value' ) ;
189+ // This indicates we have a cyclic reference in the shape
190+ // In this case we simply print the argument to shape and bail
191+ if ( argument && isCyclicReference ( argument , argumentPath ) ) {
192+ value = printValue ( argument ) ;
172193
173- const descriptor : PropDescriptor | PropTypeDescriptor =
174- getPropType ( valuePath ) ;
175- const docs = getDocblock ( propertyPath ) ;
194+ return ;
195+ }
176196
177- if ( docs ) {
178- descriptor . description = docs ;
197+ const descriptor = getPropType ( valuePath ) ;
198+ const docs = getDocblock ( propertyPath ) ;
199+
200+ if ( docs ) {
201+ descriptor . description = docs ;
202+ }
203+ descriptor . required = isRequiredPropType ( valuePath ) ;
204+ value [ propertyName ] = descriptor ;
179205 }
180- descriptor . required = isRequiredPropType ( valuePath ) ;
181- value [ propertyName ] = descriptor ;
182206 } ) ;
183207 type . value = value ;
184208 }
@@ -279,9 +303,10 @@ export default function getPropType(path: NodePath): PropTypeDescriptor {
279303
280304 if ( callee . isIdentifier ( ) ) {
281305 const propTypeHandler = propTypes . get ( callee . node . name ) ;
306+ const argument = path . get ( 'arguments' ) [ 0 ] ;
282307
283- if ( propTypeHandler ) {
284- return propTypeHandler ( path . get ( 'arguments' ) [ 0 ] ) ;
308+ if ( propTypeHandler && argument ) {
309+ return propTypeHandler ( argument ) ;
285310 }
286311 }
287312 }
0 commit comments