UNPKG

@react-native/codegen

Version:
315 lines (285 loc) • 9.77 kB
/** * 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. * * @flow strict * @format */ 'use strict'; import type {NamedShape, PropTypeAnnotation} from '../../CodegenSchema'; import type { BooleanTypeAnnotation, DoubleTypeAnnotation, FloatTypeAnnotation, Int32TypeAnnotation, ObjectTypeAnnotation, ReservedPropTypeAnnotation, StringTypeAnnotation, } from '../../CodegenSchema'; const {getEnumName} = require('../Utils'); const { generateStructName, getCppTypeForAnnotation, getEnumMaskName, getImports, } = require('./CppHelpers.js'); function getNativeTypeFromAnnotation( componentName: string, prop: | NamedShape<PropTypeAnnotation> | { name: string, typeAnnotation: | $FlowFixMe | DoubleTypeAnnotation | FloatTypeAnnotation | BooleanTypeAnnotation | Int32TypeAnnotation | StringTypeAnnotation | ObjectTypeAnnotation<PropTypeAnnotation> | ReservedPropTypeAnnotation | { +default: string, +options: $ReadOnlyArray<string>, +type: 'StringEnumTypeAnnotation', } | { +elementType: ObjectTypeAnnotation<PropTypeAnnotation>, +type: 'ArrayTypeAnnotation', }, }, nameParts: $ReadOnlyArray<string>, ): string { const typeAnnotation = prop.typeAnnotation; switch (typeAnnotation.type) { case 'BooleanTypeAnnotation': case 'StringTypeAnnotation': case 'Int32TypeAnnotation': case 'DoubleTypeAnnotation': case 'FloatTypeAnnotation': return getCppTypeForAnnotation(typeAnnotation.type); case 'ReservedPropTypeAnnotation': switch (typeAnnotation.name) { case 'ColorPrimitive': return 'SharedColor'; case 'ImageSourcePrimitive': return 'ImageSource'; case 'ImageRequestPrimitive': return 'ImageRequest'; case 'PointPrimitive': return 'Point'; case 'EdgeInsetsPrimitive': return 'EdgeInsets'; case 'DimensionPrimitive': return 'YGValue'; default: (typeAnnotation.name: empty); throw new Error('Received unknown ReservedPropTypeAnnotation'); } case 'ArrayTypeAnnotation': { const arrayType = typeAnnotation.elementType.type; if (arrayType === 'ArrayTypeAnnotation') { return `std::vector<${getNativeTypeFromAnnotation( componentName, {typeAnnotation: typeAnnotation.elementType, name: ''}, nameParts.concat([prop.name]), )}>`; } if (arrayType === 'ObjectTypeAnnotation') { const structName = generateStructName( componentName, nameParts.concat([prop.name]), ); return `std::vector<${structName}>`; } if (arrayType === 'StringEnumTypeAnnotation') { const enumName = getEnumName(componentName, prop.name); return getEnumMaskName(enumName); } const itemAnnotation = getNativeTypeFromAnnotation( componentName, { typeAnnotation: typeAnnotation.elementType, name: componentName, }, nameParts.concat([prop.name]), ); return `std::vector<${itemAnnotation}>`; } case 'ObjectTypeAnnotation': { return generateStructName(componentName, nameParts.concat([prop.name])); } case 'StringEnumTypeAnnotation': return getEnumName(componentName, prop.name); case 'Int32EnumTypeAnnotation': return getEnumName(componentName, prop.name); case 'MixedTypeAnnotation': return 'folly::dynamic'; default: (typeAnnotation: empty); throw new Error( `Received invalid typeAnnotation for ${componentName} prop ${prop.name}, received ${typeAnnotation.type}`, ); } } /// This function process some types if we need to customize them /// For example, the ImageSource and the reserved types could be trasformed into /// const address instead of using them as plain types. function convertTypesToConstAddressIfNeeded( type: string, convertibleTypes: Set<string>, ): string { if (convertibleTypes.has(type)) { return `${type} const &`; } return type; } function convertValueToSharedPointerWithMove( type: string, value: string, convertibleTypes: Set<string>, ): string { if (convertibleTypes.has(type)) { return `std::make_shared<${type}>(std::move(${value}))`; } return value; } function convertVariableToSharedPointer( type: string, convertibleTypes: Set<string>, ): string { if (convertibleTypes.has(type)) { return `std::shared_ptr<${type}>`; } return type; } function convertVariableToPointer( type: string, value: string, convertibleTypes: Set<string>, ): string { if (convertibleTypes.has(type)) { return `*${value}`; } return value; } const convertCtorParamToAddressType = (type: string): string => { const typesToConvert: Set<string> = new Set(); typesToConvert.add('ImageSource'); return convertTypesToConstAddressIfNeeded(type, typesToConvert); }; const convertCtorInitToSharedPointers = ( type: string, value: string, ): string => { const typesToConvert: Set<string> = new Set(); typesToConvert.add('ImageRequest'); return convertValueToSharedPointerWithMove(type, value, typesToConvert); }; const convertGettersReturnTypeToAddressType = (type: string): string => { const typesToConvert: Set<string> = new Set(); typesToConvert.add('ImageRequest'); return convertTypesToConstAddressIfNeeded(type, typesToConvert); }; const convertVarTypeToSharedPointer = (type: string): string => { const typesToConvert: Set<string> = new Set(); typesToConvert.add('ImageRequest'); return convertVariableToSharedPointer(type, typesToConvert); }; const convertVarValueToPointer = (type: string, value: string): string => { const typesToConvert: Set<string> = new Set(); typesToConvert.add('ImageRequest'); return convertVariableToPointer(type, value, typesToConvert); }; function getLocalImports( properties: $ReadOnlyArray<NamedShape<PropTypeAnnotation>>, ): Set<string> { const imports: Set<string> = new Set(); function addImportsForNativeName( name: | 'ColorPrimitive' | 'EdgeInsetsPrimitive' | 'ImageSourcePrimitive' | 'PointPrimitive' | 'ImageRequestPrimitive' | 'DimensionPrimitive', ) { switch (name) { case 'ColorPrimitive': imports.add('#include <react/renderer/graphics/Color.h>'); return; case 'ImageSourcePrimitive': imports.add('#include <react/renderer/imagemanager/primitives.h>'); return; case 'ImageRequestPrimitive': imports.add('#include <react/renderer/imagemanager/ImageRequest.h>'); return; case 'PointPrimitive': imports.add('#include <react/renderer/graphics/Point.h>'); return; case 'EdgeInsetsPrimitive': imports.add('#include <react/renderer/graphics/RectangleEdges.h>'); return; case 'DimensionPrimitive': imports.add('#include <yoga/Yoga.h>'); return; default: (name: empty); throw new Error(`Invalid ReservedPropTypeAnnotation name, got ${name}`); } } properties.forEach(prop => { const typeAnnotation = prop.typeAnnotation; if (typeAnnotation.type === 'ReservedPropTypeAnnotation') { addImportsForNativeName(typeAnnotation.name); } if (typeAnnotation.type === 'ArrayTypeAnnotation') { imports.add('#include <vector>'); if (typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') { imports.add('#include <cinttypes>'); } } if ( typeAnnotation.type === 'ArrayTypeAnnotation' && typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation' ) { addImportsForNativeName(typeAnnotation.elementType.name); } if ( typeAnnotation.type === 'ArrayTypeAnnotation' && typeAnnotation.elementType.type === 'ObjectTypeAnnotation' ) { imports.add('#include <react/renderer/core/propsConversions.h>'); const objectProps = typeAnnotation.elementType.properties; // $FlowFixMe[incompatible-call] the type is guaranteed to be ObjectTypeAnnotation<PropTypeAnnotation> const objectImports = getImports(objectProps); // $FlowFixMe[incompatible-call] the type is guaranteed to be ObjectTypeAnnotation<PropTypeAnnotation> const localImports = getLocalImports(objectProps); // $FlowFixMe[method-unbinding] added when improving typing for this parameters objectImports.forEach(imports.add, imports); // $FlowFixMe[method-unbinding] added when improving typing for this parameters localImports.forEach(imports.add, imports); } if (typeAnnotation.type === 'ObjectTypeAnnotation') { imports.add('#include <react/renderer/core/propsConversions.h>'); const objectImports = getImports(typeAnnotation.properties); const localImports = getLocalImports(typeAnnotation.properties); // $FlowFixMe[method-unbinding] added when improving typing for this parameters objectImports.forEach(imports.add, imports); // $FlowFixMe[method-unbinding] added when improving typing for this parameters localImports.forEach(imports.add, imports); } }); return imports; } module.exports = { getNativeTypeFromAnnotation, convertCtorParamToAddressType, convertGettersReturnTypeToAddressType, convertCtorInitToSharedPointers, convertVarTypeToSharedPointer, convertVarValueToPointer, getLocalImports, };