GenerateModuleJniCpp: Replace string replace with string templates

Summary:
## Benefits:
- Improved Readability
- Improved type-safety with templates

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D24386280

fbshipit-source-id: 9af78d8aabd86a6afb53660ff97d550973e5d11b
This commit is contained in:
Ramanpreet Nara 2020-10-19 21:56:26 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 35ee7c8246
Коммит 5a73af684d
2 изменённых файлов: 120 добавлений и 91 удалений

Просмотреть файл

@ -26,33 +26,78 @@ const {unwrapNullable} = require('../../parsers/flow/modules/utils');
type FilesOutput = Map<string, string>; type FilesOutput = Map<string, string>;
const propertyHeaderTemplate = type JSReturnType =
'static facebook::jsi::Value __hostFunction_::_HASTE_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {'; | 'VoidKind'
| 'StringKind'
| 'BooleanKind'
| 'NumberKind'
| 'PromiseKind'
| 'ObjectKind'
| 'ArrayKind';
const propertyCastTemplate = const HostFunctionTemplate = ({
'static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ::_KIND_::, "::_PROPERTY_NAME_::", "::_SIGNATURE_::", args, count);'; hasteModuleName,
propertyName,
const propertyTemplate = ` jniSignature,
${propertyHeaderTemplate} jsReturnType,
return ${propertyCastTemplate} }: $ReadOnly<{|
hasteModuleName: string,
propertyName: string,
jniSignature: string,
jsReturnType: JSReturnType,
|}>) => {
return `static facebook::jsi::Value __hostFunction_${hasteModuleName}SpecJSI_${propertyName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ${jsReturnType}, "${propertyName}", "${jniSignature}", args, count);
}`; }`;
};
const propertyDefTemplate = const ModuleClassConstructorTemplate = ({
' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_::_HASTE_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::};'; hasteModuleName,
methods,
const moduleTemplate = ` }: $ReadOnly<{|
::_TURBOMODULE_METHOD_INVOKERS_:: hasteModuleName: string,
methods: $ReadOnlyArray<{|
::_HASTE_MODULE_NAME_::SpecJSI::::_HASTE_MODULE_NAME_::SpecJSI(const JavaTurboModule::InitParams &params) propertyName: string,
argCount: number,
|}>,
|}>) => {
return `
${hasteModuleName}SpecJSI::${hasteModuleName}SpecJSI(const JavaTurboModule::InitParams &params)
: JavaTurboModule(params) { : JavaTurboModule(params) {
::_PROPERTIES_MAP_:: ${methods
.map(({propertyName, argCount}) => {
return ` methodMap_["${propertyName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${propertyName}};`;
})
.join('\n')}
}`.trim(); }`.trim();
};
const oneModuleLookupTemplate = ` if (moduleName == "::_NATIVE_MODULE_NAME_::") { const ModuleLookupTemplate = ({
return std::make_shared<::_HASTE_MODULE_NAME_::SpecJSI>(params); moduleName,
hasteModuleName,
}: $ReadOnly<{|moduleName: string, hasteModuleName: string|}>) => {
return ` if (moduleName == "${moduleName}") {
return std::make_shared<${hasteModuleName}SpecJSI>(params);
}`; }`;
};
const template = ` const FileTemplate = ({
libraryName,
include,
modules,
moduleLookups,
}: $ReadOnly<{|
libraryName: string,
include: string,
modules: string,
moduleLookups: $ReadOnlyArray<
$ReadOnly<{|
hasteModuleName: string,
moduleName: string,
|}>,
>,
|}>) => {
return `
/** /**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates. * ${'C'}opyright (c) Facebook, Inc. and its affiliates.
* *
@ -62,26 +107,27 @@ const template = `
* ${'@'}generated by codegen project: GenerateModuleJniCpp.js * ${'@'}generated by codegen project: GenerateModuleJniCpp.js
*/ */
#include ::_INCLUDE_:: #include ${include}
namespace facebook { namespace facebook {
namespace react { namespace react {
::_MODULES_:: ${modules}
std::shared_ptr<TurboModule> ::_LIBRARY_NAME_::_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) { std::shared_ptr<TurboModule> ${libraryName}_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
::_MODULE_LOOKUP_:: ${moduleLookups.map(ModuleLookupTemplate).join('\n')}
return nullptr; return nullptr;
} }
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook
`; `;
};
function translateReturnTypeToKind( function translateReturnTypeToKind(
nullableTypeAnnotation: Nullable<NativeModuleReturnTypeAnnotation>, nullableTypeAnnotation: Nullable<NativeModuleReturnTypeAnnotation>,
resolveAlias: AliasResolver, resolveAlias: AliasResolver,
): string { ): JSReturnType {
const [typeAnnotation] = unwrapNullable<NativeModuleReturnTypeAnnotation>( const [typeAnnotation] = unwrapNullable<NativeModuleReturnTypeAnnotation>(
nullableTypeAnnotation, nullableTypeAnnotation,
); );
@ -278,6 +324,7 @@ function translateMethodTypeToJniSignature(
} }
function translateMethodForImplementation( function translateMethodForImplementation(
hasteModuleName: string,
property: NativeModulePropertySchema, property: NativeModulePropertySchema,
resolveAlias: AliasResolver, resolveAlias: AliasResolver,
): string { ): string {
@ -288,41 +335,20 @@ function translateMethodForImplementation(
); );
const {returnTypeAnnotation} = propertyTypeAnnotation; const {returnTypeAnnotation} = propertyTypeAnnotation;
const numberOfParams =
propertyTypeAnnotation.params.length +
(returnTypeAnnotation.type === 'PromiseTypeAnnotation' ? 1 : 0);
const translatedArguments = propertyTypeAnnotation.params
.map(param => param.name)
.concat(
returnTypeAnnotation.type === 'PromiseTypeAnnotation' ? ['promise'] : [],
)
.slice(1)
.join(':')
.concat(':');
if ( if (
property.name === 'getConstants' && property.name === 'getConstants' &&
returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' &&
returnTypeAnnotation.properties &&
returnTypeAnnotation.properties.length === 0 returnTypeAnnotation.properties.length === 0
) { ) {
return ''; return '';
} }
return propertyTemplate
.replace( return HostFunctionTemplate({
/::_KIND_::/g, hasteModuleName,
translateReturnTypeToKind(returnTypeAnnotation, resolveAlias), propertyName: property.name,
) jniSignature: translateMethodTypeToJniSignature(property, resolveAlias),
.replace(/::_PROPERTY_NAME_::/g, property.name) jsReturnType: translateReturnTypeToKind(returnTypeAnnotation, resolveAlias),
.replace( });
/::_ARGS_::/g,
numberOfParams === 0
? ''
: (numberOfParams === 1 ? '' : ':') + translatedArguments,
)
.replace(
/::_SIGNATURE_::/g,
translateMethodTypeToJniSignature(property, resolveAlias),
);
} }
module.exports = { module.exports = {
@ -351,14 +377,20 @@ module.exports = {
const translatedMethods = properties const translatedMethods = properties
.map(property => .map(property =>
translateMethodForImplementation(property, resolveAlias), translateMethodForImplementation(
hasteModuleName,
property,
resolveAlias,
),
) )
.join('\n'); .join('\n\n');
return moduleTemplate
.replace(/::_TURBOMODULE_METHOD_INVOKERS_::/g, translatedMethods) return (
.replace( translatedMethods +
'::_PROPERTIES_MAP_::', '\n\n' +
properties ModuleClassConstructorTemplate({
hasteModuleName,
methods: properties
.map(({name: propertyName, typeAnnotation}) => { .map(({name: propertyName, typeAnnotation}) => {
const [ const [
{returnTypeAnnotation, params}, {returnTypeAnnotation, params},
@ -366,22 +398,27 @@ module.exports = {
typeAnnotation, typeAnnotation,
); );
return propertyName === 'getConstants' && if (
propertyName === 'getConstants' &&
returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' &&
returnTypeAnnotation.properties && returnTypeAnnotation.properties &&
returnTypeAnnotation.properties.length === 0 returnTypeAnnotation.properties.length === 0
? '' ) {
: propertyDefTemplate return null;
.replace(/::_PROPERTY_NAME_::/g, propertyName) }
.replace(/::_ARGS_COUNT_::/g, params.length.toString());
return {
propertyName,
argCount: params.length,
};
}) })
.join('\n'), .filter(Boolean),
) })
.replace(/::_HASTE_MODULE_NAME_::/g, hasteModuleName); );
}) })
.join('\n'); .join('\n');
const moduleLookup = Object.keys(nativeModules) const moduleLookups = Object.keys(nativeModules)
.filter(hasteModuleName => { .filter(hasteModuleName => {
const module = nativeModules[hasteModuleName]; const module = nativeModules[hasteModuleName];
return !( return !(
@ -401,24 +438,23 @@ module.exports = {
} }
return 0; return 0;
}) })
.map(hasteModuleName => { .flatMap<{|moduleName: string, hasteModuleName: string|}>(
const {moduleNames} = nativeModules[hasteModuleName]; (hasteModuleName: string) => {
return moduleNames const {moduleNames} = nativeModules[hasteModuleName];
.map(nativeModuleName => return moduleNames.map(moduleName => ({
oneModuleLookupTemplate moduleName,
.replace(/::_NATIVE_MODULE_NAME_::/g, nativeModuleName) hasteModuleName,
.replace(/::_HASTE_MODULE_NAME_::/g, hasteModuleName), }));
) },
.join('\n'); );
})
.join('\n');
const fileName = `${moduleSpecName}-generated.cpp`; const fileName = `${moduleSpecName}-generated.cpp`;
const replacedTemplate = template const replacedTemplate = FileTemplate({
.replace(/::_MODULES_::/g, modules) modules: modules,
.replace(/::_LIBRARY_NAME_::/g, libraryName) libraryName,
.replace(/::_MODULE_LOOKUP_::/g, moduleLookup) moduleLookups,
.replace(/::_INCLUDE_::/g, `"${moduleSpecName}.h"`); include: `"${moduleSpecName}.h"`,
});
return new Map([[fileName, replacedTemplate]]); return new Map([[fileName, replacedTemplate]]);
}, },
}; };

