Skip to content

Commit

Permalink
extract throwIfEventHasNoName into error-utils (facebook#37071)
Browse files Browse the repository at this point in the history
Summary:
Part of Codegen ☂️ Issue: facebook#34872

> Extract the typeAnnotation doesn't have a name error ([Flow](https://github.com/facebook/react-native/blob/e133100721939108b0f28dfa9f60ac627c804018/packages/react-native-codegen/src/parsers/flow/components/events.js#L120-L122); [TypeScript](https://github.com/facebook/react-native/blob/e133100721939108b0f28dfa9f60ac627c804018/packages/react-native-codegen/src/parsers/typescript/components/events.js#L138-L140)) in throwIfEventHasNoName function which takes a typeAnnotation and a parser as parameters. Use it in place of the if in the above call sites.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[Internal] [Changed] - Extract throwIfEventHasNoName error from parsers components events in error-utils

Pull Request resolved: facebook#37071

Test Plan:
`yarn jest react-native-codegen`
<img width="810" alt="image" src="https://user-images.githubusercontent.com/34857453/234091461-67ec4187-1f38-43e0-a4ae-eb3716377665.png">

Reviewed By: cipolleschi

Differential Revision: D45247751

Pulled By: rshest

fbshipit-source-id: ad286bfbb5c9471477981ec26da77a2b0f827732
  • Loading branch information
tarunrajput authored and jeongshin committed May 7, 2023
1 parent 8147e7b commit 8f226b6
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const {
throwIfPartialNotAnnotatingTypeParameter,
throwIfPartialWithMoreParameter,
throwIfMoreThanOneCodegenNativecommands,
throwIfEventHasNoName,
} = require('../error-utils');
const {
UnsupportedModulePropertyParserError,
Expand Down Expand Up @@ -905,3 +906,47 @@ describe('throwIfMoreThanOneConfig', () => {
}).not.toThrow();
});
});

describe('throwIfEventHasNoName', () => {
const flowParser = new FlowParser();
const typescriptParser = new TypeScriptParser();

it('throws an error if typeAnnotation of event have no name in Flow', () => {
const typeAnnotation = {};
expect(() => {
throwIfEventHasNoName(typeAnnotation, flowParser);
}).toThrowError(`typeAnnotation of event doesn't have a name`);
});

it('does not throw an error if typeAnnotation of event have a name in Flow', () => {
const typeAnnotation = {
id: {
name: 'BubblingEventHandler',
},
};

expect(() => {
throwIfEventHasNoName(typeAnnotation, flowParser);
}).not.toThrow();
});

it('throws an error if typeAnnotation of event have no name in TypeScript', () => {
const typeAnnotation = {};

expect(() => {
throwIfEventHasNoName(typeAnnotation, typescriptParser);
}).toThrowError(`typeAnnotation of event doesn't have a name`);
});

it('does not throw an error if typeAnnotation of event have a name in TypeScript', () => {
const typeAnnotation = {
typeName: {
name: 'BubblingEventHandler',
},
};

expect(() => {
throwIfEventHasNoName(typeAnnotation, typescriptParser);
}).not.toThrow();
});
});
10 changes: 10 additions & 0 deletions packages/react-native-codegen/src/parsers/error-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,15 @@ function throwIfMoreThanOneConfig(foundConfigs: Array<{[string]: string}>) {
}
}

function throwIfEventHasNoName(typeAnnotation: $FlowFixMe, parser: Parser) {
const name =
parser.language() === 'Flow' ? typeAnnotation.id : typeAnnotation.typeName;

if (!name) {
throw new Error("typeAnnotation of event doesn't have a name");
}
}

