Skip to content

Commit

Permalink
Keep only command-line related functions in swiftlint module (#5806)
Browse files Browse the repository at this point in the history
Swift 6 doesn't allow importing executable targets. So we need to
move testable logic into a framework.
  • Loading branch information
SimplyDanny authored Sep 29, 2024
1 parent 1767dab commit 246643f
Show file tree
Hide file tree
Showing 24 changed files with 144 additions and 103 deletions.
1 change: 0 additions & 1 deletion .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ build --disk_cache=~/.bazel_cache
build --experimental_remote_cache_compression
build --remote_build_event_upload=minimal
build --nolegacy_important_outputs
build --swiftcopt=-warnings-as-errors

build:release \
--compilation_mode=opt \
Expand Down
18 changes: 4 additions & 14 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -142,33 +142,23 @@ swift_library(
":SwiftLintBuiltInRules",
":SwiftLintCore",
":SwiftLintExtraRules",
"@com_github_johnsundell_collectionconcurrencykit//:CollectionConcurrencyKit",
],
)

swift_library(
name = "swiftlint.library",
swift_binary(
name = "swiftlint",
package_name = "SwiftLint",
srcs = glob(["Source/swiftlint/**/*.swift"]),
copts = copts, # TODO: strict_concurrency_copts
module_name = "swiftlint",
copts = copts,
visibility = ["//visibility:public"],
deps = [
":SwiftLintFramework",
"@com_github_johnsundell_collectionconcurrencykit//:CollectionConcurrencyKit",
"@sourcekitten_com_github_apple_swift_argument_parser//:ArgumentParser",
"@swiftlint_com_github_scottrhoyt_swifty_text_table//:SwiftyTextTable",
],
)

swift_binary(
name = "swiftlint",
copts = copts + strict_concurrency_copts,
visibility = ["//visibility:public"],
deps = [
":swiftlint.library",
],
)

apple_universal_binary(
name = "universal_swiftlint",
binary = ":swiftlint",
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ let package = Package(
.testTarget(
name: "CLITests",
dependencies: [
"swiftlint"
"SwiftLintFramework",
],
swiftSettings: swiftFeatures
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Foundation
import SwiftLintFramework

struct BenchmarkEntry {
let id: String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import CollectionConcurrencyKit
import Foundation
import SourceKittenFramework
import SwiftLintFramework

private actor CounterActor {
private var count = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import Glibc
#endif

enum ExitHelper {
static func successfullyExit() {
package enum ExitHelper {
package static func successfullyExit() {
#if os(Linux)
// Workaround for https://github.com/apple/swift/issues/59961
Glibc.exit(0)
Expand Down
2 changes: 1 addition & 1 deletion Source/SwiftLintFramework/Exports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ private let _registerAllRulesOnceImpl: Void = {
RuleRegistry.shared.register(rules: builtInRules + coreRules + extraRules())
}()

public extension RuleRegistry {
package extension RuleRegistry {
/// Register all rules. Should only be called once before any SwiftLint code is executed.
static func registerAllRulesOnce() {
_ = _registerAllRulesOnceImpl
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Dispatch
import Foundation
import SwiftLintFramework

enum LintOrAnalyzeMode {
// swiftlint:disable file_length

package enum LintOrAnalyzeMode {
case lint, analyze

var imperative: String {
package var imperative: String {
switch self {
case .lint:
return "lint"
Expand All @@ -14,7 +15,7 @@ enum LintOrAnalyzeMode {
}
}

var verb: String {
package var verb: String {
switch self {
case .lint:
return "linting"
Expand All @@ -24,8 +25,98 @@ enum LintOrAnalyzeMode {
}
}

struct LintOrAnalyzeCommand {
static func run(_ options: LintOrAnalyzeOptions) async throws {
package struct LintOrAnalyzeOptions {
let mode: LintOrAnalyzeMode
let paths: [String]
let useSTDIN: Bool
let configurationFiles: [String]
let strict: Bool
let lenient: Bool
let forceExclude: Bool
let useExcludingByPrefix: Bool
let useScriptInputFiles: Bool
let benchmark: Bool
let reporter: String?
let baseline: String?
let writeBaseline: String?
let workingDirectory: String?
let quiet: Bool
let output: String?
let progress: Bool
let cachePath: String?
let ignoreCache: Bool
let enableAllRules: Bool
let onlyRule: String?
let autocorrect: Bool
let format: Bool
let compilerLogPath: String?
let compileCommands: String?
let checkForUpdates: Bool

package init(mode: LintOrAnalyzeMode,
paths: [String],
useSTDIN: Bool,
configurationFiles: [String],
strict: Bool,
lenient: Bool,
forceExclude: Bool,
useExcludingByPrefix: Bool,
useScriptInputFiles: Bool,
benchmark: Bool,
reporter: String?,
baseline: String?,
writeBaseline: String?,
workingDirectory: String?,
quiet: Bool,
output: String?,
progress: Bool,
cachePath: String?,
ignoreCache: Bool,
enableAllRules: Bool,
onlyRule: String?,
autocorrect: Bool,
format: Bool,
compilerLogPath: String?,
compileCommands: String?,
checkForUpdates: Bool) {
self.mode = mode
self.paths = paths
self.useSTDIN = useSTDIN
self.configurationFiles = configurationFiles
self.strict = strict
self.lenient = lenient
self.forceExclude = forceExclude
self.useExcludingByPrefix = useExcludingByPrefix
self.useScriptInputFiles = useScriptInputFiles
self.benchmark = benchmark
self.reporter = reporter
self.baseline = baseline
self.writeBaseline = writeBaseline
self.workingDirectory = workingDirectory
self.quiet = quiet
self.output = output
self.progress = progress
self.cachePath = cachePath
self.ignoreCache = ignoreCache
self.enableAllRules = enableAllRules
self.onlyRule = onlyRule
self.autocorrect = autocorrect
self.format = format
self.compilerLogPath = compilerLogPath
self.compileCommands = compileCommands
self.checkForUpdates = checkForUpdates
}

var verb: String {
if autocorrect {
return "correcting"
}
return mode.verb
}
}

package struct LintOrAnalyzeCommand {
package static func run(_ options: LintOrAnalyzeOptions) async throws {
if let workingDirectory = options.workingDirectory {
if !FileManager.default.changeCurrentDirectoryPath(workingDirectory) {
throw SwiftLintError.usageError(
Expand Down Expand Up @@ -251,42 +342,6 @@ struct LintOrAnalyzeCommand {
}
}

struct LintOrAnalyzeOptions {
let mode: LintOrAnalyzeMode
let paths: [String]
let useSTDIN: Bool
let configurationFiles: [String]
let strict: Bool
let lenient: Bool
let forceExclude: Bool
let useExcludingByPrefix: Bool
let useScriptInputFiles: Bool
let benchmark: Bool
let reporter: String?
let baseline: String?
let writeBaseline: String?
let workingDirectory: String?
let quiet: Bool
let output: String?
let progress: Bool
let cachePath: String?
let ignoreCache: Bool
let enableAllRules: Bool
let onlyRule: String?
let autocorrect: Bool
let format: Bool
let compilerLogPath: String?
let compileCommands: String?
let checkForUpdates: Bool

var verb: String {
if autocorrect {
return "correcting"
}
return mode.verb
}
}

private class LintOrAnalyzeResultBuilder {
var fileBenchmark = Benchmark(name: "files")
var ruleBenchmark = Benchmark(name: "rules")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Foundation
import SourceKittenFramework
import SwiftLintFramework

typealias File = String
typealias Arguments = [String]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Dispatch
import Foundation
import SwiftLintFramework

// Inspired by https://github.com/jkandzi/Progress.swift
actor ProgressBar {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import SwiftLintFramework
package final class RulesFilter {
package struct ExcludingOptions: OptionSet {
package let rawValue: Int

final class RulesFilter {
struct ExcludingOptions: OptionSet {
let rawValue: Int
package init(rawValue: Int) {
self.rawValue = rawValue
}

static let enabled = Self(rawValue: 1 << 0)
static let disabled = Self(rawValue: 1 << 1)
static let uncorrectable = Self(rawValue: 1 << 2)
package static let enabled = Self(rawValue: 1 << 0)
package static let disabled = Self(rawValue: 1 << 1)
package static let uncorrectable = Self(rawValue: 1 << 2)
}

private let allRules: RuleList
private let enabledRules: [any Rule]

init(allRules: RuleList = RuleRegistry.shared.list, enabledRules: [any Rule]) {
package init(allRules: RuleList = RuleRegistry.shared.list, enabledRules: [any Rule]) {
self.allRules = allRules
self.enabledRules = enabledRules
}

func getRules(excluding excludingOptions: ExcludingOptions) -> RuleList {
package func getRules(excluding excludingOptions: ExcludingOptions) -> RuleList {
if excludingOptions.isEmpty {
return allRules
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Foundation

enum SwiftLintError: LocalizedError {
package enum SwiftLintError: LocalizedError {
case usageError(description: String)

var errorDescription: String? {
package var errorDescription: String? {
switch self {
case .usageError(let description):
return description
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import SwiftLintFramework

enum UpdateChecker {
static func checkForUpdates() {
package enum UpdateChecker {
package static func checkForUpdates() {
guard let url = URL(string: "https://api.github.com/repos/realm/SwiftLint/releases/latest"),
let data = sendRequest(to: url),
let latestVersionNumber = parseVersionNumber(data) else {
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion Source/swiftlint/Commands/GenerateDocs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension SwiftLint {
func run() throws {
let configuration = Configuration(configurationFiles: [config].compactMap({ $0 }))
let rulesFilter = RulesFilter(enabledRules: configuration.rules)
let rules = rulesFilter.getRules(excluding: .excludingOptions(byCommandLineOptions: rulesFilterOptions))
let rules = rulesFilter.getRules(excluding: rulesFilterOptions.excludingOptions)

try RuleListDocumentation(rules)
.write(to: URL(fileURLWithPath: path, isDirectory: true))
Expand Down
2 changes: 1 addition & 1 deletion Source/swiftlint/Commands/Rules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extension SwiftLint {
return
}
let rules = RulesFilter(enabledRules: configuration.rules)
.getRules(excluding: .excludingOptions(byCommandLineOptions: rulesFilterOptions))
.getRules(excluding: rulesFilterOptions.excludingOptions)
.list
.sorted { $0.0 < $1.0 }
if configOnly {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ArgumentParser
import SwiftLintFramework

enum LeniencyOptions: String, EnumerableFlag {
case strict, lenient
Expand Down
Loading

0 comments on commit 246643f

Please sign in to comment.