@react-native-windows/codegen 0.0.0-canary.13 → 0.0.0-canary.131

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 (61) hide show
  1. package/CHANGELOG.md +1135 -16
  2. package/README.md +1 -1
  3. package/bin.js +0 -0
  4. package/lib-commonjs/Cli.d.ts +7 -0
  5. package/lib-commonjs/Cli.js +103 -0
  6. package/lib-commonjs/Cli.js.map +1 -0
  7. package/lib-commonjs/generators/AliasGen.d.ts +12 -0
  8. package/lib-commonjs/generators/AliasGen.js +115 -0
  9. package/lib-commonjs/generators/AliasGen.js.map +1 -0
  10. package/lib-commonjs/generators/AliasManaging.d.ts +15 -0
  11. package/lib-commonjs/generators/AliasManaging.js +49 -0
  12. package/lib-commonjs/generators/AliasManaging.js.map +1 -0
  13. package/lib-commonjs/generators/GenerateComponentWindows.d.ts +13 -0
  14. package/lib-commonjs/generators/GenerateComponentWindows.js +468 -0
  15. package/lib-commonjs/generators/GenerateComponentWindows.js.map +1 -0
  16. package/lib-commonjs/generators/GenerateNM2.d.ts +15 -0
  17. package/lib-commonjs/generators/GenerateNM2.js +145 -0
  18. package/lib-commonjs/generators/GenerateNM2.js.map +1 -0
  19. package/lib-commonjs/generators/GenerateTypeScript.d.ts +11 -0
  20. package/lib-commonjs/generators/GenerateTypeScript.js +165 -0
  21. package/lib-commonjs/generators/GenerateTypeScript.js.map +1 -0
  22. package/lib-commonjs/generators/ObjectTypes.d.ts +13 -0
  23. package/lib-commonjs/generators/ObjectTypes.js +81 -0
  24. package/lib-commonjs/generators/ObjectTypes.js.map +1 -0
  25. package/lib-commonjs/generators/ParamTypes.d.ts +13 -0
  26. package/lib-commonjs/generators/ParamTypes.js +183 -0
  27. package/lib-commonjs/generators/ParamTypes.js.map +1 -0
  28. package/lib-commonjs/generators/PropObjectTypes.d.ts +18 -0
  29. package/lib-commonjs/generators/PropObjectTypes.js +208 -0
  30. package/lib-commonjs/generators/PropObjectTypes.js.map +1 -0
  31. package/lib-commonjs/generators/ReturnTypes.d.ts +10 -0
  32. package/lib-commonjs/generators/ReturnTypes.js +29 -0
  33. package/lib-commonjs/generators/ReturnTypes.js.map +1 -0
  34. package/lib-commonjs/generators/ValidateConstants.d.ts +8 -0
  35. package/lib-commonjs/generators/ValidateConstants.js +38 -0
  36. package/lib-commonjs/generators/ValidateConstants.js.map +1 -0
  37. package/lib-commonjs/generators/ValidateMethods.d.ts +14 -0
  38. package/lib-commonjs/generators/ValidateMethods.js +112 -0
  39. package/lib-commonjs/generators/ValidateMethods.js.map +1 -0
  40. package/lib-commonjs/index.d.ts +39 -0
  41. package/lib-commonjs/index.js +227 -0
  42. package/lib-commonjs/index.js.map +1 -0
  43. package/package.json +39 -21
  44. package/src/Cli.ts +69 -232
  45. package/src/generators/AliasGen.ts +195 -0
  46. package/src/generators/AliasManaging.ts +75 -0
  47. package/src/generators/GenerateComponentWindows.ts +616 -0
  48. package/src/generators/GenerateNM2.ts +128 -131
  49. package/src/generators/GenerateTypeScript.ts +250 -0
  50. package/src/generators/ObjectTypes.ts +95 -37
  51. package/src/generators/ParamTypes.ts +309 -53
  52. package/src/generators/PropObjectTypes.ts +223 -0
  53. package/src/generators/ReturnTypes.ts +38 -40
  54. package/src/generators/ValidateConstants.ts +50 -0
  55. package/src/generators/ValidateMethods.ts +270 -0
  56. package/src/index.ts +412 -0
  57. package/.eslintrc.js +0 -4
  58. package/.vscode/launch.json +0 -23
  59. package/CHANGELOG.json +0 -726
  60. package/jest.config.js +0 -1
  61. package/tsconfig.json +0 -5
