Skip to content

Commit ca640fe

Browse files
Adding support for unions in Codegen Schema
Summary: Previously, the parser was mapping to Array<any> when the element types of union were different. This caused compat checker to not recognize changes in unions of different types. `StringLiteralUnionTypeAnnotation` already had support for `types`, that can be expanded to all Union types so as to incorporate the Unions of different types. ``` { type: 'StringLiteralUnionTypeAnnotation', types: [ { type: 'StringLiteralTypeAnnotation' value: 'light' }, { type: 'StringLiteralTypeAnnotation' value: 'dark' }, ], } ``` NOTE: Generators behavior still remain unchanged hence don't allow unions of different types. Only RN Compat Checker consumes this. The value of this is that the compat checker can now error when the union of different types changes. Changelog: [Internal] Differential Revision: D86501597
1 parent ef3a858 commit ca640fe

File tree

30 files changed

+1881
-1015
lines changed

30 files changed

+1881
-1015
lines changed

packages/react-native-codegen/src/CodegenSchema.d.ts

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,52 @@ export interface Int32TypeAnnotation {
3434
readonly type: 'Int32TypeAnnotation';
3535
}
3636

37+
export interface NumberLiteralTypeAnnotation {
38+
readonly type: 'NumberLiteralTypeAnnotation';
39+
readonly value: number;
40+
}
41+
3742
export interface StringTypeAnnotation {
3843
readonly type: 'StringTypeAnnotation';
3944
}
4045

46+
export interface NumberTypeAnnotation {
47+
readonly type: 'NumberTypeAnnotation';
48+
}
49+
50+
export interface StringLiteralTypeAnnotation {
51+
readonly type: 'StringLiteralTypeAnnotation';
52+
readonly value: string;
53+
}
54+
55+
export interface BooleanLiteralTypeAnnotation {
56+
readonly type: 'BooleanLiteralTypeAnnotation';
57+
readonly value: boolean;
58+
}
59+
60+
export interface UnionTypeAnnotation<T> {
61+
readonly type: 'UnionTypeAnnotation';
62+
readonly types: readonly T[];
63+
}
64+
65+
export type StringLiteralUnionTypeAnnotation =
66+
UnionTypeAnnotation<StringLiteralTypeAnnotation>;
67+
68+
export type NumberLiteralUnionTypeAnnotation =
69+
UnionTypeAnnotation<NumberLiteralTypeAnnotation>;
70+
71+
export type BooleanLiteralUnionTypeAnnotation =
72+
UnionTypeAnnotation<BooleanLiteralTypeAnnotation>;
73+
4174
export interface VoidTypeAnnotation {
4275
readonly type: 'VoidTypeAnnotation';
4376
}
4477

