Skip to content

Commit

Permalink
Migrate from Commandant to swift-argument-parser
Browse files Browse the repository at this point in the history
  • Loading branch information
jpsim committed Dec 14, 2020
1 parent 82b00bf commit fa55508
Show file tree
Hide file tree
Showing 19 changed files with 360 additions and 563 deletions.
1 change: 0 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ opt_in_rules:
- last_where
- legacy_multiple
- legacy_random
- let_var_whitespace
- literal_expression_end_indentation
- lower_acl_than_parent
- modifier_order
Expand Down
27 changes: 0 additions & 27 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,33 +1,6 @@
{
"object": {
"pins": [
{
"package": "Commandant",
"repositoryURL": "https://github.com/Carthage/Commandant.git",
"state": {
"branch": null,
"revision": "ab68611013dec67413628ac87c1f29e8427bc8e4",
"version": "0.17.0"
}
},
{
"package": "Nimble",
"repositoryURL": "https://github.com/Quick/Nimble.git",
"state": {
"branch": null,
"revision": "7a46a5fc86cb917f69e3daf79fcb045283d8f008",
"version": "8.1.2"
}
},
{
"package": "Quick",
"repositoryURL": "https://github.com/Quick/Quick.git",
"state": {
"branch": null,
"revision": "09b3becb37cb2163919a3842a4c5fa6ec7130792",
"version": "2.2.1"
}
},
{
"package": "SourceKitten",
"repositoryURL": "https://github.com/jpsim/SourceKitten.git",
Expand Down
8 changes: 4 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.0
// swift-tools-version:5.2
import PackageDescription

#if canImport(CommonCrypto)
Expand All @@ -14,7 +14,7 @@ let package = Package(
.library(name: "SwiftLintFramework", targets: ["SwiftLintFramework"])
],
dependencies: [
.package(url: "https://github.com/Carthage/Commandant.git", .upToNextMinor(from: "0.17.0")),
.package(name: "swift-argument-parser", url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "0.3.1")),
.package(url: "https://github.com/jpsim/SourceKitten.git", .upToNextMinor(from: "0.31.0")),
.package(url: "https://github.com/jpsim/Yams.git", from: "4.0.2"),
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.9.0"),
Expand All @@ -23,15 +23,15 @@ let package = Package(
.target(
name: "swiftlint",
dependencies: [
"Commandant",
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"SwiftLintFramework",
"SwiftyTextTable",
]
),
.target(
name: "SwiftLintFramework",
dependencies: [
"SourceKittenFramework",
.product(name: "SourceKittenFramework", package: "SourceKitten"),
"Yams",
] + (addCryptoSwift ? ["CryptoSwift"] : [])
),
Expand Down
134 changes: 44 additions & 90 deletions Source/swiftlint/Commands/Analyze.swift
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")
}
}
}
91 changes: 0 additions & 91 deletions Source/swiftlint/Commands/AutoCorrect.swift

This file was deleted.

39 changes: 19 additions & 20 deletions Source/swiftlint/Commands/Docs.swift
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
}
}
Loading

0 comments on commit fa55508

Please sign in to comment.