diff --git a/packages/react-native-codegen/src/generators/components/CppHelpers.js b/packages/react-native-codegen/src/generators/components/CppHelpers.js index efeef4085b..69a1d9a61e 100644 --- a/packages/react-native-codegen/src/generators/components/CppHelpers.js +++ b/packages/react-native-codegen/src/generators/components/CppHelpers.js @@ -12,6 +12,10 @@ import type {PropTypeShape} from '../../CodegenSchema'; function upperCaseFirst(inString: string): string { + if (inString.length === 0) { + return inString; + } + return inString[0].toUpperCase() + inString.slice(1); } diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js index 22cca6895f..58c7adbf3a 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js @@ -124,6 +124,20 @@ const arrayConversionFunction = `static inline void fromRawValue(const RawValue } `; +const doubleArrayConversionFunction = `static inline void fromRawValue(const RawValue &value, std::vector> &result) { + auto items = (std::vector>)value; + for (const std::vector &item : items) { + auto nestedArray = std::vector<::_STRUCT_NAME_::>{}; + for (const RawValue &nestedItem : item) { + ::_STRUCT_NAME_:: newItem; + fromRawValue(nestedItem, newItem); + nestedArray.emplace_back(newItem); + } + result.emplace_back(nestedArray); + } +} +`; + const arrayEnumTemplate = ` using ::_ENUM_MASK_:: = uint32_t; @@ -220,18 +234,22 @@ function getNativeTypeFromAnnotation( throw new Error('Received unknown NativePrimitiveTypeAnnotation'); } case 'ArrayTypeAnnotation': { - if (typeAnnotation.elementType.type === 'ArrayTypeAnnotation') { - // TODO: Implement correctly in the next diff, this is to pass tests - return 'std::vector'; + const arrayType = typeAnnotation.elementType.type; + if (arrayType === 'ArrayTypeAnnotation') { + return `std::vector<${getNativeTypeFromAnnotation( + componentName, + {typeAnnotation: typeAnnotation.elementType, name: ''}, + nameParts.concat([prop.name]), + )}>`; } - if (typeAnnotation.elementType.type === 'ObjectTypeAnnotation') { + if (arrayType === 'ObjectTypeAnnotation') { const structName = generateStructName( componentName, nameParts.concat([prop.name]), ); return `std::vector<${structName}>`; } - if (typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') { + if (arrayType === 'StringEnumTypeAnnotation') { const enumName = getEnumName(componentName, prop.name); return getEnumMaskName(enumName); } @@ -606,6 +624,45 @@ function generateStructs( ), ); } + if ( + prop.typeAnnotation.type === 'ArrayTypeAnnotation' && + prop.typeAnnotation.elementType.type === 'ArrayTypeAnnotation' && + prop.typeAnnotation.elementType.elementType.type === + 'ObjectTypeAnnotation' + ) { + // Recursively visit all of the object properties. + // Note: this is depth first so that the nested structs are ordered first. + const elementProperties = + prop.typeAnnotation.elementType.elementType.properties; + const nestedStructs = generateStructs( + componentName, + elementProperties, + nameParts.concat([prop.name]), + ); + nestedStructs.forEach(function(value, key) { + structs.set(key, value); + }); + + // Generate this struct and its conversion function. + generateStruct( + structs, + componentName, + nameParts.concat([prop.name]), + elementProperties, + ); + + // Generate the conversion function for std:vector. + // Note: This needs to be at the end since it references the struct above. + structs.set( + `${[componentName, ...nameParts.concat([prop.name])].join( + '', + )}ArrayArrayStruct`, + doubleArrayConversionFunction.replace( + /::_STRUCT_NAME_::/g, + generateStructName(componentName, nameParts.concat([prop.name])), + ), + ); + } }); return structs; diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap index 2980b9aea8..0b209eebc5 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap @@ -156,6 +156,37 @@ static inline void fromRawValue(const RawValue &value, std::vector)value; + + auto stringProp = map.find(\\"stringProp\\"); + if (stringProp != map.end()) { + fromRawValue(stringProp->second, result.stringProp); + } +} + +static inline std::string toString(const ArrayPropsNativeComponentArrayOfArrayOfObjectStruct &value) { + return \\"[Object ArrayPropsNativeComponentArrayOfArrayOfObjectStruct]\\"; +} + +static inline void fromRawValue(const RawValue &value, std::vector> &result) { + auto items = (std::vector>)value; + for (const std::vector &item : items) { + auto nestedArray = std::vector{}; + for (const RawValue &nestedItem : item) { + ArrayPropsNativeComponentArrayOfArrayOfObjectStruct newItem; + fromRawValue(nestedItem, newItem); + nestedArray.emplace_back(newItem); + } + result.emplace_back(nestedArray); + } +} + class ArrayPropsNativeComponentProps final : public ViewProps { public: ArrayPropsNativeComponentProps() = default; @@ -173,7 +204,7 @@ class ArrayPropsNativeComponentProps final : public ViewProps { const ArrayPropsNativeComponentSizesMask sizes{static_cast(ArrayPropsNativeComponentSizes::Small)}; const std::vector object{}; const std::vector array{}; - const std::vector arrayOfArrayOfObject{}; + const std::vector> arrayOfArrayOfObject{}; }; } // namespace react