mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Support Array parsing in events (#37142)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/37142 This diff introduce support to parse arrays in events. We support parsing Arrays of: - Boolean - Double - Float - Int32 - String Enums - String - Objects - Arrays ## Changelog: [General][Added] - Add generic support for Arrays in Events parsing Reviewed By: dmytrorykun, RSNara Differential Revision: D45268779 fbshipit-source-id: 0c6eae65eb2b41ebf7b47a4cc3e0f0e5fa20d871
This commit is contained in:
committed by
Facebook GitHub Bot
parent
6f75f14883
commit
6168701887
+5
-2
@@ -113,7 +113,11 @@ export type EventTypeAnnotation =
|
||||
| FloatTypeAnnotation
|
||||
| Int32TypeAnnotation
|
||||
| StringEnumTypeAnnotation
|
||||
| ObjectTypeAnnotation<EventTypeAnnotation>;
|
||||
| ObjectTypeAnnotation<EventTypeAnnotation>
|
||||
| {
|
||||
readonly type: 'ArrayTypeAnnotation';
|
||||
readonly elementType: EventTypeAnnotation
|
||||
};
|
||||
|
||||
export type PropTypeAnnotation =
|
||||
| {
|
||||
@@ -352,4 +356,3 @@ export type NativeModuleReturnOnlyTypeAnnotation =
|
||||
| NativeModuleFunctionTypeAnnotation
|
||||
| NativeModulePromiseTypeAnnotation
|
||||
| VoidTypeAnnotation;
|
||||
|
||||
|
||||
+5
-1
@@ -128,7 +128,11 @@ export type EventTypeAnnotation =
|
||||
| Int32TypeAnnotation
|
||||
| MixedTypeAnnotation
|
||||
| StringEnumTypeAnnotation
|
||||
| ObjectTypeAnnotation<EventTypeAnnotation>;
|
||||
| ObjectTypeAnnotation<EventTypeAnnotation>
|
||||
| $ReadOnly<{
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: EventTypeAnnotation,
|
||||
}>;
|
||||
|
||||
export type PropTypeAnnotation =
|
||||
| $ReadOnly<{
|
||||
|
||||
+3
@@ -177,6 +177,9 @@ function generateSetters(
|
||||
typeAnnotation,
|
||||
extraIncludes,
|
||||
);
|
||||
case 'ArrayTypeAnnotation':
|
||||
// TODO: implement this in the next diff
|
||||
break;
|
||||
default:
|
||||
(typeAnnotation.type: empty);
|
||||
throw new Error(
|
||||
|
||||
+6
@@ -133,6 +133,9 @@ function getNativeTypeFromAnnotation(
|
||||
case 'StringEnumTypeAnnotation':
|
||||
case 'ObjectTypeAnnotation':
|
||||
return generateEventStructName([...nameParts, eventProperty.name]);
|
||||
case 'ArrayTypeAnnotation':
|
||||
// TODO: implement this in the next diff
|
||||
return '';
|
||||
default:
|
||||
(type: empty);
|
||||
throw new Error(`Received invalid event property type ${type}`);
|
||||
@@ -205,6 +208,9 @@ function generateStruct(
|
||||
case 'StringEnumTypeAnnotation':
|
||||
generateEnum(structs, typeAnnotation.options, nameParts.concat([name]));
|
||||
return;
|
||||
case 'ArrayTypeAnnotation':
|
||||
//TODO: implement this in the next diff
|
||||
break;
|
||||
default:
|
||||
(typeAnnotation.type: empty);
|
||||
throw new Error(
|
||||
|
||||
+51
@@ -84,6 +84,57 @@ const EVENT_DEFINITION = `
|
||||
object_readonly_optional_both?: ?$ReadOnly<{
|
||||
int32_optional_both?: ?Int32,
|
||||
}>,
|
||||
|
||||
boolean_array_required: $ReadOnlyArray<boolean>,
|
||||
boolean_array_optional_key?: boolean[],
|
||||
boolean_array_optional_value: ?$ReadOnlyArray<boolean>,
|
||||
boolean_array_optional_both?: ?boolean[],
|
||||
|
||||
string_array_required: $ReadOnlyArray<string>,
|
||||
string_array_optional_key?: string[],
|
||||
string_array_optional_value: ?$ReadOnlyArray<string>,
|
||||
string_array_optional_both?: ?string[],
|
||||
|
||||
double_array_required: $ReadOnlyArray<Double>,
|
||||
double_array_optional_key?: Double[],
|
||||
double_array_optional_value: ?$ReadOnlyArray<Double>,
|
||||
double_array_optional_both?: ?Double[],
|
||||
|
||||
float_array_required: $ReadOnlyArray<Float>,
|
||||
float_array_optional_key?: Float[],
|
||||
float_array_optional_value: ?$ReadOnlyArray<Float>,
|
||||
float_array_optional_both?: ?Float[],
|
||||
|
||||
int32_array_required: $ReadOnlyArray<Int32>,
|
||||
int32_array_optional_key?: Int32[],
|
||||
int32_array_optional_value: ?$ReadOnlyArray<Int32>,
|
||||
int32_array_optional_both?: ?Int32[],
|
||||
|
||||
enum_array_required: $ReadOnlyArray<('small' | 'large')>,
|
||||
enum_array_optional_key?: ('small' | 'large')[],
|
||||
enum_array_optional_value: ?$ReadOnlyArray<('small' | 'large')>,
|
||||
enum_array_optional_both?: ?('small' | 'large')[],
|
||||
|
||||
object_array_required: $ReadOnlyArray<{
|
||||
boolean_required: boolean,
|
||||
}>,
|
||||
|
||||
object_array_optional_key?: {
|
||||
string_optional_key?: string,
|
||||
}[],
|
||||
|
||||
object_array_optional_value: ?$ReadOnlyArray<{
|
||||
float_optional_value: ?Float,
|
||||
}>,
|
||||
|
||||
object_array_optional_both?: ?{
|
||||
int32_optional_both?: ?Int32,
|
||||
}[],
|
||||
|
||||
int32_array_array_required: $ReadOnlyArray<$ReadOnlyArray<Int32>>,
|
||||
int32_array_array_optional_key?: Int32[][],
|
||||
int32_array_array_optional_value: ?$ReadOnlyArray<$ReadOnlyArray<Int32>>,
|
||||
int32_array_array_optional_both?: ?Int32[][],
|
||||
`;
|
||||
|
||||
const ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS = `
|
||||
|
||||
+6912
File diff suppressed because it is too large
Load Diff
@@ -28,10 +28,7 @@ function getPropertyType(
|
||||
optional: boolean,
|
||||
typeAnnotation: $FlowFixMe,
|
||||
): NamedShape<EventTypeAnnotation> {
|
||||
const type =
|
||||
typeAnnotation.type === 'GenericTypeAnnotation'
|
||||
? typeAnnotation.id.name
|
||||
: typeAnnotation.type;
|
||||
const type = extractTypeFromTypeAnnotation(typeAnnotation);
|
||||
|
||||
switch (type) {
|
||||
case 'BooleanTypeAnnotation':
|
||||
@@ -106,12 +103,87 @@ function getPropertyType(
|
||||
type: 'MixedTypeAnnotation',
|
||||
},
|
||||
};
|
||||
case 'ArrayTypeAnnotation':
|
||||
case '$ReadOnlyArray':
|
||||
return {
|
||||
name,
|
||||
optional,
|
||||
typeAnnotation: extractArrayElementType(typeAnnotation, name),
|
||||
};
|
||||
default:
|
||||
(type: empty);
|
||||
throw new Error(`Unable to determine event type for "${name}": ${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
function extractArrayElementType(
|
||||
typeAnnotation: $FlowFixMe,
|
||||
name: string,
|
||||
): EventTypeAnnotation {
|
||||
const type = extractTypeFromTypeAnnotation(typeAnnotation);
|
||||
|
||||
switch (type) {
|
||||
case 'BooleanTypeAnnotation':
|
||||
return {type: 'BooleanTypeAnnotation'};
|
||||
case 'StringTypeAnnotation':
|
||||
return {type: 'StringTypeAnnotation'};
|
||||
case 'Int32':
|
||||
return {type: 'Int32TypeAnnotation'};
|
||||
case 'Float':
|
||||
return {type: 'FloatTypeAnnotation'};
|
||||
case 'NumberTypeAnnotation':
|
||||
case 'Double':
|
||||
return {
|
||||
type: 'DoubleTypeAnnotation',
|
||||
};
|
||||
case 'UnionTypeAnnotation':
|
||||
return {
|
||||
type: 'StringEnumTypeAnnotation',
|
||||
options: typeAnnotation.types.map(option => option.value),
|
||||
};
|
||||
case 'UnsafeMixed':
|
||||
return {type: 'MixedTypeAnnotation'};
|
||||
case 'ObjectTypeAnnotation':
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: typeAnnotation.properties.map(buildPropertiesForEvent),
|
||||
};
|
||||
case 'ArrayTypeAnnotation':
|
||||
return {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: extractArrayElementType(typeAnnotation.elementType, name),
|
||||
};
|
||||
case '$ReadOnlyArray':
|
||||
const genericParams = typeAnnotation.typeParameters.params;
|
||||
if (genericParams.length !== 1) {
|
||||
throw new Error(
|
||||
`Events only supports arrays with 1 Generic type. Found ${
|
||||
genericParams.length
|
||||
} types:\n${prettify(genericParams)}`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: extractArrayElementType(genericParams[0], name),
|
||||
};
|
||||
default:
|
||||
throw new Error(
|
||||
`Unrecognized ${type} for Array ${name} in events.\n${prettify(
|
||||
typeAnnotation,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function prettify(jsonObject: $FlowFixMe): string {
|
||||
return JSON.stringify(jsonObject, null, 2);
|
||||
}
|
||||
|
||||
function extractTypeFromTypeAnnotation(typeAnnotation: $FlowFixMe): string {
|
||||
return typeAnnotation.type === 'GenericTypeAnnotation'
|
||||
? typeAnnotation.id.name
|
||||
: typeAnnotation.type;
|
||||
}
|
||||
|
||||
function findEventArgumentsAndType(
|
||||
parser: Parser,
|
||||
typeAnnotation: $FlowFixMe,
|
||||
@@ -219,24 +291,20 @@ function buildEventSchema(
|
||||
const {argumentProps, bubblingType, paperTopLevelNameDeprecated} =
|
||||
findEventArgumentsAndType(parser, typeAnnotation, types);
|
||||
|
||||
if (bubblingType && argumentProps) {
|
||||
if (paperTopLevelNameDeprecated != null) {
|
||||
return {
|
||||
name,
|
||||
optional,
|
||||
bubblingType,
|
||||
paperTopLevelNameDeprecated,
|
||||
typeAnnotation: {
|
||||
type: 'EventTypeAnnotation',
|
||||
argument: getEventArgument(argumentProps, name),
|
||||
},
|
||||
};
|
||||
}
|
||||
if (!argumentProps) {
|
||||
throw new Error(`Unable to determine event arguments for "${name}"`);
|
||||
}
|
||||
|
||||
if (!bubblingType) {
|
||||
throw new Error(`Unable to determine event arguments for "${name}"`);
|
||||
}
|
||||
|
||||
if (paperTopLevelNameDeprecated != null) {
|
||||
return {
|
||||
name,
|
||||
optional,
|
||||
bubblingType,
|
||||
paperTopLevelNameDeprecated,
|
||||
typeAnnotation: {
|
||||
type: 'EventTypeAnnotation',
|
||||
argument: getEventArgument(argumentProps, name),
|
||||
@@ -249,6 +317,16 @@ function buildEventSchema(
|
||||
}
|
||||
|
||||
throwIfBubblingTypeIsNull(bubblingType, name);
|
||||
|
||||
return {
|
||||
name,
|
||||
optional,
|
||||
bubblingType,
|
||||
typeAnnotation: {
|
||||
type: 'EventTypeAnnotation',
|
||||
argument: getEventArgument(argumentProps, name),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
|
||||
|
||||
Vendored
+51
@@ -84,6 +84,57 @@ const EVENT_DEFINITION = `
|
||||
object_readonly_optional_both?: Readonly<{
|
||||
int32_optional_both?: Int32 | null | undefined;
|
||||
}> | null | undefined;
|
||||
|
||||
boolean_array_required: boolean[];
|
||||
boolean_array_optional_key?: boolean[];
|
||||
boolean_array_optional_value: boolean[] | null | undefined;
|
||||
boolean_array_optional_both?: boolean[] | null | undefined;
|
||||
|
||||
string_array_required: string[];
|
||||
string_array_optional_key?: (string[]);
|
||||
string_array_optional_value: (string[]) | null | undefined;
|
||||
string_array_optional_both?: (string[] | null | undefined);
|
||||
|
||||
double_array_required: Double[];
|
||||
double_array_optional_key?: Double[];
|
||||
double_array_optional_value: Double[] | null | undefined;
|
||||
double_array_optional_both?: Double[] | null | undefined;
|
||||
|
||||
float_array_required: Float[];
|
||||
float_array_optional_key?: Float[];
|
||||
float_array_optional_value: Float[] | null | undefined;
|
||||
float_array_optional_both?: Float[] | null | undefined;
|
||||
|
||||
int32_array_required: Int32[];
|
||||
int32_array_optional_key?: Int32[];
|
||||
int32_array_optional_value: Int32[] | null | undefined;
|
||||
int32_array_optional_both?: Int32[] | null | undefined;
|
||||
|
||||
enum_array_required: ('small' | 'large')[];
|
||||
enum_array_optional_key?: ('small' | 'large')[];
|
||||
enum_array_optional_value: ('small' | 'large')[] | null | undefined;
|
||||
enum_array_optional_both?: ('small' | 'large')[] | null | undefined;
|
||||
|
||||
object_array_required: {
|
||||
boolean_required: boolean;
|
||||
}[];
|
||||
|
||||
object_array_optional_key?: {
|
||||
string_optional_key?: string;
|
||||
}[];
|
||||
|
||||
object_array_optional_value: {
|
||||
float_optional_value: Float | null | undefined;
|
||||
}[] | null | undefined;
|
||||
|
||||
object_array_optional_both?: {
|
||||
int32_optional_both?: Int32 | null | undefined;
|
||||
}[] | null | undefined;
|
||||
|
||||
int32_array_array_required: Int32[][];
|
||||
int32_array_array_optional_key?: Int32[][];
|
||||
int32_array_array_optional_value: Int32[][] | null | undefined;
|
||||
int32_array_array_optional_both?: Int32[][] | null | undefined;
|
||||
`;
|
||||
|
||||
const ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS = `
|
||||
|
||||
+6912
File diff suppressed because it is too large
Load Diff
@@ -108,12 +108,76 @@ function getPropertyType(
|
||||
type: 'MixedTypeAnnotation',
|
||||
},
|
||||
};
|
||||
case 'TSArrayType':
|
||||
return {
|
||||
name,
|
||||
optional,
|
||||
typeAnnotation: extractArrayElementType(typeAnnotation, name),
|
||||
};
|
||||
default:
|
||||
(type: empty);
|
||||
throw new Error(`Unable to determine event type for "${name}": ${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
function extractArrayElementType(
|
||||
typeAnnotation: $FlowFixMe,
|
||||
name: string,
|
||||
): EventTypeAnnotation {
|
||||
const type = extractTypeFromTypeAnnotation(typeAnnotation);
|
||||
|
||||
switch (type) {
|
||||
case 'TSParenthesizedType':
|
||||
return extractArrayElementType(typeAnnotation.typeAnnotation, name);
|
||||
case 'TSBooleanKeyword':
|
||||
return {type: 'BooleanTypeAnnotation'};
|
||||
case 'TSStringKeyword':
|
||||
return {type: 'StringTypeAnnotation'};
|
||||
case 'Float':
|
||||
return {
|
||||
type: 'FloatTypeAnnotation',
|
||||
};
|
||||
case 'Int32':
|
||||
return {
|
||||
type: 'Int32TypeAnnotation',
|
||||
};
|
||||
case 'TSNumberKeyword':
|
||||
case 'Double':
|
||||
return {
|
||||
type: 'DoubleTypeAnnotation',
|
||||
};
|
||||
case 'TSUnionType':
|
||||
return {
|
||||
type: 'StringEnumTypeAnnotation',
|
||||
options: typeAnnotation.types.map(option => option.literal.value),
|
||||
};
|
||||
case 'TSTypeLiteral':
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: typeAnnotation.members.map(buildPropertiesForEvent),
|
||||
};
|
||||
case 'TSArrayType':
|
||||
return {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: extractArrayElementType(typeAnnotation.elementType, name),
|
||||
};
|
||||
default:
|
||||
throw new Error(
|
||||
`Unrecognized ${type} for Array ${name} in events.\n${JSON.stringify(
|
||||
typeAnnotation,
|
||||
null,
|
||||
2,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function extractTypeFromTypeAnnotation(typeAnnotation: $FlowFixMe): string {
|
||||
return typeAnnotation.type === 'TSTypeReference'
|
||||
? typeAnnotation.typeName.name
|
||||
: typeAnnotation.type;
|
||||
}
|
||||
|
||||
function findEventArgumentsAndType(
|
||||
parser: Parser,
|
||||
typeAnnotation: $FlowFixMe,
|
||||
|
||||
Reference in New Issue
Block a user