UNPKG

nitro-codegen

Version:

The code-generator for react-native-nitro-modules.

119 lines (106 loc) 4.34 kB
import { NitroConfig } from '../../config/NitroConfig.js'; import { includeHeader } from '../../syntax/c++/includeNitroHeader.js'; import { getAllKnownTypes } from '../../syntax/createType.js'; import { createFileMetadataString, isNotDuplicate, } from '../../syntax/helpers.js'; import { getReferencedTypes } from '../../syntax/getReferencedTypes.js'; import { SwiftCxxBridgedType } from '../../syntax/swift/SwiftCxxBridgedType.js'; import { filterDuplicateHelperBridges, indent } from '../../utils.js'; import { getTypeAs } from '../../syntax/types/getTypeAs.js'; import { HybridObjectType } from '../../syntax/types/HybridObjectType.js'; import { getForwardDeclaration } from '../../syntax/c++/getForwardDeclaration.js'; import { getHybridObjectName } from '../../syntax/getHybridObjectName.js'; const SWIFT_BRIDGE_NAMESPACE = ['bridge', 'swift']; export function createSwiftCxxBridge() { const moduleName = NitroConfig.getIosModuleName(); const bridgeName = `${moduleName}-Swift-Cxx-Bridge`; const types = getAllKnownTypes('swift').map((t) => new SwiftCxxBridgedType(t)); const bridges = types .flatMap((t) => { const referenced = getReferencedTypes(t.type); return referenced.map((r) => { const bridge = new SwiftCxxBridgedType(r); return bridge.getRequiredBridge(); }); }) .filter((b) => b != null) .flatMap((b) => [b, ...b?.dependencies]) .filter(filterDuplicateHelperBridges); const headerHelperFunctions = bridges .map((b) => `// pragma MARK: ${b.cxxType}\n${b.cxxHeader.code}`) .filter(isNotDuplicate) .join('\n\n'); const implementationHelperFunctions = bridges .map((b) => { if (b.cxxImplementation == null) return undefined; else return `// pragma MARK: ${b.cxxType}\n${b.cxxImplementation.code}`; }) .filter((c) => c != null) .filter(isNotDuplicate) .join('\n\n'); const requiredImportsHeader = bridges.flatMap((b) => b.cxxHeader.requiredIncludes); const includesHeader = requiredImportsHeader .map((i) => includeHeader(i, true)) .filter(isNotDuplicate); const forwardDeclarationsHeader = requiredImportsHeader .map((i) => i.forwardDeclaration) .filter((f) => f != null) .filter(isNotDuplicate); const includesImplementation = bridges .flatMap((b) => b.cxxImplementation?.requiredIncludes) .filter((i) => i != null) .map((i) => includeHeader(i, true)) .filter(isNotDuplicate); const namespace = NitroConfig.getCxxNamespace('c++', ...SWIFT_BRIDGE_NAMESPACE); const forwardDeclaredSwiftTypes = types .filter((t) => t.type.kind === 'hybrid-object') .map((t) => { const hybridObject = getTypeAs(t.type, HybridObjectType); const { HybridTSpecCxx } = getHybridObjectName(hybridObject.hybridObjectName); return getForwardDeclaration('class', HybridTSpecCxx, moduleName); }) .filter(isNotDuplicate); const header = ` ${createFileMetadataString(`${bridgeName}.hpp`)} #pragma once // Forward declarations of C++ defined types ${forwardDeclarationsHeader.sort().join('\n')} // Forward declarations of Swift defined types ${forwardDeclaredSwiftTypes.sort().join('\n')} // Include C++ defined types ${includesHeader.sort().join('\n')} /** * Contains specialized versions of C++ templated types so they can be accessed from Swift, * as well as helper functions to interact with those C++ types from Swift. */ namespace ${namespace} { ${indent(headerHelperFunctions, ' ')} } // namespace ${namespace} `; const source = ` ${createFileMetadataString(`${bridgeName}.cpp`)} #include "${bridgeName}.hpp" // Include C++ implementation defined types ${includesImplementation.sort().join('\n')} namespace ${namespace} { ${indent(implementationHelperFunctions, ' ')} } // namespace ${namespace} `; const files = []; files.push({ content: header, language: 'c++', name: `${bridgeName}.hpp`, platform: 'ios', subdirectory: [], }); files.push({ content: source, language: 'c++', name: `${bridgeName}.cpp`, platform: 'ios', subdirectory: [], }); return files; }