Skip to content

Commit c6d6188

Browse files
committed
fix: support Babel 8 traversal and TypeScript AST changes
1 parent acf8dd7 commit c6d6188

16 files changed

Lines changed: 103 additions & 46 deletions

.changeset/tidy-beans-smile.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
'react-docgen': patch
33
---
44

5-
Allow parsing with Babel 8 when it is supplied via an override, while preserving Babel 7's default parser behavior.
5+
Support Babel 8 dependency overrides for parsing and traversal, including TypeScript generic props, inherited interfaces, function types, and mapped types. Preserve Babel 7 compatibility.

packages/react-docgen/src/handlers/codeTypeHandler.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ function setPropDescriptor(
5555
},
5656
typeParams,
5757
);
58-
} else if (!argument.has('typeParameters')) {
58+
} else if (!(
59+
'typeParameters' in argument.node && argument.node.typeParameters
60+
)) {
5961
documentation.addComposes(id.node.name);
6062
}
6163
} else if (path.isObjectTypeProperty()) {

packages/react-docgen/src/handlers/displayNameHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const displayNameHandler: Handler = function (
2424
if (
2525
(componentDefinition.isClassDeclaration() ||
2626
componentDefinition.isFunctionDeclaration()) &&
27-
componentDefinition.has('id')
27+
componentDefinition.node.id
2828
) {
2929
documentation.set(
3030
'displayName',

packages/react-docgen/src/importer/makeFsImporter.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,14 @@ export default function makeFsImporter(
196196
}
197197
} else if (
198198
declaration.hasNode() &&
199-
declaration.has('id') &&
199+
'id' in declaration.node &&
200+
declaration.node.id &&
200201
(declaration.get('id') as NodePath).isIdentifier({ name })
201202
) {
202203
// export function/class/type/interface/enum ...
203204

204205
state.resultPath = declaration;
205-
} else if (path.has('specifiers')) {
206+
} else if (path.node.specifiers.length > 0) {
206207
// export { ... } or export x from ... or export * as x from ...
207208

208209
for (const specifierPath of path.get('specifiers')) {
@@ -213,7 +214,7 @@ export default function makeFsImporter(
213214

214215
if (exported.isIdentifier({ name })) {
215216
// export ... from ''
216-
if (path.has('source')) {
217+
if (path.node.source) {
217218
const local = specifierPath.isExportSpecifier()
218219
? specifierPath.node.local.name
219220
: 'default';

packages/react-docgen/src/utils/__tests__/getTypeParameters-test.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import getTypeArguments from '../getTypeArguments.js';
12
import type {
23
TSTypeAliasDeclaration,
34
TSTypeParameterDeclaration,
@@ -20,9 +21,9 @@ describe('getTypeParameters', () => {
2021
expect(
2122
getTypeParameters(
2223
path.get('typeParameters') as NodePath<TSTypeParameterDeclaration>,
23-
path
24-
.get('typeAnnotation')
25-
.get('typeParameters') as NodePath<TSTypeParameterInstantiation>,
24+
getTypeArguments(
25+
path.get('typeAnnotation'),
26+
) as NodePath<TSTypeParameterInstantiation>,
2627
null,
2728
),
2829
).toMatchSnapshot();
@@ -35,9 +36,9 @@ describe('getTypeParameters', () => {
3536
expect(
3637
getTypeParameters(
3738
path.get('typeParameters') as NodePath<TSTypeParameterDeclaration>,
38-
path
39-
.get('typeAnnotation')
40-
.get('typeParameters') as NodePath<TSTypeParameterInstantiation>,
39+
getTypeArguments(
40+
path.get('typeAnnotation'),
41+
) as NodePath<TSTypeParameterInstantiation>,
4142
null,
4243
),
4344
).toMatchSnapshot();

packages/react-docgen/src/utils/getFlowType.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,11 @@ function handleGenericTypeAnnotation(
174174
const resolvedPath =
175175
(typeParams && typeParams[type.name]) || resolveToValue(path.get('id'));
176176

177-
if (typeParameters.hasNode() && resolvedPath.has('typeParameters')) {
177+
if (
178+
typeParameters.hasNode() &&
179+
'typeParameters' in resolvedPath.node &&
180+
resolvedPath.node.typeParameters
181+
) {
178182
typeParams = getTypeParameters(
179183
resolvedPath.get('typeParameters') as NodePath<TypeParameterDeclaration>,
180184
typeParameters,
@@ -195,7 +199,7 @@ function handleGenericTypeAnnotation(
195199
);
196200
}
197201

198-
if (resolvedPath && resolvedPath.has('right')) {
202+
if (resolvedPath && 'right' in resolvedPath.node && resolvedPath.node.right) {
199203
type = getFlowTypeWithResolvedTypes(
200204
resolvedPath.get('right') as NodePath<FlowType>,
201205
typeParams,

packages/react-docgen/src/utils/getPropertyName.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default function getPropertyName(
4242
}
4343

4444
return null;
45-
} else if (propertyPath.has('computed')) {
45+
} else if ('computed' in propertyPath.node && propertyPath.node.computed) {
4646
const key = propertyPath.get('key') as NodePath<Expression>;
4747

4848
// Try to resolve variables and member expressions

packages/react-docgen/src/utils/getTSType.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import getTypeArguments from './getTypeArguments.js';
12
import getPropertyName from './getPropertyName.js';
23
import printValue from './printValue.js';
34
import getTypeAnnotation from '../utils/getTypeAnnotation.js';
@@ -130,12 +131,15 @@ function handleTSTypeReference(
130131
(typeParams && typeParams[type.name]) ||
131132
resolveToValue(path.get('typeName'));
132133

133-
const typeParameters = path.get('typeParameters');
134+
const typeParameters = getTypeArguments(path);
134135
const resolvedTypeParameters = resolvedPath.get('typeParameters') as NodePath<
135136
TSTypeParameterDeclaration | null | undefined
136137
>;
137138

138-
if (typeParameters.hasNode() && resolvedTypeParameters.hasNode()) {
139+
if (
140+
typeParameters.isTSTypeParameterInstantiation() &&
141+
resolvedTypeParameters.hasNode()
142+
) {
139143
typeParams = getTypeParameters(
140144
resolvedTypeParameters,
141145
typeParameters,
@@ -157,7 +161,7 @@ function handleTSTypeReference(
157161

158162
if (resolvedTypeAnnotation.hasNode()) {
159163
type = getTSTypeWithResolvedTypes(resolvedTypeAnnotation, typeParams);
160-
} else if (typeParameters.hasNode()) {
164+
} else if (typeParameters.isTSTypeParameterInstantiation()) {
161165
const params = typeParameters.get('params');
162166

163167
type = {
@@ -408,7 +412,10 @@ function handleTSTypeQuery(
408412
if (exprName.isIdentifier()) {
409413
const resolvedPath = resolveToValue(path.get('exprName'));
410414

411-
if (resolvedPath.has('typeAnnotation')) {
415+
if (
416+
'typeAnnotation' in resolvedPath.node &&
417+
resolvedPath.node.typeAnnotation
418+
) {
412419
return getTSTypeWithResolvedTypes(
413420
resolvedPath.get('typeAnnotation') as NodePath<TypeScript>,
414421
typeParams,

packages/react-docgen/src/utils/getTypeAnnotation.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,21 @@ import type { FlowType, Node, TSType } from '@babel/types';
88
export default function getTypeAnnotation<T extends Node = FlowType | TSType>(
99
path: NodePath<Node | null | undefined>,
1010
): NodePath<T> | null {
11-
if (!path.has('typeAnnotation')) return null;
11+
if (
12+
!path.node ||
13+
!('typeAnnotation' in path.node) ||
14+
!path.node.typeAnnotation
15+
)
16+
return null;
1217

1318
let resultPath = path;
1419

1520
do {
1621
resultPath = resultPath.get('typeAnnotation') as NodePath;
1722
} while (
18-
resultPath.has('typeAnnotation') &&
23+
resultPath.node &&
24+
'typeAnnotation' in resultPath.node &&
25+
resultPath.node.typeAnnotation &&
1926
!resultPath.isFlowType() &&
2027
!resultPath.isTSType()
2128
);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { NodePath } from '@babel/traverse';
2+
import type {
3+
TSTypeParameterInstantiation,
4+
TypeParameterInstantiation,
5+
} from '@babel/types';
6+
7+
/** Reads type arguments from both Babel 7 and Babel 8 ASTs. */
8+
export default function getTypeArguments(
9+
path: NodePath,
10+
): NodePath<
11+
TSTypeParameterInstantiation | TypeParameterInstantiation | null | undefined
12+
> {
13+
return path.get(
14+
'typeArguments' in path.node ? 'typeArguments' : 'typeParameters',
15+
) as NodePath<
16+
TSTypeParameterInstantiation | TypeParameterInstantiation | null | undefined
17+
>;
18+
}

0 commit comments

Comments
 (0)