@@ -0,0 +1,223 @@
1
+ import type { PropTypeAnnotation, ObjectTypeAnnotation, EventTypeAnnotation, CommandParamTypeAnnotation } from '@react-native/codegen/lib/CodegenSchema';
2
+ import type { CppCodegenOptions } from './ObjectTypes';
3
+ import {
4
+ AliasMap,
5
+ getAnonymousAliasCppName,
6
+ } from './AliasManaging';
7
+
8
+
9
+ // eslint-disable-next-line complexity
10
+ export function translateComponentPropsFieldType(type: PropTypeAnnotation,
11
+ aliases: AliasMap<ObjectTypeAnnotation<PropTypeAnnotation>>,
12
+ baseAliasName: string,
13
+ options: CppCodegenOptions): { type: string, initializer: string, alreadySupportsOptionalOrHasDefault?: boolean } {
14
+ switch (type.type) {
15
+ case 'StringTypeAnnotation':
16
+ return { type: options.cppStringType, initializer: type.default ? `{${type.default}}` : '', alreadySupportsOptionalOrHasDefault: !!type.default };
17
+ case 'FloatTypeAnnotation':
18
+ return { type: 'float', initializer: type.default ? `{${type.default}}` : '{}', alreadySupportsOptionalOrHasDefault: !!type.default };
19
+ case 'DoubleTypeAnnotation':
20
+ return { type: 'double', initializer: type.default ? `{${type.default}}` : '{}', alreadySupportsOptionalOrHasDefault: !!type.default };
21
+ case 'Int32TypeAnnotation':
22
+ return { type: 'int32_t', initializer: type.default ? `{${type.default}}` : '{}', alreadySupportsOptionalOrHasDefault: !!type.default };
23
+ case 'BooleanTypeAnnotation':
24
+ return { type: 'bool', initializer: type.default ? `{${type.default}}` : '{}', alreadySupportsOptionalOrHasDefault: !!type.default };
25
+ case 'ArrayTypeAnnotation':
26
+ let arrayTemplateArg = '';
27
+ switch (type.elementType.type) {
28
+ case 'BooleanTypeAnnotation':
29
+ arrayTemplateArg = 'bool';
30
+ break;
31
+ case 'DoubleTypeAnnotation':
32
+ arrayTemplateArg = 'double';
33
+ break;
34
+ case 'FloatTypeAnnotation':
35
+ arrayTemplateArg = 'float';
36
+ break;
37
+ case 'Int32TypeAnnotation':
38
+ arrayTemplateArg = 'int32_t';
39
+ break;
40
+ case 'StringTypeAnnotation':
41
+ arrayTemplateArg = options.cppStringType;
42
+ break;
43
+ case 'ArrayTypeAnnotation':
44
+ const innerType = translateComponentPropsFieldType(type.elementType, aliases, baseAliasName, options);
45
+ arrayTemplateArg = `std::vector<${innerType.type}>`;
46
+ break;
47
+ case 'ObjectTypeAnnotation':
48
+ arrayTemplateArg = translateComponentPropsFieldType(type.elementType, aliases, baseAliasName, options).type;
49
+ break;
50
+ case 'ReservedPropTypeAnnotation':
51
+ switch (type.elementType.name) {
52
+ case 'ColorPrimitive':
53
+ arrayTemplateArg = 'winrt::Microsoft::ReactNative::Color';
54
+ break;
55
+ case 'DimensionPrimitive':
56
+ case 'EdgeInsetsPrimitive':
57
+ case 'ImageRequestPrimitive':
58
+ case 'ImageSourcePrimitive':
59
+ case 'PointPrimitive':
60
+ arrayTemplateArg = 'winrt::Microsoft::ReactNative::JSValue'; // TODO - better handling for these types than JSValue
61
+ break;
62
+ default:
63
+ throw new Error(`Unhandled ReservedPropTypeAnnotation type: ${type.elementType.name}`);
64
+ }
65
+ break;
66
+ case 'StringEnumTypeAnnotation':
67
+ arrayTemplateArg = options.cppStringType; // TODO - better enum type handling than just passing a string
68
+ break;
69
+ default:
70
+ throw new Error(`Unhandled type: ${type.type}`);
71
+ }
72
+
73
+ return { type: `std::vector<${arrayTemplateArg}>`, initializer: '' };
74
+ case 'ReservedPropTypeAnnotation':
75
+ switch (type.name) {
76
+ case 'ColorPrimitive':
77
+ return { type: 'winrt::Microsoft::ReactNative::Color', initializer: '{nullptr}', alreadySupportsOptionalOrHasDefault: true };
78
+ case 'DimensionPrimitive':
79
+ case 'EdgeInsetsPrimitive':
80
+ case 'ImageRequestPrimitive':
81
+ case 'ImageSourcePrimitive':
82
+ case 'PointPrimitive':
83
+ return { type: 'winrt::Microsoft::ReactNative::JSValue', initializer: '{nullptr}', alreadySupportsOptionalOrHasDefault: true }; // TODO - better handling for these types than JSValue
84
+ default:
85
+ throw new Error(`Unhandled ReservedPropTypeAnnotation type: ${type.name}`);
86
+ }
87
+ case 'ObjectTypeAnnotation': {
88
+ return { type: getAnonymousAliasCppName<ObjectTypeAnnotation<PropTypeAnnotation>>(aliases, baseAliasName, type), initializer: '' };
89
+ }
90
+ case 'MixedTypeAnnotation':
91
+ return { type: 'winrt::Microsoft::ReactNative::JSValue', initializer: '{nullptr}', alreadySupportsOptionalOrHasDefault: true };
92
+ case 'Int32EnumTypeAnnotation':
93
+ return { type: 'int32_t', initializer: '' }; // TODO - better enum type handling than just passing a string
94
+ case 'StringEnumTypeAnnotation':
95
+ return { type: options.cppStringType, initializer: '' }; // TODO - better enum type handling than just passing an int
96
+ default:
97
+ throw new Error(`Unhandled type: ${(type as any).type}`);
98
+ }
99
+ }
100
+
101
+ export function translateComponentEventType(type: EventTypeAnnotation,
102
+ aliases: AliasMap<ObjectTypeAnnotation<EventTypeAnnotation>>,
103
+ baseAliasName: string,
104
+ options: CppCodegenOptions): { type: string, initializer: string, alreadySupportsOptionalOrHasDefault?: boolean } {
105
+ switch (type.type) {
106
+ case 'StringTypeAnnotation':
107
+ return { type: options.cppStringType, initializer: '' };
108
+ case 'FloatTypeAnnotation':
109
+ return { type: 'float', initializer: '{}' };
110
+ case 'DoubleTypeAnnotation':
111
+ return { type: 'double', initializer: '{}' };
112
+ case 'Int32TypeAnnotation':
113
+ return { type: 'int32_t', initializer: '{}' };
114
+ case 'BooleanTypeAnnotation':
115
+ return { type: 'bool', initializer: '{}' };
116
+ case 'ArrayTypeAnnotation':
117
+ {
118
+ let arrayTemplateArg = '';
119
+ switch (type.elementType.type) {
120
+ case 'BooleanTypeAnnotation':
121
+ arrayTemplateArg = 'bool';
122
+ break;
123
+ case 'DoubleTypeAnnotation':
124
+ arrayTemplateArg = 'double';
125
+ break;
126
+ case 'FloatTypeAnnotation':
127
+ arrayTemplateArg = 'float';
128
+ break;
129
+ case 'Int32TypeAnnotation':
130
+ arrayTemplateArg = 'int32_t';
131
+ break;
132
+ case 'StringTypeAnnotation':
133
+ arrayTemplateArg = options.cppStringType;
134
+ break;
135
+ case 'ArrayTypeAnnotation':
136
+ const innerType = translateComponentEventType(type.elementType, aliases, baseAliasName, options);
137
+ arrayTemplateArg = `std::vector<${innerType.type}>`;
138
+ break;
139
+ case 'MixedTypeAnnotation':
140
+ arrayTemplateArg = 'winrt::Microsoft::ReactNative::JSValue';
141
+ break;
142
+ case 'ObjectTypeAnnotation':
143
+ arrayTemplateArg = translateComponentEventType(type.elementType, aliases, baseAliasName, options).type;
144
+ break;
145
+ case 'StringLiteralUnionTypeAnnotation':
146
+ arrayTemplateArg = options.cppStringType; // TODO - better enum type handling than just passing a string
147
+ break;
148
+ default:
149
+ throw new Error(`Unhandled type: ${type.type}`);
150
+ }
151
+
152
+ return { type: `std::vector<${arrayTemplateArg}>`, initializer: '{}' };
153
+ }
154
+ case 'ObjectTypeAnnotation': {
155
+ return { type: getAnonymousAliasCppName<ObjectTypeAnnotation<EventTypeAnnotation>>(aliases, baseAliasName, type), initializer: '' };
156
+ }
157
+ case 'MixedTypeAnnotation': {
158
+ return { type: 'winrt::Microsoft::ReactNative::JSValue', initializer: '{nullptr}', alreadySupportsOptionalOrHasDefault: true };
159
+ }
160
+ case 'StringLiteralUnionTypeAnnotation':
161
+ return { type: options.cppStringType, initializer: '' }; // TODO - better enum type handling than just passing a string
162
+ default:
163
+ throw new Error(`Unhandled type: ${(type as any).type}`);
164
+ }
165
+ }
166
+
167
+
168
+ export function translateCommandParamType(type: CommandParamTypeAnnotation,
169
+ aliases: AliasMap<ObjectTypeAnnotation<CommandParamTypeAnnotation>>,
170
+ baseAliasName: string,
171
+ options: CppCodegenOptions): { type: string, initializer: string, alreadySupportsOptionalOrHasDefault?: boolean } {
172
+ switch (type.type) {
173
+ case 'StringTypeAnnotation':
174
+ return { type: options.cppStringType, initializer: '' };
175
+ case 'FloatTypeAnnotation':
176
+ return { type: 'float', initializer: '{}' };
177
+ case 'DoubleTypeAnnotation':
178
+ return { type: 'double', initializer: '{}' };
179
+ case 'Int32TypeAnnotation':
180
+ return { type: 'int32_t', initializer: '{}' };
181
+ case 'BooleanTypeAnnotation':
182
+ return { type: 'bool', initializer: '{}' };
183
+ case 'ArrayTypeAnnotation':
184
+ {
185
+ let arrayTemplateArg = '';
186
+ switch (type.elementType.type) {
187
+ case 'BooleanTypeAnnotation':
188
+ arrayTemplateArg = 'bool';
189
+ break;
190
+ case 'DoubleTypeAnnotation':
191
+ arrayTemplateArg = 'double';
192
+ break;
193
+ case 'FloatTypeAnnotation':
194
+ arrayTemplateArg = 'float';
195
+ break;
196
+ case 'Int32TypeAnnotation':
197
+ arrayTemplateArg = 'int32_t';
198
+ break;
199
+ case 'StringTypeAnnotation':
200
+ arrayTemplateArg = options.cppStringType;
201
+ break;
202
+ case 'MixedTypeAnnotation':
203
+ // TODO - not sure what exact value to be used here
204
+ arrayTemplateArg = 'winrt::Microsoft::ReactNative::JSValue';
205
+ break;
206
+ case 'GenericTypeAnnotation' as any: // TODO verify schema - Getting this type when running codegen on all the built in types
207
+ arrayTemplateArg = 'winrt::Microsoft::ReactNative::JSValue';
208
+ break;
209
+ default:
210
+ throw new Error(`Unhandled type: ${(type.elementType as any).type} - ${JSON.stringify(type.elementType, null, 2)}`);
211
+ }
212
+
213
+ return { type: `std::vector<${arrayTemplateArg}>`, initializer: '{}' };
214
+ }
215
+ case 'ReservedTypeAnnotation':
216
+ if ((type.name as any) !== 'RootTag') {
217
+ throw new Error(`Unhandled ReservedTypeAnnotation: ${type.name}`)
218
+ }
219
+ return { type: 'bool', initializer: '{-1}' };
220
+ default:
221
+ throw new Error(`Unhandled type: ${(type as any).type}`);
222
+ }
223
+ }
@@ -6,67 +6,65 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {
9
+ import type {
10
10
  NativeModuleReturnTypeAnnotation,
11
11
  Nullable,
12
- } from 'react-native-tscodegen';
13
- import {getAliasCppName} from './ObjectTypes';
12
+ } from '@react-native/codegen/lib/CodegenSchema';
13
+ import {AliasMap} from './AliasManaging';
14
+ import {CppCodegenOptions, translateFieldOrReturnType} from './ObjectTypes';
14
15
 
