From 6bb41d18a47e8aeb9e27db192fc5c0daa9dc1284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Osadnik?= Date: Fri, 2 Aug 2019 07:17:51 -0700 Subject: [PATCH] Add handling of optionals for generating constants structs Summary: In this diff I add handling optional values in constants object. Behaviour is slightly different when it comes to string, objects etc., so I add tests for every of these cases. Reviewed By: RSNara Differential Revision: D16599254 fbshipit-source-id: 380c5235fefeb70a521733369011e0051e18859a --- .../NativeOptionalObjectTurboModule.js | 38 ++++++++++++ .../modules/ObjCppUtils/GenerateStructs.js | 2 +- .../GenerateStructsForConstants.js | 60 ++++++++++++++----- 3 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js new file mode 100644 index 00000000000..e53d24df29f --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js @@ -0,0 +1,38 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getConstants: () => {| + D?: ?boolean, + A?: Array, + G?: any, + E?: ?{| + D?: ?boolean, + E?: ?{| + D?: ?boolean, + E?: ?{| + D?: boolean, + E?: number, + F?: string, + |}, + F?: string, + |}, + F?: string, + |}, + F?: string, + |}; +} + +export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js index 30743826ba9..728574f96be 100644 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js +++ b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js @@ -119,7 +119,7 @@ function getInlineMethodImplementation( return inlineTemplate .replace( /::_RETURN_TYPE_::/, - 'facebook::react::LazyVector> *', + 'facebook::react::LazyVector> +', ) .replace( /::_RETURN_VALUE_::/, diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js index a352af5d281..a8f7e8370bd 100644 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js +++ b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js @@ -59,11 +59,14 @@ function getBuilderInputFieldDeclaration( if (!property.optional) { return 'RCTRequired<' + annotation + '> ' + property.name + ';'; } - return annotation + ' ' + property.name + ';'; + return 'folly::Optional<' + annotation + '> ' + property.name + ';'; } const {typeAnnotation} = property; switch (typeAnnotation.type) { case 'StringTypeAnnotation': + if (property.optional) { + return 'NSString *' + property.name + ';'; + } return markRequiredIfNecessary('NSString *'); case 'NumberTypeAnnotation': case 'FloatTypeAnnotation': @@ -79,6 +82,9 @@ function getBuilderInputFieldDeclaration( ); case 'GenericObjectTypeAnnotation': case 'AnyTypeAnnotation': + if (property.optional) { + return 'id _Nullable' + property.name + ';'; + } return markRequiredIfNecessary('id'); case 'ArrayTypeAnnotation': return markRequiredIfNecessary('std::vector>'); @@ -88,31 +94,52 @@ function getBuilderInputFieldDeclaration( } } -function safeGetter(name: string) { +function safeGetter(name: string, optional: boolean) { return ` - auto ${name} = i.${name}.get(); + auto ${name} = i.${name}${optional ? '' : '.get()'}; d[@"${name}"] = ${name}; `.trim(); } -function arrayGetter(name: string) { +function arrayGetter(name: string, optional: boolean) { return ` - auto ${name} = i.${name}.get(); - d[@"${name}"] = RCTConvertVecToArray(${name}, ^id(id el_) { return el_; }); + auto ${name} = i.${name}${optional ? '' : '.get()'}; + d[@"${name}"] = RCTConvert${ + optional ? 'Optional' : '' + }VecToArray(${name}, ^id(id el_) { return el_; }); `.trim(); } -function numberAndBoolGetter(name: string) { +function boolGetter(name: string, optional: boolean) { return ` - auto ${name} = i.${name}.get(); - d[@"${name}"] = @(${name}); + auto ${name} = i.${name}${optional ? '' : '.get()'}; + d[@"${name}"] = ${ + optional + ? `${name}.hasValue() ? @((BOOL)${name}.value()) : nil` + : `@(${name})` + }; `.trim(); } -function unsafeGetter(name: string) { +function numberGetter(name: string, optional: boolean) { return ` - auto ${name} = i.${name}.get(); - d[@"${name}"] = ${name}.buildUnsafeRawValue(); + auto ${name} = i.${name}${optional ? '' : '.get()'}; + d[@"${name}"] = ${ + optional + ? `${name}.hasValue() ? @((double)${name}.value()) : nil` + : `@(${name})` + }; + `.trim(); +} + +function unsafeGetter(name: string, optional: boolean) { + return ` + auto ${name} = i.${name}${optional ? '' : '.get()'}; + d[@"${name}"] = ${ + optional + ? `${name}.hasValue() ? ${name}.value().buildUnsafeRawValue() : nil` + : `${name}.buildUnsafeRawValue()` + }; `.trim(); } @@ -122,16 +149,17 @@ function getObjectProperty(property: ObjectParamTypeAnnotation): string { case 'NumberTypeAnnotation': case 'FloatTypeAnnotation': case 'Int32TypeAnnotation': + return numberGetter(property.name, property.optional); case 'BooleanTypeAnnotation': - return numberAndBoolGetter(property.name); + return boolGetter(property.name, property.optional); case 'StringTypeAnnotation': case 'GenericObjectTypeAnnotation': case 'AnyTypeAnnotation': - return safeGetter(property.name); + return safeGetter(property.name, property.optional); case 'ObjectTypeAnnotation': - return unsafeGetter(property.name); + return unsafeGetter(property.name, property.optional); case 'ArrayTypeAnnotation': - return arrayGetter(property.name); + return arrayGetter(property.name, property.optional); case 'FunctionTypeAnnotation': default: throw new Error(`Unknown prop type, found: ${typeAnnotation.type}"`);