@@ -7,6 +7,57 @@ private let identifierRegex = try Regex("([a-zA-Z_][a-zA-Z0-9_]*)")
7
7
private let ignoreRegex = try Regex ( #"// *@ignore-import$"# )
8
8
private var cachedLines = [ String: [ String . SubSequence] ] ( )
9
9
10
+ private struct Configuration : Decodable {
11
+ let ignoredFileRegex : Regex < AnyRegexOutput > ?
12
+ let ignoredModuleRegex : Regex < AnyRegexOutput > ?
13
+ let alwaysKeepImports : Set < String >
14
+
15
+ private enum CodingKeys : String , CodingKey {
16
+ case ignoredFileRegex = " ignored-file-regex "
17
+ case ignoredModuleRegex = " ignored-module-regex "
18
+ case alwaysKeepImports = " always-keep-imports "
19
+ }
20
+
21
+ init ( ) {
22
+ self . alwaysKeepImports = [ ]
23
+ self . ignoredFileRegex = nil
24
+ self . ignoredModuleRegex = nil
25
+ }
26
+
27
+ init ( from decoder: Decoder ) throws {
28
+ let values = try decoder. container ( keyedBy: CodingKeys . self)
29
+ self . alwaysKeepImports = Set ( try values. decodeIfPresent ( [ String ] . self, forKey: . alwaysKeepImports) ?? [ ] )
30
+
31
+ if let string = try values. decodeIfPresent ( String . self, forKey: . ignoredFileRegex) {
32
+ self . ignoredFileRegex = try Regex ( string)
33
+ } else {
34
+ self . ignoredFileRegex = nil
35
+ }
36
+
37
+ if let string = try values. decodeIfPresent ( String . self, forKey: . ignoredModuleRegex) {
38
+ self . ignoredModuleRegex = try Regex ( string)
39
+ } else {
40
+ self . ignoredModuleRegex = nil
41
+ }
42
+ }
43
+
44
+ func shouldIgnoreFile( _ file: String ) -> Bool {
45
+ if let ignoredFileRegex, file. wholeMatch ( of: ignoredFileRegex) != nil {
46
+ return true
47
+ }
48
+
49
+ return false
50
+ }
51
+
52
+ func shouldIgnoreModule( _ module: String ) -> Bool {
53
+ if let ignoredModuleRegex, module. wholeMatch ( of: ignoredModuleRegex) != nil {
54
+ return true
55
+ }
56
+
57
+ return false
58
+ }
59
+ }
60
+
10
61
private func getImports( path: String , recordReader: RecordReader ) -> ( Set < String > , [ String : Int ] ) {
11
62
var importsToLineNumbers = [ String: Int] ( )
12
63
let lines = try ! String ( contentsOfFile: path) . split ( separator: " \n " , omittingEmptySubsequences: false )
@@ -92,10 +143,9 @@ private func collectUnitsAndRecords(indexStorePath: String) -> [(UnitReader, Rec
92
143
return unitsAndRecords
93
144
}
94
145
95
- func main(
146
+ private func main(
96
147
indexStorePath: String ,
97
- ignoredFileRegex: Regex < AnyRegexOutput > ? ,
98
- ignoredModuleRegex: Regex < AnyRegexOutput > ? )
148
+ configuration: Configuration )
99
149
{
100
150
if let directory = ProcessInfo . processInfo. environment [ " BUILD_WORKSPACE_DIRECTORY " ] {
101
151
FileManager . default. changeCurrentDirectoryPath ( directory)
@@ -130,9 +180,9 @@ func main(
130
180
}
131
181
132
182
for (unitReader, recordReader) in unitsAndRecords {
133
- if let ignoredFileRegex , unitReader. mainFile. wholeMatch ( of : ignoredFileRegex ) != nil {
183
+ if configuration . shouldIgnoreFile ( unitReader. mainFile) {
134
184
continue
135
- } else if let ignoredModuleRegex , unitReader. moduleName. wholeMatch ( of : ignoredModuleRegex ) != nil {
185
+ } else if configuration . shouldIgnoreModule ( unitReader. moduleName) {
136
186
continue
137
187
}
138
188
@@ -171,7 +221,7 @@ func main(
171
221
}
172
222
}
173
223
174
- let unusedImports = allImports. subtracting ( usedImports)
224
+ let unusedImports = allImports. subtracting ( usedImports) . subtracting ( configuration . alwaysKeepImports )
175
225
if !unusedImports. isEmpty {
176
226
let sedCmd = unusedImports. map { importsToLineNumbers [ $0] ! } . sorted ( ) . map { " \( $0) d " } . joined ( separator: " ; " )
177
227
let relativePath = unitReader. mainFile. replacingOccurrences ( of: pwd + " / " , with: " " )
@@ -180,19 +230,17 @@ func main(
180
230
}
181
231
}
182
232
183
- if CommandLine . arguments. count == 4 {
184
- let ignoredFileRegex = try Regex ( CommandLine . arguments [ 2 ] )
185
- let ignoredModuleRegex = try Regex ( CommandLine . arguments [ 3 ] )
233
+ if CommandLine . arguments. count == 3 {
234
+ let configurationData = try ! Data ( contentsOf : URL ( fileURLWithPath : CommandLine . arguments [ 1 ] ) )
235
+ let configuration = try ! JSONDecoder ( ) . decode ( Configuration . self , from : configurationData )
186
236
187
237
main (
188
- indexStorePath: CommandLine . arguments [ 1 ] ,
189
- ignoredFileRegex: ignoredFileRegex,
190
- ignoredModuleRegex: ignoredModuleRegex
238
+ indexStorePath: CommandLine . arguments [ 2 ] ,
239
+ configuration: configuration
191
240
)
192
241
} else {
193
242
main (
194
243
indexStorePath: CommandLine . arguments [ 1 ] ,
195
- ignoredFileRegex: nil ,
196
- ignoredModuleRegex: nil
244
+ configuration: Configuration ( )
197
245
)
198
246
}
0 commit comments