diff --git a/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js b/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js index b6c411532f812d..32eef3dcf5caae 100644 --- a/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js +++ b/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js @@ -125,6 +125,20 @@ describe('FlowParser', () => { }); }); + describe('getTypeAnnotationName', () => { + it('returns type annotation name', () => { + const typeAnnotation = { + id: { + name: 'StringTypeAnnotation', + }, + }; + + expect(parser.getTypeAnnotationName(typeAnnotation)).toBe( + 'StringTypeAnnotation', + ); + }); + }); + describe('computePartialProperties', () => { it('returns partial properties', () => { const properties = [ @@ -551,6 +565,19 @@ describe('TypeScriptParser', () => { }); }); + describe('getTypeAnnotationName', () => { + it('returns type annotation name', () => { + const typeAnnotation = { + type: 'TSTypeReference', + typeName: { + name: 'Foo', + }, + }; + + expect(parser.getTypeAnnotationName(typeAnnotation)).toEqual('Foo'); + }); + }); + describe('computePartialProperties', () => { it('returns partial properties', () => { const properties = [ diff --git a/packages/react-native-codegen/src/parsers/errors.js b/packages/react-native-codegen/src/parsers/errors.js index 09e49be0fe9ccd..b0e42ecad9555e 100644 --- a/packages/react-native-codegen/src/parsers/errors.js +++ b/packages/react-native-codegen/src/parsers/errors.js @@ -117,9 +117,7 @@ class UnsupportedGenericParserError extends ParserError { genericTypeAnnotation: $FlowFixMe, parser: Parser, ) { - const genericName = parser.nameForGenericTypeAnnotation( - genericTypeAnnotation, - ); + const genericName = parser.getTypeAnnotationName(genericTypeAnnotation); super( nativeModuleName, genericTypeAnnotation, @@ -136,9 +134,7 @@ class MissingTypeParameterGenericParserError extends ParserError { genericTypeAnnotation: $FlowFixMe, parser: Parser, ) { - const genericName = parser.nameForGenericTypeAnnotation( - genericTypeAnnotation, - ); + const genericName = parser.getTypeAnnotationName(genericTypeAnnotation); super( nativeModuleName, @@ -154,9 +150,7 @@ class MoreThanOneTypeParameterGenericParserError extends ParserError { genericTypeAnnotation: $FlowFixMe, parser: Parser, ) { - const genericName = parser.nameForGenericTypeAnnotation( - genericTypeAnnotation, - ); + const genericName = parser.getTypeAnnotationName(genericTypeAnnotation); super( nativeModuleName, diff --git a/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js b/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js index 222175272b7b79..0435bcb886c527 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js +++ b/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js @@ -32,7 +32,7 @@ function getTypeAnnotationForArray<+T>( if ( extractedTypeAnnotation.type === 'GenericTypeAnnotation' && - extractedTypeAnnotation.id.name === 'WithDefault' + parser.getTypeAnnotationName(extractedTypeAnnotation) === 'WithDefault' ) { throw new Error( 'Nested defaults such as "$ReadOnlyArray>" are not supported, please declare defaults at the top level of value definitions as in "WithDefault<$ReadOnlyArray, false>"', @@ -82,7 +82,7 @@ function getTypeAnnotationForArray<+T>( const type = extractedTypeAnnotation.type === 'GenericTypeAnnotation' - ? extractedTypeAnnotation.id.name + ? parser.getTypeAnnotationName(extractedTypeAnnotation) : extractedTypeAnnotation.type; switch (type) { @@ -170,7 +170,6 @@ function getTypeAnnotationForArray<+T>( ); } default: - (type: empty); throw new Error(`Unknown property type for "${name}": ${type}`); } } @@ -220,7 +219,7 @@ function getTypeAnnotation<+T>( if ( typeAnnotation.type === 'GenericTypeAnnotation' && - typeAnnotation.id.name === '$ReadOnlyArray' + parser.getTypeAnnotationName(typeAnnotation) === '$ReadOnlyArray' ) { return { type: 'ArrayTypeAnnotation', @@ -237,7 +236,7 @@ function getTypeAnnotation<+T>( if ( typeAnnotation.type === 'GenericTypeAnnotation' && - typeAnnotation.id.name === '$ReadOnly' + parser.getTypeAnnotationName(typeAnnotation) === '$ReadOnly' ) { return { type: 'ObjectTypeAnnotation', @@ -253,7 +252,7 @@ function getTypeAnnotation<+T>( const type = typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name + ? parser.getTypeAnnotationName(typeAnnotation) : typeAnnotation.type; switch (type) { @@ -379,7 +378,6 @@ function getTypeAnnotation<+T>( type: 'MixedTypeAnnotation', }; default: - (type: empty); throw new Error( `Unknown property type for "${name}": "${type}" in the State`, ); diff --git a/packages/react-native-codegen/src/parsers/flow/components/events.js b/packages/react-native-codegen/src/parsers/flow/components/events.js index 253de3e731d627..fa2b236722f257 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/events.js +++ b/packages/react-native-codegen/src/parsers/flow/components/events.js @@ -45,7 +45,7 @@ function getPropertyType( typeAnnotation: $FlowFixMe, parser: Parser, ): NamedShape { - const type = parser.extractTypeFromTypeAnnotation(typeAnnotation); + const type = extractTypeFromTypeAnnotation(typeAnnotation, parser); switch (type) { case 'BooleanTypeAnnotation': @@ -94,7 +94,7 @@ function extractArrayElementType( name: string, parser: Parser, ): EventTypeAnnotation { - const type = parser.extractTypeFromTypeAnnotation(typeAnnotation); + const type = extractTypeFromTypeAnnotation(typeAnnotation, parser); switch (type) { case 'BooleanTypeAnnotation': @@ -163,6 +163,15 @@ function prettify(jsonObject: $FlowFixMe): string { return JSON.stringify(jsonObject, null, 2); } +function extractTypeFromTypeAnnotation( + typeAnnotation: $FlowFixMe, + parser: Parser, +): string { + return typeAnnotation.type === 'GenericTypeAnnotation' + ? parser.getTypeAnnotationName(typeAnnotation) + : typeAnnotation.type; +} + function findEventArgumentsAndType( parser: Parser, typeAnnotation: $FlowFixMe, @@ -175,7 +184,7 @@ function findEventArgumentsAndType( paperTopLevelNameDeprecated: ?$FlowFixMe, } { throwIfEventHasNoName(typeAnnotation, parser); - const name = typeAnnotation.id.name; + const name = parser.getTypeAnnotationName(typeAnnotation); if (name === '$ReadOnly') { return { argumentProps: typeAnnotation.typeParameters.params[0].properties, @@ -236,8 +245,8 @@ function buildEventSchema( if ( typeAnnotation.type !== 'GenericTypeAnnotation' || - (typeAnnotation.id.name !== 'BubblingEventHandler' && - typeAnnotation.id.name !== 'DirectEventHandler') + (parser.getTypeAnnotationName(typeAnnotation) !== 'BubblingEventHandler' && + parser.getTypeAnnotationName(typeAnnotation) !== 'DirectEventHandler') ) { return null; } diff --git a/packages/react-native-codegen/src/parsers/flow/modules/index.js b/packages/react-native-codegen/src/parsers/flow/modules/index.js index c05e137af993ab..c50c45f2d69900 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/index.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/index.js @@ -64,7 +64,7 @@ function translateTypeAnnotation( switch (typeAnnotation.type) { case 'GenericTypeAnnotation': { - switch (typeAnnotation.id.name) { + switch (parser.getTypeAnnotationName(typeAnnotation)) { case 'RootTag': { return emitRootTag(nullable); } diff --git a/packages/react-native-codegen/src/parsers/flow/parser.js b/packages/react-native-codegen/src/parsers/flow/parser.js index b54cff76f402a6..b0d1f2df2b50d8 100644 --- a/packages/react-native-codegen/src/parsers/flow/parser.js +++ b/packages/react-native-codegen/src/parsers/flow/parser.js @@ -99,7 +99,7 @@ class FlowParser implements Parser { return 'Flow'; } - nameForGenericTypeAnnotation(typeAnnotation: $FlowFixMe): string { + getTypeAnnotationName(typeAnnotation: $FlowFixMe): string { return typeAnnotation?.id?.name; } @@ -421,7 +421,7 @@ class FlowParser implements Parser { break; } - const typeAnnotationName = this.nameForGenericTypeAnnotation(node); + const typeAnnotationName = this.getTypeAnnotationName(node); const resolvedTypeAnnotation = types[typeAnnotationName]; if (resolvedTypeAnnotation == null) { break; diff --git a/packages/react-native-codegen/src/parsers/parser.js b/packages/react-native-codegen/src/parsers/parser.js index 3c0a2b76551e73..7835107642da3e 100644 --- a/packages/react-native-codegen/src/parsers/parser.js +++ b/packages/react-native-codegen/src/parsers/parser.js @@ -127,11 +127,11 @@ export interface Parser { */ language(): ParserType; /** - * Given a type annotation for a generic type, it returns the type name. + * Given a type annotation, it returns the type name. * @parameter typeAnnotation: the annotation for a type in the AST. * @returns: the name of the type. */ - nameForGenericTypeAnnotation(typeAnnotation: $FlowFixMe): string; + getTypeAnnotationName(typeAnnotation: $FlowFixMe): string; /** * Given a type arguments, it returns a boolean specifying if the Module is Invalid. * @parameter typeArguments: the type arguments. diff --git a/packages/react-native-codegen/src/parsers/parserMock.js b/packages/react-native-codegen/src/parsers/parserMock.js index f8e9cc5d81e0d2..1a775b3079cb23 100644 --- a/packages/react-native-codegen/src/parsers/parserMock.js +++ b/packages/react-native-codegen/src/parsers/parserMock.js @@ -96,8 +96,8 @@ export class MockedParser implements Parser { return 'Flow'; } - nameForGenericTypeAnnotation(typeAnnotation: $FlowFixMe): string { - return typeAnnotation.id.name; + getTypeAnnotationName(typeAnnotation: $FlowFixMe): string { + return typeAnnotation?.id?.name; } checkIfInvalidModule(typeArguments: $FlowFixMe): boolean { diff --git a/packages/react-native-codegen/src/parsers/parsers-commons.js b/packages/react-native-codegen/src/parsers/parsers-commons.js index b837ef50ff68f8..fb5e639d6123b1 100644 --- a/packages/react-native-codegen/src/parsers/parsers-commons.js +++ b/packages/react-native-codegen/src/parsers/parsers-commons.js @@ -818,7 +818,7 @@ function getCommandTypeNameAndOptionsExpression( } return { - commandTypeName: parser.nameForGenericTypeAnnotation(typeArgumentParam), + commandTypeName: parser.getTypeAnnotationName(typeArgumentParam), commandOptionsExpression: callExpression.arguments[0], }; } @@ -998,7 +998,7 @@ function getTypeResolutionStatus( return { successful: true, type, - name: parser.nameForGenericTypeAnnotation(typeAnnotation), + name: parser.getTypeAnnotationName(typeAnnotation), }; } diff --git a/packages/react-native-codegen/src/parsers/parsers-primitives.js b/packages/react-native-codegen/src/parsers/parsers-primitives.js index 86fc443675031e..e632570db09cec 100644 --- a/packages/react-native-codegen/src/parsers/parsers-primitives.js +++ b/packages/react-native-codegen/src/parsers/parsers-primitives.js @@ -611,7 +611,7 @@ function emitCommonTypes( } const genericTypeAnnotationName = - parser.nameForGenericTypeAnnotation(typeAnnotation); + parser.getTypeAnnotationName(typeAnnotation); const emitter = typeMap[genericTypeAnnotationName]; if (!emitter) { diff --git a/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js b/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js index ecbc70299dcc39..bbe56a973e5bdb 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js @@ -121,8 +121,8 @@ function detectArrayType( // Covers: Array and ReadonlyArray if ( typeAnnotation.type === 'TSTypeReference' && - (typeAnnotation.typeName.name === 'ReadonlyArray' || - typeAnnotation.typeName.name === 'Array') + (parser.getTypeAnnotationName(typeAnnotation) === 'ReadonlyArray' || + parser.getTypeAnnotationName(typeAnnotation) === 'Array') ) { return { type: 'ArrayTypeAnnotation', @@ -378,7 +378,7 @@ function getTypeAnnotation( const type = typeAnnotation.type === 'TSTypeReference' || typeAnnotation.type === 'TSTypeAliasDeclaration' - ? typeAnnotation.typeName.name + ? parser.getTypeAnnotationName(typeAnnotation) : typeAnnotation.type; const common = getCommonTypeAnnotation( @@ -414,7 +414,6 @@ function getTypeAnnotation( `Cannot use "${type}" type annotation for "${name}": must use a specific function type like BubblingEventHandler, or DirectEventHandler`, ); default: - (type: empty); throw new Error(`Unknown prop type for "${name}": "${type}"`); } } diff --git a/packages/react-native-codegen/src/parsers/typescript/components/events.js b/packages/react-native-codegen/src/parsers/typescript/components/events.js index 3b66748816539c..bcc56ea4f51af8 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/events.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/events.js @@ -51,7 +51,10 @@ function getPropertyType( const topLevelType = parseTopLevelType(annotation); const typeAnnotation = topLevelType.type; const optional = optionalProperty || topLevelType.optional; - const type = parser.extractTypeFromTypeAnnotation(typeAnnotation); + const type = + typeAnnotation.type === 'TSTypeReference' + ? parser.getTypeAnnotationName(typeAnnotation) + : typeAnnotation.type; switch (type) { case 'TSBooleanKeyword': @@ -92,7 +95,7 @@ function extractArrayElementType( name: string, parser: Parser, ): EventTypeAnnotation { - const type = parser.extractTypeFromTypeAnnotation(typeAnnotation); + const type = extractTypeFromTypeAnnotation(typeAnnotation, parser); switch (type) { case 'TSParenthesizedType': @@ -154,6 +157,15 @@ function extractArrayElementType( } } +function extractTypeFromTypeAnnotation( + typeAnnotation: $FlowFixMe, + parser: Parser, +): string { + return typeAnnotation.type === 'TSTypeReference' + ? parser.getTypeAnnotationName(typeAnnotation) + : typeAnnotation.type; +} + function findEventArgumentsAndType( parser: Parser, typeAnnotation: $FlowFixMe, @@ -182,7 +194,7 @@ function findEventArgumentsAndType( } throwIfEventHasNoName(typeAnnotation, parser); - const name = typeAnnotation.typeName.name; + const name = parser.getTypeAnnotationName(typeAnnotation); if (name === 'Readonly') { return findEventArgumentsAndType( parser, diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/index.js b/packages/react-native-codegen/src/parsers/typescript/modules/index.js index 297b51350f11e5..4668924375cce3 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/index.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/index.js @@ -234,7 +234,7 @@ function translateTypeAnnotation( } case 'TSTypeReference': { return translateTypeReferenceAnnotation( - typeAnnotation.typeName.name, + parser.getTypeAnnotationName(typeAnnotation), nullable, typeAnnotation, hasteModuleName, diff --git a/packages/react-native-codegen/src/parsers/typescript/parser.js b/packages/react-native-codegen/src/parsers/typescript/parser.js index 80e08ba1207792..9e8dc836b4ed3a 100644 --- a/packages/react-native-codegen/src/parsers/typescript/parser.js +++ b/packages/react-native-codegen/src/parsers/typescript/parser.js @@ -94,7 +94,7 @@ class TypeScriptParser implements Parser { return 'TypeScript'; } - nameForGenericTypeAnnotation(typeAnnotation: $FlowFixMe): string { + getTypeAnnotationName(typeAnnotation: $FlowFixMe): string { return typeAnnotation?.typeName?.name; } @@ -413,7 +413,7 @@ class TypeScriptParser implements Parser { break; } - const typeAnnotationName = this.nameForGenericTypeAnnotation(node); + const typeAnnotationName = this.getTypeAnnotationName(node); const resolvedTypeAnnotation = types[typeAnnotationName]; if (resolvedTypeAnnotation == null) { break; @@ -447,7 +447,7 @@ class TypeScriptParser implements Parser { return false; } const eventNames = new Set(['BubblingEventHandler', 'DirectEventHandler']); - return eventNames.has(typeAnnotation.typeName.name); + return eventNames.has(this.getTypeAnnotationName(typeAnnotation)); } isProp(name: string, typeAnnotation: $FlowFixMe): boolean { @@ -457,7 +457,7 @@ class TypeScriptParser implements Parser { const isStyle = name === 'style' && typeAnnotation.type === 'GenericTypeAnnotation' && - typeAnnotation.typeName.name === 'ViewStyleProp'; + this.getTypeAnnotationName(typeAnnotation) === 'ViewStyleProp'; return !isStyle; }