Add `getProperties` to Parsers and update usages (#37633)

Summary:
[Codegen 138] This PR introduces `getProperties` to Parser base class and implements the function in Typescript and Flow Parsers.
This PR also gets rid of `getProperties` from :
- `packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js`
- `packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js`
and updates the usages with `getProperties` from the respective parser objects as requested on https://github.com/facebook/react-native/issues/34872

## Changelog:

[Internal] [Changed] - Add getProperties  to Parsers base class and update usages.

Pull Request resolved: https://github.com/facebook/react-native/pull/37633

Test Plan:
Run yarn jest react-native-codegen and ensure CI is green

## Screenshot of tests passing locally:

![Screenshot 2023-05-31 at 4 38 41 PM](https://github.com/facebook/react-native/assets/64726664/dd660369-eabd-4c2e-a440-a41ed6f9d47a)

Reviewed By: cipolleschi

Differential Revision: D46322882

Pulled By: rshest

fbshipit-source-id: 5506ce5ff395946ea8c1258b152716fea0142b95
This commit is contained in:
Siddarth Kumar 2023-06-05 11:48:04 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 9c11b81630
Коммит e73c00f576
10 изменённых файлов: 78 добавлений и 63 удалений

Просмотреть файл

@ -10,25 +10,10 @@
'use strict';
import type {NamedShape} from '../../../CodegenSchema.js';
const {getValueFromTypes} = require('../utils.js');
import type {TypeDeclarationMap, PropAST, ASTNode} from '../../utils';
import type {BuildSchemaFN, Parser} from '../../parser';
function getProperties(
typeName: string,
types: TypeDeclarationMap,
): $FlowFixMe {
const typeAlias = types[typeName];
try {
return typeAlias.right.typeParameters.params[0].properties;
} catch (e) {
throw new Error(
`Failed to find type definition for "${typeName}", please check that you have a valid codegen flow file`,
);
}
}
function getTypeAnnotationForArray<+T>(
name: string,
typeAnnotation: $FlowFixMe,
@ -63,6 +48,7 @@ function getTypeAnnotationForArray<+T>(
properties: flattenProperties(
objectType.typeParameters.params[0].properties,
types,
parser,
)
.map(prop => buildSchema(prop, types, parser))
.filter(Boolean),
@ -84,6 +70,7 @@ function getTypeAnnotationForArray<+T>(
properties: flattenProperties(
nestedObjectType.typeParameters.params[0].properties,
types,
parser,
)
.map(prop => buildSchema(prop, types, parser))
.filter(Boolean),
@ -190,6 +177,7 @@ function getTypeAnnotationForArray<+T>(
function flattenProperties(
typeDefinition: $ReadOnlyArray<PropAST>,
types: TypeDeclarationMap,
parser: Parser,
): $ReadOnlyArray<PropAST> {
return typeDefinition
.map(property => {
@ -197,8 +185,9 @@ function flattenProperties(
return property;
} else if (property.type === 'ObjectTypeSpreadProperty') {
return flattenProperties(
getProperties(property.argument.id.name, types),
parser.getProperties(property.argument.id.name, types),
types,
parser,
);
}
})
@ -265,6 +254,7 @@ function getTypeAnnotation<+T>(
properties: flattenProperties(
typeAnnotation.typeParameters.params[0].properties,
types,
parser,
)
.map(prop => buildSchema(prop, types, parser))
.filter(Boolean),
@ -503,7 +493,6 @@ function getSchemaInfo(
}
module.exports = {
getProperties,
getSchemaInfo,
getTypeAnnotation,
flattenProperties,

Просмотреть файл

@ -14,7 +14,6 @@ import type {ComponentSchemaBuilderConfig} from '../../schema.js';
const {getCommands} = require('./commands');
const {getEvents} = require('./events');
const {getProperties} = require('./componentsUtils.js');
const {
getOptions,
findComponentConfig,
@ -33,7 +32,7 @@ function buildComponentSchema(
const types = parser.getTypes(ast);
const propProperties = getProperties(propsTypeName, types);
const propProperties = parser.getProperties(propsTypeName, types);
const commandProperties = getCommandProperties(ast, parser);
const {extendsProps, props} = parser.getProps(propProperties, types);

Просмотреть файл

@ -511,7 +511,7 @@ class FlowParser implements Parser {
extendsProps: $ReadOnlyArray<ExtendsPropsShape>,
} {
const nonExtendsProps = this.removeKnownExtends(typeDefinition, types);
const props = flattenProperties(nonExtendsProps, types)
const props = flattenProperties(nonExtendsProps, types, this)
.map(property => buildPropSchema(property, types, this))
.filter(Boolean);
@ -520,6 +520,17 @@ class FlowParser implements Parser {
extendsProps: this.getExtendsProps(typeDefinition, types),
};
}
getProperties(typeName: string, types: TypeDeclarationMap): $FlowFixMe {
const typeAlias = types[typeName];
try {
return typeAlias.right.typeParameters.params[0].properties;
} catch (e) {
throw new Error(
`Failed to find type definition for "${typeName}", please check that you have a valid codegen flow file`,
);
}
}
}
module.exports = {

Просмотреть файл

@ -376,4 +376,6 @@ export interface Parser {
props: $ReadOnlyArray<NamedShape<PropTypeAnnotation>>,
extendsProps: $ReadOnlyArray<ExtendsPropsShape>,
};
getProperties(typeName: string, types: TypeDeclarationMap): $FlowFixMe;
}

Просмотреть файл

@ -436,7 +436,7 @@ export class MockedParser implements Parser {
extendsProps: $ReadOnlyArray<ExtendsPropsShape>,
} {
const nonExtendsProps = this.removeKnownExtends(typeDefinition, types);
const props = flattenProperties(nonExtendsProps, types)
const props = flattenProperties(nonExtendsProps, types, this)
.map(property => buildPropSchema(property, types, this))
.filter(Boolean);
@ -445,4 +445,15 @@ export class MockedParser implements Parser {
extendsProps: this.getExtendsProps(typeDefinition, types),
};
}
getProperties(typeName: string, types: TypeDeclarationMap): $FlowFixMe {
const typeAlias = types[typeName];
try {
return typeAlias.right.typeParameters.params[0].properties;
} catch (e) {
throw new Error(
`Failed to find type definition for "${typeName}", please check that you have a valid codegen flow file`,
);
}
}
}

Просмотреть файл

@ -16,36 +16,6 @@ const {
import type {TypeDeclarationMap, PropAST, ASTNode} from '../../utils';
import type {BuildSchemaFN, Parser} from '../../parser';
function getProperties(
typeName: string,
types: TypeDeclarationMap,
): $FlowFixMe {
const alias = types[typeName];
if (!alias) {
throw new Error(
`Failed to find definition for "${typeName}", please check that you have a valid codegen typescript file`,
);
}
const aliasKind =
alias.type === 'TSInterfaceDeclaration' ? 'interface' : 'type';
try {
if (aliasKind === 'interface') {
return [...(alias.extends ?? []), ...alias.body.body];
}
return (
alias.typeAnnotation.members ||
alias.typeAnnotation.typeParameters.params[0].members ||
alias.typeAnnotation.typeParameters.params
);
} catch (e) {
throw new Error(
`Failed to find ${aliasKind} definition for "${typeName}", please check that you have a valid codegen typescript file`,
);
}
}
function getUnionOfLiterals(
name: string,
forArray: boolean,
@ -175,7 +145,7 @@ function buildObjectType<T>(
parser: Parser,
buildSchema: BuildSchemaFN<T>,
): $FlowFixMe {
const flattenedProperties = flattenProperties(rawProperties, types);
const flattenedProperties = flattenProperties(rawProperties, types, parser);
const properties = flattenedProperties
.map(prop => buildSchema(prop, types, parser))
.filter(Boolean);
@ -497,6 +467,7 @@ function verifyPropNotAlreadyDefined(
function flattenProperties(
typeDefinition: $ReadOnlyArray<PropAST>,
types: TypeDeclarationMap,
parser: Parser,
): $ReadOnlyArray<PropAST> {
return typeDefinition
.map(property => {
@ -504,23 +475,29 @@ function flattenProperties(
return property;
} else if (property.type === 'TSTypeReference') {
return flattenProperties(
getProperties(property.typeName.name, types),
parser.getProperties(property.typeName.name, types),
types,
parser,
);
} else if (
property.type === 'TSExpressionWithTypeArguments' ||
property.type === 'TSInterfaceHeritage'
) {
return flattenProperties(
getProperties(property.expression.name, types),
parser.getProperties(property.expression.name, types),
types,
parser,
);
} else if (property.type === 'TSTypeLiteral') {
return flattenProperties(property.members, types);
return flattenProperties(property.members, types, parser);
} else if (property.type === 'TSInterfaceDeclaration') {
return flattenProperties(getProperties(property.id.name, types), types);
return flattenProperties(
parser.getProperties(property.id.name, types),
types,
parser,
);
} else if (property.type === 'TSIntersectionType') {
return flattenProperties(property.types, types);
return flattenProperties(property.types, types, parser);
} else {
throw new Error(
`${property.type} is not a supported object literal type.`,
@ -544,7 +521,6 @@ function flattenProperties(
}
module.exports = {
getProperties,
getSchemaInfo,
getTypeAnnotation,
flattenProperties,

Просмотреть файл

@ -183,7 +183,7 @@ function findEventArgumentsAndType(
} {
if (typeAnnotation.type === 'TSInterfaceDeclaration') {
return {
argumentProps: flattenProperties([typeAnnotation], types),
argumentProps: flattenProperties([typeAnnotation], types, parser),
paperTopLevelNameDeprecated: paperName,
bubblingType,
};

Просмотреть файл

@ -15,7 +15,6 @@ import type {ComponentSchemaBuilderConfig} from '../../schema.js';
const {getCommands} = require('./commands');
const {getEvents} = require('./events');
const {categorizeProps} = require('./extends');
const {getProperties} = require('./componentsUtils.js');
const {
getOptions,
findComponentConfig,
@ -37,7 +36,7 @@ function buildComponentSchema(
const types = parser.getTypes(ast);
const propProperties = getProperties(propsTypeName, types);
const propProperties = parser.getProperties(propsTypeName, types);
const commandProperties = getCommandProperties(ast, parser);

Просмотреть файл

@ -270,7 +270,7 @@ function translateTypeAnnotation(
return translateObjectTypeAnnotation(
hasteModuleName,
nullable,
flattenProperties([typeAnnotation], types),
flattenProperties([typeAnnotation], types, parser),
typeResolutionStatus,
baseTypes,
types,
@ -288,6 +288,7 @@ function translateTypeAnnotation(
flattenProperties(
flattenIntersectionType(typeAnnotation, types),
types,
parser,
),
typeResolutionStatus,
[],

Просмотреть файл

@ -510,7 +510,7 @@ class TypeScriptParser implements Parser {
}
// find events and props
for (const prop of flattenProperties(remaining, types)) {
for (const prop of flattenProperties(remaining, types, this)) {
const topLevelType = parseTopLevelType(
prop.typeAnnotation.typeAnnotation,
types,
@ -532,6 +532,33 @@ class TypeScriptParser implements Parser {
extendsProps,
};
}
getProperties(typeName: string, types: TypeDeclarationMap): $FlowFixMe {
const alias = types[typeName];
if (!alias) {
throw new Error(
`Failed to find definition for "${typeName}", please check that you have a valid codegen typescript file`,
);
}
const aliasKind =
alias.type === 'TSInterfaceDeclaration' ? 'interface' : 'type';
try {
if (aliasKind === 'interface') {
return [...(alias.extends ?? []), ...alias.body.body];
}
return (
alias.typeAnnotation.members ||
alias.typeAnnotation.typeParameters.params[0].members ||
alias.typeAnnotation.typeParameters.params
);
} catch (e) {
throw new Error(
`Failed to find ${aliasKind} definition for "${typeName}", please check that you have a valid codegen typescript file`,
);
}
}
}
module.exports = {