15
16
  function translateReturnType(
16
17
  type: Nullable<NativeModuleReturnTypeAnnotation>,
18
+ aliases: AliasMap,
19
+ baseAliasName: string,
20
+ options: CppCodegenOptions,
17
21
  ): string {
18
- // avoid: Property 'type' does not exist on type 'never'
19
- const returnType = type.type;
20
22
  switch (type.type) {
21
23
  case 'VoidTypeAnnotation':
22
24
  case 'PromiseTypeAnnotation':
23
25
  return 'void';
24
- case 'StringTypeAnnotation':
25
- return 'std::string';
26
- case 'NumberTypeAnnotation':
27
- case 'FloatTypeAnnotation':
28
- case 'DoubleTypeAnnotation':
29
- return 'double';
30
- case 'Int32TypeAnnotation':
31
- return 'int';
32
- case 'BooleanTypeAnnotation':
33
- return 'bool';
34
- case 'ArrayTypeAnnotation':
35
- // TODO: type.elementType
36
- return 'React::JSValueArray';
37
- case 'GenericObjectTypeAnnotation':
38
- return 'React::JSValue';
39
- case 'ObjectTypeAnnotation':
40
- // TODO: we have more information here, and could create a more specific type
41
- return 'React::JSValueObject';
42
- case 'ReservedTypeAnnotation': {
43
- // avoid: Property 'name' does not exist on type 'never'
44
- const name = type.name;
45
- // (#6597)
46
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
47
- if (name !== 'RootTag')
48
- throw new Error(
49
- `Unknown reserved function: ${name} in translateReturnType`,
50
- );
51
- return 'double';
52
- }
53
- case 'TypeAliasTypeAnnotation':
54
- return getAliasCppName(type.name);
55
26
  case 'NullableTypeAnnotation':
56
- return `std::optional<${translateReturnType(type.typeAnnotation)}>`;
27
+ return `std::optional<${translateReturnType(
28
+ type.typeAnnotation,
29
+ aliases,
30
+ baseAliasName,
31
+ options,
32
+ )}>`;
57
33
  default:
58
- throw new Error(`Unhandled type in translateReturnType: ${returnType}`);
34
+ return translateFieldOrReturnType(
35
+ type,
36
+ aliases,
37
+ baseAliasName,
38
+ 'translateReturnType',
39
+ options,
40
+ );
59
41
  }
60
42
  }
