Skip to content

Commit 7e7706c

Browse files
hramosfacebook-github-bot
authored andcommitted
Codegen: Generate ObjC structs for type aliases
Summary: **Motivation:** Match the old codegen's behavior when generating structs for type alias derived objects. **Problem description:** Take, for example, the following spec: ``` export type MyTypeAlias = { /* ... */ } export interface Spec extends TurboModule { // ... +myMethod: (paramName: MyTypeAlias) => void; // ... } ``` The codegen needs to generate a struct to expose the properties of the type alias object. The codegen was producing the following output: ``` - (void)myMethod:(JS::MyModule::SpecMyMethodParamName &)paramName; ``` ...which does not match the output from the original codegen: ``` - (void)myMethod:(JS::MyModule::MyTypeAlias &)paramName; ``` The original codegen generates a struct using the type alias name, while the new codegen was generating a struct that uses a combination of the property and parameter names. Now that type alias names are exposed in the schema, the new codegen can match the original codegen's behavior. **De-duplication of structs:** Prior to these changes, type aliases were expanded into regular object types. This meant that any spec that used a type alias more than once would lead to redundant structs getting created. With these changes, we only generate the one struct per type alias, matching the old codegen. **Expansion of type aliases:** A new type was introduced in D22200700 (facebook@e261f02), TypeAliasTypeAnnotation: ``` export type TypeAliasTypeAnnotation = $ReadOnly<{| type: 'TypeAliasTypeAnnotation', name: string, |}>; ``` This type may now appear in several locations where a `{| type: 'ObjectTypeAnnotation', properties: [] |}` otherwise would have been used. A `getTypeAliasTypeAnnotation` function is introduced which, given an alias name and an array of aliases provided by the module, will produce the actual object type annotation for the given property parameter. Changelog: [Internal] Reviewed By: RSNara Differential Revision: D22244323 fbshipit-source-id: 125fbf0d6d887bd05a99bf8b81b30bdda4f1682b
1 parent e255748 commit 7e7706c

File tree

14 files changed

+2504
-190
lines changed

14 files changed

+2504
-190
lines changed

packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
'use strict';
1212

1313
import type {SchemaType} from '../../CodegenSchema';
14-
14+
const {getTypeAliasTypeAnnotation} = require('./ObjCppUtils/Utils');
1515
type FilesOutput = Map<string, string>;
1616

