@react-native/codegen 0.72.4 → 0.73.0

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 (28) hide show
  1. package/lib/generators/components/GenerateEventEmitterCpp.js +33 -44
  2. package/lib/generators/components/GenerateEventEmitterCpp.js.flow +35 -44
  3. package/lib/generators/components/GenerateEventEmitterH.js +0 -2
  4. package/lib/generators/components/GenerateEventEmitterH.js.flow +0 -2
  5. package/lib/generators/modules/GenerateModuleCpp.js +3 -3
  6. package/lib/generators/modules/GenerateModuleCpp.js.flow +3 -3
  7. package/lib/generators/modules/GenerateModuleJavaSpec.js +1 -2
  8. package/lib/generators/modules/GenerateModuleJavaSpec.js.flow +1 -2
  9. package/lib/parsers/flow/components/index.js +19 -57
  10. package/lib/parsers/flow/components/index.js.flow +20 -63
  11. package/lib/parsers/flow/modules/index.js +16 -26
  12. package/lib/parsers/flow/modules/index.js.flow +17 -26
  13. package/lib/parsers/flow/parser.js +16 -1
  14. package/lib/parsers/flow/parser.js.flow +13 -1
  15. package/lib/parsers/parser.js.flow +19 -0
  16. package/lib/parsers/parserMock.js +9 -0
  17. package/lib/parsers/parserMock.js.flow +12 -0
  18. package/lib/parsers/parsers-commons.js +36 -0
  19. package/lib/parsers/parsers-commons.js.flow +51 -1
  20. package/lib/parsers/parsers-primitives.js +37 -35
  21. package/lib/parsers/parsers-primitives.js.flow +41 -35
  22. package/lib/parsers/typescript/components/index.js +19 -57
  23. package/lib/parsers/typescript/components/index.js.flow +18 -63
  24. package/lib/parsers/typescript/modules/index.js +16 -26
  25. package/lib/parsers/typescript/modules/index.js.flow +17 -25
  26. package/lib/parsers/typescript/parser.js +28 -1
  27. package/lib/parsers/typescript/parser.js.flow +26 -1
  28. package/package.json +1 -1
@@ -26,9 +26,7 @@ const FileTemplate = ({events, libraryName}) => `
26
26
 
27
27
  namespace facebook {
28
28
  namespace react {
29
-
30
29
  ${events}
31
-
32
30
  } // namespace react
33
31
  } // namespace facebook
34
32
  `;
