@@ -9,13 +9,42 @@ import RxSwift
9
9
let formattedName: String
10
10
let lastParamName: String?
11
11
}
12
+
13
+ struct Availability {
14
+ let iOS: String?
15
+ let macOS: String?
16
+ let watchOS: String?
17
+ let tvOS: String?
18
+
19
+ var description: String {
20
+ var constraints = [String]()
21
+ if let iOSVersion = iOS { constraints.append("iOS \(iOSVersion)") }
22
+ if let macOSVersion = macOS { constraints.append("macOS \(macOSVersion)") }
23
+ if let watchOSVersion = watchOS { constraints.append("watchOS \(watchOSVersion)") }
24
+ if let tvOSVersion = tvOS { constraints.append("tvOS \(tvOSVersion)") }
25
+ let value = "@available(\(constraints.joined(separator: ", ")), *)"
26
+ return value
27
+ }
28
+ }
29
+
30
+ struct MethodDefinition: Equatable {
31
+ let selectorName: String
32
+ let definedInTypeName: String
33
+ }
34
+
12
35
typealias MethodName = String
13
36
14
37
class Utils {
15
38
static let classNamesToMock = ["CBManager", "CBAttribute", "CBCentralManager", "CBPeripheralManager", "CBPeripheral", "CBDescriptor", "CBService", "CBCharacteristic", "CBL2CAPChannel", "CBPeer", "CBATTRequest", "CBCentral", "PeripheralProvider", "Connector", "CharacteristicNotificationManager"]
16
39
static let classNamesToTestable = ["Peripheral", "CentralManager", "PeripheralManager", "Characteristic"]
17
40
static let delegateWrapperNamesToMock = ["CBPeripheralDelegateWrapper", "CBCentralManagerDelegateWrapper", "CBPeripheralManagerDelegateWrapper"]
18
41
static let namesToMock = classNamesToMock + delegateWrapperNamesToMock
42
+ static let restrictedTypes: [String: Availability] = [
43
+ "CBManagerAuthorization": Availability(iOS: "13.0", macOS: "10.15", watchOS: "6.0", tvOS: "13.0")
44
+ ]
45
+ static let unavailableOnMac: [MethodDefinition] = [
46
+ MethodDefinition(selectorName: "centralManager(_:didUpdateANCSAuthorizationFor:)", definedInTypeName: "CBCentralManagerDelegateWrapper")
47
+ ]
19
48
20
49
static func capitalizeFirstLetter(_ text: String) -> String {
21
50
return text.prefix(1).uppercased() + text.dropFirst()
@@ -74,20 +103,22 @@ import RxSwift
74
103
75
104
static func printVariable(_ variable: Variable, useDefaultValue: Bool = false) -> String {
76
105
let forceUnwrap = variable.isOptional ? "" : "!"
106
+ let avaibilityString = restrictedTypes[variable.typeName.name]?.description.appending(" lazy ") ?? ""
107
+ let initialization = restrictedTypes[variable.typeName.name] != nil ? " = nil" : ""
77
108
if let defaultValue = variable.defaultValue, useDefaultValue {
78
109
let changedDefaultValue = changeTypeName(defaultValue)
79
- return "var \(variable.name) = \(changedDefaultValue)"
110
+ return "\(avaibilityString) var \(variable.name) = \(changedDefaultValue)"
80
111
} else {
81
112
let changedTypeName = changeTypeName(variable.typeName.name)
82
- return "var \(variable.name): \(changedTypeName)\(forceUnwrap)"
113
+ return "\(avaibilityString) var \(variable.name): \(changedTypeName)\(forceUnwrap)\(initialization )"
83
114
}
84
115
}
85
116
86
117
static func printMethodParamTypes(_ method: SourceryRuntime.Method) -> String {
87
118
return String(method.parameters.reduce("", { "\($0)\(changeTypeName($1.typeName.name)), " }).dropLast(2))
88
119
}
89
120
90
- static func printMethodName(_ method: SourceryRuntime.Method, changeTypeNames: Bool = true) -> String {
121
+ static func printMethodName(_ method: SourceryRuntime.Method, changeTypeNames: Bool = true) -> String {
91
122
var methodParams = method.parameters.reduce("", { value, parameter in
92
123
var labelPart = ""
93
124
if (value.count == 0 && parameter.argumentLabel == nil) {
@@ -101,6 +132,15 @@ import RxSwift
101
132
}).dropLast(2)
102
133
return "\(method.callName)(\(methodParams))"
103
134
}
135
+
136
+ static func removeDuplicatesVariables(_ variables: [SourceryRuntime.Variable]) -> [SourceryRuntime.Variable] {
137
+ var filteredVariables = [SourceryRuntime.Variable]()
138
+ for variable in variables {
139
+ guard !filteredVariables.contains(where: { $0.name == variable.name }) else { continue }
140
+ filteredVariables.append(variable)
141
+ }
142
+ return filteredVariables
143
+ }
104
144
}
105
145
-%>
106
146
@@ -110,7 +150,10 @@ import RxSwift
110
150
let typeToMock = type[classNameToMock]!
111
151
let supertypeName = Utils.changeTypeName(typeToMock.supertype?.name ?? "NSObject") -%>
112
152
class <%= typeToMock.name %>Mock: <%= supertypeName %> {
113
- <%_ for variable in typeToMock.variables { -%>
153
+ <%_ for containedType in typeToMock.containedTypes { -%>
154
+ class <%= containedType.localName %> {}
155
+ <% } -%>
156
+ <%_ for variable in Utils.removeDuplicatesVariables(typeToMock.variables) { -%>
114
157
<%= Utils.printVariable(variable) %>
115
158
<% } -%>
116
159
@@ -169,12 +212,25 @@ class <%= typeToMock.name %>Mock: NSObject <%= inheritedTypes %> {
169
212
170
213
override init() {
171
214
}
172
-
173
- <%_ let filteredMethods = typeToMock.methods.filter { !$0.isInitializer }
174
- for method in filteredMethods { -%>
215
+ <%_ let filteredMethods = typeToMock.methods
216
+ .filter { !$0.isInitializer }
217
+
218
+ for method in filteredMethods {
219
+ var isUnavailableOnMac = false
220
+ if let inTypeName = method.definedInTypeName?.name {
221
+ isUnavailableOnMac = !Utils.unavailableOnMac.contains(where: {
222
+ return !($0.selectorName == method.selectorName && $0.definedInTypeName == inTypeName)
223
+ })
224
+ } -%>
225
+
226
+ <%_ if isUnavailableOnMac { -%>
227
+ #if !os(macOS)
228
+ <%_ } -%>
175
229
func <%= Utils.printMethodName(method, changeTypeNames: false) %> {
176
230
}
177
-
231
+ <%_ if isUnavailableOnMac { -%>
232
+ #endif
233
+ <%_ } -%>
178
234
<%_ } -%>
179
235
}
180
236
<%_ } -%>
0 commit comments