1717
const propertyHeaderTemplate =
@@ -62,20 +62,25 @@ namespace react {
6262
} // namespace facebook
6363
`;
6464

65-
function traverseArg(arg, index): string {
65+
function traverseArg(arg, index, aliases): string {
6666
function wrap(suffix) {
6767
return `args[${index}]${suffix}`;
6868
}
6969
const {typeAnnotation} = arg;
70-
switch (typeAnnotation.type) {
70+
71+
const realTypeAnnotation =
72+
typeAnnotation.type === 'TypeAliasTypeAnnotation'
73+
? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases)
74+
: typeAnnotation;
75+
switch (realTypeAnnotation.type) {
7176
case 'ReservedFunctionValueTypeAnnotation':
72-
switch (typeAnnotation.name) {
77+
switch (realTypeAnnotation.name) {
7378
case 'RootTag':
7479
return wrap('.getNumber()');
7580
default:
76-
(typeAnnotation.name: empty);
81+
(realTypeAnnotation.name: empty);
7782
throw new Error(
78-
`Unknown prop type for "${arg.name}", found: "${typeAnnotation.name}"`,
83+
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.name}"`,
7984
);
8085
}
8186
case 'StringTypeAnnotation':
@@ -91,27 +96,26 @@ function traverseArg(arg, index): string {
9196
case 'FunctionTypeAnnotation':
9297
return `std::move(${wrap('.getObject(rt).getFunction(rt)')})`;
9398
case 'GenericObjectTypeAnnotation':
94-
case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
9599
case 'ObjectTypeAnnotation':
96100
return wrap('.getObject(rt)');
97101
case 'AnyTypeAnnotation':
98102
throw new Error(`Any type is not allowed in params for "${arg.name}"`);
99103
default:
100104
// TODO (T65847278): Figure out why this does not work.
101-
// (typeAnnotation.type: empty);
105+
// (type: empty);
102106
throw new Error(
103-
`Unknown prop type for "${arg.name}", found: "${typeAnnotation.type}"`,
107+
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`,
104108
);
105109
}
106110
}
107111

108-
function traverseProperty(property): string {
112+
function traverseProperty(property, aliases): string {
109113
const propertyTemplate =
110114
property.typeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation'
111115
? voidPropertyTemplate
112116
: nonvoidPropertyTemplate;
113117
const traversedArgs = property.typeAnnotation.params
114-
.map(traverseArg)
118+
.map((p, i) => traverseArg(p, i, aliases))
115119
.join(', ');
116120
return propertyTemplate
117121
.replace(/::_PROPERTY_NAME_::/g, property.name)
@@ -138,9 +142,9 @@ module.exports = {
138142

139143
const modules = Object.keys(nativeModules)
140144
.map(name => {
141-
const {properties} = nativeModules[name];
145+
const {aliases, properties} = nativeModules[name];
142146
const traversedProperties = properties
143-
.map(property => traverseProperty(property))
147+
.map(property => traverseProperty(property, aliases))
144148
.join('\n');
145149
return moduleTemplate
146150
.replace(/::_MODULE_PROPERTIES_::/g, traversedProperties)

packages/react-native-codegen/src/generators/modules/GenerateModuleH.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ import type {
1414
SchemaType,
1515
FunctionTypeAnnotationParamTypeAnnotation,
1616
FunctionTypeAnnotationReturn,
17+
TypeAliasTypeAnnotation,
18+
ObjectTypeAliasTypeShape,
1719
} from '../../CodegenSchema';
1820

21+
const {getTypeAliasTypeAnnotation} = require('./ObjCppUtils/Utils');
22+
1923
type FilesOutput = Map<string, string>;
2024

2125
const moduleTemplate = `
@@ -51,17 +55,23 @@ namespace react {
5155
function translatePrimitiveJSTypeToCpp(
5256
typeAnnotation:
5357
| FunctionTypeAnnotationParamTypeAnnotation
54-
| FunctionTypeAnnotationReturn,
58+
| FunctionTypeAnnotationReturn
59+
| TypeAliasTypeAnnotation,
5560
createErrorMessage: (typeName: string) => string,
61+
aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>,
5662
) {
57-
switch (typeAnnotation.type) {
63+
const realTypeAnnotation =
64+
typeAnnotation.type === 'TypeAliasTypeAnnotation'
65+
? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases)
66+
: typeAnnotation;
67+
switch (realTypeAnnotation.type) {
5868
case 'ReservedFunctionValueTypeAnnotation':
59-
switch (typeAnnotation.name) {
69+
switch (realTypeAnnotation.name) {
6070
case 'RootTag':
6171
return 'double';
6272
default:
63-
(typeAnnotation.name: empty);
64-
throw new Error(createErrorMessage(typeAnnotation.name));
73+
(realTypeAnnotation.name: empty);
74+
throw new Error(createErrorMessage(realTypeAnnotation.name));
6575
}
6676
case 'VoidTypeAnnotation':
6777
return 'void';
@@ -74,7 +84,6 @@ function translatePrimitiveJSTypeToCpp(
7484
return 'int';
7585
case 'BooleanTypeAnnotation':
7686
return 'bool';
77-
// case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
7887
case 'GenericObjectTypeAnnotation':
7988
case 'ObjectTypeAnnotation':
8089
return 'jsi::Object';
@@ -86,8 +95,8 @@ function translatePrimitiveJSTypeToCpp(
8695
return 'jsi::Value';
8796
default:
8897
// TODO (T65847278): Figure out why this does not work.
89-
// (typeAnnotation.type: empty);
90-
throw new Error(createErrorMessage(typeAnnotation.type));
98+
// (type: empty);
99+
throw new Error(createErrorMessage(realTypeAnnotation.type));
91100
}
92101
}
93102

@@ -114,7 +123,7 @@ module.exports = {
114123

115124
const modules = Object.keys(nativeModules)
116125
.map(name => {
117-
const {properties} = nativeModules[name];
126+
const {aliases, properties} = nativeModules[name];
118127
const traversedProperties = properties
119128
.map(prop => {
120129
const traversedArgs = prop.typeAnnotation.params
@@ -123,6 +132,7 @@ module.exports = {
123132
param.typeAnnotation,
124133
typeName =>
125134
`Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`,
135+
aliases,
126136
);
127137
const isObject = translatedParam.startsWith('jsi::');
128138
return (
@@ -140,6 +150,7 @@ module.exports = {
140150
prop.typeAnnotation.returnTypeAnnotation,
141151
typeName =>
142152
`Unsupported return type for ${prop.name}. Found: ${typeName}`,
153+
aliases,
143154
),
144155
)
145156
.replace(

0 commit comments

Comments
 (0)