 import Foundation
 import SourceKittenFramework
 
-public struct UnusedControlFlowLabelRule: ASTRule, ConfigurationProviderRule, AutomaticTestableRule, CorrectableRule {
+public struct UnusedControlFlowLabelRule: SubstitutionCorrectableASTRule, ConfigurationProviderRule,
+                                          AutomaticTestableRule {
     public var configuration = SeverityConfiguration(.warning)
 
     public init() {}


        return [violationRange]
    }

    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
        }
    }
}

private extension NSString {
    func substring(with token: SyntaxToken) -> String? {
        return substringWithByteRange(start: token.offset, length: token.length)
    }
}

        }
    }

    public func substitution(for violationRange: NSRange, in file: File) -> (NSRange, String) {
        var rangeToRemove = violationRange
        let contentsNSString = file.contents.bridge()
        if let byteRange = contentsNSString.NSRangeToByteRange(start: violationRange.location,
                                                               length: violationRange.length),
            let nextToken = file.syntaxMap.tokens.first(where: { $0.offset > byteRange.location }),
            let nextTokenLocation = contentsNSString.byteRangeToNSRange(start: nextToken.offset, length: 0) {
            rangeToRemove.length = nextTokenLocation.location - violationRange.location
        }

        return (rangeToRemove, "")
    }

    public 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),
            case let tokens = file.syntaxMap.tokens(inByteRange: byteRange),
            let firstToken = tokens.first,
            SyntaxKind(rawValue: firstToken.type) == .identifier,
            let tokenContent = file.contents(for: firstToken),
            case let contents = file.contents.bridge(),
            let range = contents.byteRangeToNSRange(start: offset, length: length) else {
                return []
        }
