@@ -6,6 +6,7 @@ private typealias References = (usrs: Set<String>, typealiases: Set<String>)
6
6
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
+ private let defaultReporter = SedCommandReporter ( )
9
10
10
11
private struct Configuration : Decodable {
11
12
static func attemptingPath( _ path: String ? ) -> Configuration ? {
@@ -23,17 +24,20 @@ private struct Configuration: Decodable {
23
24
let ignoredFileRegex : Regex < AnyRegexOutput > ?
24
25
let ignoredModuleRegex : Regex < AnyRegexOutput > ?
25
26
let alwaysKeepImports : Set < String >
27
+ let reporter : UnusedImportReporter
26
28
27
29
private enum CodingKeys : String , CodingKey {
28
30
case ignoredFileRegex = " ignored-file-regex "
29
31
case ignoredModuleRegex = " ignored-module-regex "
30
32
case alwaysKeepImports = " always-keep-imports "
33
+ case reporter = " reporter "
31
34
}
32
35
33
36
init ( ) {
34
37
self . alwaysKeepImports = [ ]
35
38
self . ignoredFileRegex = nil
36
39
self . ignoredModuleRegex = nil
40
+ self . reporter = defaultReporter
37
41
}
38
42
39
43
init ( from decoder: Decoder ) throws {
@@ -51,6 +55,23 @@ private struct Configuration: Decodable {
51
55
} else {
52
56
self . ignoredModuleRegex = nil
53
57
}
58
+
59
+ if let string = try values. decodeIfPresent ( String . self, forKey: . reporter) {
60
+ if string == " json " {
61
+ self . reporter = JSONReporter ( )
62
+ } else {
63
+ let invalidReporterTypeErrorMessage = """
64
+ error: requested a type of reporter that doesn't exist: ` \( string) `. "
65
+ In your unused-imports configuration try either:
66
+
67
+ 1. Removing the `reporter` key to get the default `sed` command reporter or
68
+ 2. Setting the `reporter` key to `json` to get the JSON reporter
69
+ """
70
+ fatalError ( invalidReporterTypeErrorMessage)
71
+ }
72
+ } else {
73
+ self . reporter = defaultReporter
74
+ }
54
75
}
55
76
56
77
func shouldIgnoreFile( _ file: String ) -> Bool {
@@ -68,6 +89,10 @@ private struct Configuration: Decodable {
68
89
69
90
return false
70
91
}
92
+
93
+ func didFind( sourceFilesWithUnusedImports: [ SourceFileWithUnusedImports ] ) {
94
+ self . reporter. didFind ( sourceFilesWithUnusedImports: sourceFilesWithUnusedImports)
95
+ }
71
96
}
72
97
73
98
private func getImports( path: String , recordReader: RecordReader ) -> ( Set < String > , [ String : Int ] ) {
@@ -191,6 +216,8 @@ private func main(
191
216
usrs: definedUsrs, typealiases: definedTypealiases)
192
217
}
193
218
219
+ var sourceFilesWithUnusedImports : [ SourceFileWithUnusedImports ] = [ ]
220
+
194
221
for (unitReader, recordReader) in unitsAndRecords {
195
222
if configuration. shouldIgnoreFile ( unitReader. mainFile) {
196
223
continue
@@ -235,10 +262,16 @@ private func main(
235
262
236
263
let unusedImports = allImports. subtracting ( usedImports) . subtracting ( configuration. alwaysKeepImports)
237
264
if !unusedImports. isEmpty {
238
- let sedCmd = unusedImports. map { importsToLineNumbers [ $0] ! } . sorted ( ) . map { " \( $0) d " } . joined ( separator: " ; " )
239
- let relativePath = unitReader. mainFile. replacingOccurrences ( of: pwd + " / " , with: " " )
240
- print ( " /usr/bin/sed -i \" \" ' \( sedCmd) ' ' \( relativePath) ' " )
241
- }
265
+ let sourceFileWithUnusedImports = SourceFileWithUnusedImports (
266
+ path: unitReader. mainFile. replacingOccurrences ( of: pwd + " / " , with: " " ) ,
267
+ unusedImportStatements: unusedImports. map { UnusedImportStatement ( moduleName: $0, lineNumber: importsToLineNumbers [ $0] !) } . sorted ( )
268
+ )
269
+ sourceFilesWithUnusedImports. append ( sourceFileWithUnusedImports)
270
+ }
271
+ }
272
+
273
+ if sourceFilesWithUnusedImports. count != 0 {
274
+ configuration. didFind ( sourceFilesWithUnusedImports: sourceFilesWithUnusedImports)
242
275
}
243
276
}
244
277
0 commit comments