@@ -39,16 +37,16 @@ const ComponentTemplate = ({
39
37
  dispatchEventName,
40
38
  implementation,
41
39
  }) => {
42
- const capture = implementation.includes('event')
43
- ? 'event=std::move(event)'
40
+ const capture = implementation.includes('$event')
41
+ ? '$event=std::move($event)'
44
42
  : '';
45
43
  return `
46
- void ${className}EventEmitter::${eventName}(${structName} event) const {
44
+ void ${className}EventEmitter::${eventName}(${structName} $event) const {
47
45
  dispatchEvent("${dispatchEventName}", [${capture}](jsi::Runtime &runtime) {
48
46
  ${implementation}
49
47
  });
50
48
  }
51
- `.trim();
49
+ `;
52
50
  };
53
51
  const BasicComponentTemplate = ({className, eventName, dispatchEventName}) =>
54
52
  `
@@ -58,47 +56,45 @@ void ${className}EventEmitter::${eventName}() const {
58
56
  `.trim();
59
57
  function generateSetter(variableName, propertyName, propertyParts) {
60
58
  const trailingPeriod = propertyParts.length === 0 ? '' : '.';
61
- const eventChain = `event.${propertyParts.join(
59
+ const eventChain = `$event.${propertyParts.join(
62
60
  '.',
63
61
  )}${trailingPeriod}${propertyName});`;
64
62
  return `${variableName}.setProperty(runtime, "${propertyName}", ${eventChain}`;
65
63
  }
66
64
  function generateEnumSetter(variableName, propertyName, propertyParts) {
67
65
  const trailingPeriod = propertyParts.length === 0 ? '' : '.';
68
- const eventChain = `event.${propertyParts.join(
66
+ const eventChain = `$event.${propertyParts.join(
69
67
  '.',
70
68
  )}${trailingPeriod}${propertyName})`;
71
69
  return `${variableName}.setProperty(runtime, "${propertyName}", toString(${eventChain});`;
72
70
  }
71
+ function generateObjectSetter(
72
+ variableName,
73
+ propertyName,
74
+ propertyParts,
75
+ typeAnnotation,
76
+ ) {
77
+ return `
78
+ {
79
+ auto ${propertyName} = jsi::Object(runtime);
80
+ ${generateSetters(
81
+ propertyName,
82
+ typeAnnotation.properties,
83
+ propertyParts.concat([propertyName]),
84
+ )}
85
+ ${variableName}.setProperty(runtime, "${propertyName}", ${propertyName});
86
+ }
87
+ `.trim();
88
+ }
73
89
  function generateSetters(parentPropertyName, properties, propertyParts) {
74
90
  const propSetters = properties
75
91
  .map(eventProperty => {
76
92
  const typeAnnotation = eventProperty.typeAnnotation;
77
93
  switch (typeAnnotation.type) {
78
94
  case 'BooleanTypeAnnotation':
79
- return generateSetter(
80
- parentPropertyName,
81
- eventProperty.name,
82
- propertyParts,
83
- );
84
95
  case 'StringTypeAnnotation':
85
- return generateSetter(
86
- parentPropertyName,
87
- eventProperty.name,
88
- propertyParts,
89
- );
90
96
  case 'Int32TypeAnnotation':
91
- return generateSetter(
92
- parentPropertyName,
93
- eventProperty.name,
94
- propertyParts,
95
- );
96
97
  case 'DoubleTypeAnnotation':
97
- return generateSetter(
98
- parentPropertyName,
99
- eventProperty.name,
100
- propertyParts,
101
- );
102
98
  case 'FloatTypeAnnotation':
103
99
  return generateSetter(
104
100
  parentPropertyName,
@@ -112,19 +108,12 @@ function generateSetters(parentPropertyName, properties, propertyParts) {
112
108
  propertyParts,
113
109
  );
114
110
  case 'ObjectTypeAnnotation':
115
- const propertyName = eventProperty.name;
116
- return `
117
- {
118
- auto ${propertyName} = jsi::Object(runtime);
119
- ${generateSetters(
120
- propertyName,
121
- typeAnnotation.properties,
122
- propertyParts.concat([propertyName]),
123
- )}
124
-
125
- ${parentPropertyName}.setProperty(runtime, "${propertyName}", ${propertyName});
126
- }
127
- `.trim();
111
+ return generateObjectSetter(
112
+ parentPropertyName,
113
+ eventProperty.name,
114
+ propertyParts,
115
+ typeAnnotation,
116
+ );
128
117
  default:
129
118
  typeAnnotation.type;
130
119
  throw new Error('Received invalid event property type');
@@ -145,9 +134,9 @@ function generateEvent(componentName, event) {
145
134
  )}`;
146
135
  if (event.typeAnnotation.argument) {
147
136
  const implementation = `
148
- auto payload = jsi::Object(runtime);
149
- ${generateSetters('payload', event.typeAnnotation.argument.properties, [])}
150
- return payload;
137
+ auto $payload = jsi::Object(runtime);
138
+ ${generateSetters('$payload', event.typeAnnotation.argument.properties, [])}
139
+ return $payload;
151
140
  `.trim();
152
141
  if (!event.name.startsWith('on')) {
153
142
  throw new Error('Expected the event name to start with `on`');
@@ -18,6 +18,7 @@ import type {
18
18
  NamedShape,
19
19
  EventTypeAnnotation,
20
20
  SchemaType,
21
+ ObjectTypeAnnotation,
21
22
  } from '../../CodegenSchema';
22
23
 
23
24
  // File path -> contents
@@ -48,9 +49,7 @@ const FileTemplate = ({
48
49
 
49
50
  namespace facebook {
50
51
  namespace react {
51
-
52
52
  ${events}
53
-
54
53
  } // namespace react
55
54
  } // namespace facebook
56
55
  `;
@@ -68,16 +67,16 @@ const ComponentTemplate = ({
68
67
  dispatchEventName: string,
69
68
  implementation: string,
70
69
  }) => {
71
- const capture = implementation.includes('event')
72
- ? 'event=std::move(event)'
70
+ const capture = implementation.includes('$event')
71
+ ? '$event=std::move($event)'
73
72
  : '';
74
73
  return `
75
- void ${className}EventEmitter::${eventName}(${structName} event) const {
74
+ void ${className}EventEmitter::${eventName}(${structName} $event) const {
76
75
  dispatchEvent("${dispatchEventName}", [${capture}](jsi::Runtime &runtime) {
77
76
  ${implementation}
78
77
  });
79
78
  }
80
- `.trim();
79
+ `;
81
80
  };
82
81
 
83
82
  const BasicComponentTemplate = ({
@@ -101,7 +100,7 @@ function generateSetter(
101
100
  propertyParts: $ReadOnlyArray<string>,
102
101
  ) {
103
102
  const trailingPeriod = propertyParts.length === 0 ? '' : '.';
104
- const eventChain = `event.${propertyParts.join(
103
+ const eventChain = `$event.${propertyParts.join(
105
104
  '.',
106
105
  )}${trailingPeriod}${propertyName});`;
107
106
 
@@ -114,13 +113,32 @@ function generateEnumSetter(
114
113
  propertyParts: $ReadOnlyArray<string>,
115
114
  ) {
116
115
  const trailingPeriod = propertyParts.length === 0 ? '' : '.';
117
- const eventChain = `event.${propertyParts.join(
116
+ const eventChain = `$event.${propertyParts.join(
118
117
  '.',
119
118
  )}${trailingPeriod}${propertyName})`;
120
119
 
121
120
  return `${variableName}.setProperty(runtime, "${propertyName}", toString(${eventChain});`;
122
121
  }
123
122
 
123
+ function generateObjectSetter(
124
+ variableName: string,
125
+ propertyName: string,
126
+ propertyParts: $ReadOnlyArray<string>,
127
+ typeAnnotation: ObjectTypeAnnotation<EventTypeAnnotation>,
128
+ ) {
129
+ return `
130
+ {
131
+ auto ${propertyName} = jsi::Object(runtime);
132
+ ${generateSetters(
133
+ propertyName,
134
+ typeAnnotation.properties,
135
+ propertyParts.concat([propertyName]),
136
+ )}
137
+ ${variableName}.setProperty(runtime, "${propertyName}", ${propertyName});
138
+ }
139
+ `.trim();
140
+ }
141
+
124
142
  function generateSetters(
125
143
  parentPropertyName: string,
126
144
  properties: $ReadOnlyArray<NamedShape<EventTypeAnnotation>>,
@@ -131,29 +149,9 @@ function generateSetters(
131
149
  const {typeAnnotation} = eventProperty;
132
150
  switch (typeAnnotation.type) {
133
151
  case 'BooleanTypeAnnotation':
134
- return generateSetter(
135
- parentPropertyName,
136
- eventProperty.name,
137
- propertyParts,
138
- );
139
152
  case 'StringTypeAnnotation':
140
- return generateSetter(
141
- parentPropertyName,
142
- eventProperty.name,
143
- propertyParts,
144
- );
145
153
  case 'Int32TypeAnnotation':
146
- return generateSetter(
147
- parentPropertyName,
148
- eventProperty.name,
149
- propertyParts,
150
- );
151
154
  case 'DoubleTypeAnnotation':
152
- return generateSetter(
153
- parentPropertyName,
154
- eventProperty.name,
155
- propertyParts,
156
- );
157
155
  case 'FloatTypeAnnotation':
158
156
  return generateSetter(
159
157
  parentPropertyName,
@@ -167,19 +165,12 @@ function generateSetters(
167
165
  propertyParts,
168
166
  );
169
167
  case 'ObjectTypeAnnotation':
170
- const propertyName = eventProperty.name;
171
- return `
172
- {
173
- auto ${propertyName} = jsi::Object(runtime);
174
- ${generateSetters(
175
- propertyName,
176
- typeAnnotation.properties,
177
- propertyParts.concat([propertyName]),
178
- )}
179
-
180
- ${parentPropertyName}.setProperty(runtime, "${propertyName}", ${propertyName});
181
- }
182
- `.trim();
168
+ return generateObjectSetter(
169
+ parentPropertyName,
170
+ eventProperty.name,
171
+ propertyParts,
172
+ typeAnnotation,
173
+ );
183
174
  default:
184
175
  (typeAnnotation.type: empty);
185
176
  throw new Error('Received invalid event property type');
@@ -203,9 +194,9 @@ function generateEvent(componentName: string, event: EventTypeShape): string {
203
194
 
204
195
  if (event.typeAnnotation.argument) {
205
196
  const implementation = `
206
- auto payload = jsi::Object(runtime);
207
- ${generateSetters('payload', event.typeAnnotation.argument.properties, [])}
208
- return payload;
197
+ auto $payload = jsi::Object(runtime);
198
+ ${generateSetters('$payload', event.typeAnnotation.argument.properties, [])}
199
+ return $payload;
209
200
  `.trim();
210
201
 
211
202
  if (!event.name.startsWith('on')) {
@@ -33,9 +33,7 @@ const FileTemplate = ({componentEmitters}) => `
33
33
 
34
34
  namespace facebook {
35
35
  namespace react {
36
-
37
36
  ${componentEmitters}
38
-
39
37
  } // namespace react
40
38
  } // namespace facebook
41
39
  `;
@@ -51,9 +51,7 @@ const FileTemplate = ({componentEmitters}: {componentEmitters: string}) => `
51
51
 
52
52
  namespace facebook {
53
53
  namespace react {
54
-
55
54
  ${componentEmitters}
56
-
57
55
  } // namespace react
58
56
  } // namespace facebook
59
57
  `;
@@ -91,8 +91,8 @@ const HostFunctionTemplate = ({
91
91
  }) => {
92
92
  const isNullable = returnTypeAnnotation.type === 'NullableTypeAnnotation';
93
93
  const isVoid = returnTypeAnnotation.type === 'VoidTypeAnnotation';
94
- const methodCallArgs = ['rt', ...args].join(', ');
95
- const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs})`;
94
+ const methodCallArgs = [' rt', ...args].join(',\n ');
95
+ const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(\n${methodCallArgs}\n )`;
96
96
  return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${
97
97
  isVoid
98
98
  ? `\n ${methodCall};`
@@ -168,7 +168,7 @@ function serializeArg(moduleName, arg, index, resolveAlias, enumMap) {
168
168
  } else {
169
169
  let condition = `${val}.isNull() || ${val}.isUndefined()`;
170
170
  if (optional) {
171
- condition = `count < ${index} || ${condition}`;
171
+ condition = `count <= ${index} || ${condition}`;
172
172
  }
173
173
  return `${condition} ? std::nullopt : std::make_optional(${expression})`;
174
174
  }
@@ -40,8 +40,8 @@ const HostFunctionTemplate = ({
40
40
  }>) => {
41
41
  const isNullable = returnTypeAnnotation.type === 'NullableTypeAnnotation';
42
42
  const isVoid = returnTypeAnnotation.type === 'VoidTypeAnnotation';
43
- const methodCallArgs = ['rt', ...args].join(', ');
44
- const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs})`;
43
+ const methodCallArgs = [' rt', ...args].join(',\n ');
44
+ const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(\n${methodCallArgs}\n )`;
45
45
 
46
46
  return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${
47
47
  isVoid
@@ -139,7 +139,7 @@ function serializeArg(
139
139
  } else {
140
140
  let condition = `${val}.isNull() || ${val}.isUndefined()`;
141
141
  if (optional) {
142
- condition = `count < ${index} || ${condition}`;
142
+ condition = `count <= ${index} || ${condition}`;
143
143
  }
144
144
  return `${condition} ? std::nullopt : std::make_optional(${expression})`;
145
145
  }
@@ -105,7 +105,7 @@ package ${packageName};
105
105
 
106
106
  ${imports}
107
107
 
108
- public abstract class ${className} extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule {
108
+ public abstract class ${className} extends ReactContextBaseJavaModule implements TurboModule {
109
109
  public static final String NAME = "${jsName}";
110
110
 
111
111
  public ${className}(ReactApplicationContext reactContext) {
@@ -488,7 +488,6 @@ module.exports = {
488
488
  'com.facebook.react.bridge.ReactApplicationContext',
489
489
  'com.facebook.react.bridge.ReactContextBaseJavaModule',
490
490
  'com.facebook.react.bridge.ReactMethod',
491
- 'com.facebook.react.bridge.ReactModuleWithSpec',
492
491
  'com.facebook.react.turbomodule.core.interfaces.TurboModule',
493
492
  'com.facebook.proguard.annotations.DoNotStrip',
494
493
  'javax.annotation.Nonnull',
@@ -52,7 +52,7 @@ package ${packageName};
52
52
 
53
53
  ${imports}
54
54
 
55
- public abstract class ${className} extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule {
55
+ public abstract class ${className} extends ReactContextBaseJavaModule implements TurboModule {
56
56
  public static final String NAME = "${jsName}";
57
57
 
58
58
  public ${className}(ReactApplicationContext reactContext) {
@@ -463,7 +463,6 @@ module.exports = {
463
463
  'com.facebook.react.bridge.ReactApplicationContext',
464
464
  'com.facebook.react.bridge.ReactContextBaseJavaModule',
465
465
  'com.facebook.react.bridge.ReactMethod',
466
- 'com.facebook.react.bridge.ReactModuleWithSpec',
467
466
  'com.facebook.react.turbomodule.core.interfaces.TurboModule',
468
467
  'com.facebook.proguard.annotations.DoNotStrip',
469
468
  'javax.annotation.Nonnull',
@@ -27,8 +27,11 @@ const _require6 = require('../../error-utils'),
27
27
  const _require7 = require('../../parsers-commons'),
28
28
  createComponentConfig = _require7.createComponentConfig,
29
29
  findNativeComponentType = _require7.findNativeComponentType,
30
+ propertyNames = _require7.propertyNames,
30
31
  getCommandOptions = _require7.getCommandOptions,
31
- getOptions = _require7.getOptions;
32
+ getOptions = _require7.getOptions,
33
+ getCommandTypeNameAndOptionsExpression =
34
+ _require7.getCommandTypeNameAndOptionsExpression;
32
35
 
33
36
  // $FlowFixMe[signature-verification-failure] there's no flowtype for AST
34
37
  function findComponentConfig(ast, parser) {
@@ -50,67 +53,33 @@ function findComponentConfig(ast, parser) {
50
53
  node => node.type === 'ExportNamedDeclaration',
51
54
  );
52
55
  const commandsTypeNames = namedExports
53
- .map(statement => {
54
- let callExpression;
55
- let calleeName;
56
- try {
57
- callExpression = statement.declaration.declarations[0].init;
58
- calleeName = callExpression.callee.name;
59
- } catch (e) {
60
- return;
61
- }
62
- if (calleeName !== 'codegenNativeCommands') {
63
- return;
64
- }
65
-
66
- // const statement.declaration.declarations[0].init
67
- if (callExpression.arguments.length !== 1) {
68
- throw new Error(
69
- 'codegenNativeCommands must be passed options including the supported commands',
70
- );
71
- }
72
- const typeArgumentParam = callExpression.typeArguments.params[0];
73
- if (typeArgumentParam.type !== 'GenericTypeAnnotation') {
74
- throw new Error(
75
- "codegenNativeCommands doesn't support inline definitions. Specify a file local type alias",
76
- );
77
- }
78
- return {
79
- commandTypeName: typeArgumentParam.id.name,
80
- commandOptionsExpression: callExpression.arguments[0],
81
- };
82
- })
56
+ .map(statement => getCommandTypeNameAndOptionsExpression(statement, parser))
83
57
  .filter(Boolean);
84
58
  throwIfMoreThanOneCodegenNativecommands(commandsTypeNames);
85
59
  return createComponentConfig(foundConfig, commandsTypeNames);
86
60
  }
87
- function getCommandProperties(
88
- /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
89
- * LTI update could not be added via codemod */
90
- commandTypeName,
91
- types,
92
- commandOptions,
93
- ) {
61
+ function getCommandProperties(ast, parser) {
62
+ const _findComponentConfig = findComponentConfig(ast, parser),
63
+ commandTypeName = _findComponentConfig.commandTypeName,
64
+ commandOptionsExpression = _findComponentConfig.commandOptionsExpression;
94
65
  if (commandTypeName == null) {
95
66
  return [];
96
67
  }
68
+ const types = parser.getTypes(ast);
97
69
  const typeAlias = types[commandTypeName];
98
70
  if (typeAlias.type !== 'InterfaceDeclaration') {
99
71
  throw new Error(
100
72
  `The type argument for codegenNativeCommands must be an interface, received ${typeAlias.type}`,
101
73
  );
102
74
  }
103
- let properties;
104
- try {
105
- properties = typeAlias.body.properties;
106
- } catch (e) {
75
+ const properties = parser.bodyProperties(typeAlias);
76
+ if (!properties) {
107
77
  throw new Error(
108
78
  `Failed to find type definition for "${commandTypeName}", please check that you have a valid codegen flow file`,
109
79
  );
110
80
  }
111
- const flowPropertyNames = properties
112
- .map(property => property && property.key && property.key.name)
113
- .filter(Boolean);
81
+ const flowPropertyNames = propertyNames(properties);
82
+ const commandOptions = getCommandOptions(commandOptionsExpression);
114
83
  if (commandOptions == null || commandOptions.supportedCommands == null) {
115
84
  throw new Error(
116
85
  'codegenNativeCommands must be given an options object with supportedCommands array',
@@ -133,20 +102,13 @@ function getCommandProperties(
133
102
 
134
103
  // $FlowFixMe[signature-verification-failure] there's no flowtype for AST
135
104
  function buildComponentSchema(ast, parser) {
136
- const _findComponentConfig = findComponentConfig(ast, parser),
137
- componentName = _findComponentConfig.componentName,
138
- propsTypeName = _findComponentConfig.propsTypeName,
139
- commandTypeName = _findComponentConfig.commandTypeName,
140
- commandOptionsExpression = _findComponentConfig.commandOptionsExpression,
141
- optionsExpression = _findComponentConfig.optionsExpression;
105
+ const _findComponentConfig2 = findComponentConfig(ast, parser),
106
+ componentName = _findComponentConfig2.componentName,
107
+ propsTypeName = _findComponentConfig2.propsTypeName,
108
+ optionsExpression = _findComponentConfig2.optionsExpression;
142
109
  const types = parser.getTypes(ast);
143
110
  const propProperties = getProperties(propsTypeName, types);
144
- const commandOptions = getCommandOptions(commandOptionsExpression);
145
- const commandProperties = getCommandProperties(
146
- commandTypeName,
147
- types,
148
- commandOptions,
149
- );
111
+ const commandProperties = getCommandProperties(ast, parser);
150
112
  const extendsProps = getExtendsProps(propProperties, types);
151
113
  const options = getOptions(optionsExpression);
152
114
  const nonExtendsProps = removeKnownExtends(propProperties, types);
@@ -10,8 +10,6 @@
10
10
 
11
11
  'use strict';
12
12
  import type {Parser} from '../../parser';
13
- import type {TypeDeclarationMap} from '../../utils';
14
- import type {CommandOptions} from '../../parsers-commons';
15
13
  import type {ComponentSchemaBuilderConfig} from '../../schema.js';
16
14
 
17
15
  const {getCommands} = require('./commands');
@@ -23,8 +21,10 @@ const {throwIfMoreThanOneCodegenNativecommands} = require('../../error-utils');
23
21
  const {
24
22
  createComponentConfig,
25
23
  findNativeComponentType,
24
+ propertyNames,
26
25
  getCommandOptions,
27
26
  getOptions,
27
+ getCommandTypeNameAndOptionsExpression,
28
28
  } = require('../../parsers-commons');
29
29
 
30
30
  // $FlowFixMe[signature-verification-failure] there's no flowtype for AST
@@ -53,40 +53,7 @@ function findComponentConfig(ast: $FlowFixMe, parser: Parser) {
53
53
  );
54
54
 
55
55
  const commandsTypeNames = namedExports
56
- .map(statement => {
57
- let callExpression;
58
- let calleeName;
59
- try {
60
- callExpression = statement.declaration.declarations[0].init;
61
- calleeName = callExpression.callee.name;
62
- } catch (e) {
63
- return;
64
- }
65
-
66
- if (calleeName !== 'codegenNativeCommands') {
67
- return;
68
- }
69
-
70
- // const statement.declaration.declarations[0].init
71
- if (callExpression.arguments.length !== 1) {
72
- throw new Error(
73
- 'codegenNativeCommands must be passed options including the supported commands',
74
- );
75
- }
76
-
77
- const typeArgumentParam = callExpression.typeArguments.params[0];
78
-
79
- if (typeArgumentParam.type !== 'GenericTypeAnnotation') {
80
- throw new Error(
81
- "codegenNativeCommands doesn't support inline definitions. Specify a file local type alias",
82
- );
83
- }
84
-
85
- return {
86
- commandTypeName: typeArgumentParam.id.name,
87
- commandOptionsExpression: callExpression.arguments[0],
88
- };
89
- })
56
+ .map(statement => getCommandTypeNameAndOptionsExpression(statement, parser))
90
57
  .filter(Boolean);
91
58
 
92
59
  throwIfMoreThanOneCodegenNativecommands(commandsTypeNames);
@@ -94,16 +61,16 @@ function findComponentConfig(ast: $FlowFixMe, parser: Parser) {
94
61
  return createComponentConfig(foundConfig, commandsTypeNames);
95
62
  }
96
63
 
97
- function getCommandProperties(
98
- /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
99
- * LTI update could not be added via codemod */
100
- commandTypeName,
101
- types: TypeDeclarationMap,
102
- commandOptions: ?CommandOptions,
103
- ) {
64
+ function getCommandProperties(ast: $FlowFixMe, parser: Parser) {
65
+ const {commandTypeName, commandOptionsExpression} = findComponentConfig(
66
+ ast,
67
+ parser,
68
+ );
69
+
104
70
  if (commandTypeName == null) {
105
71
  return [];
106
72
  }
73
+ const types = parser.getTypes(ast);
107
74
 
108
75
  const typeAlias = types[commandTypeName];
109
76
 
@@ -113,18 +80,16 @@ function getCommandProperties(
113
80
  );
114
81
  }
115
82
 
116
- let properties;
117
- try {
118
- properties = typeAlias.body.properties;
119
- } catch (e) {
83
+ const properties = parser.bodyProperties(typeAlias);
84
+ if (!properties) {
120
85
  throw new Error(
121
86
  `Failed to find type definition for "${commandTypeName}", please check that you have a valid codegen flow file`,
122
87
  );
123
88
  }
124
89
 
125
- const flowPropertyNames = properties
126
- .map(property => property && property.key && property.key.name)
127
- .filter(Boolean);
90
+ const flowPropertyNames = propertyNames(properties);
91
+
92
+ const commandOptions = getCommandOptions(commandOptionsExpression);
128
93
 
129
94
  if (commandOptions == null || commandOptions.supportedCommands == null) {
130
95
  throw new Error(
@@ -153,24 +118,16 @@ function buildComponentSchema(
153
118
  ast: $FlowFixMe,
154
119
  parser: Parser,
155
120
  ): ComponentSchemaBuilderConfig {
156
- const {
157
- componentName,
158
- propsTypeName,
159
- commandTypeName,
160
- commandOptionsExpression,
161
- optionsExpression,
162
- } = findComponentConfig(ast, parser);
121
+ const {componentName, propsTypeName, optionsExpression} = findComponentConfig(
122
+ ast,
123
+ parser,
124
+ );
163
125
 
164
126
  const types = parser.getTypes(ast);
165
127
 
166
128
  const propProperties = getProperties(propsTypeName, types);
167
- const commandOptions = getCommandOptions(commandOptionsExpression);
168
129
 
169
- const commandProperties = getCommandProperties(
170
- commandTypeName,
171
- types,
172
- commandOptions,
173
- );
130
+ const commandProperties = getCommandProperties(ast, parser);
174
131
 
175
132
  const extendsProps = getExtendsProps(propProperties, types);
176
133
  const options = getOptions(optionsExpression);