From 2eae30995a36ce4dece3f8835f3cdd313ec37b3d Mon Sep 17 00:00:00 2001 From: Marcelo Fabri Date: Thu, 26 Jul 2018 07:54:35 -0700 Subject: [PATCH] Fix autocorrection for `redundant_type_annotation` Fixes #2314 --- CHANGELOG.md | 4 ++ Rules.md | 20 ++++-- .../Rules/RedundantTypeAnnotationRule.swift | 64 ++++++++++++------- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82377e1e8da..345bc670c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,10 @@ [Marcelo Fabri](https://github.com/marcelofabri) [#2233](https://github.com/realm/SwiftLint/issues/2233) +* Fix autocorrection for `redundant_type_annotation` rule. + [Marcelo Fabri](https://github.com/marcelofabri) + [#2314](https://github.com/realm/SwiftLint/issues/2314) + ## 0.26.0: Maytagged Pointers #### Breaking diff --git a/Rules.md b/Rules.md index c7e8bb1fe61..97946fbfc1b 100644 --- a/Rules.md +++ b/Rules.md @@ -13496,27 +13496,35 @@ var url: CustomStringConvertible = URL() Triggering Examples ```swift -↓var url:URL=URL() +var url↓:URL=URL() ``` ```swift -↓var url:URL = URL(string: "") +var url↓:URL = URL(string: "") ``` ```swift -↓var url: URL = URL() +var url↓: URL = URL() ``` ```swift -↓let url: URL = URL() +let url↓: URL = URL() ``` ```swift -lazy ↓var url: URL = URL() +lazy var url↓: URL = URL() ``` ```swift -↓let alphanumerics: CharacterSet = CharacterSet.alphanumerics +let alphanumerics↓: CharacterSet = CharacterSet.alphanumerics +``` + +```swift +class ViewController: UIViewController { + func someMethod() { + let myVar↓: Int = Int(5) + } +} ``` diff --git a/Source/SwiftLintFramework/Rules/RedundantTypeAnnotationRule.swift b/Source/SwiftLintFramework/Rules/RedundantTypeAnnotationRule.swift index d4e7d28218a..0182663aba6 100644 --- a/Source/SwiftLintFramework/Rules/RedundantTypeAnnotationRule.swift +++ b/Source/SwiftLintFramework/Rules/RedundantTypeAnnotationRule.swift @@ -18,18 +18,39 @@ public struct RedundantTypeAnnotationRule: Rule, OptInRule, CorrectableRule, "var url: CustomStringConvertible = URL()" ], triggeringExamples: [ - "↓var url:URL=URL()", - "↓var url:URL = URL(string: \"\")", - "↓var url: URL = URL()", - "↓let url: URL = URL()", - "lazy ↓var url: URL = URL()", - "↓let alphanumerics: CharacterSet = CharacterSet.alphanumerics" + "var url↓:URL=URL()", + "var url↓:URL = URL(string: \"\")", + "var url↓: URL = URL()", + "let url↓: URL = URL()", + "lazy var url↓: URL = URL()", + "let alphanumerics↓: CharacterSet = CharacterSet.alphanumerics", + """ + class ViewController: UIViewController { + func someMethod() { + let myVar↓: Int = Int(5) + } + } + """ ], corrections: [ "var url↓: URL = URL()": "var url = URL()", "let url↓: URL = URL()": "let url = URL()", "let alphanumerics↓: CharacterSet = CharacterSet.alphanumerics": - "let alphanumerics = CharacterSet.alphanumerics" + "let alphanumerics = CharacterSet.alphanumerics", + """ + class ViewController: UIViewController { + func someMethod() { + let myVar↓: Int = Int(5) + } + } + """: + """ + class ViewController: UIViewController { + func someMethod() { + let myVar = Int(5) + } + } + """ ] ) @@ -47,39 +68,37 @@ public struct RedundantTypeAnnotationRule: Rule, OptInRule, CorrectableRule, public func correct(file: File) -> [Correction] { let violatingRanges = file.ruleEnabled(violatingRanges: violationRanges(in: file), for: self) - let typeAnnotationRanges = violatingRanges.map { typeAnnotationRange(in: file, violationRange: $0) } var correctedContents = file.contents var adjustedLocations = [Int]() - for typeAnnotationRange in typeAnnotationRanges.reversed() { - if let indexRange = correctedContents.nsrangeToIndexRange(typeAnnotationRange) { + for violatingRange in violatingRanges.reversed() { + if let indexRange = correctedContents.nsrangeToIndexRange(violatingRange) { correctedContents = correctedContents.replacingCharacters(in: indexRange, with: "") - adjustedLocations.insert(typeAnnotationRange.location, at: 0) + adjustedLocations.insert(violatingRange.location, at: 0) } } file.write(correctedContents) return adjustedLocations.map { - Correction(ruleDescription: type(of: self).description, location: Location(file: file, characterOffset: $0)) + Correction(ruleDescription: type(of: self).description, + location: Location(file: file, characterOffset: $0)) } } private func violationRanges(in file: File) -> [NSRange] { - - let pattern = "(var|let)\\s?\\w+:\\s?\\w+\\s?=\\s?\\w+(\\(|.)" - + let typeAnnotationPattern = ":\\s?\\w+" + let pattern = "(var|let)\\s?\\w+\(typeAnnotationPattern)\\s?=\\s?\\w+(\\(|.)" let foundRanges = file.match(pattern: pattern, with: [.keyword, .identifier, .typeidentifier, .identifier]) - - return foundRanges.filter { range in !isFalsePositive(in: file, range: range) } - } - - private func typeAnnotationRange(in file: File, violationRange: NSRange) -> NSRange { - return file.match(pattern: ":\\s?\\w+", excludingSyntaxKinds: [])[0] + return foundRanges + .filter { !isFalsePositive(in: file, range: $0) } + .compactMap { + file.match(pattern: typeAnnotationPattern, + excludingSyntaxKinds: SyntaxKind.commentAndStringKinds, range: $0).first + } } private func isFalsePositive(in file: File, range: NSRange) -> Bool { - let substring = file.contents.bridge().substring(with: range) let components = substring.components(separatedBy: "=") @@ -93,7 +112,6 @@ public struct RedundantTypeAnnotationRule: Rule, OptInRule, CorrectableRule, } let rhsTypeName = components[1].trimmingCharacters(in: charactersToTrimFromRhs) - return lhsTypeName != rhsTypeName } }