diff --git a/CHANGELOG.md b/CHANGELOG.md index fad5ef05d..0538a2301 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,12 @@ * Make forceExclude work with directly specified files. [jimmya](https://github.com/jimmya) [#4609](https://github.com/realm/SwiftLint/issues/4609) + [#4609](https://github.com/realm/SwiftLint/issues/4609) + +* Adds `all` pseudo-rule for `opt_in_rules` - enables all opt in rules + that are not listed in `disabled_rules` + [Martin Redington](https://github.com/mildm8nnered) + [#4540](https://github.com/realm/SwiftLint/issues/4540) * Separate analyzer rules as an independent section in the rule directory of the reference. diff --git a/README.md b/README.md index 40d04a4ed..23ce3776a 100644 --- a/README.md +++ b/README.md @@ -483,7 +483,10 @@ run SwiftLint from. The following parameters can be configured: Rule inclusion: * `disabled_rules`: Disable rules from the default enabled set. -* `opt_in_rules`: Enable rules that are not part of the default set. +* `opt_in_rules`: Enable rules that are not part of the default set. The + special `all` rule will enable all opt in rules, except the rules + listed in `disabled_rules`. Analyzer rules will not be enabled by + `all`, but can be listed explicitly. * `only_rules`: Only the rules specified in this list will be enabled. Cannot be specified alongside `disabled_rules` or `opt_in_rules`. * `analyzer_rules`: This is an entirely separate list of rules that are only diff --git a/Source/SwiftLintFramework/Extensions/Configuration+RulesMode.swift b/Source/SwiftLintFramework/Extensions/Configuration+RulesMode.swift index 2b5b5ebd5..97f725b55 100644 --- a/Source/SwiftLintFramework/Extensions/Configuration+RulesMode.swift +++ b/Source/SwiftLintFramework/Extensions/Configuration+RulesMode.swift @@ -61,8 +61,19 @@ public extension Configuration { self = .only(Set(onlyRules + analyzerRules)) } else { warnAboutDuplicates(in: disabledRules) - warnAboutDuplicates(in: optInRules + analyzerRules) - self = .default(disabled: Set(disabledRules), optIn: Set(optInRules + analyzerRules)) + + let effectiveOptInRules: [String] + if optInRules.contains(RuleIdentifier.all.stringRepresentation) { + let allOptInRules = primaryRuleList.list.compactMap { ruleID, ruleType in + ruleType is OptInRule.Type && !(ruleType is AnalyzerRule.Type) ? ruleID : nil + } + effectiveOptInRules = Array(Set(allOptInRules + optInRules)) + } else { + effectiveOptInRules = optInRules + } + + warnAboutDuplicates(in: effectiveOptInRules + analyzerRules) + self = .default(disabled: Set(disabledRules), optIn: Set(effectiveOptInRules + analyzerRules)) } } diff --git a/Source/SwiftLintFramework/Extensions/Configuration+RulesWrapper.swift b/Source/SwiftLintFramework/Extensions/Configuration+RulesWrapper.swift index c25d8c93c..c7456ac8f 100644 --- a/Source/SwiftLintFramework/Extensions/Configuration+RulesWrapper.swift +++ b/Source/SwiftLintFramework/Extensions/Configuration+RulesWrapper.swift @@ -49,7 +49,7 @@ internal extension Configuration { case var .default(disabledRuleIdentifiers, optInRuleIdentifiers): customRulesFilter = { !disabledRuleIdentifiers.contains($0.identifier) } disabledRuleIdentifiers = validate(ruleIds: disabledRuleIdentifiers, valid: validRuleIdentifiers) - optInRuleIdentifiers = validate(ruleIds: optInRuleIdentifiers, valid: validRuleIdentifiers) + optInRuleIdentifiers = validate(optInRuleIds: optInRuleIdentifiers, valid: validRuleIdentifiers) resultingRules = allRulesWrapped.filter { tuple in let id = type(of: tuple.rule).description.identifier return !disabledRuleIdentifiers.contains(id) @@ -113,6 +113,10 @@ internal extension Configuration { } // MARK: - Methods: Validation + private func validate(optInRuleIds: Set, valid: Set) -> Set { + validate(ruleIds: optInRuleIds, valid: valid.union([RuleIdentifier.all.stringRepresentation])) + } + private func validate(ruleIds: Set, valid: Set, silent: Bool = false) -> Set { // Process invalid rule identifiers if !silent { @@ -220,12 +224,12 @@ internal extension Configuration { validRuleIdentifiers: Set ) -> RulesMode { let childDisabled = child.validate(ruleIds: childDisabled, valid: validRuleIdentifiers) - let childOptIn = child.validate(ruleIds: childOptIn, valid: validRuleIdentifiers) + let childOptIn = child.validate(optInRuleIds: childOptIn, valid: validRuleIdentifiers) switch mode { // Switch parent's mode. Child is in default mode. case var .default(disabled, optIn): disabled = validate(ruleIds: disabled, valid: validRuleIdentifiers) - optIn = child.validate(ruleIds: optIn, valid: validRuleIdentifiers) + optIn = child.validate(optInRuleIds: optIn, valid: validRuleIdentifiers) // Only use parent disabled / optIn if child config doesn't tell the opposite return .default(