@@ -23,16 +23,37 @@ struct Config {
23
23
/// Files from the target which includes plugin and target dependencies
24
24
/// present in current package manifest are checked.
25
25
case direct
26
- /// Represents to check all local targets .
26
+ /// Represents to check all local target dependencies .
27
27
///
28
28
/// Files from the target which includes plugin and all targets
29
- /// that are in the same project/package.
29
+ /// that are in the same project/package that are dependencies
30
+ /// of this target.
30
31
case local
31
32
/// Represents to check current target and all dependencies.
32
33
///
33
34
/// Files from the target which includes plugin and all its
34
35
/// dependencies are checked.
35
36
case recursive
37
+
38
+ /// Creates a new instance by decoding from the given decoder.
39
+ ///
40
+ /// This initializer throws an error if reading from the decoder fails,
41
+ /// or if the data read is corrupted or otherwise invalid.
42
+ ///
43
+ /// - Parameter decoder: The decoder to read data from.
44
+ init ( from decoder: Decoder ) throws {
45
+ let rawValue = try String ( from: decoder) . lowercased ( )
46
+ guard let value = Self ( rawValue: rawValue) else {
47
+ throw DecodingError . typeMismatch (
48
+ Self . self,
49
+ . init(
50
+ codingPath: decoder. codingPath,
51
+ debugDescription: " Data doesn't match any case "
52
+ )
53
+ )
54
+ }
55
+ self = value
56
+ }
36
57
}
37
58
}
38
59
@@ -47,7 +68,7 @@ extension Config: Codable {
47
68
let container = try decoder. container ( keyedBy: CodingKeys . self)
48
69
self . scan =
49
70
try container. decodeIfPresent (
50
- ScanMode . self, forKey : . scan
71
+ ScanMode . self, forCaseInsensitiveKey : . scan
51
72
) ?? . target
52
73
}
53
74
@@ -63,3 +84,45 @@ extension Config: Codable {
63
84
#endif
64
85
}
65
86
}
87
+
88
+ extension KeyedDecodingContainerProtocol {
89
+ /// Decodes a value of the given type for the given key case-insensitively,
90
+ /// if present.
91
+ ///
92
+ /// This method returns `nil` if the container does not have a value
93
+ /// associated with key case-insensitively, or if the value is null.
94
+ ///
95
+ /// - Parameters:
96
+ /// - type: The type of value to decode.
97
+ /// - key: The key that the decoded value is associated with.
98
+ ///
99
+ /// - Returns: A decoded value of the requested type, or `nil`
100
+ /// if the `Decoder` does not have an entry associated with the given
101
+ /// key, or if the value is a null value.
102
+ ///
103
+ /// - Throws: `DecodingError.typeMismatch` if the encountered
104
+ /// encoded value is not convertible to the requested type or the key
105
+ /// value matches multiple value case-insensitively.
106
+ func decodeIfPresent< T: Decodable > (
107
+ _ type: T . Type ,
108
+ forCaseInsensitiveKey key: Key
109
+ ) throws -> T ? {
110
+ let keys = self . allKeys. filter { eachKey in
111
+ eachKey. stringValue. lowercased ( ) == key. stringValue. lowercased ( )
112
+ }
113
+
114
+ guard keys. count <= 1 else {
115
+ throw DecodingError . typeMismatch (
116
+ type,
117
+ . init(
118
+ codingPath: codingPath,
119
+ debugDescription: """
120
+ Duplicate keys found, keys are case-insensitive.
121
+ """
122
+ )
123
+ )
124
+ }
125
+
126
+ return try decodeIfPresent ( type, forKey: keys. first ?? key)
127
+ }
128
+ }
0 commit comments