Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/MockoloFramework/Utils/StringExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ extension String {
static let arrayTypeSugarName = "[]"
static let dictionaryTypeSugarName = "[:]"
static let optionalTypeSugarName = "?"
static let optionalAutounwrappedTypeSugarName = "!"

var safeName: String {
var text = self
Expand Down
56 changes: 37 additions & 19 deletions Sources/MockoloFramework/Utils/SwiftType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ struct SwiftType: Equatable, CustomStringConvertible {
var kind: Kind
var attributes: [String] = []
var someOrAny: SomeOrAny?
var isIUO: Bool = false
var hasEllipsis: Bool = false

var typeName: String {
Expand Down Expand Up @@ -88,6 +87,8 @@ struct SwiftType: Equatable, CustomStringConvertible {
switch nominal.name {
case .optionalTypeSugarName where nominal.genericParameterTypes.count == 1:
repr += "\(nominal.genericParameterTypes[0])?"
case .optionalAutounwrappedTypeSugarName where nominal.genericParameterTypes.count == 1:
repr += "\(nominal.genericParameterTypes[0])!"
case .arrayTypeSugarName where nominal.genericParameterTypes.count == 1:
repr += "[\(nominal.genericParameterTypes[0])]"
case .dictionaryTypeSugarName where nominal.genericParameterTypes.count == 2:
Expand Down Expand Up @@ -121,14 +122,6 @@ struct SwiftType: Equatable, CustomStringConvertible {
case .composition(let composition):
repr += composition.elements.map(\.description).joined(separator: " & ")
}
if isIUO {
switch kind {
case .tuple, .nominal:
repr += "!"
case .closure, .composition:
repr = "(\(repr))!"
}
}
if hasEllipsis {
repr += "..."
}
Expand Down Expand Up @@ -191,7 +184,11 @@ struct SwiftType: Equatable, CustomStringConvertible {
}

var isOptional: Bool {
isNominal(named: .optional) || isNominal(named: .optionalTypeSugarName)
isNominal(named: .optional) || isNominal(named: .optionalTypeSugarName) || isNominal(named: .optionalAutounwrappedTypeSugarName)
}

var isIUO: Bool {
isNominal(named: .optionalAutounwrappedTypeSugarName)
}

var isSelf: Bool {
Expand Down Expand Up @@ -286,9 +283,8 @@ struct SwiftType: Equatable, CustomStringConvertible {
ret = unwrapped
}
}
ret.isIUO = true

return ret.description
return ret.iuoWrapped().description
}

func defaultVal(with overrides: [String: String]? = nil, overrideKey: String = "", isInitParam: Bool = false) -> String? {
Expand Down Expand Up @@ -343,7 +339,7 @@ struct SwiftType: Equatable, CustomStringConvertible {
var processedType = subtype.processTypeParams(with: typeParams)
processedType.attributes.removeAll(where: { $0 == .inout })
processedType.attributes.removeAll(where: { $0 == .escaping })
processedType.isIUO = false
processedType.unwrapIUO()
return processedType
}

Expand Down Expand Up @@ -456,10 +452,9 @@ struct SwiftType: Equatable, CustomStringConvertible {
returnAsType = unwrapped
asSuffix = "?"
} else if returnType.isIUO {
displayableReturnType = .Any
displayableReturnType.isIUO = true
displayableReturnType = .Any.iuoWrapped()
var asType = returnType
asType.isIUO = false
asType.unwrapIUO()
returnAsType = asType
} else if returnType.isSelf {
returnAsType = .Self
Expand All @@ -476,11 +471,18 @@ struct SwiftType: Equatable, CustomStringConvertible {
returnTypeCast = " as! " + .`Self`
}

// `!` (IUO) is illegal inside a closure type, so an IUO param/return must render as a plain
// optional here (it still witnesses the IUO requirement).
displayableReturnType.unwrapIUO()
var resultType = SwiftType(
kind: .closure(.init(
isAsync: isAsync,
throwing: throwing,
arguments: params.map { .init(type: $0.processTypeParams(with: typeParams)) },
arguments: params.map {
var argType = $0.processTypeParams(with: typeParams)
argType.unwrapIUO()
return .init(type: argType)
},
returning: displayableReturnType
))
)
Expand Down Expand Up @@ -630,8 +632,7 @@ extension SwiftType {
case .implicitlyUnwrappedOptionalType(let syntax):
// T!
let base = SwiftType(typeSyntax: syntax.wrappedType)
self = base.optionalWrapped()
self.isIUO = true
self = base.iuoWrapped()

case .identifierType(let syntax):
// T<U>
Expand Down Expand Up @@ -720,6 +721,12 @@ extension SwiftType {
)
}

func iuoWrapped() -> SwiftType {
return copy(
kind: .nominal(.init(name: .optionalAutounwrappedTypeSugarName, genericParameterTypes: [.init(kind: kind)]))
)
}

func optionalUnwrapped() -> SwiftType? {
guard isOptional else {
return nil
Expand All @@ -730,6 +737,17 @@ extension SwiftType {
return nominal.genericParameterTypes.first
}

mutating func unwrapIUO() {
guard isNominal(named: .optionalAutounwrappedTypeSugarName) else {
return
}
guard case .nominal(let nominal) = kind,
let wrapped = nominal.genericParameterTypes.first else {
return
}
self = wrapped
}

func copy(kind: Kind) -> Self {
var copy = self
copy.kind = kind
Expand Down
34 changes: 34 additions & 0 deletions Tests/TestFuncs/TestBasicFuncs/FixtureNonSimpleFuncs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,40 @@ import MockoloFramework
}
}

@Fixture enum iuoFuncs {
/// @mockable
public protocol IUOFunc {
func f(x: Int!) -> Int!
subscript(i: Int!) -> Int! { get }
}

@Fixture enum expected {
public class IUOFuncMock: IUOFunc {
public init() { }
public private(set) var fCallCount = 0
public var fHandler: ((Int) -> Int)?
public func f(x: Int!) -> Int! {
fCallCount += 1
if let fHandler = fHandler {
return fHandler(x)
}
return nil
}
public private(set) var subscriptCallCount = 0
public var subscriptHandler: ((Int) -> Int)?
public subscript(i: Int!) -> Int! {
get {
subscriptCallCount += 1
if let subscriptHandler = subscriptHandler {
return subscriptHandler(i)
}
return nil
}
}
}
}
}

@Fixture enum subscripts {
/// @mockable
protocol SubscriptProtocol {
Expand Down
5 changes: 5 additions & 0 deletions Tests/TestFuncs/TestBasicFuncs/FuncBasicTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class BasicFuncTests: MockoloTestCase {
dstContent: subscripts.expected._source)
}

func testIUOFuncs() {
verify(srcContent: iuoFuncs._source,
dstContent: iuoFuncs.expected._source)
}

func testGetOnlySubscripts() {
verify(srcContent: getOnlySubscripts._source,
dstContent: getOnlySubscripts.expected._source)
Expand Down
21 changes: 21 additions & 0 deletions Tests/TestVars/FixtureNonSimpleVars.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,24 @@ import MockoloFramework
}
}
}

@Fixture enum iuoVars {
/// @mockable
public protocol IUOVar {
var a: Int! { get }
var b: Int! { get set }
}

@Fixture enum expected {
public class IUOVarMock: IUOVar {
public init() { }
public init(a: Int! = nil, b: Int! = nil) {
self.a = a
self.b = b
}
public var a: Int! = nil
public private(set) var bSetCallCount = 0
public var b: Int! = nil { didSet { bSetCallCount += 1 } }
}
}
}
5 changes: 5 additions & 0 deletions Tests/TestVars/VarTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ class VarTests: MockoloTestCase {
allowSetCallCount: true)
}

func testIUOVars() {
verify(srcContent: iuoVars._source,
dstContent: iuoVars.expected._source)
}

#if compiler(>=6.0)
func testAsyncThrows() {
verify(srcContent: asyncThrowsVars._source,
Expand Down