From 55004d554c391262b64d0c728cc4b785a065a265 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Wed, 14 Dec 2016 17:13:17 -0800 Subject: [PATCH 1/2] make VoidReturnRule correctable --- CHANGELOG.md | 4 +- .../Rules/VoidReturnRule.swift | 52 +++++++++++++++---- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37d2066a6..b139dffae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,8 +82,10 @@ [Aaron McTavish](https://github.com/aamctustwo) [#970](https://github.com/realm/SwiftLint/issues/970) -* Add `void_return` rule to validate usage of `-> Void` over `-> ()`. +* Add correctable `void_return` rule to validate usage of `-> Void` + over `-> ()`. [Marcelo Fabri](https://github.com/marcelofabri) + [JP Simard](https://github.com/jpsim) [#964](https://github.com/realm/SwiftLint/issues/964) * Add `empty_parameters` rule to validate usage of `() -> ` over `Void -> `. diff --git a/Source/SwiftLintFramework/Rules/VoidReturnRule.swift b/Source/SwiftLintFramework/Rules/VoidReturnRule.swift index 701a71471..97ab87b23 100644 --- a/Source/SwiftLintFramework/Rules/VoidReturnRule.swift +++ b/Source/SwiftLintFramework/Rules/VoidReturnRule.swift @@ -9,7 +9,7 @@ import Foundation import SourceKittenFramework -public struct VoidReturnRule: Rule, ConfigurationProviderRule { +public struct VoidReturnRule: ConfigurationProviderRule, CorrectableRule { public var configuration = SeverityConfiguration(.warning) public init() {} @@ -31,26 +31,60 @@ public struct VoidReturnRule: Rule, ConfigurationProviderRule { "func foo(completion: () -> ↓())\n", "func foo(completion: () -> ↓( ))\n", "let foo: (ConfigurationTests) -> () throws -> ↓())\n" + ], + corrections: [ + "let abc: () -> () = {}\n": "let abc: () -> Void = {}\n", + "func foo(completion: () -> ())\n": "func foo(completion: () -> Void)\n", + "func foo(completion: () -> ( ))\n": "func foo(completion: () -> Void)\n", + "let foo: (ConfigurationTests) -> () throws -> ())\n": + "let foo: (ConfigurationTests) -> () throws -> Void)\n" ] ) public func validateFile(_ file: File) -> [StyleViolation] { + return violationRanges(file: file).map { + StyleViolation(ruleDescription: type(of: self).description, + severity: configuration.severity, + location: Location(file: file, characterOffset: $0.location)) + } + } + + private func violationRanges(file: File) -> [NSRange] { let kinds = SyntaxKind.commentAndStringKinds() - let pattern = "->\\s*\\(\\s*\\)\\s*(?!->)" + let parensPattern = "\\(\\s*\\)" + let pattern = "->\\s*\(parensPattern)\\s*(?!->)" let excludingPattern = "(\(pattern))\\s*(throws\\s+)?->" return file.matchPattern(pattern, excludingSyntaxKinds: kinds, excludingPattern: excludingPattern) { $0.rangeAt(1) }.flatMap { + let parensRegex = NSRegularExpression.forcePattern(parensPattern) + return parensRegex.firstMatch(in: file.contents, range: $0)?.range + } + } - let range = file.contents.bridge().substring(with: $0).bridge().range(of: "(") - guard range.location != NSNotFound else { - return nil + public func correctFile(_ file: File) -> [Correction] { + let violatingRanges = file.ruleEnabledViolatingRanges(violationRanges(file: file), + forRule: self) + return writeToFile(file, violatingRanges: violatingRanges) + } + + private func writeToFile(_ file: File, violatingRanges: [NSRange]) -> [Correction] { + var correctedContents = file.contents + var adjustedLocations = [Int]() + + for violatingRange in violatingRanges.reversed() { + if let indexRange = correctedContents.nsrangeToIndexRange(violatingRange) { + correctedContents = correctedContents + .replacingCharacters(in: indexRange, with: "Void") + adjustedLocations.insert(violatingRange.location, at: 0) } + } - let offset = range.location + $0.location - return StyleViolation(ruleDescription: type(of: self).description, - severity: configuration.severity, - location: Location(file: file, characterOffset: offset)) + file.write(correctedContents) + + return adjustedLocations.map { + Correction(ruleDescription: type(of: self).description, + location: Location(file: file, characterOffset: $0)) } } } From ea33f68c856602a6ee50f2fe279ef353359e4f60 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Thu, 15 Dec 2016 00:36:16 -0800 Subject: [PATCH 2/2] fix compilation on Linux --- Source/SwiftLintFramework/Rules/VoidReturnRule.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/SwiftLintFramework/Rules/VoidReturnRule.swift b/Source/SwiftLintFramework/Rules/VoidReturnRule.swift index 97ab87b23..22897cb85 100644 --- a/Source/SwiftLintFramework/Rules/VoidReturnRule.swift +++ b/Source/SwiftLintFramework/Rules/VoidReturnRule.swift @@ -58,7 +58,7 @@ public struct VoidReturnRule: ConfigurationProviderRule, CorrectableRule { return file.matchPattern(pattern, excludingSyntaxKinds: kinds, excludingPattern: excludingPattern) { $0.rangeAt(1) }.flatMap { let parensRegex = NSRegularExpression.forcePattern(parensPattern) - return parensRegex.firstMatch(in: file.contents, range: $0)?.range + return parensRegex.firstMatch(in: file.contents, options: [], range: $0)?.range } }