@@ -6,6 +6,7 @@ private typealias References = (usrs: Set<String>, typealiases: Set<String>)
66private let identifierRegex = try Regex ( " ([a-zA-Z_][a-zA-Z0-9_]*) " )
77private let ignoreRegex = try Regex ( #"// *@ignore-import$"# )
88private var cachedLines = [ String: [ String . SubSequence] ] ( )
9+ private let defaultReporter = SedCommandReporter ( )
910
1011private struct Configuration : Decodable {
1112 static func attemptingPath( _ path: String ? ) -> Configuration ? {
@@ -23,17 +24,20 @@ private struct Configuration: Decodable {
2324 let ignoredFileRegex : Regex < AnyRegexOutput > ?
2425 let ignoredModuleRegex : Regex < AnyRegexOutput > ?
2526 let alwaysKeepImports : Set < String >
27+ let reporter : UnusedImportReporter
2628
2729 private enum CodingKeys : String , CodingKey {
2830 case ignoredFileRegex = " ignored-file-regex "
2931 case ignoredModuleRegex = " ignored-module-regex "
3032 case alwaysKeepImports = " always-keep-imports "
33+ case reporter = " reporter "
3134 }
3235
3336 init ( ) {
3437 self . alwaysKeepImports = [ ]
3538 self . ignoredFileRegex = nil
3639 self . ignoredModuleRegex = nil
40+ self . reporter = defaultReporter
3741 }
3842
3943 init ( from decoder: Decoder ) throws {
@@ -51,6 +55,23 @@ private struct Configuration: Decodable {
5155 } else {
5256 self . ignoredModuleRegex = nil
5357 }
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+ }
5475 }
5576
5677 func shouldIgnoreFile( _ file: String ) -> Bool {
@@ -68,6 +89,10 @@ private struct Configuration: Decodable {
6889
6990 return false
7091 }
92+
93+ func didFind( sourceFilesWithUnusedImports: [ SourceFileWithUnusedImports ] ) {
94+ self . reporter. didFind ( sourceFilesWithUnusedImports: sourceFilesWithUnusedImports)
95+ }
7196}
7297
7398private func getImports( path: String , recordReader: RecordReader ) -> ( Set < String > , [ String : Int ] ) {
@@ -191,6 +216,8 @@ private func main(
191216 usrs: definedUsrs, typealiases: definedTypealiases)
192217 }
193218
219+ var sourceFilesWithUnusedImports : [ SourceFileWithUnusedImports ] = [ ]
220+
194221 for (unitReader, recordReader) in unitsAndRecords {
195222 if configuration. shouldIgnoreFile ( unitReader. mainFile) {
196223 continue
@@ -235,10 +262,16 @@ private func main(
235262
236263 let unusedImports = allImports. subtracting ( usedImports) . subtracting ( configuration. alwaysKeepImports)
237264 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)
242275 }
243276}
244277
0 commit comments