func serialize()

in Generator/Sources/NeedleFramework/Generating/Serializers/OutputSerializer.swift [40:156]


    func serialize() -> String {
        // Dependency factories have deterministic names, so we can only define a
        // factory once, or the code won't compile.
        var registeredFactories: Set<String> = []
        // We generate parent traversal functions to improve compile time on large
        // codebases. This tells us how many levels deep the tree goes.
        var maxLevel: Int = 1

        let providersSection = providers
            .map { (provider: SerializedProvider) in
                if let providerMaxLevel = provider.attributes.maxLevel {
                    if providerMaxLevel > maxLevel {
                        maxLevel = providerMaxLevel
                    }
                }
                if let factoryName = provider.attributes.factoryName {
                    if registeredFactories.contains(factoryName) {
                        return ""
                    }
                    registeredFactories.insert(factoryName)
                }
                return provider.content
            }
            .joined()

        let dynamicProvidersSection = dynamicProviders
            .map { (provider: SerializedProvider) in provider.content }
            .joined()
    
        let traversalHelpers = (1...maxLevel).map { num in
            return """
            private func parent\(num)(_ component: NeedleFoundation.Scope) -> NeedleFoundation.Scope {
                return component\(String(repeating: ".parent", count: num))
            }
            """
        }.joined(separator: "\n\n")
        
        let needleDependenciesHash = needleVersionHash.map { return "\"\($0)\""} ?? "nil"

        let importsJoined = imports.joined(separator: "\n")

        // With Swift 5.6 and an amd64 target, having a function body that is
        // thousands of lines long causes a severe compile performance
        // regression. We were seeing compilation take 4.5x what an x86_64
        // target would take. As a result, this code splits the calls to
        // register the dependencies into functions around 50 lines long.
        // Through some basic testing, this seemed to produce the best results.
        let linesPerHelper = 50
        var registrationHelperFuncs: [String] = []
        let registrations: [String] = providers
            .map { (provider: SerializedProvider) in
                provider.registration
            }
            .filter {
                !$0.isEmpty
            }
        let registrationBody = stride(from: 0, to: registrations.count, by: linesPerHelper)
            .map {
                let helperBody = registrations[$0 ..< Swift.min($0 + linesPerHelper, registrations.count)]
                    .joined()
                    .replacingOccurrences(of: "\n", with: "\n    ")
                    .trimmingCharacters(in: .whitespacesAndNewlines)
                let regNum = ($0 / linesPerHelper) + 1
                registrationHelperFuncs.append("""
                @inline(never) private func register\(regNum)() {
                    \(helperBody)
                }
                """)
                return "register\(regNum)()"
            }
            .joined(separator: "\n    ")
        let registrationHelpers = registrationHelperFuncs.joined(separator: "\n\n")

        return """
        \(headerDocContent)

        \(importsJoined)
        
        // swiftlint:disable unused_declaration
        private let needleDependenciesHash : String? = \(needleDependenciesHash)

        // MARK: - Traversal Helpers

        \(traversalHelpers)

        // MARK: - Providers

        #if !NEEDLE_DYNAMIC
        
        \(providersSection)
        #else
        \(dynamicProvidersSection)
        
        #endif
        
        private func factoryEmptyDependencyProvider(_ component: NeedleFoundation.Scope) -> AnyObject {
            return EmptyDependencyProvider(component: component)
        }

        // MARK: - Registration
        private func registerProviderFactory(_ componentPath: String, _ factory: @escaping (NeedleFoundation.Scope) -> AnyObject) {
            __DependencyProviderRegistry.instance.registerDependencyProviderFactory(for: componentPath, factory)
        }

        #if !NEEDLE_DYNAMIC
        
        \(registrationHelpers)
        #endif
        
        public func registerProviderFactories() {
        #if !NEEDLE_DYNAMIC
            \(registrationBody)
        #endif
        }

        """
    }