Skip to content

Commit

Permalink
Merge branch 'main' into jgrubb-redundant-type-interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
SimplyDanny authored Nov 12, 2024
2 parents e8b3990 + 3344fc6 commit a041b3a
Show file tree
Hide file tree
Showing 57 changed files with 249 additions and 118 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@
* The `redundant_type_annotation` rule gains a new option,
`ignore_properties`, that skips enforcement on members in a
type declaration (like a `struct`). This helps the rule coexist with
the `explicit_type_interface` rule that requires such redundancy.
the `explicit_type_interface` rule that requires such redundancy.
[jaredgrubb](https://github.com/jaredgrubb)
[#3750](https://github.com/realm/SwiftLint/issues/3750)

* Adds a `lenient` configuration file setting, equivalent to the `--lenient`
command line option.
[Martin Redington](https://github.com/mildm8nnered)
[#5801](https://github.com/realm/SwiftLint/issues/5801)

#### Bug Fixes

* Run command plugin in whole package if no targets are defined in the
Expand All @@ -46,6 +51,11 @@
[SimplyDanny](https://github.com/SimplyDanny)
[#5167](https://github.com/realm/SwiftLint/issues/5167)

* Only pass cache path and directory paths to commands that accept these arguments
in the command plugin.
[SimplyDanny](https://github.com/SimplyDanny)
[#5848](https://github.com/realm/SwiftLint/issues/5848)

* Do not throw deprecation warning if deprecated property is not
presented in configuration.
[chipp](https://github.com/chipp)
Expand Down
4 changes: 1 addition & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ GEM
public_suffix (4.0.7)
rchardet (1.8.0)
redcarpet (3.6.0)
rexml (3.3.6)
strscan
rexml (3.3.9)
rouge (4.3.0)
ruby-macho (2.5.1)
ruby2_keywords (0.0.5)
Expand All @@ -134,7 +133,6 @@ GEM
faraday (>= 0.17.3, < 3)
sqlite3 (1.7.3-arm64-darwin)
sqlite3 (1.7.3-x86_64-linux)
strscan (3.1.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
typhoeus (1.4.0)
Expand Down
22 changes: 18 additions & 4 deletions Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import Foundation
import PackagePlugin

private let commandsNotExpectingPaths: Set<String> = [
"docs",
"generate-docs",
"baseline",
"reporters",
"rules",
"version",
]

private let commandsWithoutCachPathOption: Set<String> = commandsNotExpectingPaths.union([
"analyze",
])

@main
struct SwiftLintCommandPlugin: CommandPlugin {
func performCommand(context: PluginContext, arguments: [String]) throws {
Expand All @@ -13,7 +26,7 @@ struct SwiftLintCommandPlugin: CommandPlugin {
let targets = targetNames.isEmpty
? context.package.targets
: try context.package.targets(named: targetNames)
guard !targets.isEmpty else {
if targets.isEmpty || !commandsNotExpectingPaths.isDisjoint(with: arguments) {
try run(with: context, arguments: arguments)
return
}
Expand All @@ -34,11 +47,12 @@ struct SwiftLintCommandPlugin: CommandPlugin {
process.currentDirectoryURL = URL(fileURLWithPath: context.package.directory.string)
process.executableURL = URL(fileURLWithPath: try context.tool(named: "swiftlint").path.string)
process.arguments = arguments
if !arguments.contains("analyze") {
// The analyze command does not support the `--cache-path` argument.
if commandsWithoutCachPathOption.isDisjoint(with: arguments) {
process.arguments! += ["--cache-path", "\(context.pluginWorkDirectory.string)"]
}
process.arguments! += [directory]
if commandsNotExpectingPaths.isDisjoint(with: arguments) {
process.arguments! += [directory]
}

try process.run()
process.waitUntilExit()
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,9 @@ allow_zero_lintable_files: false
# If true, SwiftLint will treat all warnings as errors.
strict: false

# If true, SwiftLint will treat all errors as warnings.
lenient: false

# The path to a baseline file, which will be used to filter out detected violations.
baseline: Baseline.json

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ private extension SwiftLintFile {
let path = self.path,
let response = try? Request.index(file: path, arguments: compilerArguments).sendIfNotDisabled()
else {
Issue.indexingError(path: path, ruleID: CaptureVariableRule.description.identifier).print()
Issue.indexingError(path: path, ruleID: CaptureVariableRule.identifier).print()
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import SwiftSyntax

// TODO: [12/23/2024] Remove deprecation warning after ~2 years.
private let warnDeprecatedOnceImpl: Void = {
Issue.ruleDeprecated(ruleID: InertDeferRule.description.identifier).print()
Issue.ruleDeprecated(ruleID: InertDeferRule.identifier).print()
}()

private func warnDeprecatedOnce() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ struct TypesafeArrayInitRule: AnalyzerRule {
return []
}
guard compilerArguments.isNotEmpty else {
Issue.missingCompilerArguments(path: file.path, ruleID: Self.description.identifier).print()
Issue.missingCompilerArguments(path: file.path, ruleID: Self.identifier).print()
return []
}
return Self.parentRule.validate(file: file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import SwiftSyntax

// TODO: [12/22/2024] Remove deprecation warning after ~2 years.
private let warnDeprecatedOnceImpl: Void = {
Issue.ruleDeprecated(ruleID: UnusedCaptureListRule.description.identifier).print()
Issue.ruleDeprecated(ruleID: UnusedCaptureListRule.identifier).print()
}()

private func warnDeprecatedOnce() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ struct UnusedDeclarationRule: AnalyzerRule, CollectingRule {

func collectInfo(for file: SwiftLintFile, compilerArguments: [String]) -> Self.FileUSRs {
guard compilerArguments.isNotEmpty else {
Issue.missingCompilerArguments(path: file.path, ruleID: Self.description.identifier).print()
Issue.missingCompilerArguments(path: file.path, ruleID: Self.identifier).print()
return .empty
}

guard let index = file.index(compilerArguments: compilerArguments), index.value.isNotEmpty else {
Issue.indexingError(path: file.path, ruleID: Self.description.identifier).print()
Issue.indexingError(path: file.path, ruleID: Self.identifier).print()
return .empty
}

guard let editorOpen = (try? Request.editorOpen(file: file.file).sendIfNotDisabled())
.map(SourceKittenDictionary.init) else {
Issue.fileNotReadable(path: file.path, ruleID: Self.description.identifier).print()
Issue.fileNotReadable(path: file.path, ruleID: Self.identifier).print()
return .empty
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ struct UnusedImportRule: CorrectableRule, AnalyzerRule {

private func importUsage(in file: SwiftLintFile, compilerArguments: [String]) -> [ImportUsage] {
guard compilerArguments.isNotEmpty else {
Issue.missingCompilerArguments(path: file.path, ruleID: Self.description.identifier).print()
Issue.missingCompilerArguments(path: file.path, ruleID: Self.identifier).print()
return []
}

Expand Down Expand Up @@ -178,7 +178,7 @@ private extension SwiftLintFile {
file: path!, offset: token.offset, arguments: compilerArguments
)
guard let cursorInfo = (try? cursorInfoRequest.sendIfNotDisabled()).map(SourceKittenDictionary.init) else {
Issue.missingCursorInfo(path: path, ruleID: UnusedImportRule.description.identifier).print()
Issue.missingCursorInfo(path: path, ruleID: UnusedImportRule.identifier).print()
continue
}
if nextIsModuleImport {
Expand Down Expand Up @@ -213,7 +213,7 @@ private extension SwiftLintFile {
func operatorImports(arguments: [String], processedTokenOffsets: Set<ByteCount>) -> Set<String> {
guard let index = (try? Request.index(file: path!, arguments: arguments).sendIfNotDisabled())
.map(SourceKittenDictionary.init) else {
Issue.indexingError(path: path, ruleID: UnusedImportRule.description.identifier).print()
Issue.indexingError(path: path, ruleID: UnusedImportRule.identifier).print()
return []
}

Expand All @@ -236,7 +236,7 @@ private extension SwiftLintFile {
)
guard let cursorInfo = (try? cursorInfoRequest.sendIfNotDisabled())
.map(SourceKittenDictionary.init) else {
Issue.missingCursorInfo(path: path, ruleID: UnusedImportRule.description.identifier).print()
Issue.missingCursorInfo(path: path, ruleID: UnusedImportRule.identifier).print()
continue
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct ExplicitSelfRule: CorrectableRule, AnalyzerRule {

private func violationRanges(in file: SwiftLintFile, compilerArguments: [String]) -> [NSRange] {
guard compilerArguments.isNotEmpty else {
Issue.missingCompilerArguments(path: file.path, ruleID: Self.description.identifier).print()
Issue.missingCompilerArguments(path: file.path, ruleID: Self.identifier).print()
return []
}

Expand All @@ -69,7 +69,7 @@ struct ExplicitSelfRule: CorrectableRule, AnalyzerRule {

return cursorsMissingExplicitSelf.compactMap { cursorInfo in
guard let byteOffset = (cursorInfo["swiftlint.offset"] as? Int64).flatMap(ByteCount.init) else {
Issue.genericWarning("Cannot convert offsets in '\(Self.description.identifier)' rule.").print()
Issue.genericWarning("Cannot convert offsets in '\(Self.identifier)' rule.").print()
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions Source/SwiftLintCore/Documentation/RuleDocumentation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ struct RuleDocumentation {
var ruleName: String { ruleType.description.name }

/// The identifier of the documented rule.
var ruleIdentifier: String { ruleType.description.identifier }
var ruleIdentifier: String { ruleType.identifier }

/// The name of the file on disk for this rule documentation.
var fileName: String { "\(ruleType.description.identifier).md" }
var fileName: String { "\(ruleType.identifier).md" }

/// The contents of the file for this rule documentation.
var fileContents: String {
Expand Down Expand Up @@ -81,7 +81,7 @@ private func h2(_ text: String) -> String { "## \(text)" }

private func detailsSummary(_ rule: some Rule) -> String {
let ruleDescription = """
* **Identifier:** `\(type(of: rule).description.identifier)`
* **Identifier:** `\(type(of: rule).identifier)`
* **Enabled by default:** \(rule is any OptInRule ? "No" : "Yes")
* **Supports autocorrection:** \(rule is any CorrectableRule ? "Yes" : "No")
* **Kind:** \(type(of: rule).description.kind)
Expand Down
2 changes: 1 addition & 1 deletion Source/SwiftLintCore/Extensions/Configuration+Cache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ extension Configuration {
}

let cacheRulesDescriptions = rules
.map { rule in [type(of: rule).description.identifier, rule.cacheDescription] }
.map { rule in [type(of: rule).identifier, rule.cacheDescription] }
.sorted { $0[0] < $1[0] }
let jsonObject: [Any] = [rootDirectory, cacheRulesDescriptions]
if let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extension Configuration {
cachePath: cachePath,
allowZeroLintableFiles: childConfiguration.allowZeroLintableFiles,
strict: childConfiguration.strict,
lenient: childConfiguration.lenient,
baseline: childConfiguration.baseline,
writeBaseline: childConfiguration.writeBaseline,
checkForUpdates: childConfiguration.checkForUpdates
Expand Down
4 changes: 3 additions & 1 deletion Source/SwiftLintCore/Extensions/Configuration+Parsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extension Configuration {
case analyzerRules = "analyzer_rules"
case allowZeroLintableFiles = "allow_zero_lintable_files"
case strict = "strict"
case lenient = "lenient"
case baseline = "baseline"
case writeBaseline = "write_baseline"
case checkForUpdates = "check_for_updates"
Expand Down Expand Up @@ -66,7 +67,7 @@ extension Configuration {
allRulesWrapped = try ruleList.allRulesWrapped(configurationDict: dict)
} catch let RuleListError.duplicatedConfigurations(ruleType) {
let aliases = ruleType.description.deprecatedAliases.map { "'\($0)'" }.joined(separator: ", ")
let identifier = ruleType.description.identifier
let identifier = ruleType.identifier
throw Issue.genericWarning(
"Multiple configurations found for '\(identifier)'. Check for any aliases: \(aliases)."
)
Expand Down Expand Up @@ -103,6 +104,7 @@ extension Configuration {
pinnedVersion: dict[Key.swiftlintVersion.rawValue].map { ($0 as? String) ?? String(describing: $0) },
allowZeroLintableFiles: dict[Key.allowZeroLintableFiles.rawValue] as? Bool ?? false,
strict: dict[Key.strict.rawValue] as? Bool ?? false,
lenient: dict[Key.lenient.rawValue] as? Bool ?? false,
baseline: dict[Key.baseline.rawValue] as? String,
writeBaseline: dict[Key.writeBaseline.rawValue] as? String,
checkForUpdates: dict[Key.checkForUpdates.rawValue] as? Bool ?? false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public extension Configuration {
/// - returns: The rule for the specified ID, if configured in this configuration.
func configuredRule(forID ruleID: String) -> (any Rule)? {
rules.first { rule in
if type(of: rule).description.identifier == ruleID {
if type(of: rule).identifier == ruleID {
if let customRules = rule as? CustomRules {
return customRules.configuration.customRuleConfigurations.isNotEmpty
}
Expand Down
16 changes: 8 additions & 8 deletions Source/SwiftLintCore/Extensions/Configuration+RulesWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal extension Configuration {

private var invalidRuleIdsWarnedAbout: Set<String> = []
private var validRuleIdentifiers: Set<String> {
let regularRuleIdentifiers = allRulesWrapped.map { type(of: $0.rule).description.identifier }
let regularRuleIdentifiers = allRulesWrapped.map { type(of: $0.rule).identifier }
let configurationCustomRulesIdentifiers =
(allRulesWrapped.first { $0.rule is CustomRules }?.rule as? CustomRules)?.customRuleIdentifiers ?? []
return Set(regularRuleIdentifiers + configurationCustomRulesIdentifiers)
Expand Down Expand Up @@ -42,15 +42,15 @@ internal extension Configuration {
customRulesFilter = { onlyRulesRuleIdentifiers.contains($0.identifier) }
let onlyRulesRuleIdentifiers = validate(ruleIds: onlyRulesRuleIdentifiers, valid: validRuleIdentifiers)
resultingRules = allRulesWrapped.filter { tuple in
onlyRulesRuleIdentifiers.contains(type(of: tuple.rule).description.identifier)
onlyRulesRuleIdentifiers.contains(type(of: tuple.rule).identifier)
}.map(\.rule)

case var .defaultConfiguration(disabledRuleIdentifiers, optInRuleIdentifiers):
customRulesFilter = { !disabledRuleIdentifiers.contains($0.identifier) }
disabledRuleIdentifiers = validate(ruleIds: disabledRuleIdentifiers, valid: validRuleIdentifiers)
optInRuleIdentifiers = validate(optInRuleIds: optInRuleIdentifiers, valid: validRuleIdentifiers)
resultingRules = allRulesWrapped.filter { tuple in
let id = type(of: tuple.rule).description.identifier
let id = type(of: tuple.rule).identifier
return !disabledRuleIdentifiers.contains(id)
&& (!(tuple.rule is any OptInRule) || optInRuleIdentifiers.contains(id))
}.map(\.rule)
Expand All @@ -65,7 +65,7 @@ internal extension Configuration {

// Sort by name
resultingRules = resultingRules.sorted {
type(of: $0).description.identifier < type(of: $1).description.identifier
type(of: $0).identifier < type(of: $1).identifier
}

// Store & return
Expand All @@ -82,7 +82,7 @@ internal extension Configuration {
case let .onlyConfiguration(onlyRules), let .onlyCommandLine(onlyRules):
return validate(
ruleIds: Set(allRulesWrapped
.map { type(of: $0.rule).description.identifier }
.map { type(of: $0.rule).identifier }
.filter { !onlyRules.contains($0) }),
valid: validRuleIdentifiers,
silent: true
Expand Down Expand Up @@ -249,7 +249,7 @@ internal extension Configuration {
case var .onlyConfiguration(onlyRules):
// Also add identifiers of child custom rules iff the custom_rules rule is enabled
// (parent custom rules are already added)
if (onlyRules.contains { $0 == CustomRules.description.identifier }) {
if (onlyRules.contains { $0 == CustomRules.identifier }) {
if let childCustomRulesRule = (child.allRulesWrapped.first { $0.rule is CustomRules })?.rule
as? CustomRules {
onlyRules = onlyRules.union(
Expand Down Expand Up @@ -279,7 +279,7 @@ internal extension Configuration {
.filter {
!isOptInRule($0, allRulesWrapped: newAllRulesWrapped)
},
optIn: Set(newAllRulesWrapped.map { type(of: $0.rule).description.identifier }
optIn: Set(newAllRulesWrapped.map { type(of: $0.rule).identifier }
.filter {
!childDisabled.contains($0)
&& isOptInRule($0, allRulesWrapped: newAllRulesWrapped)
Expand All @@ -298,7 +298,7 @@ internal extension Configuration {
}

let isOptInRule = allRulesWrapped
.first { type(of: $0.rule).description.identifier == identifier }?.rule is any OptInRule
.first { type(of: $0.rule).identifier == identifier }?.rule is any OptInRule
Self.isOptInRuleCache[identifier] = isOptInRule
return isOptInRule
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public struct ChildOptionSeverityConfiguration<Parent: Rule>: RuleConfiguration,
public mutating func apply(configuration: Any) throws {
guard let configString = configuration as? String,
let optionSeverity = ChildOptionSeverity(rawValue: configString.lowercased()) else {
throw Issue.invalidConfiguration(ruleID: Parent.description.identifier)
throw Issue.invalidConfiguration(ruleID: Parent.identifier)
}
self.optionSeverity = optionSeverity
}
Expand Down
Loading

0 comments on commit a041b3a

Please sign in to comment.