-
Notifications
You must be signed in to change notification settings - Fork 104
/
TypeWrapper.swift
127 lines (117 loc) · 5.04 KB
/
TypeWrapper.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
class TypeWrapper {
let type: SourceryRuntime.TypeName
let isVariadic: Bool
var vPref: String { return isVariadic ? "[" : "" }
var vSuff: String { return isVariadic ? "]" : "" }
var unwrapped: String {
return type.unwrappedTypeName
}
var unwrappedReplacingSelf: String {
return replacingSelf(unwrap: true)
}
var stripped: String {
if type.isImplicitlyUnwrappedOptional {
return "\(vPref)\(unwrappedReplacingSelf)?\(vSuff)"
} else if type.isOptional {
return "\(vPref)\(unwrappedReplacingSelf)?\(vSuff)"
} else {
return "\(vPref)\(unwrappedReplacingSelf)\(vSuff)"
}
}
var nestedParameter: String {
if type.isImplicitlyUnwrappedOptional {
return "Parameter<\(vPref)\(unwrappedReplacingSelf)?\(vSuff)>"
} else if type.isOptional {
return "Parameter<\(vPref)\(unwrappedReplacingSelf)?\(vSuff)>"
} else {
return "Parameter<\(vPref)\(unwrappedReplacingSelf)\(vSuff)>"
}
}
var isSelfType: Bool {
return unwrapped == "Self"
}
func isSelfTypeRecursive() -> Bool {
if let tuple = type.tuple {
for element in tuple.elements {
guard !TypeWrapper(element.typeName).isSelfTypeRecursive() else { return true }
}
} else if let array = type.array {
return TypeWrapper(array.elementTypeName).isSelfTypeRecursive()
} else if let dictionary = type.dictionary {
guard !TypeWrapper(dictionary.valueTypeName).isSelfTypeRecursive() else { return true }
guard !TypeWrapper(dictionary.keyTypeName).isSelfTypeRecursive() else { return true }
} else if let closure = type.closure {
guard !TypeWrapper(closure.actualReturnTypeName).isSelfTypeRecursive() else { return true }
for parameter in closure.parameters {
guard !TypeWrapper(parameter.typeName).isSelfTypeRecursive() else { return true }
}
}
return isSelfType
}
init(_ type: SourceryRuntime.TypeName, _ isVariadic: Bool = false) {
self.type = type
self.isVariadic = isVariadic
}
func isGeneric(_ types: [String]) -> Bool {
guard !type.isVoid else { return false }
return isGeneric(name: unwrapped, generics: types)
}
private func isGeneric(name: String, generics: [String]) -> Bool {
let name = "(\(name.replacingOccurrences(of: " ", with: "")))"
let modifiers = "[\\?\\!]*"
return generics.contains(where: { generic in
let wrapped = "([\\(]\(generic)\(modifiers)[\\)\\.])"
let constraint = "([<,]\(generic)\(modifiers)[>,\\.])"
let arrays = "([\\[:]\(generic)\(modifiers)[\\],\\.:])"
let tuples = "([\\(,]\(generic)\(modifiers)[,\\.\\)])"
let closures = "((\\-\\>)\(generic)\(modifiers)[,\\.\\)])"
let pattern = "\(wrapped)|\(constraint)|\(arrays)|\(tuples)|\(closures)"
guard let regex = try? NSRegularExpression(pattern: pattern) else { return false }
return regex.firstMatch(in: name, options: [], range: NSRange(location: 0, length: (name as NSString).length)) != nil
})
}
func replacingSelf(unwrap: Bool = false) -> String {
guard isSelfTypeRecursive() else {
return unwrap ? self.unwrapped : "\(type)"
}
if isSelfType {
let optionality: String = {
if type.isImplicitlyUnwrappedOptional {
return "!"
} else if type.isOptional {
return "?"
} else {
return ""
}
}()
return unwrap ? Current.selfType : Current.selfType + optionality
} else if let tuple = type.tuple {
let inner = tuple.elements.map({ TypeWrapper($0.typeName).replacingSelf() }).joined(separator: ",")
let value = "(\(inner))"
return value
} else if let array = type.array {
let value = "[\(TypeWrapper(array.elementTypeName).replacingSelf())]"
return value
} else if let dictionary = type.dictionary {
let value = "[" +
"\(TypeWrapper(dictionary.valueTypeName).replacingSelf())"
+ ":" +
"\(TypeWrapper(dictionary.keyTypeName).replacingSelf())"
+ "]"
return value
} else if let closure = type.closure {
let returnType = TypeWrapper(closure.actualReturnTypeName).replacingSelf()
let inner = closure.parameters
.map { TypeWrapper($0.typeName).replacingSelf() }
.joined(separator: ",")
let throwing = closure.throws ? "throws " : ""
let value = "(\(inner)) \(throwing)-> \(returnType)"
return value
} else {
return (unwrap ? self.unwrapped : "\(type)")
}
}
func replacingSelfRespectingVariadic() -> String {
return "\(vPref)\(replacingSelf())\(vSuff)"
}
}