/** * 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 {SchemaType} from '../../../CodegenSchema'; import type {MethodSerializationOutput} from './serializeMethod'; const {createAliasResolver, getModules} = require('../Utils'); const {StructCollector} = require('./StructCollector'); const {serializeStruct} = require('./header/serializeStruct'); const {serializeMethod} = require('./serializeMethod'); const {serializeModuleSource} = require('./source/serializeModule'); type FilesOutput = Map; const ModuleDeclarationTemplate = ({ moduleName, structDeclarations, protocolMethods, }: $ReadOnly<{| moduleName: string, structDeclarations: string, protocolMethods: string, |}>) => ` ${structDeclarations} @protocol Native${moduleName}Spec ${protocolMethods} @end namespace facebook { namespace react { /** * ObjC++ class for module '${moduleName}' */ class JSI_EXPORT Native${moduleName}SpecJSI : public ObjCTurboModule { public: Native${moduleName}SpecJSI(const ObjCTurboModule::InitParams ¶ms); }; } // namespace react } // namespace facebook `; const HeaderFileTemplate = ({ moduleDeclarations, structInlineMethods, }: $ReadOnly<{| moduleDeclarations: string, structInlineMethods: string, |}>) => ` /** * ${'C'}opyright (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. * * ${'@'}generated by codegen project: GenerateModuleHObjCpp.js */ #ifndef __cplusplus #error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. #endif #import #import #import #import #import #import #import #import #import #import ${moduleDeclarations} ${structInlineMethods} `; const SourceFileTemplate = ({ headerFileName, moduleImplementations, }: $ReadOnly<{| headerFileName: string, moduleImplementations: string, |}>) => ` /** * ${'C'}opyright (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. * * ${'@'}generated by an internal genrule from Flow types. * * We create an umbrella header (and corresponding implementation) here since * Cxx compilation in BUCK has a limitation: source-code producing genrule()s * must have a single output. More files => more genrule()s => slower builds. */ #import "${headerFileName}" ${moduleImplementations} `; module.exports = { generate( libraryName: string, schema: SchemaType, moduleSpecName: string, ): FilesOutput { const nativeModules = getModules(schema); const moduleDeclarations: Array = []; const structInlineMethods: Array = []; const moduleImplementations: Array = []; const moduleNames: Array = Object.keys(nativeModules).sort(); for (const moduleName of moduleNames) { const {aliases, properties} = nativeModules[moduleName]; const resolveAlias = createAliasResolver(aliases); const structCollector = new StructCollector(); const methodSerializations: Array = []; const serializeProperty = property => { methodSerializations.push( ...serializeMethod( moduleName, property, structCollector, resolveAlias, ), ); }; /** * Note: As we serialize NativeModule methods, we insert structs into * StructCollector, as we encounter them. */ properties .filter(property => property.name !== 'getConstants') .forEach(serializeProperty); properties .filter(property => property.name === 'getConstants') .forEach(serializeProperty); const generatedStructs = structCollector.getAllStructs(); const structStrs = []; const methodStrs = []; for (const struct of generatedStructs) { const {methods, declaration} = serializeStruct(moduleName, struct); structStrs.push(declaration); methodStrs.push(methods); } moduleDeclarations.push( ModuleDeclarationTemplate({ moduleName: moduleName, structDeclarations: structStrs.join('\n'), protocolMethods: methodSerializations .map(({protocolMethod}) => protocolMethod) .join('\n'), }), ); structInlineMethods.push(methodStrs.join('\n')); moduleImplementations.push( serializeModuleSource( moduleName, generatedStructs, methodSerializations.filter( ({selector}) => selector !== '@selector(constantsToExport)', ), ), ); } const headerFileName = `${moduleSpecName}.h`; const headerFile = HeaderFileTemplate({ moduleDeclarations: moduleDeclarations.join('\n'), structInlineMethods: structInlineMethods.join('\n'), }); const sourceFileName = `${moduleSpecName}-generated.mm`; const sourceFile = SourceFileTemplate({ headerFileName, moduleImplementations: moduleImplementations.join('\n'), }); return new Map([ [headerFileName, headerFile], [sourceFileName, sourceFile], ]); }, };