-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AutoCodePatterns.yml
124 lines (123 loc) · 5.14 KB
/
AutoCodePatterns.yml
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
scope:
# include: # either using `include` or `exclude`, if both are configured, the `exclude` will be ingored.
# - /a.swift # include this file - ending with `.swift`
# - /a/ # include this path prefix
exclude:
- /a.swift # exclude this file - ending with `.swift`
- /a/ # exclude this path prefix
rules:
-
rule: autoEnvironmentKey # rule name to help reason about the purpose of the rule
selector: # the criteria to apply this rule, could be a combinstion of type, inheritence, included names, excluded names
type: struct # the data type
inherits: # the inheritence
- EnvironmentKey # only the type that inherits this type will be eligible for this rule
imports: # the frameworks that need to be imported in the file
- SwiftUI
# The transform if the rule applies. The code quoted by `#` will be expanded.
# If the code inside two # need to expand again, quote it using two `|`. In this case, #name# becomes |name|
# In total, we have 3 types of expansion so far: name, type, properties.
# Name expansion will be based on the type name
# Type expansion will be based on the data type name
# Properties expansion will be based on the properties defined in the type.
# Properties expansion is different from name and type expansion as it could be a loop in cased of more than 1 properties defined in the type.
# Both name and type expansion can have transformers followed.
# All the transformers are separated using `*` and they will be applied into name and type in order.
# And they all have a straightforward name to reason about their functionality.
# The possible transformers for name and type are:
# `identity`, `lowerInitial`, `upperInitial`: these 3 don't need parameter
# `replaceTo(Value)`, `removeSuffix(Value)`, `addSuffix(Value)`, `removePrefix(Value)`, `addPrefix(Value)`: these 4 need one parameters, just put a new string in bracket without quotes.
# `replace(oldValue,newValue)`: these one need two parameters, it will replace the oldValue to newValue using `String.replacingOccurrences(of:with:)`
# Combine these in orders to get the right possible name
# Properties expansion needs a `joiner`. For example `#properties*joiner( && )<lhs.|name| == rhs.|name|>#`.
# in this case the name inside this property expansion was quoted using `|`.
# Can also do the same for type here if you need type in the destination code.
# Can even following the transformers like |name.upperInital| or |type.lowerInitial| etc. Combine them in a sensible way to get the code looks right.
# transform: >
# extension EnvironmentValues {
# var #name*lowerInitial#: String {
# get { self[#name#.self] }
# set { self[#name#.self] = newValue }
# }
#
# var #name*lowerInitial*removeSuffix(Key)*addSuffix(Value)#: String {
# get { self[#name#.self] }
# set { self[#name#.self] = newValue }
# }
# }
# If feeling swifty, choose code transform instead. The codeTransform below is identical to the transform above.
# Even though it looks wordy for this case, this approach might be useful for some cases where need more flexibilities of transforming code.
# The `name` is a `String` type and `properties` is an array of tuple type of `(name: String, type: String)`
# The code write can directly access to these two values
codeTransform: | # Write swift code as usual and assign the final result to `generatedCode` variable in `String` format
let name1 = name.prefix(1).lowercased() + name.dropFirst()
let name2 = (name.prefix(1).lowercased() + name.dropFirst()).replacingOccurrences(of: "Key", with: "Value")
generatedCode =
"""
extension EnvironmentValues {
var \(name1): String {
get { self[\(name).self] }
set { self[\(name).self] = newValue }
}
var \(name2): String {
get { self[\(name).self] }
set { self[\(name).self] = newValue }
}
}
"""
-
rule: autoTraitDefinition
selector:
type: struct
inherits:
- UITraitDefinition
imports:
- SwiftUI
transform: >
extension UITraitCollection {
var #name*addPrefix(is)*removeSuffix(Trait)#: Bool { self[#name#.self] }
}
extension UIMutableTraits {
var #name*addPrefix(is)*removeSuffix(Trait)#: Bool {
get { self[#name#.self] }
set { self[#name#.self] = newValue }
}
}
-
rule: autoViewModifier
selector:
type: struct
inherits:
- ViewModifier
imports:
- SwiftUI
transform: >
extension View {
func #name*lowerInitial#(#properties*joiner(, )<|name|: |type|>#) -> some View {
modifier(#name#(#properties*joiner(, )<|name|: |name|>#))
}
}
-
rule: autoEquatable
selector:
type: class
inherits:
- MyType
transform: >
extension #name#: Equatable {
static func == (lhs: #name#, rhs: #name#) -> Bool {
#properties*joiner( && )<lhs.|name| == rhs.|name|>#
}
}
-
rule: autoHashable
selector:
type: class
inherits:
- MyType
transform: >
extension #name#: Hashable {
func hash(into hasher: inout Hasher) {
#properties*joiner()<hasher.combine(|name|)>#
}
}