-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate from Commandant to swift-argument-parser
- Loading branch information
Showing
19 changed files
with
360 additions
and
563 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,52 @@ | ||
import Commandant | ||
import ArgumentParser | ||
import SwiftLintFramework | ||
|
||
struct AnalyzeCommand: CommandProtocol { | ||
let verb = "analyze" | ||
let function = "[Experimental] Run analysis rules" | ||
extension SwiftLint { | ||
struct Analyze: ParsableCommand { | ||
static let configuration = CommandConfiguration(abstract: "Run analysis rules") | ||
|
||
func run(_ options: AnalyzeOptions) -> Result<(), CommandantError<()>> { | ||
let options = LintOrAnalyzeOptions(options) | ||
if options.autocorrect { | ||
return autocorrect(options) | ||
} else { | ||
return LintOrAnalyzeCommand.run(options) | ||
} | ||
} | ||
|
||
private func autocorrect(_ options: LintOrAnalyzeOptions) -> Result<(), CommandantError<()>> { | ||
let storage = RuleStorage() | ||
let configuration = Configuration(options: options) | ||
return configuration.visitLintableFiles(options: options, cache: nil, storage: storage) { linter in | ||
let corrections = linter.correct(using: storage) | ||
if !corrections.isEmpty && !options.quiet { | ||
let correctionLogs = corrections.map({ $0.consoleDescription }) | ||
queuedPrint(correctionLogs.joined(separator: "\n")) | ||
} | ||
}.flatMap { files in | ||
if !options.quiet { | ||
let pluralSuffix = { (collection: [Any]) -> String in | ||
return collection.count != 1 ? "s" : "" | ||
} | ||
queuedPrintError("Done correcting \(files.count) file\(pluralSuffix(files))!") | ||
} | ||
return .success(()) | ||
} | ||
} | ||
} | ||
@OptionGroup | ||
var common: LintOrAnalyzeArguments | ||
@Option(help: pathOptionDescription(for: .analyze)) | ||
var path: String? | ||
@Flag(help: quietOptionDescription(for: .analyze)) | ||
var quiet = false | ||
@Option(help: "The path of the full xcodebuild log to use when running AnalyzerRules.") | ||
var compilerLogPath: String? | ||
@Option(help: "The path of a compilation database to use when running AnalyzerRules.") | ||
var compileCommands: String? | ||
@Argument(help: pathsArgumentDescription(for: .analyze)) | ||
var paths = [String]() | ||
|
||
struct AnalyzeOptions: OptionsProtocol { | ||
let paths: [String] | ||
let configurationFiles: [String] | ||
let strict: Bool | ||
let lenient: Bool | ||
let forceExclude: Bool | ||
let excludeByPrefix: Bool | ||
let useScriptInputFiles: Bool | ||
let benchmark: Bool | ||
let reporter: String | ||
let quiet: Bool | ||
let enableAllRules: Bool | ||
let autocorrect: Bool | ||
let compilerLogPath: String | ||
let compileCommands: String | ||
mutating func run() throws { | ||
let options = LintOrAnalyzeOptions( | ||
mode: .analyze, | ||
paths: paths + [path ?? ""], | ||
useSTDIN: false, | ||
configurationFiles: common.config, | ||
strict: common.strict, | ||
lenient: common.lenient, | ||
forceExclude: common.forceExclude, | ||
useExcludingByPrefix: common.useAlternativeExcluding, | ||
useScriptInputFiles: common.useScriptInputFiles, | ||
benchmark: common.benchmark, | ||
reporter: common.reporter, | ||
quiet: quiet, | ||
cachePath: nil, | ||
ignoreCache: true, | ||
enableAllRules: false, | ||
autocorrect: common.fix, | ||
compilerLogPath: compilerLogPath, | ||
compileCommands: compileCommands | ||
) | ||
|
||
// swiftlint:disable line_length | ||
static func create(_ path: String) -> (_ configurationFiles: [String]) -> (_ strict: Bool) -> (_ lenient: Bool) -> (_ forceExclude: Bool) -> (_ excludeByPrefix: Bool) -> (_ useScriptInputFiles: Bool) -> (_ benchmark: Bool) -> (_ reporter: String) -> (_ quiet: Bool) -> (_ enableAllRules: Bool) -> (_ autocorrect: Bool) -> (_ compilerLogPath: String) -> (_ compileCommands: String) -> (_ paths: [String]) -> AnalyzeOptions { | ||
return { configurationFiles in { strict in { lenient in { forceExclude in { excludeByPrefix in { useScriptInputFiles in { benchmark in { reporter in { quiet in { enableAllRules in { autocorrect in { compilerLogPath in { compileCommands in { paths in | ||
let allPaths: [String] | ||
if !path.isEmpty { | ||
allPaths = [path] | ||
} else { | ||
allPaths = paths | ||
let result = LintOrAnalyzeCommand.run(options) | ||
switch result { | ||
case .success: | ||
return | ||
case .failure(let error): | ||
throw error | ||
} | ||
|
||
return self.init(paths: allPaths, configurationFiles: configurationFiles, strict: strict, lenient: lenient, forceExclude: forceExclude, excludeByPrefix: excludeByPrefix, useScriptInputFiles: useScriptInputFiles, benchmark: benchmark, reporter: reporter, quiet: quiet, enableAllRules: enableAllRules, autocorrect: autocorrect, compilerLogPath: compilerLogPath, compileCommands: compileCommands) | ||
// swiftlint:enable line_length | ||
}}}}}}}}}}}}}} | ||
} | ||
|
||
static func evaluate(_ mode: CommandMode) -> Result<AnalyzeOptions, CommandantError<CommandantError<()>>> { | ||
return create | ||
<*> mode <| pathOption(action: "analyze") | ||
<*> mode <| configOption | ||
<*> mode <| Option(key: "strict", defaultValue: false, | ||
usage: "upgrades warnings to serious violations (errors)") | ||
<*> mode <| Option(key: "lenient", defaultValue: false, | ||
usage: "downgrades serious violations to warnings, warning threshold is disabled") | ||
<*> mode <| Option(key: "force-exclude", defaultValue: false, | ||
usage: "exclude files in config `excluded` even if their paths are explicitly specified") | ||
<*> mode <| useAlternativeExcludingOption | ||
<*> mode <| useScriptInputFilesOption | ||
<*> mode <| Option(key: "benchmark", defaultValue: false, | ||
usage: "save benchmarks to benchmark_files.txt " + | ||
"and benchmark_rules.txt") | ||
<*> mode <| Option(key: "reporter", defaultValue: "", | ||
usage: "the reporter used to log errors and warnings") | ||
<*> mode <| quietOption(action: "linting") | ||
<*> mode <| Option(key: "enable-all-rules", defaultValue: false, | ||
usage: "run all rules, even opt-in and disabled ones, ignoring `only_rules`") | ||
<*> mode <| Option(key: "autocorrect", defaultValue: false, | ||
usage: "correct violations whenever possible") | ||
<*> mode <| Option(key: "compiler-log-path", defaultValue: "", | ||
usage: "the path of the full xcodebuild log to use when linting AnalyzerRules") | ||
<*> mode <| Option(key: "compile-commands", defaultValue: "", | ||
usage: "the path of a compilation database to use when linting AnalyzerRules") | ||
// This should go last to avoid eating other args | ||
<*> mode <| pathsArgument(action: "analyze") | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,29 @@ | ||
import Commandant | ||
import ArgumentParser | ||
import Foundation | ||
|
||
struct ShowDocsCommand: CommandProtocol { | ||
let verb = "docs" | ||
let function = "Open SwiftLint Docs on web browser" | ||
extension SwiftLint { | ||
struct Docs: ParsableCommand { | ||
static let configuration = CommandConfiguration( | ||
abstract: "Open SwiftLint documentation website in the default web browser" | ||
) | ||
|
||
func run(_ options: NoOptions<CommandantError<()>>) -> Result<(), CommandantError<()>> { | ||
let url = URL(string: "https://realm.github.io/SwiftLint")! | ||
open(url) | ||
return .success(()) | ||
mutating func run() throws { | ||
open(URL(string: "https://realm.github.io/SwiftLint")!) | ||
} | ||
} | ||
} | ||
|
||
private extension ShowDocsCommand { | ||
func open(_ url: URL) { | ||
let process = Process() | ||
private func open(_ url: URL) { | ||
let process = Process() | ||
#if os(Linux) | ||
process.executableURL = URL(fileURLWithPath: "/usr/bin/env") | ||
let command = "xdg-open" | ||
process.arguments = [command, url.absoluteString] | ||
try? process.run() | ||
process.executableURL = URL(fileURLWithPath: "/usr/bin/env") | ||
let command = "xdg-open" | ||
process.arguments = [command, url.absoluteString] | ||
try? process.run() | ||
#else | ||
process.launchPath = "/usr/bin/env" | ||
let command = "open" | ||
process.arguments = [command, url.absoluteString] | ||
process.launch() | ||
process.launchPath = "/usr/bin/env" | ||
let command = "open" | ||
process.arguments = [command, url.absoluteString] | ||
process.launch() | ||
#endif | ||
} | ||
} |
Oops, something went wrong.