mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
GenerateModuleCpp: Replace string replace with string templates
Summary: ## Benefits: - Improved Readability - Improved type-safety with templates Changelog: [Internal] Differential Revision: D24386276 fbshipit-source-id: d5913122221960c06c5256af10ace1d2f7a60b49
This commit is contained in:
committed by
Facebook GitHub Bot
parent
de32fd2539
commit
33789ba0ea
+93
-64
@@ -24,32 +24,60 @@ const {unwrapNullable} = require('../../parsers/flow/modules/utils');
|
||||
|
||||
type FilesOutput = Map<string, string>;
|
||||
|
||||
const propertyHeaderTemplate =
|
||||
'static jsi::Value __hostFunction_::_HASTE_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {';
|
||||
const HostFunctionTemplate = ({
|
||||
hasteModuleName,
|
||||
methodName,
|
||||
isVoid,
|
||||
args,
|
||||
}: $ReadOnly<{
|
||||
hasteModuleName: string,
|
||||
methodName: string,
|
||||
isVoid: boolean,
|
||||
args: Array<string>,
|
||||
}>) => {
|
||||
const methodCallArgs = ['rt', ...args].join(', ');
|
||||
const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs});`;
|
||||
|
||||
const propertyCastTemplate =
|
||||
'static_cast<::_HASTE_MODULE_NAME_::CxxSpecJSI *>(&turboModule)->::_PROPERTY_NAME_::(rt::_ARGS_::);';
|
||||
|
||||
const nonvoidPropertyTemplate = `${propertyHeaderTemplate}
|
||||
return ${propertyCastTemplate}
|
||||
}`.trim();
|
||||
|
||||
const voidPropertyTemplate = `${propertyHeaderTemplate}
|
||||
${propertyCastTemplate}
|
||||
return jsi::Value::undefined();
|
||||
return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${
|
||||
isVoid ? `\n ${methodCall}` : ''
|
||||
}
|
||||
return ${isVoid ? 'jsi::Value::undefined();' : methodCall}
|
||||
}`;
|
||||
};
|
||||
|
||||
const proprertyDefTemplate =
|
||||
' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_::_HASTE_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::};';
|
||||
const ModuleTemplate = ({
|
||||
hasteModuleName,
|
||||
hostFunctions,
|
||||
moduleName,
|
||||
methods,
|
||||
}: $ReadOnly<{|
|
||||
hasteModuleName: string,
|
||||
hostFunctions: $ReadOnlyArray<string>,
|
||||
moduleName: string,
|
||||
methods: $ReadOnlyArray<
|
||||
$ReadOnly<{|methodName: string, paramCount: number|}>,
|
||||
>,
|
||||
|}>) => {
|
||||
return `${hostFunctions.join('\n')}
|
||||
|
||||
const moduleTemplate = `::_MODULE_PROPERTIES_::
|
||||
${hasteModuleName}CxxSpecJSI::${hasteModuleName}CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: TurboModule("${moduleName}", jsInvoker) {
|
||||
${methods
|
||||
.map(({methodName, paramCount}) => {
|
||||
return ` methodMap_["${methodName}"] = MethodMetadata {${paramCount}, __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}};`;
|
||||
})
|
||||
.join('\n')}
|
||||
}`;
|
||||
};
|
||||
|
||||
::_HASTE_MODULE_NAME_::CxxSpecJSI::::_HASTE_MODULE_NAME_::CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: TurboModule("::_NATIVE_MODULE_NAME_::", jsInvoker) {
|
||||
::_PROPERTIES_MAP_::
|
||||
}`.trim();
|
||||
|
||||
const template = `/**
|
||||
const FileTemplate = ({
|
||||
libraryName,
|
||||
modules,
|
||||
}: $ReadOnly<{
|
||||
libraryName: string,
|
||||
modules: string,
|
||||
}>) => {
|
||||
return `/**
|
||||
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
@@ -58,19 +86,20 @@ const template = `/**
|
||||
* ${'@'}generated by codegen project: GenerateModuleH.js
|
||||
*/
|
||||
|
||||
#include <react/modules/::_LIBRARY_NAME_::/NativeModules.h>
|
||||
#include <react/modules/${libraryName}/NativeModules.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
::_MODULES_::
|
||||
${modules}
|
||||
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
`;
|
||||
};
|
||||
|
||||
function traverseArg(
|
||||
function serializeArg(
|
||||
arg: NativeModuleMethodParamSchema,
|
||||
index: number,
|
||||
resolveAlias: AliasResolver,
|
||||
@@ -127,7 +156,8 @@ function traverseArg(
|
||||
}
|
||||
}
|
||||
|
||||
function traverseProperty(
|
||||
function serializePropertyIntoHostFunction(
|
||||
hasteModuleName: string,
|
||||
property: NativeModulePropertySchema,
|
||||
resolveAlias: AliasResolver,
|
||||
): string {
|
||||
@@ -136,16 +166,17 @@ function traverseProperty(
|
||||
] = unwrapNullable<NativeModuleFunctionTypeAnnotation>(
|
||||
property.typeAnnotation,
|
||||
);
|
||||
const propertyTemplate =
|
||||
propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation'
|
||||
? voidPropertyTemplate
|
||||
: nonvoidPropertyTemplate;
|
||||
const traversedArgs = propertyTypeAnnotation.params
|
||||
.map((p, i) => traverseArg(p, i, resolveAlias))
|
||||
.join(', ');
|
||||
return propertyTemplate
|
||||
.replace(/::_PROPERTY_NAME_::/g, property.name)
|
||||
.replace(/::_ARGS_::/g, traversedArgs === '' ? '' : ', ' + traversedArgs);
|
||||
const isVoid =
|
||||
propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation';
|
||||
|
||||
return HostFunctionTemplate({
|
||||
hasteModuleName,
|
||||
methodName: property.name,
|
||||
isVoid,
|
||||
args: propertyTypeAnnotation.params.map((p, i) =>
|
||||
serializeArg(p, i, resolveAlias),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@@ -157,7 +188,7 @@ module.exports = {
|
||||
const nativeModules = getModules(schema);
|
||||
|
||||
const modules = Object.keys(nativeModules)
|
||||
.map(hasteModuleName => {
|
||||
.map((hasteModuleName: string) => {
|
||||
const nativeModule = nativeModules[hasteModuleName];
|
||||
const {
|
||||
aliases,
|
||||
@@ -165,39 +196,37 @@ module.exports = {
|
||||
moduleNames,
|
||||
} = nativeModule;
|
||||
const resolveAlias = createAliasResolver(aliases);
|
||||
const traversedProperties = properties
|
||||
.map(property => traverseProperty(property, resolveAlias))
|
||||
.join('\n');
|
||||
return (
|
||||
moduleTemplate
|
||||
.replace(/::_MODULE_PROPERTIES_::/g, traversedProperties)
|
||||
// TODO: What happens when there are more than one NativeModule requires?
|
||||
.replace('::_NATIVE_MODULE_NAME_::', moduleNames[0])
|
||||
.replace(
|
||||
'::_PROPERTIES_MAP_::',
|
||||
properties
|
||||
.map(
|
||||
({
|
||||
name: propertyName,
|
||||
typeAnnotation: nullableTypeAnnotation,
|
||||
}) => {
|
||||
const [{params}] = unwrapNullable(nullableTypeAnnotation);
|
||||
return proprertyDefTemplate
|
||||
.replace(/::_PROPERTY_NAME_::/g, propertyName)
|
||||
.replace(/::_ARGS_COUNT_::/g, params.length.toString());
|
||||
},
|
||||
)
|
||||
.join('\n'),
|
||||
)
|
||||
.replace(/::_HASTE_MODULE_NAME_::/g, hasteModuleName)
|
||||
const hostFunctions = properties.map(property =>
|
||||
serializePropertyIntoHostFunction(
|
||||
hasteModuleName,
|
||||
property,
|
||||
resolveAlias,
|
||||
),
|
||||
);
|
||||
|
||||
return ModuleTemplate({
|
||||
hasteModuleName,
|
||||
hostFunctions,
|
||||
// TODO: What happens when there are more than one NativeModule requires?
|
||||
moduleName: moduleNames[0],
|
||||
methods: properties.map(
|
||||
({name: propertyName, typeAnnotation: nullableTypeAnnotation}) => {
|
||||
const [{params}] = unwrapNullable(nullableTypeAnnotation);
|
||||
return {
|
||||
methodName: propertyName,
|
||||
paramCount: params.length,
|
||||
};
|
||||
},
|
||||
),
|
||||
});
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
const fileName = 'NativeModules.cpp';
|
||||
const replacedTemplate = template
|
||||
.replace(/::_MODULES_::/g, modules)
|
||||
.replace(/::_LIBRARY_NAME_::/g, libraryName);
|
||||
const replacedTemplate = FileTemplate({
|
||||
modules,
|
||||
libraryName,
|
||||
});
|
||||
return new Map([[fileName, replacedTemplate]]);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user