diff --git a/CHANGELOG.md b/CHANGELOG.md index a651a4a63..ab4aa546f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,9 @@ [Marcelo Fabri](https://github.com/marcelofabri) [#2883](https://github.com/realm/SwiftLint/issues/2883) +* Make `toggle_bool` rule substitution correctable. + [MaxHaertwig](https://github.com/maxhaertwig) + #### Bug Fixes * None. diff --git a/Rules.md b/Rules.md index 33a48cbb4..167044e87 100644 --- a/Rules.md +++ b/Rules.md @@ -19447,7 +19447,7 @@ TODOs and FIXMEs should be resolved. Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version --- | --- | --- | --- | --- | --- -`toggle_bool` | Disabled | No | idiomatic | No | 4.2.0 +`toggle_bool` | Disabled | Yes | idiomatic | No | 4.2.0 Prefer `someBool.toggle()` over `someBool = !someBool`. diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift index c831dd3d3..73010f00c 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift @@ -1,6 +1,7 @@ +import Foundation import SourceKittenFramework -public struct ToggleBoolRule: ConfigurationProviderRule, OptInRule, AutomaticTestableRule { +public struct ToggleBoolRule: SubstitutionCorrectableRule, ConfigurationProviderRule, OptInRule, AutomaticTestableRule { public var configuration = SeverityConfiguration(.warning) public init() {} @@ -22,16 +23,32 @@ public struct ToggleBoolRule: ConfigurationProviderRule, OptInRule, AutomaticTes "↓isHidden = !isHidden\n", "↓view.clipsToBounds = !view.clipsToBounds\n", "func foo() { ↓abc = !abc }" + ], + corrections: [ + "↓isHidden = !isHidden\n": "isHidden.toggle()\n", + "↓view.clipsToBounds = !view.clipsToBounds\n": "view.clipsToBounds.toggle()\n", + "func foo() { ↓abc = !abc }": "func foo() { abc.toggle() }" ] ) public func validate(file: File) -> [StyleViolation] { - let pattern = "(? [NSRange] { + let pattern = "(? (NSRange, String) { + let violationString = file.contents.bridge().substring(with: violationRange) + let identifier = violationString.components(separatedBy: .whitespaces).first { !$0.isEmpty } + return (violationRange, identifier! + ".toggle()") + } }