Skip to content

Commit

Permalink
Merge pull request #1229 from realm/jp-refactor
Browse files Browse the repository at this point in the history
Refactor SourceKit member access
  • Loading branch information
jpsim authored Jan 22, 2017
2 parents c81c871 + 29cdc86 commit 2380381
Show file tree
Hide file tree
Showing 42 changed files with 259 additions and 215 deletions.
79 changes: 73 additions & 6 deletions Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,68 @@ import Foundation
import SourceKittenFramework

extension Dictionary where Key: ExpressibleByStringLiteral {

/// Accessibility.
var accessibility: String? {
return self["key.accessibility"] as? String
}
/// Body length.
var bodyLength: Int? {
return (self["key.bodylength"] as? Int64).flatMap({ Int($0) })
}
/// Body offset.
var bodyOffset: Int? {
return (self["key.bodyoffset"] as? Int64).flatMap({ Int($0) })
}
/// Kind.
var kind: String? {
return self["key.kind"] as? String
}
/// Length.
var length: Int? {
return (self["key.length"] as? Int64).flatMap({ Int($0) })
}
/// Name.
var name: String? {
return self["key.name"] as? String
}
/// Name length.
var nameLength: Int? {
return (self["key.namelength"] as? Int64).flatMap({ Int($0) })
}
/// Name offset.
var nameOffset: Int? {
return (self["key.nameoffset"] as? Int64).flatMap({ Int($0) })
}
/// Offset.
var offset: Int? {
return (self["key.offset"] as? Int64).flatMap({ Int($0) })
}
/// Setter accessibility.
var setterAccessibility: String? {
return self["key.setter_accessibility"] as? String
}
/// Type name.
var typeName: String? {
return self["key.typename"] as? String
}
/// Column where the token's declaration begins.
var docColumn: Int? {
return (self["key.doc.column"] as? Int64).flatMap({ Int($0) })
}
/// Line where the token's declaration begins.
var docLine: Int? {
return (self["key.doc.line"] as? Int64).flatMap({ Int($0) })
}
/// Parsed scope start.
var docType: Int? {
return (self["key.doc.type"] as? Int64).flatMap({ Int($0) })
}
/// Parsed scope start end.
var usr: Int? {
return (self["key.usr"] as? Int64).flatMap({ Int($0) })
}

var enclosedSwiftAttributes: [String] {
let array = self["key.attributes"] as? [SourceKitRepresentable] ?? []
return array.flatMap { ($0 as? [String: String])?["key.attribute"] }
Expand All @@ -20,9 +82,14 @@ extension Dictionary where Key: ExpressibleByStringLiteral {
return substructure.flatMap { $0 as? [String: SourceKitRepresentable] }
}

var elements: [[String: SourceKitRepresentable]]? {
let elements = self["key.elements"] as? [SourceKitRepresentable]
return elements?.flatMap { $0 as? [String: SourceKitRepresentable] }
}

var enclosedVarParameters: [[String: SourceKitRepresentable]] {
return substructure.flatMap { subDict -> [[String: SourceKitRepresentable]] in
guard let kindString = subDict["key.kind"] as? String else {
guard let kindString = subDict.kind else {
return []
}

Expand All @@ -32,7 +99,7 @@ extension Dictionary where Key: ExpressibleByStringLiteral {
// with Swift 2.3, a closure parameter is inside another .varParameter and not inside an .argument
let parameters = subDict.enclosedVarParameters + [subDict]
return parameters.filter {
$0["key.typename"] != nil
$0.typeName != nil
}
case .three:
return [subDict]
Expand All @@ -47,7 +114,7 @@ extension Dictionary where Key: ExpressibleByStringLiteral {

var enclosedArguments: [[String: SourceKitRepresentable]] {
return substructure.flatMap { subDict -> [[String: SourceKitRepresentable]] in
guard let kindString = subDict["key.kind"] as? String else {
guard let kindString = subDict.kind else {
return []
}

Expand All @@ -68,14 +135,14 @@ extension Dictionary where Key: ExpressibleByStringLiteral {

var inheritedTypes: [String] {
let array = self["key.inheritedtypes"] as? [SourceKitRepresentable] ?? []
return array.flatMap { ($0 as? [String: String])?["key.name"] }
return array.flatMap { ($0 as? [String: String])?.name }
}

internal func extractCallsToSuper(methodName: String) -> [String] {
let superCall = "super.\(methodName)"
return substructure.flatMap { elems in
guard let type = (elems["key.kind"] as? String).flatMap({ SwiftExpressionKind(rawValue: $0) }),
let name = elems["key.name"] as? String,
guard let type = elems.kind.flatMap({ SwiftExpressionKind(rawValue: $0) }),
let name = elems.name,
type == .call && superCall.contains(name)
else { return nil }
return name
Expand Down
6 changes: 3 additions & 3 deletions Source/SwiftLintFramework/Extensions/File+Cache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ private struct RebuildQueue {
guard !queue.isEmpty else { return }
let allDeclarationsByType = queue.flatMap { structure -> (String, [String])? in
guard let firstSubstructureDict = structure.dictionary.substructure.first,
let name = firstSubstructureDict["key.name"] as? String,
let kind = (firstSubstructureDict["key.kind"] as? String).flatMap(SwiftDeclarationKind.init),
let name = firstSubstructureDict.name,
let kind = (firstSubstructureDict.kind).flatMap(SwiftDeclarationKind.init),
kind == .protocol,
case let substructure = firstSubstructureDict.substructure,
!substructure.isEmpty else {
return nil
}
return (name, substructure.flatMap({ $0["key.name"] as? String }))
return (name, substructure.flatMap({ $0.name }))
}
allDeclarationsByType.forEach { self.allDeclarationsByType[$0.0] = $0.1 }
queue.removeAll(keepingCapacity: false)
Expand Down
4 changes: 2 additions & 2 deletions Source/SwiftLintFramework/Extensions/File+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ extension File {

internal func validateVariableName(_ dictionary: [String: SourceKitRepresentable],
kind: SwiftDeclarationKind) -> (name: String, offset: Int)? {
guard let name = dictionary["key.name"] as? String,
let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
guard let name = dictionary.name,
let offset = dictionary.offset,
SwiftDeclarationKind.variableKinds().contains(kind) && !name.hasPrefix("$") else {
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extension String {
}

internal func nameStrippingLeadingUnderscoreIfPrivate(_ dict: [String: SourceKitRepresentable]) -> String {
if let aclString = dict["key.accessibility"] as? String,
if let aclString = dict.accessibility,
let acl = AccessControlLevel(identifier: aclString),
acl.isPrivate && characters.first == "_" {
return substring(from: index(after: startIndex))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@ extension Structure {

func parse(_ dictionary: [String: SourceKitRepresentable]) {
guard let
offset = (dictionary["key.offset"] as? Int64).map({ Int($0) }),
let byteRange = (dictionary["key.length"] as? Int64)
.map({ Int($0) })
.map({ NSRange(location: offset, length: $0) }),
offset = dictionary.offset,
let byteRange = dictionary.length.map({ NSRange(location: offset, length: $0) }),
NSLocationInRange(byteOffset, byteRange) else {
return
}
if let kind = dictionary["key.kind"] as? String {
if let kind = dictionary.kind {
results.append((kind: kind, byteRange: byteRange))
}
dictionary.substructure.forEach(parse)
Expand Down
2 changes: 1 addition & 1 deletion Source/SwiftLintFramework/Protocols/ASTRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extension ASTRule where KindType.RawValue == String {

public func validate(file: File, dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
return dictionary.substructure.flatMap { subDict -> [StyleViolation] in
guard let kindString = subDict["key.kind"] as? String,
guard let kindString = subDict.kind,
let kind = KindType(rawValue: kindString) else {
return []
}
Expand Down
9 changes: 4 additions & 5 deletions Source/SwiftLintFramework/Rules/AttributesRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
private func validateTestableImport(file: File) -> [StyleViolation] {
let pattern = "@testable[\n]+\\s*import"
return file.match(pattern: pattern).flatMap { range, kinds -> StyleViolation? in
guard kinds.count == 2 &&
kinds.first == .attributeBuiltin && kinds.last == .keyword else {
return nil
guard kinds == [.attributeBuiltin, .keyword] else {
return nil
}

let contents = file.contents.bridge()
Expand All @@ -84,7 +83,7 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
let attributes = parseAttributes(dictionary: dictionary)

guard !attributes.isEmpty,
let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
let offset = dictionary.offset,
let (line, _) = file.contents.bridge().lineAndCharacter(forByteOffset: offset) else {
return []
}
Expand Down Expand Up @@ -174,7 +173,7 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
private func violation(dictionary: [String: SourceKitRepresentable],
file: File) -> [StyleViolation] {
let location: Location
if let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }) {
if let offset = dictionary.offset {
location = Location(file: file, byteOffset: offset)
} else {
location = Location(file: file.path)
Expand Down
10 changes: 5 additions & 5 deletions Source/SwiftLintFramework/Rules/ClassDelegateProtocolRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public struct ClassDelegateProtocolRule: ASTRule, ConfigurationProviderRule {
}

// Check if name contains "Delegate"
guard let name = (dictionary["key.name"] as? String), isDelegateProtocol(name) else {
guard let name = dictionary.name, isDelegateProtocol(name) else {
return []
}

Expand All @@ -58,10 +58,10 @@ public struct ClassDelegateProtocolRule: ASTRule, ConfigurationProviderRule {
}

// Check if : class
guard let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
let nameOffset = (dictionary["key.nameoffset"] as? Int64).flatMap({ Int($0) }),
let nameLength = (dictionary["key.namelength"] as? Int64).flatMap({ Int($0) }),
let bodyOffset = (dictionary["key.bodyoffset"] as? Int64).flatMap({ Int($0) }),
guard let offset = dictionary.offset,
let nameOffset = dictionary.nameOffset,
let nameLength = dictionary.nameLength,
let bodyOffset = dictionary.bodyOffset,
case let contents = file.contents.bridge(),
case let start = nameOffset + nameLength,
let range = contents.byteRangeToNSRange(start: start, length: bodyOffset - start),
Expand Down
14 changes: 7 additions & 7 deletions Source/SwiftLintFramework/Rules/ClosureEndIndentationRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
}

let contents = file.contents.bridge()
guard let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
let length = (dictionary["key.length"] as? Int64).flatMap({ Int($0) }),
let bodyLength = (dictionary["key.bodylength"] as? Int64).flatMap({ Int($0) }),
let nameOffset = (dictionary["key.nameoffset"] as? Int64).flatMap({ Int($0) }),
let nameLength = (dictionary["key.namelength"] as? Int64).flatMap({ Int($0) }),
guard let offset = dictionary.offset,
let length = dictionary.length,
let bodyLength = dictionary.bodyLength,
let nameOffset = dictionary.nameOffset,
let nameLength = dictionary.nameLength,
bodyLength > 0,
case let endOffset = offset + length - 1,
contents.substringWithByteRange(start: endOffset, length: 1) == "}",
Expand Down Expand Up @@ -89,8 +89,8 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
}

private func startOffset(forDictionary dictionary: [String: SourceKitRepresentable], file: File) -> Int? {
guard let nameOffset = (dictionary["key.nameoffset"] as? Int64).flatMap({ Int($0) }),
let nameLength = (dictionary["key.namelength"] as? Int64).flatMap({ Int($0) }) else {
guard let nameOffset = dictionary.nameOffset,
let nameLength = dictionary.nameLength else {
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ public struct ClosureParameterPositionRule: ASTRule, ConfigurationProviderRule {
return []
}

guard let nameOffset = (dictionary["key.nameoffset"] as? Int64).flatMap({ Int($0) }),
let nameLength = (dictionary["key.namelength"] as? Int64).flatMap({ Int($0) }),
let bodyLength = (dictionary["key.bodylength"] as? Int64).flatMap({ Int($0) }),
guard let nameOffset = dictionary.nameOffset,
let nameLength = dictionary.nameLength,
let bodyLength = dictionary.bodyLength,
bodyLength > 0 else {
return []
}
Expand All @@ -70,8 +70,7 @@ public struct ClosureParameterPositionRule: ASTRule, ConfigurationProviderRule {
// parameters from inner closures are reported on the top-level one, so we can't just
// use the first and last parameters to check, we need to check all of them
return parameters.flatMap { param -> StyleViolation? in
guard let paramOffset = (param["key.offset"] as? Int64).flatMap({ Int($0) }),
paramOffset > rangeStart else {
guard let paramOffset = param.offset, paramOffset > rangeStart else {
return nil
}

Expand Down
15 changes: 7 additions & 8 deletions Source/SwiftLintFramework/Rules/ColonRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ extension ColonRule {
}

return dictionary.substructure.flatMap { subDict -> [NSRange] in
guard let kindString = subDict["key.kind"] as? String,
guard let kindString = subDict.kind,
let kind = KindType(rawValue: kindString) else {
return []
}
Expand All @@ -252,7 +252,7 @@ extension ColonRule {
return ranges.filter {
guard let colon = contents.substringWithByteRange(start: $0.location,
length: $0.length) else {
return false
return false
}

if configuration.flexibleRightSpacing {
Expand All @@ -265,17 +265,16 @@ extension ColonRule {
}

private func colonRanges(dictionary: [String: SourceKitRepresentable]) -> [NSRange]? {
guard let elements = dictionary["key.elements"] as? [SourceKitRepresentable],
guard let elements = dictionary.elements,
elements.count % 2 == 0 else {
return nil
}

let expectedKind = "source.lang.swift.structure.elem.expr"
let ranges: [NSRange] = elements.flatMap {
guard let subDict = $0 as? [String: SourceKitRepresentable],
subDict["key.kind"] as? String == expectedKind,
let offset = (subDict["key.offset"] as? Int64).map({ Int($0) }),
let length = (subDict["key.length"] as? Int64).map({ Int($0) }) else {
let ranges: [NSRange] = elements.flatMap { subDict in
guard subDict.kind == expectedKind,
let offset = subDict.offset,
let length = subDict.length else {
return nil
}

Expand Down
11 changes: 5 additions & 6 deletions Source/SwiftLintFramework/Rules/CompilerProtocolInitRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,16 @@ public struct CompilerProtocolInitRule: ASTRule, ConfigurationProviderRule {

private func violationRanges(in file: File, kind: SwiftExpressionKind,
dictionary: [String: SourceKitRepresentable]) -> [NSRange] {
guard kind == .call,
let name = dictionary["key.name"] as? String else {
return []
guard kind == .call, let name = dictionary.name else {
return []
}

for compilerProtocol in ExpressibleByCompiler.allProtocols {
guard compilerProtocol.initCallNames.contains(name),
case let arguments = dictionary.enclosedArguments.flatMap({ $0["key.name"] as? String }),
case let arguments = dictionary.enclosedArguments.flatMap({ $0.name }),
compilerProtocol.match(arguments: arguments),
let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
let length = (dictionary["key.length"] as? Int64).flatMap({ Int($0) }),
let offset = dictionary.offset,
let length = dictionary.length,
let range = file.contents.bridge().byteRangeToNSRange(start: offset, length: length) else {
continue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public struct CyclomaticComplexityRule: ASTRule, ConfigurationProviderRule {
let complexity = measureComplexity(in: file, dictionary: dictionary)

for parameter in configuration.params where complexity > parameter.value {
let offset = Int(dictionary["key.offset"] as? Int64 ?? 0)
let offset = dictionary.offset ?? 0
return [StyleViolation(ruleDescription: type(of: self).description,
severity: parameter.severity,
location: Location(file: file, byteOffset: offset),
Expand All @@ -62,7 +62,7 @@ public struct CyclomaticComplexityRule: ASTRule, ConfigurationProviderRule {
var hasSwitchStatements = false

let complexity = dictionary.substructure.reduce(0) { complexity, subDict in
guard let kind = subDict["key.kind"] as? String else {
guard let kind = subDict.kind else {
return complexity
}

Expand Down Expand Up @@ -95,8 +95,8 @@ public struct CyclomaticComplexityRule: ASTRule, ConfigurationProviderRule {

private func reduceSwitchComplexity(initialComplexity complexity: Int, file: File,
dictionary: [String: SourceKitRepresentable]) -> Int {
let bodyOffset = Int(dictionary["key.bodyoffset"] as? Int64 ?? 0)
let bodyLength = Int(dictionary["key.bodylength"] as? Int64 ?? 0)
let bodyOffset = dictionary.bodyOffset ?? 0
let bodyLength = dictionary.bodyLength ?? 0

let c = file.contents.bridge()
.substringWithByteRange(start: bodyOffset, length: bodyLength) ?? ""
Expand Down
2 changes: 1 addition & 1 deletion Source/SwiftLintFramework/Rules/DynamicInlineRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public struct DynamicInlineRule: ASTRule, ConfigurationProviderRule {
case let attributes = dictionary.enclosedSwiftAttributes,
attributes.contains("source.decl.attribute.dynamic"),
attributes.contains("source.decl.attribute.inline"),
let funcByteOffset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
let funcByteOffset = dictionary.offset,
let funcOffset = file.contents.bridge()
.byteRangeToNSRange(start: funcByteOffset, length: 0)?.location,
case let inlinePattern = regex("@inline"),
Expand Down
Loading

0 comments on commit 2380381

Please sign in to comment.