mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
6bb41d18a4
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
212 lines
6.1 KiB
JavaScript
212 lines
6.1 KiB
JavaScript
/**
|
|
* 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 strict
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import type {ObjectParamTypeAnnotation} from '../../../CodegenSchema';
|
|
const {flatObjects, capitalizeFirstLetter} = require('./Utils');
|
|
|
|
const structTemplate = `
|
|
namespace JS {
|
|
namespace Native::_MODULE_NAME_:: {
|
|
struct ::_STRUCT_NAME_:: {
|
|
|
|
struct Builder {
|
|
struct Input {
|
|
::_INPUT_::
|
|
};
|
|
|
|
/** Initialize with a set of values */
|
|
Builder(const Input i);
|
|
/** Initialize with an existing ::_STRUCT_NAME_:: */
|
|
Builder(::_STRUCT_NAME_:: i);
|
|
/** Builds the object. Generally used only by the infrastructure. */
|
|
NSDictionary *buildUnsafeRawValue() const { return _factory(); };
|
|
private:
|
|
NSDictionary *(^_factory)(void);
|
|
};
|
|
|
|
static ::_STRUCT_NAME_:: fromUnsafeRawValue(NSDictionary *const v) { return {v}; }
|
|
NSDictionary *unsafeRawValue() const { return _v; }
|
|
private:
|
|
::_STRUCT_NAME_::(NSDictionary *const v) : _v(v) {}
|
|
NSDictionary *_v;
|
|
};
|
|
}
|
|
}
|
|
|
|
inline JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::Builder::Builder(const Input i) : _factory(^{
|
|
NSMutableDictionary *d = [NSMutableDictionary new];
|
|
::_PROPERTIES_::
|
|
return d;
|
|
}) {}
|
|
inline JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::Builder::Builder(::_STRUCT_NAME_:: i) : _factory(^{
|
|
return i.unsafeRawValue();
|
|
}) {}`;
|
|
|
|
function getBuilderInputFieldDeclaration(
|
|
property: ObjectParamTypeAnnotation,
|
|
name: string,
|
|
): string {
|
|
function markRequiredIfNecessary(annotation) {
|
|
if (!property.optional) {
|
|
return 'RCTRequired<' + 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':
|
|
case 'Int32TypeAnnotation':
|
|
return markRequiredIfNecessary('double');
|
|
case 'BooleanTypeAnnotation':
|
|
return markRequiredIfNecessary('bool');
|
|
case 'ObjectTypeAnnotation':
|
|
return markRequiredIfNecessary(
|
|
`JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
|
|
property.name,
|
|
)}::Builder`,
|
|
);
|
|
case 'GenericObjectTypeAnnotation':
|
|
case 'AnyTypeAnnotation':
|
|
if (property.optional) {
|
|
return 'id<NSObject> _Nullable' + property.name + ';';
|
|
}
|
|
return markRequiredIfNecessary('id<NSObject>');
|
|
case 'ArrayTypeAnnotation':
|
|
return markRequiredIfNecessary('std::vector<id<NSObject>>');
|
|
case 'FunctionTypeAnnotation':
|
|
default:
|
|
throw new Error(`Unknown prop type, found: ${typeAnnotation.type}"`);
|
|
}
|
|
}
|
|
|
|
function safeGetter(name: string, optional: boolean) {
|
|
return `
|
|
auto ${name} = i.${name}${optional ? '' : '.get()'};
|
|
d[@"${name}"] = ${name};
|
|
`.trim();
|
|
}
|
|
|
|
function arrayGetter(name: string, optional: boolean) {
|
|
return `
|
|
auto ${name} = i.${name}${optional ? '' : '.get()'};
|
|
d[@"${name}"] = RCTConvert${
|
|
optional ? 'Optional' : ''
|
|
}VecToArray(${name}, ^id(id<NSObject> el_) { return el_; });
|
|
`.trim();
|
|
}
|
|
|
|
function boolGetter(name: string, optional: boolean) {
|
|
return `
|
|
auto ${name} = i.${name}${optional ? '' : '.get()'};
|
|
d[@"${name}"] = ${
|
|
optional
|
|
? `${name}.hasValue() ? @((BOOL)${name}.value()) : nil`
|
|
: `@(${name})`
|
|
};
|
|
`.trim();
|
|
}
|
|
|
|
function numberGetter(name: string, optional: boolean) {
|
|
return `
|
|
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();
|
|
}
|
|
|
|
function getObjectProperty(property: ObjectParamTypeAnnotation): string {
|
|
const {typeAnnotation} = property;
|
|
switch (typeAnnotation.type) {
|
|
case 'NumberTypeAnnotation':
|
|
case 'FloatTypeAnnotation':
|
|
case 'Int32TypeAnnotation':
|
|
return numberGetter(property.name, property.optional);
|
|
case 'BooleanTypeAnnotation':
|
|
return boolGetter(property.name, property.optional);
|
|
case 'StringTypeAnnotation':
|
|
case 'GenericObjectTypeAnnotation':
|
|
case 'AnyTypeAnnotation':
|
|
return safeGetter(property.name, property.optional);
|
|
case 'ObjectTypeAnnotation':
|
|
return unsafeGetter(property.name, property.optional);
|
|
case 'ArrayTypeAnnotation':
|
|
return arrayGetter(property.name, property.optional);
|
|
case 'FunctionTypeAnnotation':
|
|
default:
|
|
throw new Error(`Unknown prop type, found: ${typeAnnotation.type}"`);
|
|
}
|
|
}
|
|
|
|
function generateStructsForConstants(
|
|
annotations: $ReadOnlyArray<
|
|
$ReadOnly<{|
|
|
name: string,
|
|
object: $ReadOnly<{|
|
|
type: 'ObjectTypeAnnotation',
|
|
properties: $ReadOnlyArray<ObjectParamTypeAnnotation>,
|
|
|}>,
|
|
|}>,
|
|
>,
|
|
): string {
|
|
return flatObjects(annotations, true)
|
|
.reduce(
|
|
(acc, object) =>
|
|
acc.concat(
|
|
structTemplate
|
|
.replace(
|
|
/::_INPUT_::/g,
|
|
object.properties
|
|
.map(property =>
|
|
getBuilderInputFieldDeclaration(property, object.name),
|
|
)
|
|
.join('\n '),
|
|
)
|
|
.replace(
|
|
/::_PROPERTIES_::/g,
|
|
object.properties
|
|
.map(property => getObjectProperty(property))
|
|
.join('\n'),
|
|
)
|
|
.replace(/::_STRUCT_NAME_::/g, object.name),
|
|
),
|
|
[],
|
|
)
|
|
.reverse()
|
|
.join('\n')
|
|
.replace(/SpecGetConstantsReturnType/g, 'Constants')
|
|
.replace(/GetConstantsReturnType/g, 'Constants');
|
|
}
|
|
module.exports = {
|
|
generateStructsForConstants,
|
|
capitalizeFirstLetter,
|
|
};
|