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
}
"""
}