61
43
 
62
44
  export function translateSpecReturnType(
63
45
  type: Nullable<NativeModuleReturnTypeAnnotation>,
46
+ aliases: AliasMap,
47
+ baseAliasName: string,
48
+ options: CppCodegenOptions,
64
49
  ) {
65
- return translateReturnType(type);
50
+ return translateReturnType(
51
+ type,
52
+ aliases,
53
+ `${baseAliasName}_returnType`,
54
+ options,
55
+ );
66
56
  }
67
57
 
68
58
  export function translateImplReturnType(
69
59
  type: Nullable<NativeModuleReturnTypeAnnotation>,
60
+ aliases: AliasMap,
61
+ baseAliasName: string,
62
+ options: CppCodegenOptions,
70
63
  ) {
71
- return translateReturnType(type);
64
+ return translateReturnType(
65
+ type,
66
+ aliases,
67
+ `${baseAliasName}_returnType`,
68
+ options,
69
+ );
72
70
  }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ * Licensed under the MIT License.
4
+ * @format
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ import type {NativeModuleSchema} from '@react-native/codegen/lib/CodegenSchema';
10
+ import {AliasMap, getAnonymousAliasCppName} from './AliasManaging';
11
+
12
+ export function generateValidateConstants(
13
+ nativeModule: NativeModuleSchema,
14
+ aliases: AliasMap,
15
+ ): [string, string] | undefined {
16
+ const candidates = nativeModule.spec.methods.filter(
17
+ prop => prop.name === 'getConstants',
18
+ );
19
+ if (candidates.length === 0) {
20
+ return undefined;
21
+ }
22
+
23
+ const getConstant = candidates[0];
24
+ const funcType =
25
+ getConstant.typeAnnotation.type === 'NullableTypeAnnotation'
26
+ ? getConstant.typeAnnotation.typeAnnotation
27
+ : getConstant.typeAnnotation;
28
+ if (
29
+ funcType.params.length > 0 ||
30
+ funcType.returnTypeAnnotation.type !== 'ObjectTypeAnnotation'
31
+ ) {
32
+ return undefined;
33
+ }
34
+
35
+ const constantType = funcType.returnTypeAnnotation;
36
+ if (constantType.properties.length === 0) {
37
+ return undefined;
38
+ }
39
+
40
+ const cppName = getAnonymousAliasCppName(aliases, 'Constants', constantType);
41
+
42
+ return [
43
+ ` TypedConstant<${cppName}>{0},`,
44
+ ` REACT_SHOW_CONSTANT_SPEC_ERRORS(
45
+ 0,
46
+ "${cppName}",
47
+ " REACT_GET_CONSTANTS(GetConstants) ${cppName} GetConstants() noexcept {/*implementation*/}\\n"
48
+ " REACT_GET_CONSTANTS(GetConstants) static ${cppName} GetConstants() noexcept {/*implementation*/}\\n");`,
49
+ ];
50
+ }
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ * Licensed under the MIT License.
4
+ * @format
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ import type {
10
+ NativeModuleEventEmitterShape,
11
+ NativeModuleFunctionTypeAnnotation,
12
+ NativeModulePropertyShape,
13
+ NativeModuleSchema,
14
+ } from '@react-native/codegen/lib/CodegenSchema';
15
+ import {AliasMap} from './AliasManaging';
16
+ import type {CppCodegenOptions} from './ObjectTypes';
17
+ import {
18
+ translateArgs,
19
+ translateSpecArgs,
20
+ translateEventEmitterArgs,
21
+ } from './ParamTypes';
22
+ import {translateImplReturnType, translateSpecReturnType} from './ReturnTypes';
23
+
24
+ function isMethodSync(funcType: NativeModuleFunctionTypeAnnotation) {
25
+ return (
26
+ funcType.returnTypeAnnotation.type !== 'VoidTypeAnnotation' &&
27
+ funcType.returnTypeAnnotation.type !== 'PromiseTypeAnnotation'
28
+ );
29
+ }
30
+
31
+ function getPossibleMethodSignatures(
32
+ prop: NativeModulePropertyShape,
33
+ funcType: NativeModuleFunctionTypeAnnotation,
34
+ aliases: AliasMap,
35
+ baseAliasName: string,
36
+ options: CppCodegenOptions,
37
+ ): string[] {
38
+ const args = translateArgs(funcType.params, aliases, baseAliasName, options);
39
+ if (funcType.returnTypeAnnotation.type === 'PromiseTypeAnnotation') {
40
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
41
+ if (funcType.returnTypeAnnotation.elementType) {
42
+ args.push(
43
+ `::React::ReactPromise<${translateImplReturnType(
44
+ funcType.returnTypeAnnotation.elementType,
45
+ aliases,
46
+ baseAliasName,
47
+ options,
48
+ )}> &&result`,
49
+ );
50
+ } else {
51
+ args.push('::React::ReactPromise<::React::JSValue> &&result');
52
+ }
53
+ }
54
+
55
+ // TODO: be much more exhaustive on the possible method signatures that can be used..
56
+ const sig = `REACT_${isMethodSync(funcType) ? 'SYNC_' : ''}METHOD(${
57
+ prop.name
58
+ }) ${translateImplReturnType(
59
+ funcType.returnTypeAnnotation,
60
+ aliases,
61
+ baseAliasName,
62
+ options,
63
+ )} ${prop.name}(${args.join(', ')}) noexcept { /* implementation */ }`;
64
+
65
+ const staticsig = `REACT_${isMethodSync(funcType) ? 'SYNC_' : ''}METHOD(${
66
+ prop.name
67
+ }) static ${translateImplReturnType(
68
+ funcType.returnTypeAnnotation,
69
+ aliases,
70
+ baseAliasName,
71
+ options,
72
+ )} ${prop.name}(${args.join(', ')}) noexcept { /* implementation */ }`;
73
+
74
+ return [sig, staticsig];
75
+ }
76
+
77
+ function translatePossibleMethodSignatures(
78
+ prop: NativeModulePropertyShape,
79
+ funcType: NativeModuleFunctionTypeAnnotation,
80
+ aliases: AliasMap,
81
+ baseAliasName: string,
82
+ options: CppCodegenOptions,
83
+ ): string {
84
+ return getPossibleMethodSignatures(
85
+ prop,
86
+ funcType,
87
+ aliases,
88
+ baseAliasName,
89
+ options,
90
+ )
91
+ .map(sig => `" ${sig}\\n"`)
92
+ .join('\n ');
93
+ }
94
+
95
+ function renderProperties(
96
+ methods: ReadonlyArray<NativeModulePropertyShape>,
97
+ aliases: AliasMap,
98
+ tuple: boolean,
99
+ options: CppCodegenOptions,
100
+ ): {code: string; numberOfProperties: number} {
101
+ // TODO: generate code for constants
102
+ const properties = methods
103
+ .filter(prop => prop.name !== 'getConstants')
104
+ .map((prop, index) => {
105
+ // TODO: prop.optional === true
106
+ // TODO: prop.typeAnnotation.type === 'NullableTypeAnnotation'
107
+ const propAliasName = prop.name;
108
+ const funcType =
109
+ prop.typeAnnotation.type === 'NullableTypeAnnotation'
110
+ ? prop.typeAnnotation.typeAnnotation
111
+ : prop.typeAnnotation;
112
+
113
+ const traversedArgs = translateSpecArgs(
114
+ funcType.params,
115
+ aliases,
116
+ propAliasName,
117
+ options,
118
+ );
119
+
120
+ const translatedReturnParam = translateSpecReturnType(
121
+ funcType.returnTypeAnnotation,
122
+ aliases,
123
+ propAliasName,
124
+ options,
125
+ );
126
+
127
+ if (funcType.returnTypeAnnotation.type === 'PromiseTypeAnnotation') {
128
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
129
+ if (funcType.returnTypeAnnotation.elementType) {
130
+ traversedArgs.push(
131
+ `Promise<${translateSpecReturnType(
132
+ funcType.returnTypeAnnotation.elementType,
133
+ aliases,
134
+ propAliasName,
135
+ options,
136
+ )}>`,
137
+ );
138
+ } else {
139
+ traversedArgs.push('Promise<::React::JSValue>');
140
+ }
141
+ }
142
+
143
+ if (tuple) {
144
+ return ` ${
145
+ isMethodSync(funcType) ? 'Sync' : ''
146
+ }Method<${translatedReturnParam}(${traversedArgs.join(
147
+ ', ',
148
+ )}) noexcept>{${index}, L"${prop.name}"},`;
149
+ } else {
150
+ return ` REACT_SHOW_METHOD_SPEC_ERRORS(
151
+ ${index},
152
+ "${prop.name}",
153
+ ${translatePossibleMethodSignatures(
154
+ prop,
155
+ funcType,
156
+ aliases,
157
+ propAliasName,
158
+ options,
159
+ )});`;
160
+ }
161
+ });
162
+
163
+ return {code: properties.join('\n'), numberOfProperties: properties.length};
164
+ }
165
+
166
+ function getPossibleEventEmitterSignatures(
167
+ eventEmitter: NativeModuleEventEmitterShape,
168
+ aliases: AliasMap,
169
+ options: CppCodegenOptions,
170
+ ): string[] {
171
+ const traversedArgs = translateEventEmitterArgs(
172
+ eventEmitter.typeAnnotation.typeAnnotation,
173
+ aliases,
174
+ eventEmitter.name,
175
+ options,
176
+ );
177
+ return [
178
+ `REACT_EVENT(${eventEmitter.name}) std::function<void(${traversedArgs})> ${eventEmitter.name};`,
179
+ ];
180
+ }
181
+
182
+ function translatePossibleEventSignatures(
183
+ eventEmitter: NativeModuleEventEmitterShape,
184
+ aliases: AliasMap,
185
+ options: CppCodegenOptions,
186
+ ): string {
187
+ return getPossibleEventEmitterSignatures(eventEmitter, aliases, options)
188
+ .map(sig => `" ${sig}\\n"`)
189
+ .join('\n ');
190
+ }
191
+
192
+ function renderEventEmitters(
193
+ eventEmitters: ReadonlyArray<NativeModuleEventEmitterShape>,
194
+ indexOffset: number,
195
+ aliases: AliasMap,
196
+ tuple: boolean,
197
+ options: CppCodegenOptions,
198
+ ): string {
199
+ return eventEmitters
200
+ .map((eventEmitter, index) => {
201
+ const traversedArgs = translateEventEmitterArgs(
202
+ eventEmitter.typeAnnotation.typeAnnotation,
203
+ aliases,
204
+ eventEmitter.name,
205
+ options,
206
+ );
207
+
208
+ if (tuple) {
209
+ return ` EventEmitter<void(${traversedArgs})>{${
210
+ index + indexOffset
211
+ }, L"${eventEmitter.name}"},`;
212
+ } else {
213
+ return ` REACT_SHOW_EVENTEMITTER_SPEC_ERRORS(
214
+ ${index + indexOffset},
215
+ "${eventEmitter.name}",
216
+ ${translatePossibleEventSignatures(
217
+ eventEmitter,
218
+ aliases,
219
+ options,
220
+ )});`;
221
+ }
222
+ })
223
+ .join('\n');
224
+ }
225
+
226
+ export function generateValidateMethods(
227
+ nativeModule: NativeModuleSchema,
228
+ aliases: AliasMap,
229
+ options: CppCodegenOptions,
230
+ ): {
231
+ traversedProperties: string;
232
+ traversedEventEmitters: string;
233
+ traversedPropertyTuples: string;
234
+ traversedEventEmitterTuples: string;
235
+ } {
236
+ const methods = nativeModule.spec.methods;
237
+ const eventEmitters = nativeModule.spec.eventEmitters;
238
+ const traversedProperties = renderProperties(
239
+ methods,
240
+ aliases,
241
+ false,
242
+ options,
243
+ );
244
+ const traversedEventEmitters = renderEventEmitters(
245
+ eventEmitters,
246
+ traversedProperties.numberOfProperties,
247
+ aliases,
248
+ false,
249
+ options,
250
+ );
251
+ const traversedPropertyTuples = renderProperties(
252
+ methods,
253
+ aliases,
254
+ true,
255
+ options,
256
+ );
257
+ const traversedEventEmitterTuples = renderEventEmitters(
258
+ eventEmitters,
259
+ traversedProperties.numberOfProperties,
260
+ aliases,
261
+ true,
262
+ options,
263
+ );
264
+ return {
265
+ traversedPropertyTuples: traversedPropertyTuples.code,
266
+ traversedEventEmitterTuples,
267
+ traversedProperties: traversedProperties.code,
268
+ traversedEventEmitters,
269
+ };
270
+ }