support Array param for native component command in codegen (#41894)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41894

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D51866557

fbshipit-source-id: 595de8d49c0654b36d70a2c8872173fd6232a2be
This commit is contained in:
Zeya Peng 2023-12-12 18:48:47 -08:00 коммит произвёл Facebook GitHub Bot
Родитель d5114a4b9f
Коммит c848bf9545
11 изменённых файлов: 119 добавлений и 3 удалений

Просмотреть файл

@ -213,7 +213,8 @@ export type CommandParamTypeAnnotation =
| Int32TypeAnnotation
| DoubleTypeAnnotation
| FloatTypeAnnotation
| StringTypeAnnotation;
| StringTypeAnnotation
| ArrayTypeAnnotation;
export type ReservedTypeAnnotation = $ReadOnly<{
type: 'ReservedTypeAnnotation',

Просмотреть файл

@ -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');

Просмотреть файл

@ -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}`);

Просмотреть файл

@ -171,6 +171,8 @@ function getCommandArgJavaType(param: NamedShape<CommandParamTypeAnnotation>) {
return 'int';
case 'StringTypeAnnotation':
return 'String';
case 'ArrayTypeAnnotation':
return 'ReadableArray';
default:
(typeAnnotation.type: empty);
throw new Error('Receieved invalid typeAnnotation');

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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',
},
},
},
],
},
},

Просмотреть файл

@ -222,6 +222,7 @@ NS_ASSUME_NONNULL_BEGIN
@protocol RCTCommandNativeComponentViewProtocol <NSObject>
- (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

Просмотреть файл

@ -271,6 +271,9 @@ public class CommandNativeComponentManagerDelegate<T extends View, U extends Bas
case \\"hotspotUpdate\\":
mViewManager.hotspotUpdate(view, args.getInt(0), args.getInt(1));
break;
case \\"addItems\\":
mViewManager.addItems(view, args.getArray(0));
break;
}
}
}

Просмотреть файл

@ -143,11 +143,13 @@ package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
public interface CommandNativeComponentManagerInterface<T extends View> {
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);
}
",
}

Просмотреть файл

@ -234,6 +234,10 @@ export const Commands = {
hotspotUpdate(ref, x, y) {
dispatchCommand(ref, \\"hotspotUpdate\\", [x, y]);
},
addItems(ref, items) {
dispatchCommand(ref, \\"addItems\\", [items]);
}
};
",

Просмотреть файл

@ -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(