in Sources/MockoloFramework/Templates/NominalTemplate.swift [270:355]
func processAssociatedTypes(`in` models: [(String, Model)], acl: String) -> (
aliasItems: String,
typeparameters: String,
whereClauses: String,
renderedModelNames: Set<String>
) {
let addAcl = declKindOfMockAnnotatedBaseType == .protocol ? acl : ""
let allWhereConstraints = genericWhereConstraints + models.flatMap { ($1 as? AssociatedTypeModel)?.whereConstraints ?? [] }
let hasWhereConstraints = !allWhereConstraints.isEmpty
let aliasModels = [String: [TypealiasRenderableModel]](
grouping: models.compactMap { $1 as? TypealiasRenderableModel },
by: \.name
).sorted(path: \.key)
// If there is a where, do not output typealias as it may not satisfy the conditions
if hasWhereConstraints {
let aliasItems = aliasModels.compactMap { (name, candidates) in
if let defaultType = candidates.firstNonNil(\.defaultType) {
return """
\(1.tab)// Unavailable due to the presence of generic constraints
\(1.tab)// \(addAcl)\(String.typealias) \(name) = \(defaultType.displayName)
"""
}
return nil
}.joined(separator: "\n")
let typeparameters = aliasModels.map { (name, candidates) in
mergeAssociatedTypes(
name: name,
models: candidates.compactMap { $0 as? AssociatedTypeModel }
)
}
return (
aliasItems: aliasItems,
typeparameters: typeparameters.isEmpty ? "" : "<\(typeparameters.joined(separator: ", "))>",
whereClauses: allWhereConstraints.isEmpty ? "" : "where \(allWhereConstraints.joined(separator: ", ")) ",
renderedModelNames: Set(aliasModels.map(\.key))
)
}
var aliasItems: String = ""
var typeparameters: [String] = []
var renderedModelNames: Set<String> = []
for (name, candidates) in aliasModels {
// If only one default type exists and the others have no constraints, use it directly.
let havingDefaults = candidates.filter { $0.defaultType != nil }
if havingDefaults.count == 1 && !candidates
.filter({ $0 !== havingDefaults[0] })
.contains(where: \.hasGenericConstraints) {
continue
}
// If there are no constraints on all candidates, use Any automatically.
if candidates.allSatisfy({ !$0.hasGenericConstraints }) {
aliasItems.append("\(1.tab)\(addAcl)\(String.typealias) \(name) = Any\n")
} else {
// The other cases, gather all constraints
let typeparameter = mergeAssociatedTypes(
name: name,
models: candidates.compactMap { $0 as? AssociatedTypeModel }
)
typeparameters.append(typeparameter)
}
renderedModelNames.insert(name)
}
return (
aliasItems: aliasItems,
typeparameters: typeparameters.isEmpty ? "" : "<\(typeparameters.joined(separator: ", "))>",
whereClauses: allWhereConstraints.isEmpty ? "" : "where \(allWhereConstraints.joined(separator: ", ")) ",
renderedModelNames: renderedModelNames
)
func mergeAssociatedTypes(name: String, models: [AssociatedTypeModel]) -> String {
let inheritances = models.flatMap(\.inheritances)
let typeparameter = if inheritances.isEmpty {
name
} else {
"\(name): \(inheritances.joined(separator: " & "))"
}
return typeparameter
}
}