diff --git a/Sources/MockoloFramework/Models/ClosureModel.swift b/Sources/MockoloFramework/Models/ClosureModel.swift index 2b471079..38a3b472 100644 --- a/Sources/MockoloFramework/Models/ClosureModel.swift +++ b/Sources/MockoloFramework/Models/ClosureModel.swift @@ -31,7 +31,7 @@ final class ClosureModel: Model { } - init(name: String, genericTypeParams: [ParamModel], paramNames: [String], paramTypes: [Type], suffix: String, returnType: Type) { + init(name: String, genericTypeParams: [ParamModel], paramNames: [String], paramTypes: [Type], suffix: String, returnType: Type, encloser: String) { self.name = name + .handlerSuffix self.suffix = suffix let genericTypeNameList = genericTypeParams.map(path: \.name) @@ -39,7 +39,7 @@ final class ClosureModel: Model { self.paramNames = paramNames self.paramTypes = paramTypes self.funcReturnType = returnType - self.type = Type.toClosureType(with: paramTypes, typeParams: genericTypeNameList, suffix: suffix, returnType: returnType) + self.type = Type.toClosureType(with: paramTypes, typeParams: genericTypeNameList, suffix: suffix, returnType: returnType, encloser: encloser) } func render(with identifier: String, encloser: String, useTemplateFunc: Bool = false, useMockObservable: Bool = false, enableFuncArgsHistory: Bool = false) -> String? { diff --git a/Sources/MockoloFramework/Models/MethodModel.swift b/Sources/MockoloFramework/Models/MethodModel.swift index ce289280..8e1d23a2 100644 --- a/Sources/MockoloFramework/Models/MethodModel.swift +++ b/Sources/MockoloFramework/Models/MethodModel.swift @@ -102,7 +102,7 @@ final class MethodModel: Model { return ret }() - lazy var handler: ClosureModel? = { + func handler(encloser: String) -> ClosureModel? { if isInitializer { return nil } @@ -114,10 +114,11 @@ final class MethodModel: Model { paramNames: paramNames, paramTypes: paramTypes, suffix: suffix, - returnType: type) + returnType: type, + encloser: encloser) return ret - }() + } init(name: String, @@ -192,7 +193,7 @@ final class MethodModel: Model { accessLevel: accessLevel, suffix: suffix, argsHistory: argsHistory, - handler: handler) + handler: handler(encloser: encloser)) return result } } diff --git a/Sources/MockoloFramework/Parsers/ViaSwiftSyntax/SwiftSyntaxExtensions.swift b/Sources/MockoloFramework/Parsers/ViaSwiftSyntax/SwiftSyntaxExtensions.swift index 2b263913..86feb40a 100644 --- a/Sources/MockoloFramework/Parsers/ViaSwiftSyntax/SwiftSyntaxExtensions.swift +++ b/Sources/MockoloFramework/Parsers/ViaSwiftSyntax/SwiftSyntaxExtensions.swift @@ -256,7 +256,7 @@ extension ProtocolDeclSyntax: EntityNode { var name: String { return identifier.text } - + var accessLevel: String { return self.modifiers?.acl ?? "" } diff --git a/Sources/MockoloFramework/Templates/MethodTemplate.swift b/Sources/MockoloFramework/Templates/MethodTemplate.swift index 1261322c..3a1ab1d8 100644 --- a/Sources/MockoloFramework/Templates/MethodTemplate.swift +++ b/Sources/MockoloFramework/Templates/MethodTemplate.swift @@ -34,7 +34,7 @@ extension MethodModel { var template = "" let returnTypeName = returnType.isUnknown ? "" : returnType.typeName - + let acl = accessLevel.isEmpty ? "" : accessLevel+" " let genericTypeDeclsStr = genericTypeParams.compactMap {$0.render(with: "", encloser: "")}.joined(separator: ", ") let genericTypesStr = genericTypeDeclsStr.isEmpty ? "" : "<\(genericTypeDeclsStr)>" @@ -142,4 +142,3 @@ extension MethodModel { return template } } - diff --git a/Sources/MockoloFramework/Utils/StringExtensions.swift b/Sources/MockoloFramework/Utils/StringExtensions.swift index ba0b1be1..ec146153 100644 --- a/Sources/MockoloFramework/Utils/StringExtensions.swift +++ b/Sources/MockoloFramework/Utils/StringExtensions.swift @@ -41,6 +41,7 @@ extension String { static let `inout` = "inout" static let hasBlankInit = "_hasBlankInit" + static let `Self` = "Self" static let `static` = "static" static let importSpace = "import " static public let `class` = "class" diff --git a/Sources/MockoloFramework/Utils/TypeParser.swift b/Sources/MockoloFramework/Utils/TypeParser.swift index 8a76928e..4f4d94d9 100644 --- a/Sources/MockoloFramework/Utils/TypeParser.swift +++ b/Sources/MockoloFramework/Utils/TypeParser.swift @@ -129,6 +129,10 @@ public final class Type { return typeName.hasPrefix(String.escaping) } + var isSelf: Bool { + return typeName == String.`Self` + } + var splitByClosure: Bool { let arg = typeName if let closureOpRange = arg.range(of: String.closureArrow) { @@ -499,7 +503,8 @@ public final class Type { } - static func toClosureType(with params: [Type], typeParams: [String], suffix: String, returnType: Type) -> Type { + static func toClosureType(with params: [Type], typeParams: [String], suffix: String, returnType: Type, encloser: String) -> Type { + let displayableParamTypes = params.map { (subtype: Type) -> String in return subtype.processTypeParams(with: typeParams) @@ -507,6 +512,7 @@ public final class Type { let displayableParamStr = displayableParamTypes.joined(separator: ", ") var displayableReturnType = returnType.typeName + let returnComps = displayableReturnType.literalComponents var returnAsStr = "" @@ -521,6 +527,8 @@ public final class Type { } else if returnType.isIUO { displayableReturnType = .any + "!" returnAsStr.removeLast() + } else if returnType.isSelf { + returnAsStr = String.`Self` } else { displayableReturnType = .any } @@ -530,6 +538,11 @@ public final class Type { } } + if returnType.isSelf { + displayableReturnType = encloser + returnTypeCast = " as! " + String.`Self` + } + let isSimpleTuple = displayableReturnType.hasPrefix("(") && displayableReturnType.hasSuffix(")") && displayableReturnType.components(separatedBy: CharacterSet(charactersIn: "()")).filter({!$0.isEmpty}).count <= 1 diff --git a/Tests/TestNonSimpleCases/FixtureNonSimpleFuncs.swift b/Tests/TestNonSimpleCases/FixtureNonSimpleFuncs.swift index af00eaab..2558f432 100644 --- a/Tests/TestNonSimpleCases/FixtureNonSimpleFuncs.swift +++ b/Tests/TestNonSimpleCases/FixtureNonSimpleFuncs.swift @@ -87,7 +87,7 @@ class SubscriptProtocolMock: SubscriptProtocol { static subscript(key: Int) -> AnyObject? { get { subscriptCallCount += 1 - + if let subscriptHandler = subscriptHandler { return subscriptHandler(key) } @@ -100,7 +100,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(_ key: Int) -> AnyObject { get { subscriptKeyCallCount += 1 - + if let subscriptKeyHandler = subscriptKeyHandler { return subscriptKeyHandler(key) } @@ -113,7 +113,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(key: Int) -> AnyObject? { get { subscriptKeyIntCallCount += 1 - + if let subscriptKeyIntHandler = subscriptKeyIntHandler { return subscriptKeyIntHandler(key) } @@ -126,7 +126,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(index: String) -> CGImage? { get { subscriptIndexCallCount += 1 - + if let subscriptIndexHandler = subscriptIndexHandler { return subscriptIndexHandler(index) } @@ -139,7 +139,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(memoizeKey: Int) -> CGRect? { get { subscriptMemoizeKeyCallCount += 1 - + if let subscriptMemoizeKeyHandler = subscriptMemoizeKeyHandler { return subscriptMemoizeKeyHandler(memoizeKey) } @@ -152,7 +152,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(position: Int) -> Any { get { subscriptPositionCallCount += 1 - + if let subscriptPositionHandler = subscriptPositionHandler { return subscriptPositionHandler(position) } @@ -165,7 +165,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(index: String.Index) -> Double { get { subscriptIndexStringIndexCallCount += 1 - + if let subscriptIndexStringIndexHandler = subscriptIndexStringIndexHandler { return subscriptIndexStringIndexHandler(index) } @@ -178,7 +178,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(safe index: String.Index) -> Double? { get { subscriptSafeCallCount += 1 - + if let subscriptSafeHandler = subscriptSafeHandler { return subscriptSafeHandler(index) } @@ -191,7 +191,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(range: Range) -> String { get { subscriptRangeCallCount += 1 - + if let subscriptRangeHandler = subscriptRangeHandler { return subscriptRangeHandler(range) } @@ -204,7 +204,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(path: String) -> ((Double) -> Float)? { get { subscriptPathCallCount += 1 - + if let subscriptPathHandler = subscriptPathHandler { return subscriptPathHandler(path) } @@ -217,7 +217,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(dynamicMember keyPath: ReferenceWritableKeyPath) -> T { get { subscriptDynamicMemberCallCount += 1 - + if let subscriptDynamicMemberHandler = subscriptDynamicMemberHandler { return subscriptDynamicMemberHandler(keyPath) as! T } @@ -230,7 +230,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(dynamicMember keyPath: ReferenceWritableKeyPath) -> T { get { subscriptDynamicMemberTCallCount += 1 - + if let subscriptDynamicMemberTHandler = subscriptDynamicMemberTHandler { return subscriptDynamicMemberTHandler(keyPath) as! T } @@ -243,7 +243,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(dynamicMember keyPath: WritableKeyPath) -> Value { get { subscriptDynamicMemberTWritableKeyPathTValueCallCount += 1 - + if let subscriptDynamicMemberTWritableKeyPathTValueHandler = subscriptDynamicMemberTWritableKeyPathTValueHandler { return subscriptDynamicMemberTWritableKeyPathTValueHandler(keyPath) } @@ -256,7 +256,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(_ parameter: T) -> T { get { subscriptParameterCallCount += 1 - + if let subscriptParameterHandler = subscriptParameterHandler { return subscriptParameterHandler(parameter) as! T } @@ -269,7 +269,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(keyPath: ReferenceWritableKeyPath) -> Array { get { subscriptKeyPathCallCount += 1 - + if let subscriptKeyPathHandler = subscriptKeyPathHandler { return subscriptKeyPathHandler(keyPath) as! Array } @@ -282,7 +282,7 @@ class SubscriptProtocolMock: SubscriptProtocol { subscript(keyPath: ReferenceWritableKeyPath, on schedulerType: T) -> Array { get { subscriptKeyPathOnCallCount += 1 - + if let subscriptKeyPathOnHandler = subscriptKeyPathOnHandler { return subscriptKeyPathOnHandler(keyPath, schedulerType) as! Array } @@ -294,11 +294,11 @@ class SubscriptProtocolMock: SubscriptProtocol { public class KeyValueSubscriptingMock: KeyValueSubscripting { - - + + public init() { - + } public typealias Key = Any public typealias Value = Any @@ -307,7 +307,7 @@ public class KeyValueSubscriptingMock: KeyValueSubscripting { public subscript(key: Key) -> Value? { get { subscriptCallCount += 1 - + if let subscriptHandler = subscriptHandler { return subscriptHandler(key) } @@ -320,7 +320,7 @@ public class KeyValueSubscriptingMock: KeyValueSubscripting { public subscript(key: Key, default defaultValue: @autoclosure () -> Value) -> Value { get { subscriptKeyCallCount += 1 - + if let subscriptKeyHandler = subscriptKeyHandler { return subscriptKeyHandler(key, defaultValue()) } @@ -346,16 +346,16 @@ let variadicFuncMock = import Foundation class NonSimpleFuncsMock: NonSimpleFuncs { - + init() { - + } - + var barCallCount = 0 var barHandler: ((String, Int..., [Double]) -> (Float?))? func bar(_ arg: String, x: Int..., y: [Double]) -> Float? { barCallCount += 1 - + if let barHandler = barHandler { return barHandler(arg, x, y) } @@ -380,19 +380,19 @@ import Foundation class NonSimpleFuncsMock: NonSimpleFuncs { - - - + + + init() { - - + + } - + var passCallCount = 0 var passHandler: ((@autoclosure () -> Int) throws -> (Any))? func pass(handler: @autoclosure () -> Int) rethrows -> T { passCallCount += 1 - + if let passHandler = passHandler { return try passHandler(handler()) as! T } @@ -418,27 +418,27 @@ let closureArgFuncMock = """ import Foundation class NonSimpleFuncsMock: NonSimpleFuncs { - + init() { - + } - + var catCallCount = 0 var catHandler: ((String, [String: String]?, () throws -> Any) throws -> (Any))? func cat(named arg: String, tags: [String: String]?, closure: () throws -> T) rethrows -> T { catCallCount += 1 - + if let catHandler = catHandler { return try catHandler(arg, tags, closure) as! T } fatalError("catHandler returns can't have a default value thus its handler must be set") } - + var moreCallCount = 0 var moreHandler: ((String, [String: String]?, (Any) throws -> ()) throws -> (Any))? func more(named arg: String, tags: [String: String]?, closure: (T) throws -> ()) rethrows -> T { moreCallCount += 1 - + if let moreHandler = moreHandler { return try moreHandler(arg, tags, closure) as! T } @@ -466,11 +466,11 @@ import Foundation class NonSimpleFuncsMock: NonSimpleFuncs { - + init() { - + } var maxCallCount = 0 var maxHandler: ((Int) -> ((() -> Void)?))? @@ -514,3 +514,33 @@ class NonSimpleFuncsMock: NonSimpleFuncs { } } """ + +let returnSelfFunc = """ +import Foundation + +/// \(String.mockAnnotation) +protocol NonSimpleFuncs { +@discardableResult +func returnSelf() -> Self +} +""" + +let returnSelfFuncMock = """ + +import Foundation + + +class NonSimpleFuncsMock: NonSimpleFuncs { + init() { } + + var returnSelfCallCount = 0 + var returnSelfHandler: (() -> (NonSimpleFuncsMock))? + func returnSelf() -> Self { + returnSelfCallCount += 1 + if let returnSelfHandler = returnSelfHandler { + return returnSelfHandler() as! Self + } + fatalError("returnSelfHandler returns can't have a default value thus its handler must be set") + } +} +""" diff --git a/Tests/TestNonSimpleCases/NonSimpleCaseTests.swift b/Tests/TestNonSimpleCases/NonSimpleCaseTests.swift index faec64ca..6ed80cc4 100644 --- a/Tests/TestNonSimpleCases/NonSimpleCaseTests.swift +++ b/Tests/TestNonSimpleCases/NonSimpleCaseTests.swift @@ -37,4 +37,9 @@ class NonSimpleVarTests: MockoloTestCase { verify(srcContent: forArgClosureFunc, dstContent: forArgClosureFuncMock) } + + func testReturnSelfFunc() { + verify(srcContent: returnSelfFunc, + dstContent: returnSelfFuncMock) + } }