78+
export interface TupleTypeAnnotation {
79+
readonly type: 'TupleTypeAnnotation';
80+
readonly types: StringLiteralTypeAnnotation | NumberLiteralTypeAnnotation;
81+
}
82+
4583
export interface ObjectTypeAnnotation<T> {
4684
readonly type: 'ObjectTypeAnnotation';
4785
readonly properties: readonly NamedShape<T>[];
@@ -304,10 +342,6 @@ export interface NativeModuleStringLiteralTypeAnnotation {
304342
readonly value: string;
305343
}
306344

307-
export interface StringLiteralUnionTypeAnnotation {
308-
readonly type: 'StringLiteralUnionTypeAnnotation';
309-
readonly types: NativeModuleStringLiteralTypeAnnotation[];
310-
}
311345

312346
export interface NativeModuleNumberTypeAnnotation {
313347
readonly type: 'NumberTypeAnnotation';
@@ -369,14 +403,18 @@ export interface NativeModulePromiseTypeAnnotation {
369403
readonly elementType: Nullable<NativeModuleBaseTypeAnnotation> | VoidTypeAnnotation;
370404
}
371405

372-
export type UnionTypeAnnotationMemberType =
373-
| 'NumberTypeAnnotation'
374-
| 'ObjectTypeAnnotation'
375-
| 'StringTypeAnnotation';
406+
export type NativeModuleUnionTypeAnnotationMemberType =
407+
| NativeModuleObjectTypeAnnotation
408+
| StringLiteralTypeAnnotation
409+
| NumberLiteralTypeAnnotation
410+
| BooleanLiteralTypeAnnotation
411+
| BooleanTypeAnnotation
412+
| StringTypeAnnotation
413+
| NumberTypeAnnotation;
376414

377415
export interface NativeModuleUnionTypeAnnotation {
378416
readonly type: 'UnionTypeAnnotation';
379-
readonly memberType: UnionTypeAnnotationMemberType;
417+
readonly memberType: NativeModuleUnionTypeAnnotationMemberType;
380418
}
381419

382420
export interface NativeModuleMixedTypeAnnotation {

packages/react-native-codegen/src/CodegenSchema.js

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,29 @@ export type StringTypeAnnotation = $ReadOnly<{
4747
type: 'StringTypeAnnotation',
4848
}>;
4949

50+
export type NumberTypeAnnotation = $ReadOnly<{
51+
type: 'NumberTypeAnnotation',
52+
}>;
53+
5054
export type StringLiteralTypeAnnotation = $ReadOnly<{
5155
type: 'StringLiteralTypeAnnotation',
5256
value: string,
5357
}>;
5458

55-
export type StringLiteralUnionTypeAnnotation = $ReadOnly<{
56-
type: 'StringLiteralUnionTypeAnnotation',
57-
types: $ReadOnlyArray<StringLiteralTypeAnnotation>,
59+
export type BooleanLiteralTypeAnnotation = $ReadOnly<{
60+
type: 'BooleanLiteralTypeAnnotation',
61+
value: boolean,
5862
}>;
5963

64+
export type StringLiteralUnionTypeAnnotation =
65+
UnionTypeAnnotation<StringLiteralTypeAnnotation>;
66+
67+
export type NumberLiteralUnionTypeAnnotation =
68+
UnionTypeAnnotation<NumberLiteralTypeAnnotation>;
69+
70+
export type BooleanLiteralUnionTypeAnnotation =
71+
UnionTypeAnnotation<BooleanLiteralTypeAnnotation>;
72+
6073
export type VoidTypeAnnotation = $ReadOnly<{
6174
type: 'VoidTypeAnnotation',
6275
}>;
@@ -68,6 +81,16 @@ export type ObjectTypeAnnotation<+T> = $ReadOnly<{
6881
baseTypes?: $ReadOnlyArray<string>,
6982
}>;
7083

84+
export type UnionTypeAnnotation<+T> = $ReadOnly<{
85+
type: 'UnionTypeAnnotation',
86+
types: $ReadOnlyArray<T>,
87+
}>;
88+
89+
export type TupleTypeAnnotation = $ReadOnly<{
90+
type: 'TupleTypeAnnotation',
91+
types: StringLiteralTypeAnnotation | NumberLiteralTypeAnnotation,
92+
}>;
93+
7194
export type MixedTypeAnnotation = $ReadOnly<{
7295
type: 'MixedTypeAnnotation',
7396
}>;
@@ -358,15 +381,17 @@ export type NativeModulePromiseTypeAnnotation = $ReadOnly<{
358381
elementType: VoidTypeAnnotation | Nullable<NativeModuleBaseTypeAnnotation>,
359382
}>;
360383

361-
export type UnionTypeAnnotationMemberType =
362-
| 'NumberTypeAnnotation'
363-
| 'ObjectTypeAnnotation'
364-
| 'StringTypeAnnotation';
384+
export type NativeModuleUnionTypeAnnotationMemberType =
385+
| NativeModuleObjectTypeAnnotation
386+
| StringLiteralTypeAnnotation
387+
| NumberLiteralTypeAnnotation
388+
| BooleanLiteralTypeAnnotation
389+
| BooleanTypeAnnotation
390+
| StringTypeAnnotation
391+
| NumberTypeAnnotation;
365392

366-
export type NativeModuleUnionTypeAnnotation = $ReadOnly<{
367-
type: 'UnionTypeAnnotation',
368-
memberType: UnionTypeAnnotationMemberType,
369-
}>;
393+
export type NativeModuleUnionTypeAnnotation =
394+
UnionTypeAnnotation<NativeModuleUnionTypeAnnotationMemberType>;
370395

371396
export type NativeModuleMixedTypeAnnotation = $ReadOnly<{
372397
type: 'MixedTypeAnnotation',
@@ -396,6 +421,7 @@ export type NativeModuleBaseTypeAnnotation =
396421
| StringLiteralUnionTypeAnnotation
397422
| NativeModuleNumberTypeAnnotation
398423
| NumberLiteralTypeAnnotation
424+
| BooleanLiteralTypeAnnotation
399425
| Int32TypeAnnotation
400426
| DoubleTypeAnnotation
401427
| FloatTypeAnnotation

packages/react-native-codegen/src/generators/components/CppHelpers.js

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,23 @@
1212
import type {
1313
EventTypeAnnotation,
1414
NamedShape,
15+
NativeModuleUnionTypeAnnotation,
1516
PropTypeAnnotation,
1617
} from '../../CodegenSchema';
1718

1819
const {getEnumName, toSafeCppString} = require('../Utils');
1920

21+
const NumberTypes = ['NumberTypeAnnotation', 'NumberLiteralTypeAnnotation'];
22+
const StringTypes = ['StringTypeAnnotation', 'StringLiteralTypeAnnotation'];
23+
const ObjectTypes = ['ObjectTypeAnnotation'];
24+
const BooleanTypes = ['BooleanTypeAnnotation', 'BooleanLiteralTypeAnnotation'];
25+
const ValidTypes = [
26+
...NumberTypes,
27+
...ObjectTypes,
28+
...StringTypes,
29+
...BooleanTypes,
30+
];
31+
2032
function toIntEnumValueName(propName: string, value: number): string {
2133
return `${toSafeCppString(propName)}${value}`;
2234
}
@@ -61,7 +73,47 @@ function getCppArrayTypeForAnnotation(
6173
case 'Int32TypeAnnotation':
6274
case 'MixedTypeAnnotation':
6375
return `std::vector<${getCppTypeForAnnotation(typeElement.type)}>`;
64-
case 'StringLiteralUnionTypeAnnotation':
76+
case 'UnionTypeAnnotation':
77+
const union: NativeModuleUnionTypeAnnotation = typeElement;
78+
const isUnionOfType = (types: $ReadOnlyArray<string>): boolean => {
79+
return union.types.every(memberTypeAnnotation =>
80+
types.includes(memberTypeAnnotation.type),
81+
);
82+
};
83+
84+
if (isUnionOfType(NumberTypes)) {
85+
return `std::vector<${getCppTypeForAnnotation('DoubleTypeAnnotation')}>`;
86+
}
87+
88+
if (isUnionOfType(ObjectTypes)) {
89+
if (!structParts) {
90+
throw new Error(
91+
`Trying to generate the event emitter for an Array of ${typeElement.type} without informations to generate the generic type`,
92+
);
93+
}
94+
return `std::vector<${generateEventStructName(structParts)}>`;
95+
}
96+
97+
if (isUnionOfType(StringTypes)) {
98+
if (!structParts) {
99+
throw new Error(
100+
`Trying to generate the event emitter for an Array of ${typeElement.type} without informations to generate the generic type`,
101+
);
102+
}
103+
return `std::vector<${generateEventStructName(structParts)}>`;
104+
}
105+
106+
if (isUnionOfType(BooleanTypes)) {
107+
return `std::vector<${getCppTypeForAnnotation('BooleanTypeAnnotation')}>`;
108+
}
109+
110+
const invalidTypes = union.types.filter(member => {
111+
return !ValidTypes.includes(member.type);
112+
});
113+
114+
throw new Error(
115+
`Unsupported union member types: ${invalidTypes.join(', ')}"`,
116+
);
65117
case 'ObjectTypeAnnotation':
66118
if (!structParts) {
67119
throw new Error(

packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ function handleArrayElementType(
207207
loopLocalVariable,
208208
val => `jsi::valueFromDynamic(runtime, ${val})`,
209209
);
210-
case 'StringLiteralUnionTypeAnnotation':
210+
case 'UnionTypeAnnotation':
211211
return setValueAtIndex(
212212
propertyName,
213213
indexVariable,
@@ -320,7 +320,7 @@ function generateSetters(
320320
usingEvent,
321321
prop => `jsi::valueFromDynamic(runtime, ${prop})`,
322322
);
323-
case 'StringLiteralUnionTypeAnnotation':
323+
case 'UnionTypeAnnotation':
324324
return generateSetter(
325325
parentPropertyName,
326326
eventProperty.name,

packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ function getNativeTypeFromAnnotation(
128128
case 'FloatTypeAnnotation':
129129
case 'MixedTypeAnnotation':
130130
return getCppTypeForAnnotation(type);
131-
case 'StringLiteralUnionTypeAnnotation':
131+
case 'UnionTypeAnnotation':
132132
case 'ObjectTypeAnnotation':
133133
return generateEventStructName([...nameParts, eventProperty.name]);
134134
case 'ArrayTypeAnnotation':
@@ -188,7 +188,7 @@ function handleGenerateStructForArray(
188188
nameParts.concat([name]),
189189
nullthrows(elementType.properties),
190190
);
191-
} else if (elementType.type === 'StringLiteralUnionTypeAnnotation') {
191+
} else if (elementType.type === 'UnionTypeAnnotation') {
192192
generateEnum(
193193
structs,
194194
elementType.types.map(literal => literal.value),
@@ -251,7 +251,7 @@ function generateStruct(
251251
nullthrows(typeAnnotation.properties),
252252
);
253253
return;
254-
case 'StringLiteralUnionTypeAnnotation':
254+
case 'UnionTypeAnnotation':
255255
generateEnum(
256256
structs,
257257
typeAnnotation.types.map(literal => literal.value),

packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,7 @@ const EVENT_PROPS: SchemaType = {
12731273
typeAnnotation: {
12741274
type: 'ArrayTypeAnnotation',
12751275
elementType: {
1276-
type: 'StringLiteralUnionTypeAnnotation',
1276+
type: 'UnionTypeAnnotation',
12771277
types: [
12781278
{
12791279
type: 'StringLiteralTypeAnnotation',
@@ -1383,7 +1383,7 @@ const EVENT_PROPS: SchemaType = {
13831383
name: 'orientation',
13841384
optional: false,
13851385
typeAnnotation: {
1386-
type: 'StringLiteralUnionTypeAnnotation',
1386+
type: 'UnionTypeAnnotation',
13871387
types: [
13881388
{
13891389
type: 'StringLiteralTypeAnnotation',

0 commit comments

Comments
 (0)