Add shitty implementation of correction

This commit is contained in:
JP Simard
2019-01-05 19:11:39 -08:00
committed by Marcelo Fabri
parent d863fc9fb7
commit eb8f398683
@@ -1,7 +1,7 @@
import Foundation
import SourceKittenFramework
public struct UnusedControlFlowLabelRule: ASTRule, ConfigurationProviderRule, AutomaticTestableRule {
public struct UnusedControlFlowLabelRule: ASTRule, ConfigurationProviderRule, AutomaticTestableRule, CorrectableRule {
public var configuration = SeverityConfiguration(.warning)
public init() {}
@@ -51,6 +51,38 @@ public struct UnusedControlFlowLabelRule: ASTRule, ConfigurationProviderRule, Au
}
} while true
"""
],
corrections: [
"↓loop: while true { break }": "while true { break }",
"↓loop: while true { break loop1 }": "while true { break loop1 }",
"↓loop: while true { break outerLoop }": "while true { break outerLoop }",
"↓loop: for x in array { break }": "for x in array { break }",
"""
↓label: switch number {
case 1: print("1")
case 2: print("2")
default: break
}
""": """
switch number {
case 1: print("1")
case 2: print("2")
default: break
}
""",
"""
↓loop: repeat {
if x == 10 {
break
}
} while true
""": """
repeat {
if x == 10 {
break
}
} while true
"""
]
)
@@ -58,6 +90,40 @@ public struct UnusedControlFlowLabelRule: ASTRule, ConfigurationProviderRule, Au
public func validate(file: File, kind: StatementKind,
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
return self.violationRanges(in: file, kind: kind, dictionary: dictionary).map { range in
StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity,
location: Location(file: file, characterOffset: range.location))
}
}
public func correct(file: File) -> [Correction] {
let matches = violationRanges(in: file)
.filter { !file.ruleEnabled(violatingRanges: [$0], for: self).isEmpty }
guard !matches.isEmpty else { return [] }
let description = type(of: self).description
var corrections = [Correction]()
var contents = file.contents
for range in matches {
var rangeToRemove = range
if let byteRange = file.contents.bridge().NSRangeToByteRange(start: range.location, length: range.length),
let nextToken = file.syntaxMap.tokens.first(where: { $0.offset > byteRange.location }),
let nextTokenCharacterLocation = file.contents.bridge().byteRangeToNSRange(start: nextToken.offset, length: 0) {
rangeToRemove.length = nextTokenCharacterLocation.location - range.location
}
contents = contents.bridge().replacingCharacters(in: rangeToRemove, with: "")
let location = Location(file: file, characterOffset: range.location)
corrections.append(Correction(ruleDescription: description, location: location))
}
file.write(contents)
return corrections
}
private func violationRanges(in file: File, kind: StatementKind,
dictionary: [String: SourceKitRepresentable]) -> [NSRange] {
guard type(of: self).kinds.contains(kind),
let offset = dictionary.offset, let length = dictionary.length,
case let byteRange = NSRange(location: offset, length: length),
@@ -75,11 +141,26 @@ public struct UnusedControlFlowLabelRule: ASTRule, ConfigurationProviderRule, Au
return []
}
return [
StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity,
location: Location(file: file, byteOffset: firstToken.offset))
]
return [file.contents.bridge().byteRangeToNSRange(start: firstToken.offset, length: firstToken.length)!]
}
private func violationRanges(in file: File, dictionary: [String: SourceKitRepresentable]) -> [NSRange] {
let ranges = dictionary.substructure.flatMap { subDict -> [NSRange] in
var ranges = violationRanges(in: file, dictionary: subDict)
if let kind = subDict.kind.flatMap(StatementKind.init(rawValue:)) {
ranges += violationRanges(in: file, kind: kind, dictionary: subDict)
}
return ranges
}
return ranges.unique
}
private func violationRanges(in file: File) -> [NSRange] {
return violationRanges(in: file, dictionary: file.structure.dictionary).sorted { lhs, rhs in
lhs.location > rhs.location
}
}
}
@@ -88,3 +169,9 @@ private extension NSString {
return substringWithByteRange(start: token.offset, length: token.length)
}
}
extension Collection where Element == SyntaxToken {
func firstToken(afterByteOffset byteOffset: Int) -> SyntaxToken? {
return first(where: { $0.offset > byteOffset })
}
}