Skip to content

Commit

Permalink
Fix codegen to add T of Promise<T> in CodegenSchema.js (#35345)
Browse files Browse the repository at this point in the history
Summary:
`Promise<T>` is used very often in turbo module as function return types. So `T` is a critical thing for type safety. To enable future generator to produce more specific type for `Promise`, `T` is added to the schema.

## Changelog

[General] [Changed] - Fix codegen to add `T` of `Promise<T>` in CodegenSchema.js

Pull Request resolved: #35345

Test Plan: `yarn jest react-native-codegen` passed

Reviewed By: lunaleaps

Differential Revision: D41304647

Pulled By: cipolleschi

fbshipit-source-id: 6cdd2357b83d4d8007c881a7090cbb8969f3ae9d
  • Loading branch information
ZihanChen-MSFT authored and facebook-github-bot committed Nov 29, 2022
1 parent f0972cb commit 8a38e03
Show file tree
Hide file tree
Showing 9 changed files with 351 additions and 29 deletions.
1 change: 1 addition & 0 deletions packages/react-native-codegen/src/CodegenSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ export type NativeModuleTypeAliasTypeAnnotation = $ReadOnly<{

export type NativeModulePromiseTypeAnnotation = $ReadOnly<{
type: 'PromiseTypeAnnotation',
elementType?: Nullable<NativeModuleBaseTypeAnnotation>,
}>;

export type UnionTypeAnnotationMemberType =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,31 @@ describe('typeAliasResolution', () => {
describe('emitPromise', () => {
const moduleName = 'testModuleName';

function emitPromiseForUnitTest(
typeAnnotation: $FlowFixMe,
nullable: boolean,
): $FlowFixMe {
return emitPromise(
moduleName,
typeAnnotation,
parser,
nullable,
// mock translateTypeAnnotation function
/* types: TypeDeclarationMap */
{},
/* aliasMap: {...NativeModuleAliasMap} */
{},
/* tryParse: ParserErrorCapturer */
function <T>(_: () => T) {
return null;
},
/* cxxOnly: boolean */
false,
/* the translateTypeAnnotation function */
(_, elementType) => elementType,
);
}

describe("when typeAnnotation doesn't have exactly one typeParameter", () => {
const typeAnnotation = {
typeParameters: {
Expand All @@ -350,9 +375,7 @@ describe('emitPromise', () => {
};
it('throws an IncorrectlyParameterizedGenericParserError error', () => {
const nullable = false;
expect(() =>
emitPromise(moduleName, typeAnnotation, parser, nullable),
).toThrow();
expect(() => emitPromiseForUnitTest(typeAnnotation, nullable)).toThrow();
});
});

Expand All @@ -370,16 +393,12 @@ describe('emitPromise', () => {
describe('when nullable is true', () => {
const nullable = true;
it('returns nullable type annotation', () => {
const result = emitPromise(
moduleName,
typeAnnotation,
parser,
nullable,
);
const result = emitPromiseForUnitTest(typeAnnotation, nullable);
const expected = {
type: 'NullableTypeAnnotation',
typeAnnotation: {
type: 'PromiseTypeAnnotation',
elementType: 1,
},
};

Expand All @@ -389,14 +408,10 @@ describe('emitPromise', () => {
describe('when nullable is false', () => {
const nullable = false;
it('returns non nullable type annotation', () => {
const result = emitPromise(
moduleName,
typeAnnotation,
parser,
nullable,
);
const result = emitPromiseForUnitTest(typeAnnotation, nullable);
const expected = {
type: 'PromiseTypeAnnotation',
elementType: 1,
};

expect(result).toEqual(expected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const {compareSnaps, compareTsArraySnaps} = require('../compareSnaps.js');

const flowFixtures = require('../../flow/modules/__test_fixtures__/fixtures.js');
const flowSnaps = require('../../../../src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap');
const flowExtraCases = [];
const flowExtraCases = ['PROMISE_WITH_COMMONLY_USED_TYPES'];
const tsFixtures = require('../../typescript/modules/__test_fixtures__/fixtures.js');
const tsSnaps = require('../../../../src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap');
const tsExtraCases = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,44 @@ export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModuleCxx');
`;

const PROMISE_WITH_COMMONLY_USED_TYPES = `
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
'use strict';
import type {TurboModule} from '../RCTExport';
import * as TurboModuleRegistry from '../TurboModuleRegistry';
export type Season = 'Spring' | 'Summer' | 'Autumn' | 'Winter';
export type CustomObject = {|
field1: Array<Object>,
field2: boolean,
field3: string,
type: 'A_String_Literal',
|};
export interface Spec extends TurboModule {
returnStringArray(): Promise<Array<string>>;
returnObjectArray(): Promise<Array<Object>>;
returnNullableNumber(): Promise<number | null>;
returnEmpty(): Promise<empty>;
returnIndex(): Promise<{ [string]: 'authorized' | 'denied' | 'undetermined' | true | false }>;
returnEnum() : Promise<Season>;
returnObject() : Promise<CustomObject>;
}
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
`;

module.exports = {
NATIVE_MODULE_WITH_OBJECT_WITH_OBJECT_DEFINED_IN_FILE_AS_PROPERTY,
NATIVE_MODULE_WITH_ARRAY_WITH_UNION_AND_TOUPLE,
Expand All @@ -705,4 +743,5 @@ module.exports = {
ANDROID_ONLY_NATIVE_MODULE,
IOS_ONLY_NATIVE_MODULE,
CXX_ONLY_NATIVE_MODULE,
PROMISE_WITH_COMMONLY_USED_TYPES,
};
Original file line number Diff line number Diff line change
Expand Up @@ -1506,7 +1506,20 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE
'modules': {
'NativeSampleTurboModule': {
'type': 'NativeModule',
'aliases': {},
'aliases': {
'SomeObj': {
'type': 'ObjectTypeAnnotation',
'properties': [
{
'name': 'a',
'optional': false,
'typeAnnotation': {
'type': 'StringTypeAnnotation'
}
}
]
}
},
'spec': {
'properties': [
{
Expand All @@ -1515,7 +1528,10 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation'
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'StringTypeAnnotation'
}
},
'params': []
}
Expand All @@ -1526,7 +1542,10 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation'
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'StringTypeAnnotation'
}
},
'params': []
}
Expand All @@ -1537,7 +1556,11 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation'
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'TypeAliasTypeAnnotation',
'name': 'SomeObj'
}
},
'params': []
}
Expand Down Expand Up @@ -1727,3 +1750,168 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNSAFE_O
}
}"
`;

exports[`RN Codegen Flow Parser can generate fixture PROMISE_WITH_COMMONLY_USED_TYPES 1`] = `
"{
'modules': {
'NativeSampleTurboModule': {
'type': 'NativeModule',
'aliases': {
'CustomObject': {
'type': 'ObjectTypeAnnotation',
'properties': [
{
'name': 'field1',
'optional': false,
'typeAnnotation': {
'type': 'ArrayTypeAnnotation',
'elementType': {
'type': 'GenericObjectTypeAnnotation'
}
}
},
{
'name': 'field2',
'optional': false,
'typeAnnotation': {
'type': 'BooleanTypeAnnotation'
}
},
{
'name': 'field3',
'optional': false,
'typeAnnotation': {
'type': 'StringTypeAnnotation'
}
},
{
'name': 'type',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
}
}
]
}
},
'spec': {
'properties': [
{
'name': 'returnStringArray',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'ArrayTypeAnnotation',
'elementType': {
'type': 'StringTypeAnnotation'
}
}
},
'params': []
}
},
{
'name': 'returnObjectArray',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'ArrayTypeAnnotation',
'elementType': {
'type': 'GenericObjectTypeAnnotation'
}
}
},
'params': []
}
},
{
'name': 'returnNullableNumber',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation'
},
'params': []
}
},
{
'name': 'returnEmpty',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation'
},
'params': []
}
},
{
'name': 'returnIndex',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'ObjectTypeAnnotation',
'properties': [
{
'name': 'key',
'optional': false,
'typeAnnotation': {
'type': 'GenericObjectTypeAnnotation'
}
}
]
}
},
'params': []
}
},
{
'name': 'returnEnum',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
}
},
'params': []
}
},
{
'name': 'returnObject',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'TypeAliasTypeAnnotation',
'name': 'CustomObject'
}
},
'params': []
}
}
]
},
'moduleNames': [
'SampleTurboModule'
]
}
}
}"
`;
Loading

0 comments on commit 8a38e03

Please sign in to comment.