@react-native/codegen 0.72.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +21 -0
  2. package/lib/CodegenSchema.js +11 -0
  3. package/lib/CodegenSchema.js.flow +351 -0
  4. package/lib/SchemaValidator.js +54 -0
  5. package/lib/SchemaValidator.js.flow +67 -0
  6. package/lib/cli/combine/combine-js-to-schema-cli.js +50 -0
  7. package/lib/cli/combine/combine-js-to-schema-cli.js.flow +49 -0
  8. package/lib/cli/combine/combine-js-to-schema.js +110 -0
  9. package/lib/cli/combine/combine-js-to-schema.js.flow +48 -0
  10. package/lib/cli/combine/combine-utils.js +118 -0
  11. package/lib/cli/combine/combine-utils.js.flow +85 -0
  12. package/lib/cli/generators/generate-all.js +65 -0
  13. package/lib/cli/generators/generate-all.js.flow +66 -0
  14. package/lib/cli/parser/parser-cli.js +55 -0
  15. package/lib/cli/parser/parser-cli.js.flow +18 -0
  16. package/lib/cli/parser/parser.js +35 -0
  17. package/lib/cli/parser/parser.js.flow +37 -0
  18. package/lib/cli/parser/parser.sh +15 -0
  19. package/lib/generators/RNCodegen.js +207 -0
  20. package/lib/generators/RNCodegen.js.flow +284 -0
  21. package/lib/generators/Utils.js +31 -0
  22. package/lib/generators/Utils.js.flow +33 -0
  23. package/lib/generators/__test_fixtures__/fixtures.js +79 -0
  24. package/lib/generators/__test_fixtures__/fixtures.js.flow +82 -0
  25. package/lib/generators/components/ComponentsGeneratorUtils.js +217 -0
  26. package/lib/generators/components/ComponentsGeneratorUtils.js.flow +304 -0
  27. package/lib/generators/components/CppHelpers.js +188 -0
  28. package/lib/generators/components/CppHelpers.js.flow +228 -0
  29. package/lib/generators/components/GenerateComponentDescriptorH.js +75 -0
  30. package/lib/generators/components/GenerateComponentDescriptorH.js.flow +95 -0
  31. package/lib/generators/components/GenerateComponentHObjCpp.js +327 -0
  32. package/lib/generators/components/GenerateComponentHObjCpp.js.flow +418 -0
  33. package/lib/generators/components/GenerateEventEmitterCpp.js +199 -0
  34. package/lib/generators/components/GenerateEventEmitterCpp.js.flow +273 -0
  35. package/lib/generators/components/GenerateEventEmitterH.js +224 -0
  36. package/lib/generators/components/GenerateEventEmitterH.js.flow +315 -0
  37. package/lib/generators/components/GeneratePropsCpp.js +126 -0
  38. package/lib/generators/components/GeneratePropsCpp.js.flow +161 -0
  39. package/lib/generators/components/GeneratePropsH.js +606 -0
  40. package/lib/generators/components/GeneratePropsH.js.flow +778 -0
  41. package/lib/generators/components/GeneratePropsJavaDelegate.js +287 -0
  42. package/lib/generators/components/GeneratePropsJavaDelegate.js.flow +348 -0
  43. package/lib/generators/components/GeneratePropsJavaInterface.js +237 -0
  44. package/lib/generators/components/GeneratePropsJavaInterface.js.flow +288 -0
  45. package/lib/generators/components/GeneratePropsJavaPojo/PojoCollector.js +157 -0
  46. package/lib/generators/components/GeneratePropsJavaPojo/PojoCollector.js.flow +187 -0
  47. package/lib/generators/components/GeneratePropsJavaPojo/index.js +66 -0
  48. package/lib/generators/components/GeneratePropsJavaPojo/index.js.flow +80 -0
  49. package/lib/generators/components/GeneratePropsJavaPojo/serializePojo.js +273 -0
  50. package/lib/generators/components/GeneratePropsJavaPojo/serializePojo.js.flow +296 -0
  51. package/lib/generators/components/GenerateShadowNodeCpp.js +73 -0
  52. package/lib/generators/components/GenerateShadowNodeCpp.js.flow +95 -0
  53. package/lib/generators/components/GenerateShadowNodeH.js +91 -0
  54. package/lib/generators/components/GenerateShadowNodeH.js.flow +124 -0
  55. package/lib/generators/components/GenerateStateCpp.js +70 -0
  56. package/lib/generators/components/GenerateStateCpp.js.flow +92 -0
  57. package/lib/generators/components/GenerateStateH.js +93 -0
  58. package/lib/generators/components/GenerateStateH.js.flow +111 -0
  59. package/lib/generators/components/GenerateTests.js +165 -0
  60. package/lib/generators/components/GenerateTests.js.flow +219 -0
  61. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderH.js +91 -0
  62. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderH.js.flow +107 -0
  63. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js +89 -0
  64. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js.flow +105 -0
  65. package/lib/generators/components/GenerateViewConfigJs.js +410 -0
  66. package/lib/generators/components/GenerateViewConfigJs.js.flow +484 -0
  67. package/lib/generators/components/JavaHelpers.js +87 -0
  68. package/lib/generators/components/JavaHelpers.js.flow +119 -0
  69. package/lib/generators/components/__test_fixtures__/fixtures.js +1641 -0
  70. package/lib/generators/components/__test_fixtures__/fixtures.js.flow +1672 -0
  71. package/lib/generators/modules/GenerateModuleCpp.js +299 -0
  72. package/lib/generators/modules/GenerateModuleCpp.js.flow +278 -0
  73. package/lib/generators/modules/GenerateModuleH.js +373 -0
  74. package/lib/generators/modules/GenerateModuleH.js.flow +355 -0
  75. package/lib/generators/modules/GenerateModuleJavaSpec.js +571 -0
  76. package/lib/generators/modules/GenerateModuleJavaSpec.js.flow +553 -0
  77. package/lib/generators/modules/GenerateModuleJniCpp.js +505 -0
  78. package/lib/generators/modules/GenerateModuleJniCpp.js.flow +523 -0
  79. package/lib/generators/modules/GenerateModuleJniH.js +138 -0
  80. package/lib/generators/modules/GenerateModuleJniH.js.flow +148 -0
  81. package/lib/generators/modules/GenerateModuleObjCpp/StructCollector.js +262 -0
  82. package/lib/generators/modules/GenerateModuleObjCpp/StructCollector.js.flow +208 -0
  83. package/lib/generators/modules/GenerateModuleObjCpp/Utils.js +25 -0
  84. package/lib/generators/modules/GenerateModuleObjCpp/Utils.js.flow +32 -0
  85. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js +337 -0
  86. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js.flow +288 -0
  87. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js +330 -0
  88. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js.flow +279 -0
  89. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js +25 -0
  90. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js.flow +35 -0
  91. package/lib/generators/modules/GenerateModuleObjCpp/index.js +185 -0
  92. package/lib/generators/modules/GenerateModuleObjCpp/index.js.flow +219 -0
  93. package/lib/generators/modules/GenerateModuleObjCpp/serializeMethod.js +529 -0
  94. package/lib/generators/modules/GenerateModuleObjCpp/serializeMethod.js.flow +510 -0
  95. package/lib/generators/modules/GenerateModuleObjCpp/source/serializeModule.js +96 -0
  96. package/lib/generators/modules/GenerateModuleObjCpp/source/serializeModule.js.flow +121 -0
  97. package/lib/generators/modules/Utils.js +34 -0
  98. package/lib/generators/modules/Utils.js.flow +53 -0
  99. package/lib/generators/modules/__test_fixtures__/fixtures.js +1658 -0
  100. package/lib/generators/modules/__test_fixtures__/fixtures.js.flow +1669 -0
  101. package/lib/parsers/consistency/compareSnaps.js +84 -0
  102. package/lib/parsers/error-utils.js +284 -0
  103. package/lib/parsers/error-utils.js.flow +295 -0
  104. package/lib/parsers/errors.js +350 -0
  105. package/lib/parsers/errors.js.flow +439 -0
  106. package/lib/parsers/flow/components/__test_fixtures__/failures.js +583 -0
  107. package/lib/parsers/flow/components/__test_fixtures__/failures.js.flow +600 -0
  108. package/lib/parsers/flow/components/__test_fixtures__/fixtures.js +1001 -0
  109. package/lib/parsers/flow/components/__test_fixtures__/fixtures.js.flow +1016 -0
  110. package/lib/parsers/flow/components/commands.js +104 -0
  111. package/lib/parsers/flow/components/commands.js.flow +123 -0
  112. package/lib/parsers/flow/components/componentsUtils.js +446 -0
  113. package/lib/parsers/flow/components/componentsUtils.js.flow +496 -0
  114. package/lib/parsers/flow/components/events.js +233 -0
  115. package/lib/parsers/flow/components/events.js.flow +262 -0
  116. package/lib/parsers/flow/components/extends.js +52 -0
  117. package/lib/parsers/flow/components/extends.js.flow +66 -0
  118. package/lib/parsers/flow/components/index.js +267 -0
  119. package/lib/parsers/flow/components/index.js.flow +226 -0
  120. package/lib/parsers/flow/components/options.js +72 -0
  121. package/lib/parsers/flow/components/options.js.flow +87 -0
  122. package/lib/parsers/flow/components/props.js +47 -0
  123. package/lib/parsers/flow/components/props.js.flow +60 -0
  124. package/lib/parsers/flow/components/schema.js +106 -0
  125. package/lib/parsers/flow/components/schema.js.flow +62 -0
  126. package/lib/parsers/flow/index.js +80 -0
  127. package/lib/parsers/flow/index.js.flow +85 -0
  128. package/lib/parsers/flow/modules/__test_fixtures__/failures.js +215 -0
  129. package/lib/parsers/flow/modules/__test_fixtures__/failures.js.flow +223 -0
  130. package/lib/parsers/flow/modules/__test_fixtures__/fixtures.js +724 -0
  131. package/lib/parsers/flow/modules/__test_fixtures__/fixtures.js.flow +747 -0
  132. package/lib/parsers/flow/modules/index.js +528 -0
  133. package/lib/parsers/flow/modules/index.js.flow +420 -0
  134. package/lib/parsers/flow/parser.js +109 -0
  135. package/lib/parsers/flow/parser.js.flow +83 -0
  136. package/lib/parsers/flow/utils.js +108 -0
  137. package/lib/parsers/flow/utils.js.flow +123 -0
  138. package/lib/parsers/parser.js +11 -0
  139. package/lib/parsers/parser.js.flow +70 -0
  140. package/lib/parsers/parserMock.js +96 -0
  141. package/lib/parsers/parserMock.js.flow +68 -0
  142. package/lib/parsers/parsers-commons.js +448 -0
  143. package/lib/parsers/parsers-commons.js.flow +447 -0
  144. package/lib/parsers/parsers-primitives.js +387 -0
  145. package/lib/parsers/parsers-primitives.js.flow +383 -0
  146. package/lib/parsers/parsers-utils.js +18 -0
  147. package/lib/parsers/parsers-utils.js.flow +19 -0
  148. package/lib/parsers/schema/index.js +23 -0
  149. package/lib/parsers/schema/index.js.flow +26 -0
  150. package/lib/parsers/typescript/components/__test_fixtures__/failures.js +489 -0
  151. package/lib/parsers/typescript/components/__test_fixtures__/failures.js.flow +505 -0
  152. package/lib/parsers/typescript/components/__test_fixtures__/fixtures.js +1151 -0
  153. package/lib/parsers/typescript/components/__test_fixtures__/fixtures.js.flow +1168 -0
  154. package/lib/parsers/typescript/components/commands.js +132 -0
  155. package/lib/parsers/typescript/components/commands.js.flow +151 -0
  156. package/lib/parsers/typescript/components/componentsUtils.js +471 -0
  157. package/lib/parsers/typescript/components/componentsUtils.js.flow +521 -0
  158. package/lib/parsers/typescript/components/events.js +240 -0
  159. package/lib/parsers/typescript/components/events.js.flow +262 -0
  160. package/lib/parsers/typescript/components/extends.js +88 -0
  161. package/lib/parsers/typescript/components/extends.js.flow +103 -0
  162. package/lib/parsers/typescript/components/index.js +277 -0
  163. package/lib/parsers/typescript/components/index.js.flow +239 -0
  164. package/lib/parsers/typescript/components/options.js +72 -0
  165. package/lib/parsers/typescript/components/options.js.flow +87 -0
  166. package/lib/parsers/typescript/components/props.js +39 -0
  167. package/lib/parsers/typescript/components/props.js.flow +48 -0
  168. package/lib/parsers/typescript/components/schema.js +106 -0
  169. package/lib/parsers/typescript/components/schema.js.flow +62 -0
  170. package/lib/parsers/typescript/index.js +85 -0
  171. package/lib/parsers/typescript/index.js.flow +94 -0
  172. package/lib/parsers/typescript/modules/__test_fixtures__/failures.js +160 -0
  173. package/lib/parsers/typescript/modules/__test_fixtures__/failures.js.flow +167 -0
  174. package/lib/parsers/typescript/modules/__test_fixtures__/fixtures.js +701 -0
  175. package/lib/parsers/typescript/modules/__test_fixtures__/fixtures.js.flow +727 -0
  176. package/lib/parsers/typescript/modules/index.js +543 -0
  177. package/lib/parsers/typescript/modules/index.js.flow +435 -0
  178. package/lib/parsers/typescript/parseTopLevelType.js +203 -0
  179. package/lib/parsers/typescript/parseTopLevelType.js.flow +243 -0
  180. package/lib/parsers/typescript/parser.js +105 -0
  181. package/lib/parsers/typescript/parser.js.flow +87 -0
  182. package/lib/parsers/typescript/utils.js +101 -0
  183. package/lib/parsers/typescript/utils.js.flow +115 -0
  184. package/lib/parsers/utils.js +273 -0
  185. package/lib/parsers/utils.js.flow +266 -0
  186. package/package.json +45 -0
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const _require = require('./JavaHelpers'),
14
+ getImports = _require.getImports,
15
+ toSafeJavaString = _require.toSafeJavaString,
16
+ getInterfaceJavaClassName = _require.getInterfaceJavaClassName,
17
+ getDelegateJavaClassName = _require.getDelegateJavaClassName;
18
+
19
+ // File path -> contents
20
+
21
+ const FileTemplate = ({
22
+ packageName,
23
+ imports,
24
+ className,
25
+ extendClasses,
26
+ interfaceClassName,
27
+ methods,
28
+ }) => `/**
29
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
30
+ *
31
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
32
+ * once the code is regenerated.
33
+ *
34
+ * ${'@'}generated by codegen project: GeneratePropsJavaDelegate.js
35
+ */
36
+
37
+ package ${packageName};
38
+
39
+ ${imports}
40
+
41
+ public class ${className}<T extends ${extendClasses}, U extends BaseViewManagerInterface<T> & ${interfaceClassName}<T>> extends BaseViewManagerDelegate<T, U> {
42
+ public ${className}(U viewManager) {
43
+ super(viewManager);
44
+ }
45
+ ${methods}
46
+ }
47
+ `;
48
+ const PropSetterTemplate = ({propCases}) =>
49
+ `
50
+ @Override
51
+ public void setProperty(T view, String propName, @Nullable Object value) {
52
+ ${propCases}
53
+ }
54
+ `.trim();
55
+ const CommandsTemplate = ({commandCases}) =>
56
+ `
57
+ @Override
58
+ public void receiveCommand(T view, String commandName, ReadableArray args) {
59
+ switch (commandName) {
60
+ ${commandCases}
61
+ }
62
+ }
63
+ `.trim();
64
+ function getJavaValueForProp(prop, componentName) {
65
+ const typeAnnotation = prop.typeAnnotation;
66
+ switch (typeAnnotation.type) {
67
+ case 'BooleanTypeAnnotation':
68
+ if (typeAnnotation.default === null) {
69
+ return 'value == null ? null : (Boolean) value';
70
+ } else {
71
+ return `value == null ? ${typeAnnotation.default.toString()} : (boolean) value`;
72
+ }
73
+ case 'StringTypeAnnotation':
74
+ const defaultValueString =
75
+ typeAnnotation.default === null
76
+ ? 'null'
77
+ : `"${typeAnnotation.default}"`;
78
+ return `value == null ? ${defaultValueString} : (String) value`;
79
+ case 'Int32TypeAnnotation':
80
+ return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
81
+ case 'DoubleTypeAnnotation':
82
+ if (prop.optional) {
83
+ return `value == null ? ${typeAnnotation.default}f : ((Double) value).doubleValue()`;
84
+ } else {
85
+ return 'value == null ? Double.NaN : ((Double) value).doubleValue()';
86
+ }
87
+ case 'FloatTypeAnnotation':
88
+ if (typeAnnotation.default === null) {
89
+ return 'value == null ? null : ((Double) value).floatValue()';
90
+ } else if (prop.optional) {
91
+ return `value == null ? ${typeAnnotation.default}f : ((Double) value).floatValue()`;
92
+ } else {
93
+ return 'value == null ? Float.NaN : ((Double) value).floatValue()';
94
+ }
95
+ case 'ReservedPropTypeAnnotation':
96
+ switch (typeAnnotation.name) {
97
+ case 'ColorPrimitive':
98
+ return 'ColorPropConverter.getColor(value, view.getContext())';
99
+ case 'ImageSourcePrimitive':
100
+ return '(ReadableMap) value';
101
+ case 'ImageRequestPrimitive':
102
+ return '(ReadableMap) value';
103
+ case 'PointPrimitive':
104
+ return '(ReadableMap) value';
105
+ case 'EdgeInsetsPrimitive':
106
+ return '(ReadableMap) value';
107
+ default:
108
+ typeAnnotation.name;
109
+ throw new Error('Received unknown ReservedPropTypeAnnotation');
110
+ }
111
+ case 'ArrayTypeAnnotation': {
112
+ return '(ReadableArray) value';
113
+ }
114
+ case 'ObjectTypeAnnotation': {
115
+ return '(ReadableMap) value';
116
+ }
117
+ case 'StringEnumTypeAnnotation':
118
+ return '(String) value';
119
+ case 'Int32EnumTypeAnnotation':
120
+ return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
121
+ default:
122
+ typeAnnotation;
123
+ throw new Error('Received invalid typeAnnotation');
124
+ }
125
+ }
126
+ function generatePropCasesString(component, componentName) {
127
+ if (component.props.length === 0) {
128
+ return 'super.setProperty(view, propName, value);';
129
+ }
130
+ const cases = component.props
131
+ .map(prop => {
132
+ return `case "${prop.name}":
133
+ mViewManager.set${toSafeJavaString(
134
+ prop.name,
135
+ )}(view, ${getJavaValueForProp(prop, componentName)});
136
+ break;`;
137
+ })
138
+ .join('\n' + ' ');
139
+ return `switch (propName) {
140
+ ${cases}
141
+ default:
142
+ super.setProperty(view, propName, value);
143
+ }`;
144
+ }
145
+ function getCommandArgJavaType(param, index) {
146
+ const typeAnnotation = param.typeAnnotation;
147
+ switch (typeAnnotation.type) {
148
+ case 'ReservedTypeAnnotation':
149
+ switch (typeAnnotation.name) {
150
+ case 'RootTag':
151
+ return `args.getDouble(${index})`;
152
+ default:
153
+ typeAnnotation.name;
154
+ throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
155
+ }
156
+ case 'BooleanTypeAnnotation':
157
+ return `args.getBoolean(${index})`;
158
+ case 'DoubleTypeAnnotation':
159
+ return `args.getDouble(${index})`;
160
+ case 'FloatTypeAnnotation':
161
+ return `(float) args.getDouble(${index})`;
162
+ case 'Int32TypeAnnotation':
163
+ return `args.getInt(${index})`;
164
+ case 'StringTypeAnnotation':
165
+ return `args.getString(${index})`;
166
+ default:
167
+ typeAnnotation.type;
168
+ throw new Error(`Receieved invalid type: ${typeAnnotation.type}`);
169
+ }
170
+ }
171
+ function getCommandArguments(command) {
172
+ return [
173
+ 'view',
174
+ ...command.typeAnnotation.params.map(getCommandArgJavaType),
175
+ ].join(', ');
176
+ }
177
+ function generateCommandCasesString(component, componentName) {
178
+ if (component.commands.length === 0) {
179
+ return null;
180
+ }
181
+ const commandMethods = component.commands
182
+ .map(command => {
183
+ return `case "${command.name}":
184
+ mViewManager.${toSafeJavaString(
185
+ command.name,
186
+ false,
187
+ )}(${getCommandArguments(command)});
188
+ break;`;
189
+ })
190
+ .join('\n' + ' ');
191
+ return commandMethods;
192
+ }
193
+ function getClassExtendString(component) {
194
+ const extendString = component.extendsProps
195
+ .map(extendProps => {
196
+ switch (extendProps.type) {
197
+ case 'ReactNativeBuiltInType':
198
+ switch (extendProps.knownTypeName) {
199
+ case 'ReactNativeCoreViewProps':
200
+ return 'View';
201
+ default:
202
+ extendProps.knownTypeName;
203
+ throw new Error('Invalid knownTypeName');
204
+ }
205
+ default:
206
+ extendProps.type;
207
+ throw new Error('Invalid extended type');
208
+ }
209
+ })
210
+ .join('');
211
+ return extendString;
212
+ }
213
+ function getDelegateImports(component) {
214
+ const imports = getImports(component, 'delegate');
215
+ // The delegate needs ReadableArray for commands always.
216
+ // The interface doesn't always need it
217
+ if (component.commands.length > 0) {
218
+ imports.add('import com.facebook.react.bridge.ReadableArray;');
219
+ }
220
+ imports.add('import androidx.annotation.Nullable;');
221
+ imports.add('import com.facebook.react.uimanager.BaseViewManagerDelegate;');
222
+ imports.add('import com.facebook.react.uimanager.BaseViewManagerInterface;');
223
+ return imports;
224
+ }
225
+ function generateMethods(propsString, commandsString) {
226
+ return [
227
+ PropSetterTemplate({
228
+ propCases: propsString,
229
+ }),
230
+ commandsString != null
231
+ ? CommandsTemplate({
232
+ commandCases: commandsString,
233
+ })
234
+ : '',
235
+ ]
236
+ .join('\n\n ')
237
+ .trimRight();
238
+ }
239
+ module.exports = {
240
+ generate(libraryName, schema, packageName, assumeNonnull = false) {
241
+ // TODO: This doesn't support custom package name yet.
242
+ const normalizedPackageName = 'com.facebook.react.viewmanagers';
243
+ const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`;
244
+ const files = new Map();
245
+ Object.keys(schema.modules).forEach(moduleName => {
246
+ const module = schema.modules[moduleName];
247
+ if (module.type !== 'Component') {
248
+ return;
249
+ }
250
+ const components = module.components;
251
+ // No components in this module
252
+ if (components == null) {
253
+ return;
254
+ }
255
+ return Object.keys(components)
256
+ .filter(componentName => {
257
+ const component = components[componentName];
258
+ return !(
259
+ component.excludedPlatforms &&
260
+ component.excludedPlatforms.includes('android')
261
+ );
262
+ })
263
+ .forEach(componentName => {
264
+ const component = components[componentName];
265
+ const className = getDelegateJavaClassName(componentName);
266
+ const interfaceClassName = getInterfaceJavaClassName(componentName);
267
+ const imports = getDelegateImports(component);
268
+ const propsString = generatePropCasesString(component, componentName);
269
+ const commandsString = generateCommandCasesString(
270
+ component,
271
+ componentName,
272
+ );
273
+ const extendString = getClassExtendString(component);
274
+ const replacedTemplate = FileTemplate({
275
+ imports: Array.from(imports).sort().join('\n'),
276
+ packageName: normalizedPackageName,
277
+ className,
278
+ extendClasses: extendString,
279
+ methods: generateMethods(propsString, commandsString),
280
+ interfaceClassName: interfaceClassName,
281
+ });
282
+ files.set(`${outputDir}/${className}.java`, replacedTemplate);
283
+ });
284
+ });
285
+ return files;
286
+ },
287
+ };
@@ -0,0 +1,348 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+ import type {CommandParamTypeAnnotation} from '../../CodegenSchema';
13
+
14
+ import type {
15
+ NamedShape,
16
+ CommandTypeAnnotation,
17
+ ComponentShape,
18
+ PropTypeAnnotation,
19
+ SchemaType,
20
+ } from '../../CodegenSchema';
21
+ const {
22
+ getImports,
23
+ toSafeJavaString,
24
+ getInterfaceJavaClassName,
25
+ getDelegateJavaClassName,
26
+ } = require('./JavaHelpers');
27
+
28
+ // File path -> contents
29
+ type FilesOutput = Map<string, string>;
30
+
31
+ const FileTemplate = ({
32
+ packageName,
33
+ imports,
34
+ className,
35
+ extendClasses,
36
+ interfaceClassName,
37
+ methods,
38
+ }: {
39
+ packageName: string,
40
+ imports: string,
41
+ className: string,
42
+ extendClasses: string,
43
+ interfaceClassName: string,
44
+ methods: string,
45
+ }) => `/**
46
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
47
+ *
48
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
49
+ * once the code is regenerated.
50
+ *
51
+ * ${'@'}generated by codegen project: GeneratePropsJavaDelegate.js
52
+ */
53
+
54
+ package ${packageName};
55
+
56
+ ${imports}
57
+
58
+ public class ${className}<T extends ${extendClasses}, U extends BaseViewManagerInterface<T> & ${interfaceClassName}<T>> extends BaseViewManagerDelegate<T, U> {
59
+ public ${className}(U viewManager) {
60
+ super(viewManager);
61
+ }
62
+ ${methods}
63
+ }
64
+ `;
65
+
66
+ const PropSetterTemplate = ({propCases}: {propCases: string}) =>
67
+ `
68
+ @Override
69
+ public void setProperty(T view, String propName, @Nullable Object value) {
70
+ ${propCases}
71
+ }
72
+ `.trim();
73
+
74
+ const CommandsTemplate = ({commandCases}: {commandCases: string}) =>
75
+ `
76
+ @Override
77
+ public void receiveCommand(T view, String commandName, ReadableArray args) {
78
+ switch (commandName) {
79
+ ${commandCases}
80
+ }
81
+ }
82
+ `.trim();
83
+
84
+ function getJavaValueForProp(
85
+ prop: NamedShape<PropTypeAnnotation>,
86
+ componentName: string,
87
+ ): string {
88
+ const typeAnnotation = prop.typeAnnotation;
89
+
90
+ switch (typeAnnotation.type) {
91
+ case 'BooleanTypeAnnotation':
92
+ if (typeAnnotation.default === null) {
93
+ return 'value == null ? null : (Boolean) value';
94
+ } else {
95
+ return `value == null ? ${typeAnnotation.default.toString()} : (boolean) value`;
96
+ }
97
+ case 'StringTypeAnnotation':
98
+ const defaultValueString =
99
+ typeAnnotation.default === null
100
+ ? 'null'
101
+ : `"${typeAnnotation.default}"`;
102
+ return `value == null ? ${defaultValueString} : (String) value`;
103
+ case 'Int32TypeAnnotation':
104
+ return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
105
+ case 'DoubleTypeAnnotation':
106
+ if (prop.optional) {
107
+ return `value == null ? ${typeAnnotation.default}f : ((Double) value).doubleValue()`;
108
+ } else {
109
+ return 'value == null ? Double.NaN : ((Double) value).doubleValue()';
110
+ }
111
+ case 'FloatTypeAnnotation':
112
+ if (typeAnnotation.default === null) {
113
+ return 'value == null ? null : ((Double) value).floatValue()';
114
+ } else if (prop.optional) {
115
+ return `value == null ? ${typeAnnotation.default}f : ((Double) value).floatValue()`;
116
+ } else {
117
+ return 'value == null ? Float.NaN : ((Double) value).floatValue()';
118
+ }
119
+ case 'ReservedPropTypeAnnotation':
120
+ switch (typeAnnotation.name) {
121
+ case 'ColorPrimitive':
122
+ return 'ColorPropConverter.getColor(value, view.getContext())';
123
+ case 'ImageSourcePrimitive':
124
+ return '(ReadableMap) value';
125
+ case 'ImageRequestPrimitive':
126
+ return '(ReadableMap) value';
127
+ case 'PointPrimitive':
128
+ return '(ReadableMap) value';
129
+ case 'EdgeInsetsPrimitive':
130
+ return '(ReadableMap) value';
131
+ default:
132
+ (typeAnnotation.name: empty);
133
+ throw new Error('Received unknown ReservedPropTypeAnnotation');
134
+ }
135
+ case 'ArrayTypeAnnotation': {
136
+ return '(ReadableArray) value';
137
+ }
138
+ case 'ObjectTypeAnnotation': {
139
+ return '(ReadableMap) value';
140
+ }
141
+ case 'StringEnumTypeAnnotation':
142
+ return '(String) value';
143
+ case 'Int32EnumTypeAnnotation':
144
+ return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
145
+ default:
146
+ (typeAnnotation: empty);
147
+ throw new Error('Received invalid typeAnnotation');
148
+ }
149
+ }
150
+
151
+ function generatePropCasesString(
152
+ component: ComponentShape,
153
+ componentName: string,
154
+ ) {
155
+ if (component.props.length === 0) {
156
+ return 'super.setProperty(view, propName, value);';
157
+ }
158
+
159
+ const cases = component.props
160
+ .map(prop => {
161
+ return `case "${prop.name}":
162
+ mViewManager.set${toSafeJavaString(
163
+ prop.name,
164
+ )}(view, ${getJavaValueForProp(prop, componentName)});
165
+ break;`;
166
+ })
167
+ .join('\n' + ' ');
168
+
169
+ return `switch (propName) {
170
+ ${cases}
171
+ default:
172
+ super.setProperty(view, propName, value);
173
+ }`;
174
+ }
175
+
176
+ function getCommandArgJavaType(
177
+ param: NamedShape<CommandParamTypeAnnotation>,
178
+ index: number,
179
+ ) {
180
+ const {typeAnnotation} = param;
181
+
182
+ switch (typeAnnotation.type) {
183
+ case 'ReservedTypeAnnotation':
184
+ switch (typeAnnotation.name) {
185
+ case 'RootTag':
186
+ return `args.getDouble(${index})`;
187
+ default:
188
+ (typeAnnotation.name: empty);
189
+ throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
190
+ }
191
+ case 'BooleanTypeAnnotation':
192
+ return `args.getBoolean(${index})`;
193
+ case 'DoubleTypeAnnotation':
194
+ return `args.getDouble(${index})`;
195
+ case 'FloatTypeAnnotation':
196
+ return `(float) args.getDouble(${index})`;
197
+ case 'Int32TypeAnnotation':
198
+ return `args.getInt(${index})`;
199
+ case 'StringTypeAnnotation':
200
+ return `args.getString(${index})`;
201
+ default:
202
+ (typeAnnotation.type: empty);
203
+ throw new Error(`Receieved invalid type: ${typeAnnotation.type}`);
204
+ }
205
+ }
206
+
207
+ function getCommandArguments(
208
+ command: NamedShape<CommandTypeAnnotation>,
209
+ ): string {
210
+ return [
211
+ 'view',
212
+ ...command.typeAnnotation.params.map(getCommandArgJavaType),
213
+ ].join(', ');
214
+ }
215
+
216
+ function generateCommandCasesString(
217
+ component: ComponentShape,
218
+ componentName: string,
219
+ ) {
220
+ if (component.commands.length === 0) {
221
+ return null;
222
+ }
223
+
224
+ const commandMethods = component.commands
225
+ .map(command => {
226
+ return `case "${command.name}":
227
+ mViewManager.${toSafeJavaString(
228
+ command.name,
229
+ false,
230
+ )}(${getCommandArguments(command)});
231
+ break;`;
232
+ })
233
+ .join('\n' + ' ');
234
+
235
+ return commandMethods;
236
+ }
237
+
238
+ function getClassExtendString(component: ComponentShape): string {
239
+ const extendString = component.extendsProps
240
+ .map(extendProps => {
241
+ switch (extendProps.type) {
242
+ case 'ReactNativeBuiltInType':
243
+ switch (extendProps.knownTypeName) {
244
+ case 'ReactNativeCoreViewProps':
245
+ return 'View';
246
+ default:
247
+ (extendProps.knownTypeName: empty);
248
+ throw new Error('Invalid knownTypeName');
249
+ }
250
+ default:
251
+ (extendProps.type: empty);
252
+ throw new Error('Invalid extended type');
253
+ }
254
+ })
255
+ .join('');
256
+
257
+ return extendString;
258
+ }
259
+
260
+ function getDelegateImports(component: ComponentShape) {
261
+ const imports = getImports(component, 'delegate');
262
+ // The delegate needs ReadableArray for commands always.
263
+ // The interface doesn't always need it
264
+ if (component.commands.length > 0) {
265
+ imports.add('import com.facebook.react.bridge.ReadableArray;');
266
+ }
267
+ imports.add('import androidx.annotation.Nullable;');
268
+ imports.add('import com.facebook.react.uimanager.BaseViewManagerDelegate;');
269
+ imports.add('import com.facebook.react.uimanager.BaseViewManagerInterface;');
270
+
271
+ return imports;
272
+ }
273
+
274
+ function generateMethods(
275
+ propsString: string,
276
+ commandsString: null | string,
277
+ ): string {
278
+ return [
279
+ PropSetterTemplate({propCases: propsString}),
280
+ commandsString != null
281
+ ? CommandsTemplate({commandCases: commandsString})
282
+ : '',
283
+ ]
284
+ .join('\n\n ')
285
+ .trimRight();
286
+ }
287
+
288
+ module.exports = {
289
+ generate(
290
+ libraryName: string,
291
+ schema: SchemaType,
292
+ packageName?: string,
293
+ assumeNonnull: boolean = false,
294
+ ): FilesOutput {
295
+ // TODO: This doesn't support custom package name yet.
296
+ const normalizedPackageName = 'com.facebook.react.viewmanagers';
297
+ const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`;
298
+
299
+ const files = new Map<string, string>();
300
+ Object.keys(schema.modules).forEach(moduleName => {
301
+ const module = schema.modules[moduleName];
302
+ if (module.type !== 'Component') {
303
+ return;
304
+ }
305
+
306
+ const {components} = module;
307
+ // No components in this module
308
+ if (components == null) {
309
+ return;
310
+ }
311
+
312
+ return Object.keys(components)
313
+ .filter(componentName => {
314
+ const component = components[componentName];
315
+ return !(
316
+ component.excludedPlatforms &&
317
+ component.excludedPlatforms.includes('android')
318
+ );
319
+ })
320
+ .forEach(componentName => {
321
+ const component = components[componentName];
322
+ const className = getDelegateJavaClassName(componentName);
323
+ const interfaceClassName = getInterfaceJavaClassName(componentName);
324
+
325
+ const imports = getDelegateImports(component);
326
+ const propsString = generatePropCasesString(component, componentName);
327
+ const commandsString = generateCommandCasesString(
328
+ component,
329
+ componentName,
330
+ );
331
+ const extendString = getClassExtendString(component);
332
+
333
+ const replacedTemplate = FileTemplate({
334
+ imports: Array.from(imports).sort().join('\n'),
335
+ packageName: normalizedPackageName,
336
+ className,
337
+ extendClasses: extendString,
338
+ methods: generateMethods(propsString, commandsString),
339
+ interfaceClassName: interfaceClassName,
340
+ });
341
+
342
+ files.set(`${outputDir}/${className}.java`, replacedTemplate);
343
+ });
344
+ });
345
+
346
+ return files;
347
+ },
348
+ };