Просмотреть файл

@ -17,7 +17,6 @@ Map {
namespace facebook { namespace facebook {
namespace react { namespace react {
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, \\"difficult\\", \\"(Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;\\", args, count); return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, \\"difficult\\", \\"(Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;\\", args, count);
} }
@ -117,7 +116,6 @@ static facebook::jsi::Value __hostFunction_AliasTurboModuleSpecJSI_cropImage(fac
AliasTurboModuleSpecJSI::AliasTurboModuleSpecJSI(const JavaTurboModule::InitParams &params) AliasTurboModuleSpecJSI::AliasTurboModuleSpecJSI(const JavaTurboModule::InitParams &params)
: JavaTurboModule(params) { : JavaTurboModule(params) {
methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_AliasTurboModuleSpecJSI_cropImage}; methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_AliasTurboModuleSpecJSI_cropImage};
} }
@ -167,12 +165,10 @@ static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_delete
NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const JavaTurboModule::InitParams &params) NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const JavaTurboModule::InitParams &params)
: JavaTurboModule(params) { : JavaTurboModule(params) {
methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos}; methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos};
methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll}; methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll};
methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos}; methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos};
} }
static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, VoidKind, \\"reportFatalException\\", \\"(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;D)V\\", args, count); return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, VoidKind, \\"reportFatalException\\", \\"(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;D)V\\", args, count);
} }
@ -235,7 +231,6 @@ Map {
namespace facebook { namespace facebook {
namespace react { namespace react {
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getConstants\\", \\"()Ljava/util/Map;\\", args, count); return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getConstants\\", \\"()Ljava/util/Map;\\", args, count);
} }
@ -325,7 +320,6 @@ Map {
namespace facebook { namespace facebook {
namespace react { namespace react {
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count); return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count);
} }
@ -342,7 +336,6 @@ static facebook::jsi::Value __hostFunction_NativeSampleTurboModule2SpecJSI_voidF
NativeSampleTurboModule2SpecJSI::NativeSampleTurboModule2SpecJSI(const JavaTurboModule::InitParams &params) NativeSampleTurboModule2SpecJSI::NativeSampleTurboModule2SpecJSI(const JavaTurboModule::InitParams &params)
: JavaTurboModule(params) { : JavaTurboModule(params) {
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc}; methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc};
} }