From db17e969facf6fa86603e2ada8a8b4aa578b0f12 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Mon, 8 Jul 2019 03:48:26 -0700 Subject: [PATCH] codegen: fix array of enums generation Summary: While working on D16090949 I discovered that the code being generated for an array of enums was not correctly converted to mask. The type that holds the mask can't be enum class but other container type, I used `uint32_t`. Reviewed By: shergin Differential Revision: D16109338 fbshipit-source-id: 237077adaafe631eda973bc76cefa49035bbcd66 --- .../src/generators/GeneratePropsH.js | 45 ++++++++++++------- .../__snapshots__/GeneratePropsH-test.js.snap | 34 ++++++++------ 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/packages/react-native-codegen/src/generators/GeneratePropsH.js b/packages/react-native-codegen/src/generators/GeneratePropsH.js index 5c332ad15db..c098374d728 100644 --- a/packages/react-native-codegen/src/generators/GeneratePropsH.js +++ b/packages/react-native-codegen/src/generators/GeneratePropsH.js @@ -17,8 +17,6 @@ import type {PropTypeShape, SchemaType} from '../CodegenSchema'; // File path -> contents type FilesOutput = Map; -type TypeAnnotation = $PropertyType; - const template = ` /** * Copyright (c) Facebook, Inc. and its affiliates. @@ -70,23 +68,31 @@ static inline std::string toString(const ::_ENUM_NAME_:: &value) { `.trim(); const arrayEnumTemplate = ` -enum class ::_ENUM_NAME_::: uint32_t { +using ::_ENUM_MASK_:: = uint32_t; + +enum class ::_ENUM_NAME_::: ::_ENUM_MASK_:: { ::_VALUES_:: }; constexpr bool operator&( - const enum ::_ENUM_NAME_:: lhs, - const enum ::_ENUM_NAME_:: rhs) { - return ((uint32_t)lhs & (uint32_t)rhs); + ::_ENUM_MASK_:: const lhs, + enum ::_ENUM_NAME_:: const rhs) { + return lhs & static_cast<::_ENUM_MASK_::>(rhs); } -constexpr bool operator|( - const enum ::_ENUM_NAME_:: lhs, - const enum ::_ENUM_NAME_:: rhs) { - return ((uint32_t)lhs | (uint32_t)rhs); +constexpr ::_ENUM_MASK_:: operator|( + ::_ENUM_MASK_:: const lhs, + enum ::_ENUM_NAME_:: const rhs) { + return lhs | static_cast<::_ENUM_MASK_::>(rhs); } -static inline void fromRawValue(const RawValue &value, ::_ENUM_NAME_:: &result) { +constexpr void operator|=( + ::_ENUM_MASK_:: &lhs, + enum ::_ENUM_NAME_:: const rhs) { + lhs = lhs | static_cast<::_ENUM_MASK_::>(rhs); +} + +static inline void fromRawValue(const RawValue &value, ::_ENUM_MASK_:: &result) { auto items = std::vector{value}; for (const auto &item : items) { ::_FROM_CASES_:: @@ -94,7 +100,7 @@ static inline void fromRawValue(const RawValue &value, ::_ENUM_NAME_:: &result) } } -static inline std::string toString(const ::_ENUM_NAME_:: &value) { +static inline std::string toString(const ::_ENUM_MASK_:: &value) { auto result = std::string{}; auto separator = std::string{", "}; @@ -158,7 +164,8 @@ function getNativeTypeFromAnnotation(componentName: string, prop): string { ); } if (typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') { - return getEnumName(componentName, prop.name); + const enumName = getEnumName(componentName, prop.name); + return getEnumMaskName(enumName); } const itemAnnotation = getNativeTypeFromAnnotation(componentName, { typeAnnotation: typeAnnotation.elementType, @@ -211,9 +218,12 @@ function convertDefaultTypeToString(componentName: string, prop): string { 'A default is required for array StringEnumTypeAnnotation', ); } - return `${getEnumName(componentName, prop.name)}::${toSafeCppString( + const enumName = getEnumName(componentName, prop.name); + const enumMaskName = getEnumMaskName(enumName); + const defaultValue = `${enumName}::${toSafeCppString( typeAnnotation.elementType.default || '', )}`; + return `static_cast<${enumMaskName}>(${defaultValue})`; default: return ''; } @@ -233,6 +243,10 @@ function getEnumName(componentName, propName): string { return `${componentName}${uppercasedPropName}`; } +function getEnumMaskName(enumName: string): string { + return `${enumName}Mask`; +} + function convertValueToEnumOption(value: string): string { return toSafeCppString(value); } @@ -253,7 +267,7 @@ function generateArrayEnumString( .map( option => `if (item == "${option}") { - result = (${enumName})(result | ${enumName}::${toSafeCppString(option)}); + result |= ${enumName}::${toSafeCppString(option)}; continue; }`, ) @@ -270,6 +284,7 @@ function generateArrayEnumString( return arrayEnumTemplate .replace(/::_ENUM_NAME_::/g, enumName) + .replace(/::_ENUM_MASK_::/g, getEnumMaskName(enumName)) .replace('::_VALUES_::', values) .replace('::_FROM_CASES_::', fromCases) .replace('::_TO_CASES_::', toCases); diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap index 09abc277082..ed3e7a50c47 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap @@ -21,39 +21,47 @@ Map { namespace facebook { namespace react { -enum class ArrayPropsNativeComponentSizes: uint32_t { +using ArrayPropsNativeComponentSizesMask = uint32_t; + +enum class ArrayPropsNativeComponentSizes: ArrayPropsNativeComponentSizesMask { Small = 1 << 0, Large = 1 << 1 }; constexpr bool operator&( - const enum ArrayPropsNativeComponentSizes lhs, - const enum ArrayPropsNativeComponentSizes rhs) { - return ((uint32_t)lhs & (uint32_t)rhs); + ArrayPropsNativeComponentSizesMask const lhs, + enum ArrayPropsNativeComponentSizes const rhs) { + return lhs & static_cast(rhs); } -constexpr bool operator|( - const enum ArrayPropsNativeComponentSizes lhs, - const enum ArrayPropsNativeComponentSizes rhs) { - return ((uint32_t)lhs | (uint32_t)rhs); +constexpr ArrayPropsNativeComponentSizesMask operator|( + ArrayPropsNativeComponentSizesMask const lhs, + enum ArrayPropsNativeComponentSizes const rhs) { + return lhs | static_cast(rhs); } -static inline void fromRawValue(const RawValue &value, ArrayPropsNativeComponentSizes &result) { +constexpr void operator|=( + ArrayPropsNativeComponentSizesMask &lhs, + enum ArrayPropsNativeComponentSizes const rhs) { + lhs = lhs | static_cast(rhs); +} + +static inline void fromRawValue(const RawValue &value, ArrayPropsNativeComponentSizesMask &result) { auto items = std::vector{value}; for (const auto &item : items) { if (item == \\"small\\") { - result = (ArrayPropsNativeComponentSizes)(result | ArrayPropsNativeComponentSizes::Small); + result |= ArrayPropsNativeComponentSizes::Small; continue; } if (item == \\"large\\") { - result = (ArrayPropsNativeComponentSizes)(result | ArrayPropsNativeComponentSizes::Large); + result |= ArrayPropsNativeComponentSizes::Large; continue; } abort(); } } -static inline std::string toString(const ArrayPropsNativeComponentSizes &value) { +static inline std::string toString(const ArrayPropsNativeComponentSizesMask &value) { auto result = std::string{}; auto separator = std::string{\\", \\"}; @@ -83,7 +91,7 @@ class ArrayPropsNativeComponentProps final : public ViewProps { const std::vector colors{}; const std::vector srcs{}; const std::vector points{}; - const ArrayPropsNativeComponentSizes sizes{ArrayPropsNativeComponentSizes::Small}; + const ArrayPropsNativeComponentSizesMask sizes{static_cast(ArrayPropsNativeComponentSizes::Small)}; }; } // namespace react