diff --git a/packages/react-native-codegen/src/CodegenSchema.js b/packages/react-native-codegen/src/CodegenSchema.js index 1708e8939b4..d286d3a79fd 100644 --- a/packages/react-native-codegen/src/CodegenSchema.js +++ b/packages/react-native-codegen/src/CodegenSchema.js @@ -213,7 +213,8 @@ export type CommandParamTypeAnnotation = | Int32TypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation - | StringTypeAnnotation; + | StringTypeAnnotation + | ArrayTypeAnnotation; export type ReservedTypeAnnotation = $ReadOnly<{ type: 'ReservedTypeAnnotation', diff --git a/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js b/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js index 0d71e25434c..3422c0c68bb 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js +++ b/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js @@ -171,6 +171,8 @@ function getObjCParamType(param: Param): string { return 'NSInteger'; case 'StringTypeAnnotation': return 'NSString *'; + case 'ArrayTypeAnnotation': + return 'const NSArray *'; default: (typeAnnotation.type: empty); throw new Error('Received invalid param type annotation'); @@ -199,6 +201,8 @@ function getObjCExpectedKindParamType(param: Param): string { return '[NSNumber class]'; case 'StringTypeAnnotation': return '[NSString class]'; + case 'ArrayTypeAnnotation': + return '[NSArray class]'; default: (typeAnnotation.type: empty); throw new Error('Received invalid param type annotation'); @@ -227,6 +231,8 @@ function getReadableExpectedKindParamType(param: Param): string { return 'number'; case 'StringTypeAnnotation': return 'string'; + case 'ArrayTypeAnnotation': + return 'array'; default: (typeAnnotation.type: empty); throw new Error('Received invalid param type annotation'); @@ -258,6 +264,8 @@ function getObjCRightHandAssignmentParamType( return `[(NSNumber *)arg${index} intValue]`; case 'StringTypeAnnotation': return `(NSString *)arg${index}`; + case 'ArrayTypeAnnotation': + return `(NSArray *)arg${index}`; default: (typeAnnotation.type: empty); throw new Error('Received invalid param type annotation'); diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js index a2eb1e8ae8e..6e485fedbf9 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js @@ -202,6 +202,8 @@ function getCommandArgJavaType( return `args.getInt(${index})`; case 'StringTypeAnnotation': return `args.getString(${index})`; + case 'ArrayTypeAnnotation': + return `args.getArray(${index})`; default: (typeAnnotation.type: empty); throw new Error(`Receieved invalid type: ${typeAnnotation.type}`); diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js index 834ed5ec511..c8afd851e42 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js @@ -171,6 +171,8 @@ function getCommandArgJavaType(param: NamedShape) { return 'int'; case 'StringTypeAnnotation': return 'String'; + case 'ArrayTypeAnnotation': + return 'ReadableArray'; default: (typeAnnotation.type: empty); throw new Error('Receieved invalid typeAnnotation'); diff --git a/packages/react-native-codegen/src/generators/components/JavaHelpers.js b/packages/react-native-codegen/src/generators/components/JavaHelpers.js index 48556d47db6..9b835bb6f91 100644 --- a/packages/react-native-codegen/src/generators/components/JavaHelpers.js +++ b/packages/react-native-codegen/src/generators/components/JavaHelpers.js @@ -127,6 +127,15 @@ function getImports( } }); + component.commands.forEach(command => { + command.typeAnnotation.params.forEach(param => { + const cmdParamType = param.typeAnnotation.type; + if (cmdParamType === 'ArrayTypeAnnotation') { + imports.add('import com.facebook.react.bridge.ReadableArray;'); + } + }); + }); + return imports; } diff --git a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js index 65f7a46d25b..3b6915f33f9 100644 --- a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js @@ -1726,6 +1726,28 @@ const COMMANDS_AND_PROPS: SchemaType = { }, }, }, + { + name: 'addItems', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + params: [ + { + name: 'items', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringTypeAnnotation', + }, + }, + }, + ], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + }, + }, ], }, }, diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap index b232a9446ff..c8b74b0aeb2 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap @@ -222,6 +222,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol RCTCommandNativeComponentViewProtocol - (void)handleRootTag:(double)rootTag; - (void)hotspotUpdate:(NSInteger)x y:(NSInteger)y; +- (void)addItems:(const NSArray *)items; @end RCT_EXTERN inline void RCTCommandNativeComponentHandleCommand( @@ -277,6 +278,26 @@ NSObject *arg1 = args[1]; return; } +if ([commandName isEqualToString:@\\"addItems\\"]) { +#if RCT_DEBUG + if ([args count] != 1) { + RCTLogError(@\\"%@ command %@ received %d arguments, expected %d.\\", @\\"CommandNativeComponent\\", commandName, (int)[args count], 1); + return; + } +#endif + + NSObject *arg0 = args[0]; +#if RCT_DEBUG + if (!RCTValidateTypeOfViewCommandArgument(arg0, [NSArray class], @\\"array\\", @\\"CommandNativeComponent\\", commandName, @\\"1st\\")) { + return; + } +#endif + const NSArray * items = (NSArray *)arg0; + + [componentView addItems:items]; + return; +} + #if RCT_DEBUG RCTLogError(@\\"%@ received command %@, which is not a supported command.\\", @\\"CommandNativeComponent\\", commandName); #endif diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap index 9bec5993102..3e4de5ef984 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap @@ -271,6 +271,9 @@ public class CommandNativeComponentManagerDelegate { void setAccessibilityHint(T view, @Nullable String value); void handleRootTag(T view, double rootTag); void hotspotUpdate(T view, int x, int y); + void addItems(T view, ReadableArray items); } ", } diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap index e88cd1abe90..f7728272a89 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -234,6 +234,10 @@ export const Commands = { hotspotUpdate(ref, x, y) { dispatchCommand(ref, \\"hotspotUpdate\\", [x, y]); + }, + + addItems(ref, items) { + dispatchCommand(ref, \\"addItems\\", [items]); } }; ", diff --git a/packages/react-native-codegen/src/parsers/flow/components/commands.js b/packages/react-native-codegen/src/parsers/flow/components/commands.js index 594f54345bd..c8ce0b157cb 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/commands.js +++ b/packages/react-native-codegen/src/parsers/flow/components/commands.js @@ -11,6 +11,7 @@ 'use strict'; import type { + CommandParamTypeAnnotation, CommandTypeAnnotation, NamedShape, } from '../../../CodegenSchema.js'; @@ -21,7 +22,24 @@ const {getValueFromTypes} = require('../utils.js'); // $FlowFixMe[unclear-type] there's no flowtype for ASTs type EventTypeAST = Object; -function buildCommandSchema(property: EventTypeAST, types: TypeDeclarationMap) { +function buildCommandSchema( + property: EventTypeAST, + types: TypeDeclarationMap, +): $ReadOnly<{ + name: string, + optional: boolean, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + params: $ReadOnlyArray<{ + name: string, + optional: boolean, + typeAnnotation: CommandParamTypeAnnotation, + }>, + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + }, +}> { const name = property.key.name; const optional = property.optional; const value = getValueFromTypes(property.value, types); @@ -48,7 +66,7 @@ function buildCommandSchema(property: EventTypeAST, types: TypeDeclarationMap) { paramValue.type === 'GenericTypeAnnotation' ? paramValue.id.name : paramValue.type; - let returnType; + let returnType: CommandParamTypeAnnotation; switch (type) { case 'RootTag': @@ -82,6 +100,30 @@ function buildCommandSchema(property: EventTypeAST, types: TypeDeclarationMap) { type: 'StringTypeAnnotation', }; break; + case 'Array': + case '$ReadOnlyArray': + if (!paramValue.type === 'GenericTypeAnnotation') { + throw new Error( + 'Array and $ReadOnlyArray are GenericTypeAnnotation for array', + ); + } + returnType = { + type: 'ArrayTypeAnnotation', + elementType: { + // TODO: T172453752 support complex type annotation for array element + type: paramValue.typeParameters.params[0].type, + }, + }; + break; + case 'ArrayTypeAnnotation': + returnType = { + type: 'ArrayTypeAnnotation', + elementType: { + // TODO: T172453752 support complex type annotation for array element + type: paramValue.elementType.type, + }, + }; + break; default: (type: empty); throw new Error(