Skip to content

Commit

Permalink
Fix autocorrection for redundant_type_annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelofabri authored and sjavora committed Mar 9, 2019
1 parent b79a8de commit 2eae309
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 29 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 14 additions & 6 deletions Rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -13496,27 +13496,35 @@ var url: CustomStringConvertible = URL()
<summary>Triggering Examples</summary>
```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)
}
}
```
</details>
Expand Down
64 changes: 41 additions & 23 deletions Source/SwiftLintFramework/Rules/RedundantTypeAnnotationRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
"""
]
)

Expand All @@ -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: "=")
Expand All @@ -93,7 +112,6 @@ public struct RedundantTypeAnnotationRule: Rule, OptInRule, CorrectableRule,
}

let rhsTypeName = components[1].trimmingCharacters(in: charactersToTrimFromRhs)

return lhsTypeName != rhsTypeName
}
}

0 comments on commit 2eae309

Please sign in to comment.