Sources/MockoloFramework/Templates/ClosureTemplate.swift (60 lines of code) (raw):
//
// Copyright (c) 2018. Uber Technologies
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
extension ClosureModel {
func applyClosureTemplate(type: SwiftType,
cast: String?,
name: String,
params: [(String, SwiftType)],
returnDefaultType: SwiftType) -> String {
let handlerParamValsStr = params.map { (argName, argType) -> String in
if argType.isAutoclosure {
return argName.safeName + "()"
}
if argType.isInOut {
return "&" + argName.safeName
}
if argType.hasClosure && argType.isOptional,
let renderedClosure = renderOptionalGenericClosure(argType: argType, argName: argName) {
return renderedClosure
}
return argName.safeName
}.joined(separator: ", ")
let handlerReturnDefault = renderReturnDefaultStatement(name: name, type: returnDefaultType)
let prefix = [
throwing.hasError ? String.try + " " : nil,
isAsync ? String.await + " " : nil,
].compactMap { $0 }.joined()
let returnStr = returnDefaultType.isVoid ? "" : "return "
return """
\(2.tab)if let \(name) = \(name) {
\(3.tab)\(returnStr)\(prefix)\(name)(\(handlerParamValsStr))\(cast ?? "")
\(2.tab)}
\(2.tab)\(handlerReturnDefault)
"""
}
private func renderReturnDefaultStatement(name: String, type: SwiftType) -> String {
guard !type.isVoid else { return "" }
if let result = type.defaultVal() {
if result.isEmpty {
return ""
}
return "return \(result)"
}
return "\(String.fatalError)(\"\(name) returns can't have a default value thus its handler must be set\")"
}
private func renderOptionalGenericClosure(
argType: SwiftType,
argName: String
) -> String? {
let literalComponents = argType.typeName.literalComponents
for genericTypeName in genericTypeNames {
if literalComponents.contains(genericTypeName) {
var processTypeParams = argType.processTypeParams(with: genericTypeNames)
let closureCast = processTypeParams.withoutTrailingCharacters(["!", "?"])
return argName.safeName +
" as? " +
closureCast
}
}
return nil
}
}