diff --git a/Sources/MockoloFramework/Templates/ClosureTemplate.swift b/Sources/MockoloFramework/Templates/ClosureTemplate.swift index dd683962..8a2fed93 100644 --- a/Sources/MockoloFramework/Templates/ClosureTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClosureTemplate.swift @@ -35,6 +35,10 @@ extension ClosureModel { if argType.isInOut { return "&" + argName.safeName } + if argType.hasClosure && argType.isOptional, + let renderedClosure = renderOptionalGenericClosure(argType: argType, argName: argName) { + return renderedClosure + } return argName.safeName } handlerParamValsStr = zipped.joined(separator: ", ") @@ -70,4 +74,21 @@ extension ClosureModel { } return "return \(result)" } + + private func renderOptionalGenericClosure( + argType: Type, + 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 + } } diff --git a/Sources/MockoloFramework/Utils/StringExtensions.swift b/Sources/MockoloFramework/Utils/StringExtensions.swift index ec146153..0ff53cd0 100644 --- a/Sources/MockoloFramework/Utils/StringExtensions.swift +++ b/Sources/MockoloFramework/Utils/StringExtensions.swift @@ -135,7 +135,16 @@ extension String { var withRightParen: String { return "\(self))" } - + + mutating func withoutTrailingCharacters(_ characters: [String]) -> String { + for character in characters { + if hasSuffix(character) { + _ = self.removeLast() + } + } + return self + } + func canBeInitParam(type: String, isStatic: Bool) -> Bool { return !(isStatic || type == .unknownVal || (type.hasSuffix("?") && type.contains(String.closureArrow)) || isGenerated(type: Type(type))) diff --git a/Tests/TestGenericFuncs/FixtureGenericFunc.swift b/Tests/TestGenericFuncs/FixtureGenericFunc.swift index 0f4fb0c5..53b75e0d 100644 --- a/Tests/TestGenericFuncs/FixtureGenericFunc.swift +++ b/Tests/TestGenericFuncs/FixtureGenericFunc.swift @@ -49,6 +49,7 @@ protocol GenericFunc { func tell(_ type: ResponseType, with handler: @escaping (BodyType) -> ()) -> Disposable func pull(events: [SomeEvent], value: T, once: Bool, closure: @escaping (T?) -> ()) func pull(events: [SomeEvent], until: U?, closure: @escaping () -> ()) + func optionalPull(events: [SomeEvent], value: T, once: Bool, closure: ((T?) -> ())?) func add(n1: T, n2: T?) func add (a: T?, b: T?) func add (a: T, b: T) @@ -133,6 +134,15 @@ class GenericFuncMock: GenericFunc { pullEventsHandler(events, until, closure) } + } + var optionalPullCallCount = 0 + var optionalPullHandler: (([SomeEvent], Any, Bool, ((Any?) -> ())?) -> ())? + func optionalPull(events: [SomeEvent], value: T, once: Bool, closure: ((T?) -> ())?) { + optionalPullCallCount += 1 + if let optionalPullHandler = optionalPullHandler { + optionalPullHandler(events, value, once, closure as? ((Any?) -> ())) + } + } var addCallCount = 0 var addHandler: ((Any, Any?) -> ())?