module.exports = {
throwIfModuleInterfaceIsMisnamed,
throwIfUnsupportedFunctionReturnTypeAnnotationParserError,
Expand All @@ -330,4 +339,5 @@ module.exports = {
throwIfMoreThanOneCodegenNativecommands,
throwIfConfigNotfound,
throwIfMoreThanOneConfig,
throwIfEventHasNoName,
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import type {
NamedShape,
EventTypeAnnotation,
} from '../../../CodegenSchema.js';
import type {Parser} from '../../parser';
const {throwIfEventHasNoName} = require('../../error-utils');

function getPropertyType(
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
Expand Down Expand Up @@ -108,6 +110,7 @@ function getPropertyType(
}

function findEventArgumentsAndType(
parser: Parser,
typeAnnotation: $FlowFixMe,
types: TypeMap,
bubblingType: void | 'direct' | 'bubble',
Expand All @@ -117,9 +120,7 @@ function findEventArgumentsAndType(
bubblingType: ?('direct' | 'bubble'),
paperTopLevelNameDeprecated: ?$FlowFixMe,
} {
if (!typeAnnotation.id) {
throw new Error("typeAnnotation of event doesn't have a name");
}
throwIfEventHasNoName(typeAnnotation, parser);
const name = typeAnnotation.id.name;
if (name === '$ReadOnly') {
return {
Expand All @@ -144,13 +145,15 @@ function findEventArgumentsAndType(
};
}
return findEventArgumentsAndType(
parser,
typeAnnotation.typeParameters.params[0],
types,
eventType,
paperTopLevelNameDeprecated,
);
} else if (types[name]) {
return findEventArgumentsAndType(
parser,
types[name].right,
types,
bubblingType,
Expand Down Expand Up @@ -191,6 +194,7 @@ function getEventArgument(argumentProps, name: $FlowFixMe) {
function buildEventSchema(
types: TypeMap,
property: EventTypeAST,
parser: Parser,
): ?EventTypeShape {
const name = property.key.name;
const optional =
Expand All @@ -210,7 +214,7 @@ function buildEventSchema(
}

const {argumentProps, bubblingType, paperTopLevelNameDeprecated} =
findEventArgumentsAndType(typeAnnotation, types);
findEventArgumentsAndType(parser, typeAnnotation, types);

if (bubblingType && argumentProps) {
if (paperTopLevelNameDeprecated != null) {
Expand Down Expand Up @@ -258,10 +262,11 @@ type TypeMap = {
function getEvents(
eventTypeAST: $ReadOnlyArray<EventTypeAST>,
types: TypeMap,
parser: Parser,
): $ReadOnlyArray<EventTypeShape> {
return eventTypeAST
.filter(property => property.type === 'ObjectTypeProperty')
.map(property => buildEventSchema(types, property))
.map(property => buildEventSchema(types, property, parser))
.filter(Boolean);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function buildComponentSchema(
const {extendsProps, props} = getProps(propProperties, types);

const options = getOptions(optionsExpression);
const events = getEvents(propProperties, types);
const events = getEvents(propProperties, types, parser);
const commands = getCommands(commandProperties, types);

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import type {
EventTypeAnnotation,
} from '../../../CodegenSchema.js';
import type {TypeDeclarationMap} from '../../utils';
import type {Parser} from '../../parser';
const {flattenProperties} = require('./componentsUtils');
const {parseTopLevelType} = require('../parseTopLevelType');
const {throwIfEventHasNoName} = require('../../error-utils');

function getPropertyType(
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
Expand Down Expand Up @@ -110,6 +112,7 @@ function getPropertyType(
}

function findEventArgumentsAndType(
parser: Parser,
typeAnnotation: $FlowFixMe,
types: TypeDeclarationMap,
bubblingType: void | 'direct' | 'bubble',
Expand All @@ -135,12 +138,11 @@ function findEventArgumentsAndType(
};
}
if (!typeAnnotation.typeName) {
throw new Error("typeAnnotation of event doesn't have a name");
}
throwIfEventHasNoName(typeAnnotation, parser);
const name = typeAnnotation.typeName.name;
if (name === 'Readonly') {
return findEventArgumentsAndType(
parser,
typeAnnotation.typeParameters.params[0],
types,
bubblingType,
Expand All @@ -163,6 +165,7 @@ function findEventArgumentsAndType(
};
default:
return findEventArgumentsAndType(
parser,
typeAnnotation.typeParameters.params[0],
types,
eventType,
Expand All @@ -175,6 +178,7 @@ function findEventArgumentsAndType(
elementType = elementType.typeAnnotation;
}
return findEventArgumentsAndType(
parser,
elementType,
types,
bubblingType,
Expand Down Expand Up @@ -214,6 +218,7 @@ type EventTypeAST = Object;
function buildEventSchema(
types: TypeDeclarationMap,
property: EventTypeAST,
parser: Parser,
): EventTypeShape {
// unpack WithDefault, (T) or T|U
const topLevelType = parseTopLevelType(
Expand All @@ -225,7 +230,7 @@ function buildEventSchema(
const typeAnnotation = topLevelType.type;
const optional = property.optional || topLevelType.optional;
const {argumentProps, bubblingType, paperTopLevelNameDeprecated} =
findEventArgumentsAndType(typeAnnotation, types);
findEventArgumentsAndType(parser, typeAnnotation, types);

if (!argumentProps) {
throw new Error(`Unable to determine event arguments for "${name}"`);
Expand Down Expand Up @@ -260,8 +265,11 @@ function buildEventSchema(
function getEvents(
eventTypeAST: $ReadOnlyArray<EventTypeAST>,
types: TypeDeclarationMap,
parser: Parser,
): $ReadOnlyArray<EventTypeShape> {
return eventTypeAST.map(property => buildEventSchema(types, property));
return eventTypeAST.map(property =>
buildEventSchema(types, property, parser),
);
}

module.exports = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function buildComponentSchema(
const componentEventAsts: Array<PropsAST> = [];
categorizeProps(propProperties, types, componentEventAsts);
const {props, extendsProps} = getProps(propProperties, types);
const events = getEvents(componentEventAsts, types);
const events = getEvents(componentEventAsts, types, parser);
const commands = getCommands(commandProperties, types);

return {
Expand Down

0 comments on commit 8f226b6

Please sign in to comment.