amis-rpc-design/node_modules/@react-native/codegen/lib/parsers/flow/components/events.js
2023-10-07 19:42:30 +08:00

234 lines
6.0 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
*/
'use strict';
function getPropertyType(
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
name,
optional,
typeAnnotation,
) {
const type =
typeAnnotation.type === 'GenericTypeAnnotation'
? typeAnnotation.id.name
: typeAnnotation.type;
switch (type) {
case 'BooleanTypeAnnotation':
return {
name,
optional,
typeAnnotation: {
type: 'BooleanTypeAnnotation',
},
};
case 'StringTypeAnnotation':
return {
name,
optional,
typeAnnotation: {
type: 'StringTypeAnnotation',
},
};
case 'Int32':
return {
name,
optional,
typeAnnotation: {
type: 'Int32TypeAnnotation',
},
};
case 'Double':
return {
name,
optional,
typeAnnotation: {
type: 'DoubleTypeAnnotation',
},
};
case 'Float':
return {
name,
optional,
typeAnnotation: {
type: 'FloatTypeAnnotation',
},
};
case '$ReadOnly':
return getPropertyType(
name,
optional,
typeAnnotation.typeParameters.params[0],
);
case 'ObjectTypeAnnotation':
return {
name,
optional,
typeAnnotation: {
type: 'ObjectTypeAnnotation',
properties: typeAnnotation.properties.map(buildPropertiesForEvent),
},
};
case 'UnionTypeAnnotation':
return {
name,
optional,
typeAnnotation: {
type: 'StringEnumTypeAnnotation',
options: typeAnnotation.types.map(option => option.value),
},
};
default:
type;
throw new Error(`Unable to determine event type for "${name}": ${type}`);
}
}
function findEventArgumentsAndType(
typeAnnotation,
types,
bubblingType,
paperName,
) {
if (!typeAnnotation.id) {
throw new Error("typeAnnotation of event doesn't have a name");
}
const name = typeAnnotation.id.name;
if (name === '$ReadOnly') {
return {
argumentProps: typeAnnotation.typeParameters.params[0].properties,
paperTopLevelNameDeprecated: paperName,
bubblingType,
};
} else if (name === 'BubblingEventHandler' || name === 'DirectEventHandler') {
const eventType = name === 'BubblingEventHandler' ? 'bubble' : 'direct';
const paperTopLevelNameDeprecated =
typeAnnotation.typeParameters.params.length > 1
? typeAnnotation.typeParameters.params[1].value
: null;
if (
typeAnnotation.typeParameters.params[0].type ===
'NullLiteralTypeAnnotation'
) {
return {
argumentProps: [],
bubblingType: eventType,
paperTopLevelNameDeprecated,
};
}
return findEventArgumentsAndType(
typeAnnotation.typeParameters.params[0],
types,
eventType,
paperTopLevelNameDeprecated,
);
} else if (types[name]) {
return findEventArgumentsAndType(
types[name].right,
types,
bubblingType,
paperName,
);
} else {
return {
argumentProps: null,
bubblingType: null,
paperTopLevelNameDeprecated: null,
};
}
}
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
function buildPropertiesForEvent(property) {
const name = property.key.name;
const optional =
property.value.type === 'NullableTypeAnnotation' || property.optional;
let typeAnnotation =
property.value.type === 'NullableTypeAnnotation'
? property.value.typeAnnotation
: property.value;
return getPropertyType(name, optional, typeAnnotation);
}
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
function getEventArgument(argumentProps, name) {
return {
type: 'ObjectTypeAnnotation',
properties: argumentProps.map(buildPropertiesForEvent),
};
}
function buildEventSchema(types, property) {
const name = property.key.name;
const optional =
property.optional || property.value.type === 'NullableTypeAnnotation';
let typeAnnotation =
property.value.type === 'NullableTypeAnnotation'
? property.value.typeAnnotation
: property.value;
if (
typeAnnotation.type !== 'GenericTypeAnnotation' ||
(typeAnnotation.id.name !== 'BubblingEventHandler' &&
typeAnnotation.id.name !== 'DirectEventHandler')
) {
return null;
}
const _findEventArgumentsAn = findEventArgumentsAndType(
typeAnnotation,
types,
),
argumentProps = _findEventArgumentsAn.argumentProps,
bubblingType = _findEventArgumentsAn.bubblingType,
paperTopLevelNameDeprecated =
_findEventArgumentsAn.paperTopLevelNameDeprecated;
if (bubblingType && argumentProps) {
if (paperTopLevelNameDeprecated != null) {
return {
name,
optional,
bubblingType,
paperTopLevelNameDeprecated,
typeAnnotation: {
type: 'EventTypeAnnotation',
argument: getEventArgument(argumentProps, name),
},
};
}
return {
name,
optional,
bubblingType,
typeAnnotation: {
type: 'EventTypeAnnotation',
argument: getEventArgument(argumentProps, name),
},
};
}
if (argumentProps === null) {
throw new Error(`Unable to determine event arguments for "${name}"`);
}
if (bubblingType === null) {
throw new Error(`Unable to determine event arguments for "${name}"`);
}
}
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
function getEvents(eventTypeAST, types) {
return eventTypeAST
.filter(property => property.type === 'ObjectTypeProperty')
.map(property => buildEventSchema(types, property))
.filter(Boolean);
}
module.exports = {
getEvents,
};