Skip to content

Commit

Permalink
move extendsForProp into parsers-commons (#37052)
Browse files Browse the repository at this point in the history
Summary:
[Codegen 94] This PR attempts to extracts the logic of `extendsForProp` function from the following locations :
- `parsers/flow/components/extends.js`
- `parsers/typescript/components/props.js`
since they are the same and move the function to `parsers/parsers-commons.js` as requested on #34872

## Changelog:

[Internal] [Changed] - Move `extendsForProp` to parser-commons and update usages.

Pull Request resolved: #37052

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

Reviewed By: cipolleschi

Differential Revision: D45225880

Pulled By: rshest

fbshipit-source-id: 45199089746d58d9e9494b28040b34c2a0eb31fe
  • Loading branch information
siddarthkay authored and facebook-github-bot committed Apr 26, 2023
1 parent 5ff19f0 commit c937162
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import type {ASTNode} from '../utils';
import type {NamedShape} from '../../../CodegenSchema.js';
const {getValueFromTypes} = require('../utils.js');
import type {TypeDeclarationMap} from '../../utils';
import type {TypeDeclarationMap, PropAST} from '../../utils';

function getProperties(
typeName: string,
Expand Down Expand Up @@ -499,9 +499,6 @@ function getSchemaInfo(
};
}

// $FlowFixMe[unclear-type] there's no flowtype for ASTs
type PropAST = Object;

module.exports = {
getProperties,
getSchemaInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function buildComponentSchema(

const propProperties = getProperties(propsTypeName, types);
const commandProperties = getCommandProperties(ast, parser);
const {extendsProps, props} = getProps(propProperties, types);
const {extendsProps, props} = getProps(propProperties, types, parser);

const options = getOptions(optionsExpression);
const events = getEvents(propProperties, types, parser);
Expand Down
23 changes: 13 additions & 10 deletions packages/react-native-codegen/src/parsers/flow/components/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,15 @@ import type {
NamedShape,
PropTypeAnnotation,
} from '../../../CodegenSchema.js';
import type {TypeDeclarationMap} from '../../utils';
import type {TypeDeclarationMap, PropAST} from '../../utils';
import type {Parser} from '../../parser';

const {
flattenProperties,
getSchemaInfo,
getTypeAnnotation,
} = require('./componentsUtils.js');

// $FlowFixMe[unclear-type] there's no flowtype for ASTs
type PropAST = Object;

type ExtendsForProp = null | {
type: 'ReactNativeBuiltInType',
knownTypeName: 'ReactNativeCoreViewProps',
Expand Down Expand Up @@ -58,11 +56,13 @@ function buildPropSchema(
function extendsForProp(
prop: PropAST,
types: TypeDeclarationMap,
parser: Parser,
): ExtendsForProp {
if (!prop.argument) {
const argument = parser.argumentForProp(prop);
if (!argument) {
console.log('null', prop);
}
const name = prop.argument.id.name;
const name = parser.nameForArgument(prop);

if (types[name] != null) {
// This type is locally defined in the file
Expand All @@ -84,21 +84,23 @@ function extendsForProp(
function removeKnownExtends(
typeDefinition: $ReadOnlyArray<PropAST>,
types: TypeDeclarationMap,
parser: Parser,
): $ReadOnlyArray<PropAST> {
return typeDefinition.filter(
prop =>
prop.type !== 'ObjectTypeSpreadProperty' ||
extendsForProp(prop, types) === null,
extendsForProp(prop, types, parser) === null,
);
}

function getExtendsProps(
typeDefinition: $ReadOnlyArray<PropAST>,
types: TypeDeclarationMap,
parser: Parser,
): $ReadOnlyArray<ExtendsPropsShape> {
return typeDefinition
.filter(prop => prop.type === 'ObjectTypeSpreadProperty')
.map(prop => extendsForProp(prop, types))
.map(prop => extendsForProp(prop, types, parser))
.filter(Boolean);
}
/**
Expand All @@ -108,18 +110,19 @@ function getExtendsProps(
function getProps(
typeDefinition: $ReadOnlyArray<PropAST>,
types: TypeDeclarationMap,
parser: Parser,
): {
props: $ReadOnlyArray<NamedShape<PropTypeAnnotation>>,
extendsProps: $ReadOnlyArray<ExtendsPropsShape>,
} {
const nonExtendsProps = removeKnownExtends(typeDefinition, types);
const nonExtendsProps = removeKnownExtends(typeDefinition, types, parser);
const props = flattenProperties(nonExtendsProps, types)
.map(property => buildPropSchema(property, types))
.filter(Boolean);

return {
props,
extendsProps: getExtendsProps(typeDefinition, types),
extendsProps: getExtendsProps(typeDefinition, types, parser),
};
}

Expand Down
10 changes: 9 additions & 1 deletion packages/react-native-codegen/src/parsers/flow/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type {
} from '../../CodegenSchema';
import type {ParserType} from '../errors';
import type {Parser} from '../parser';
import type {ParserErrorCapturer, TypeDeclarationMap} from '../utils';
import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from '../utils';

const {flowTranslateTypeAnnotation} = require('./modules');

Expand Down Expand Up @@ -329,6 +329,14 @@ class FlowParser implements Parser {
convertKeywordToTypeAnnotation(keyword: string): string {
return keyword;
}

argumentForProp(prop: PropAST): $FlowFixMe {
return prop.argument;
}

nameForArgument(prop: PropAST): $FlowFixMe {
return prop.argument.id.name;
}
}

module.exports = {
Expand Down
16 changes: 15 additions & 1 deletion packages/react-native-codegen/src/parsers/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type {
NativeModuleEnumMap,
} from '../CodegenSchema';
import type {ParserType} from './errors';
import type {ParserErrorCapturer, TypeDeclarationMap} from './utils';
import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from './utils';

/**
* This is the main interface for Parsers of various languages.
Expand Down Expand Up @@ -255,4 +255,18 @@ export interface Parser {
* @returns: converted TypeAnnotation to Keywords
*/
convertKeywordToTypeAnnotation(keyword: string): string;

/**
* Given a prop return its arguments.
* @parameter prop
* @returns: Arguments of the prop
*/
argumentForProp(prop: PropAST): $FlowFixMe;

/**
* Given a prop return its name.
* @parameter prop
* @returns: name property
*/
nameForArgument(prop: PropAST): $FlowFixMe;
}
10 changes: 9 additions & 1 deletion packages/react-native-codegen/src/parsers/parserMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type {
NativeModuleAliasMap,
NativeModuleEnumMap,
} from '../CodegenSchema';
import type {ParserErrorCapturer, TypeDeclarationMap} from './utils';
import type {ParserErrorCapturer, PropAST, TypeDeclarationMap} from './utils';

// $FlowFixMe[untyped-import] there's no flowtype flow-parser
const flowParser = require('flow-parser');
Expand Down Expand Up @@ -243,4 +243,12 @@ export class MockedParser implements Parser {
convertKeywordToTypeAnnotation(keyword: string): string {
return keyword;
}

argumentForProp(prop: PropAST): $FlowFixMe {
return prop.expression;
}

nameForArgument(prop: PropAST): $FlowFixMe {
return prop.expression.name;
}
}
38 changes: 37 additions & 1 deletion packages/react-native-codegen/src/parsers/parsers-commons.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type {

import type {Parser} from './parser';
import type {ParserType} from './errors';
import type {ParserErrorCapturer, TypeDeclarationMap} from './utils';
import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from './utils';
import type {ComponentSchemaBuilderConfig} from './schema.js';

const {
Expand Down Expand Up @@ -69,6 +69,11 @@ export type CommandOptions = $ReadOnly<{
// $FlowFixMe[unclear-type] TODO(T108222691): Use flow-types for @babel/parser
type OptionsAST = Object;

type ExtendedPropResult = {
type: 'ReactNativeBuiltInType',
knownTypeName: 'ReactNativeCoreViewProps',
} | null;

function wrapModuleSchema(
nativeModuleSchema: NativeModuleSchema,
hasteModuleName: string,
Expand Down Expand Up @@ -817,6 +822,36 @@ function propertyNames(
.filter(Boolean);
}

function extendsForProp(
prop: PropAST,
types: TypeDeclarationMap,
parser: Parser,
): ExtendedPropResult {
const argument = parser.argumentForProp(prop);

if (!argument) {
console.log('null', prop);
}

const name = parser.nameForArgument(prop);

if (types[name] != null) {
// This type is locally defined in the file
return null;
}

switch (name) {
case 'ViewProps':
return {
type: 'ReactNativeBuiltInType',
knownTypeName: 'ReactNativeCoreViewProps',
};
default: {
throw new Error(`Unable to handle prop spread: ${name}`);
}
}
}

module.exports = {
wrapModuleSchema,
unwrapNullable,
Expand All @@ -836,4 +871,5 @@ module.exports = {
getCommandOptions,
getOptions,
getCommandTypeNameAndOptionsExpression,
extendsForProp,
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const {
parseTopLevelType,
flattenIntersectionType,
} = require('../parseTopLevelType');
import type {TypeDeclarationMap} from '../../utils';
import type {TypeDeclarationMap, PropAST} from '../../utils';

function getProperties(
typeName: string,
Expand Down Expand Up @@ -463,9 +463,6 @@ function getSchemaInfo(
};
}
// $FlowFixMe[unclear-type] TODO(T108222691): Use flow-types for @babel/parser
type PropAST = Object;
function verifyPropNotAlreadyDefined(
props: $ReadOnlyArray<PropAST>,
needleProp: PropAST,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function buildComponentSchema(

const componentEventAsts: Array<PropsAST> = [];
categorizeProps(propProperties, types, componentEventAsts);
const {props, extendsProps} = getProps(propProperties, types);
const {props, extendsProps} = getProps(propProperties, types, parser);
const events = getEvents(componentEventAsts, types, parser);
const commands = getCommands(commandProperties, types);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
*/

'use strict';

const {getSchemaInfo, getTypeAnnotation} = require('./componentsUtils.js');

import type {NamedShape, PropTypeAnnotation} from '../../../CodegenSchema.js';
import type {TypeDeclarationMap} from '../../utils';
import type {TypeDeclarationMap, PropAST} from '../../utils';
import type {ExtendsPropsShape} from '../../../CodegenSchema.js';
import type {Parser} from '../../parser';

const {flattenProperties} = require('./componentsUtils.js');
const {parseTopLevelType} = require('../parseTopLevelType');

// $FlowFixMe[unclear-type] there's no flowtype for ASTs
type PropAST = Object;
const {extendsForProp} = require('../../parsers-commons');

function buildPropSchema(
property: PropAST,
Expand Down Expand Up @@ -59,32 +59,10 @@ function isProp(name: string, typeAnnotation: $FlowFixMe): boolean {
return !isStyle;
}

function extendsForProp(prop: PropAST, types: TypeDeclarationMap) {
if (!prop.expression) {
console.log('null', prop);
}
const name = prop.expression.name;

if (types[name] != null) {
// This type is locally defined in the file
return null;
}

switch (name) {
case 'ViewProps':
return {
type: 'ReactNativeBuiltInType',
knownTypeName: 'ReactNativeCoreViewProps',
};
default: {
throw new Error(`Unable to handle prop spread: ${name}`);
}
}
}

function getProps(
typeDefinition: $ReadOnlyArray<PropAST>,
types: TypeDeclarationMap,
parser: Parser,
): {
props: $ReadOnlyArray<NamedShape<PropTypeAnnotation>>,
extendsProps: $ReadOnlyArray<ExtendsPropsShape>,
Expand All @@ -96,7 +74,7 @@ function getProps(
for (const prop of typeDefinition) {
// find extends
if (prop.type === 'TSExpressionWithTypeArguments') {
const extend = extendsForProp(prop, types);
const extend = extendsForProp(prop, types, parser);
if (extend) {
extendsProps.push(extend);
continue;
Expand Down
10 changes: 9 additions & 1 deletion packages/react-native-codegen/src/parsers/typescript/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type {
} from '../../CodegenSchema';
import type {ParserType} from '../errors';
import type {Parser} from '../parser';
import type {ParserErrorCapturer, TypeDeclarationMap} from '../utils';
import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from '../utils';

const {typeScriptTranslateTypeAnnotation} = require('./modules');

Expand Down Expand Up @@ -328,6 +328,14 @@ class TypeScriptParser implements Parser {

return keyword;
}

argumentForProp(prop: PropAST): $FlowFixMe {
return prop.expression;
}

nameForArgument(prop: PropAST): $FlowFixMe {
return prop.expression.name;
}
}

module.exports = {
Expand Down
3 changes: 3 additions & 0 deletions packages/react-native-codegen/src/parsers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ function extractNativeModuleName(filename: string): string {

export type ParserErrorCapturer = <T>(fn: () => T) => ?T;

// $FlowFixMe[unclear-type] there's no flowtype for ASTs
export type PropAST = Object;

function createParserErrorCapturer(): [
Array<ParserError>,
ParserErrorCapturer,
Expand Down

0 comments on commit c937162

Please sign in to comment.