Skip to content

Commit

Permalink
Merge pull request #2924 from realm/speedup/use-swift-declaration-kin…
Browse files Browse the repository at this point in the history
…ds-enums-instead-of-rawValues

Use swift enums instead of raw values
  • Loading branch information
PaulTaykalo authored Nov 7, 2019
2 parents f845af6 + 2a308c1 commit 0db1f9c
Show file tree
Hide file tree
Showing 75 changed files with 206 additions and 225 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

#### Enhancements

* Speedup Swiftlint by using swift enums instead of raw values.
[PaulTaykalo](https://github.com/PaulTaykalo)
[#2924](https://github.com/realm/SwiftLint/issues/2924)

* Speed up Identical Operands rule by using syntaxmap instead of
regular expressions.
[PaulTaykalo](https://github.com/PaulTaykalo)
Expand Down
33 changes: 18 additions & 15 deletions Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@ public struct SourceKittenDictionary {
public let value: [String: SourceKitRepresentable]
public let substructure: [SourceKittenDictionary]

public let expressionKind: SwiftExpressionKind?
public let declarationKind: SwiftDeclarationKind?
public let statementKind: StatementKind?

public let accessibility: AccessControlLevel?

init(_ value: [String: SourceKitRepresentable]) {
self.value = value

let substructure = value["key.substructure"] as? [SourceKitRepresentable] ?? []
self.substructure = substructure.compactMap { $0 as? [String: SourceKitRepresentable] }
.map(SourceKittenDictionary.init)
}

/// Accessibility.
var accessibility: String? {
return value["key.accessibility"] as? String
let stringKind = value["key.kind"] as? String
self.expressionKind = stringKind.flatMap(SwiftExpressionKind.init)
self.declarationKind = stringKind.flatMap(SwiftDeclarationKind.init)
self.statementKind = stringKind.flatMap(StatementKind.init)

self.accessibility = (value["key.accessibility"] as? String).flatMap(AccessControlLevel.init(identifier:))
}

/// Body length
Expand Down Expand Up @@ -101,14 +109,10 @@ public struct SourceKittenDictionary {

var enclosedVarParameters: [SourceKittenDictionary] {
return substructure.flatMap { subDict -> [SourceKittenDictionary] in
guard let kindString = subDict.kind else {
return []
}

if SwiftDeclarationKind(rawValue: kindString) == .varParameter {
if subDict.declarationKind == .varParameter {
return [subDict]
} else if SwiftExpressionKind(rawValue: kindString) == .argument ||
SwiftExpressionKind(rawValue: kindString) == .closure {
} else if subDict.expressionKind == .argument ||
subDict.expressionKind == .closure {
return subDict.enclosedVarParameters
}

Expand All @@ -118,9 +122,8 @@ public struct SourceKittenDictionary {

var enclosedArguments: [SourceKittenDictionary] {
return substructure.flatMap { subDict -> [SourceKittenDictionary] in
guard let kindString = subDict.kind,
SwiftExpressionKind(rawValue: kindString) == .argument else {
return []
guard subDict.expressionKind == .argument else {
return []
}

return [subDict]
Expand All @@ -138,7 +141,7 @@ public struct SourceKittenDictionary {
}
let superCall = "super.\(methodNameWithoutArguments)"
return substructure.flatMap { elems -> [String] in
guard let type = elems.kind.flatMap(SwiftExpressionKind.init),
guard let type = elems.expressionKind,
let name = elems.name,
type == .call && superCall == name else {
return elems.extractCallsToSuper(methodName: methodName)
Expand Down
3 changes: 1 addition & 2 deletions Source/SwiftLintFramework/Extensions/String+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ extension String {
}

internal func nameStrippingLeadingUnderscoreIfPrivate(_ dict: SourceKittenDictionary) -> String {
if let aclString = dict.accessibility,
let acl = AccessControlLevel(identifier: aclString),
if let acl = dict.accessibility,
acl.isPrivate && first == "_" {
return String(self[index(after: startIndex)...])
}
Expand Down
2 changes: 1 addition & 1 deletion Source/SwiftLintFramework/Helpers/NamespaceCollector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct NamespaceCollector {

init?(dictionary: SourceKittenDictionary, namespace: [String]) {
guard let name = dictionary.name,
let kind = dictionary.kind.flatMap(SwiftDeclarationKind.init),
let kind = dictionary.declarationKind,
let offset = dictionary.offset else {
return nil
}
Expand Down
24 changes: 21 additions & 3 deletions Source/SwiftLintFramework/Protocols/ASTRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import SourceKittenFramework
public protocol ASTRule: Rule {
associatedtype KindType: RawRepresentable
func validate(file: File, kind: KindType, dictionary: SourceKittenDictionary) -> [StyleViolation]
func kind(from dictionary: SourceKittenDictionary) -> KindType?
}

public extension ASTRule where KindType.RawValue == String {
public extension ASTRule {
func validate(file: File) -> [StyleViolation] {
return validate(file: file, dictionary: file.structureDictionary)
}
Expand All @@ -14,12 +15,29 @@ public extension ASTRule where KindType.RawValue == String {
return dictionary.substructure.flatMap { subDict -> [StyleViolation] in
var violations = validate(file: file, dictionary: subDict)

if let kindString = subDict.kind,
let kind = KindType(rawValue: kindString) {
if let kind = self.kind(from: subDict) {
violations += validate(file: file, kind: kind, dictionary: subDict)
}

return violations
}
}
}

public extension ASTRule where KindType == SwiftDeclarationKind {
func kind(from dictionary: SourceKittenDictionary) -> KindType? {
return dictionary.declarationKind
}
}

public extension ASTRule where KindType == SwiftExpressionKind {
func kind(from dictionary: SourceKittenDictionary) -> KindType? {
return dictionary.expressionKind
}
}

public extension ASTRule where KindType == StatementKind {
func kind(from dictionary: SourceKittenDictionary) -> KindType? {
return dictionary.statementKind
}
}
3 changes: 1 addition & 2 deletions Source/SwiftLintFramework/Protocols/CallPairRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ extension CallPairRule {
private func methodCall(forByteOffset byteOffset: Int, excludingOffset: Int,
dictionary: SourceKittenDictionary,
predicate: (SourceKittenDictionary) -> Bool) -> Int? {
if let kindString = dictionary.kind,
SwiftExpressionKind(rawValue: kindString) == .call,
if dictionary.expressionKind == .call,
let bodyOffset = dictionary.offset,
let bodyLength = dictionary.length,
let offset = dictionary.offset {
Expand Down
2 changes: 1 addition & 1 deletion Source/SwiftLintFramework/Protocols/Rule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ extension SubstitutionCorrectableASTRule where KindType.RawValue == String {
let ranges = dictionary.substructure.flatMap { subDict -> [NSRange] in
var ranges = violationRanges(in: file, dictionary: subDict)

if let kind = subDict.kind.flatMap(KindType.init) {
if let kind = self.kind(from: subDict) {
ranges += violationRanges(in: file, kind: kind, dictionary: subDict)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public struct BlockBasedKVORule: ASTRule, ConfigurationProviderRule, AutomaticTe
private extension Array where Element == SourceKittenDictionary {
var parameterTypes: [String] {
return compactMap { element in
guard element.kind.flatMap(SwiftDeclarationKind.init) == .varParameter else {
guard element.declarationKind == .varParameter else {
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public struct ConvenienceTypeRule: ASTRule, OptInRule, ConfigurationProviderRule
}

let containsInstanceDeclarations = dictionary.substructure.contains { dict in
guard let kind = dict.kind.flatMap(SwiftDeclarationKind.init(rawValue:)) else {
guard let kind = dict.declarationKind else {
return false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public struct ExplicitACLRule: OptInRule, ConfigurationProviderRule, AutomaticTe
return nil
}

guard let kind = element.kind.flatMap(SwiftDeclarationKind.init(rawValue:)),
guard let kind = element.declarationKind,
!extensionKinds.contains(kind) else {
return nil
}
Expand Down Expand Up @@ -116,7 +116,7 @@ public struct ExplicitACLRule: OptInRule, ConfigurationProviderRule, AutomaticTe

private func internalTypeElements(in element: SourceKittenElement) -> [SourceKittenElement] {
return element.substructure.flatMap { element -> [SourceKittenElement] in
guard let elementKind = element.kind.flatMap(SwiftDeclarationKind.init(rawValue:)) else {
guard let elementKind = element.declarationKind else {
return []
}

Expand All @@ -125,11 +125,11 @@ public struct ExplicitACLRule: OptInRule, ConfigurationProviderRule, AutomaticTe
return []
}

let isPrivate = element.accessibility.flatMap(AccessControlLevel.init(rawValue:))?.isPrivate ?? false
let isPrivate = element.accessibility?.isPrivate ?? false
let internalTypeElementsInSubstructure = elementKind.childsAreExemptFromACL || isPrivate ? [] :
internalTypeElements(in: element)

if element.accessibility.flatMap(AccessControlLevel.init(identifier:)) == .internal {
if element.accessibility == .internal {
return internalTypeElementsInSubstructure + [element]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public struct ExplicitEnumRawValueRule: ASTRule, OptInRule, ConfigurationProvide
private func substructureElements(of dict: SourceKittenDictionary,
matching kind: SwiftDeclarationKind) -> [SourceKittenDictionary] {
return dict.substructure
.filter { $0.kind.flatMap(SwiftDeclarationKind.init) == kind }
.filter { $0.declarationKind == kind }
}

private func enumElementsMissingInitExpr(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ public struct ExplicitTopLevelACLRule: OptInRule, ConfigurationProviderRule, Aut
let dictionary = file.structureDictionary
let internalTypesOffsets = dictionary.substructure.compactMap { element -> Int? in
// ignore extensions
guard let kind = element.kind.flatMap(SwiftDeclarationKind.init(rawValue:)),
guard let kind = element.declarationKind,
!extensionKinds.contains(kind) else {
return nil
}

if element.accessibility.flatMap(AccessControlLevel.init(identifier:)) == .internal {
if element.accessibility == .internal {
return element.offset
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ public struct ExplicitTypeInterfaceRule: OptInRule, ConfigurationProviderRule {
return dictionary.substructure.flatMap({ subDict -> [StyleViolation] in
var violations = validate(file: file, dictionary: subDict, parentStructure: dictionary)

if let kindString = subDict.kind,
let kind = SwiftDeclarationKind(rawValue: kindString) {
if let kind = subDict.declarationKind {
violations += validate(file: file, kind: kind, dictionary: subDict, parentStructure: dictionary)
}

Expand Down Expand Up @@ -157,9 +156,8 @@ private extension SourceKittenDictionary {
}

func contains(_ statements: Set<StatementKind>) -> Bool {
guard let kind = kind,
let statement = StatementKind(rawValue: kind) else {
return false
guard let statement = statementKind else {
return false
}
return statements.contains(statement)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ public struct ExtensionAccessModifierRule: ASTRule, ConfigurationProviderRule, O
}

let declarations = dictionary.substructure.compactMap { entry -> (acl: AccessControlLevel, offset: Int)? in
guard entry.kind.flatMap(SwiftDeclarationKind.init) != nil,
let acl = entry.accessibility.flatMap(AccessControlLevel.init(identifier:)),
guard entry.declarationKind != nil,
let acl = entry.accessibility,
let offset = entry.offset else {
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ private let typeAndExtensionKinds = SwiftDeclarationKind.typeKinds + [.extension
private extension SourceKittenDictionary {
func recursiveDeclaredTypeNames() -> [String] {
let subNames = substructure.flatMap { $0.recursiveDeclaredTypeNames() }
if let kind = kind.flatMap(SwiftDeclarationKind.init),
if let kind = declarationKind,
typeAndExtensionKinds.contains(kind), let name = name {
return [name] + subNames
}
Expand Down
6 changes: 3 additions & 3 deletions Source/SwiftLintFramework/Rules/Idiomatic/ForWhereRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public struct ForWhereRule: ASTRule, ConfigurationProviderRule, AutomaticTestabl
let subDictionary = forBody(dictionary: dictionary),
subDictionary.substructure.count == 1,
let bodyDictionary = subDictionary.substructure.first,
bodyDictionary.kind.flatMap(StatementKind.init) == .if,
bodyDictionary.statementKind == .if,
isOnlyOneIf(dictionary: bodyDictionary),
isOnlyIfInsideFor(forDictionary: subDictionary, ifDictionary: bodyDictionary, file: file),
!isComplexCondition(dictionary: bodyDictionary, file: file),
Expand All @@ -110,7 +110,7 @@ public struct ForWhereRule: ASTRule, ConfigurationProviderRule, AutomaticTestabl

private func forBody(dictionary: SourceKittenDictionary) -> SourceKittenDictionary? {
return dictionary.substructure.first(where: { subDict -> Bool in
subDict.kind.flatMap(StatementKind.init) == .brace
subDict.statementKind == .brace
})
}

Expand All @@ -120,7 +120,7 @@ public struct ForWhereRule: ASTRule, ConfigurationProviderRule, AutomaticTestabl
return false
}

return dictionary.substructure.first?.kind.flatMap(StatementKind.init) == .brace
return dictionary.substructure.first?.statementKind == .brace
}

private func isOnlyIfInsideFor(forDictionary: SourceKittenDictionary,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public struct FunctionDefaultParameterAtEndRule: ASTRule, ConfigurationProviderR
let isNotClosure = { !self.isClosureParameter(dictionary: $0) }
let params = dictionary.substructure
.flatMap { subDict -> [SourceKittenDictionary] in
guard subDict.kind.flatMap(SwiftDeclarationKind.init) == .varParameter else {
guard subDict.declarationKind == .varParameter else {
return []
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public struct LegacyConstructorRule: ASTRule, CorrectableRule, ConfigurationProv
dictionary: SourceKittenDictionary) -> [SourceKittenDictionary] {
return dictionary.substructure.flatMap { subDict -> [SourceKittenDictionary] in
var dictionaries = violations(in: file, dictionary: subDict)
if let kind = subDict.kind.flatMap(SwiftExpressionKind.init(rawValue:)) {
if let kind = subDict.expressionKind {
dictionaries += violations(in: file, kind: kind, dictionary: subDict)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ public struct NimbleOperatorRule: ConfigurationProviderRule, OptInRule, Correcta

let containsCall = file.structureDictionary.structures(forByteOffset: byteRange.upperBound - 1)
.contains(where: { dict -> Bool in
return dict.kind.flatMap(SwiftExpressionKind.init) == .call &&
(dict.name ?? "").starts(with: "expect")
return dict.expressionKind == .call && (dict.name ?? "").starts(with: "expect")
})

return containsCall
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public struct PrivateOverFilePrivateRule: ConfigurationProviderRule, Substitutio
}

if !configuration.validateExtensions &&
dictionary.kind.flatMap(SwiftDeclarationKind.init) == .extension {
dictionary.declarationKind == .extension {
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ public struct RedundantObjcAttributeRule: SubstitutionCorrectableRule, Configura
return dictionary.substructure.flatMap { subDict -> [NSRange] in
var violations = violationRanges(file: file, dictionary: subDict, parentStructure: dictionary)

if let kindString = subDict.kind,
let kind = SwiftDeclarationKind(rawValue: kindString) {
if let kind = subDict.declarationKind {
violations += violationRanges(file: file, kind: kind, dictionary: subDict, parentStructure: dictionary)
}

Expand All @@ -61,9 +60,9 @@ public struct RedundantObjcAttributeRule: SubstitutionCorrectableRule, Configura

let isInObjcVisibleScope = { () -> Bool in
guard let parentStructure = parentStructure,
let kind = dictionary.kind.flatMap(SwiftDeclarationKind.init),
let parentKind = parentStructure.kind.flatMap(SwiftDeclarationKind.init),
let acl = dictionary.accessibility.flatMap(AccessControlLevel.init(identifier:)) else {
let kind = dictionary.declarationKind,
let parentKind = parentStructure.declarationKind,
let acl = dictionary.accessibility else {
return false
}

Expand Down Expand Up @@ -91,7 +90,7 @@ public struct RedundantObjcAttributeRule: SubstitutionCorrectableRule, Configura

private extension SourceKittenDictionary {
var isObjcAndIBDesignableDeclaredExtension: Bool {
guard let kind = kind, let declaration = SwiftDeclarationKind(rawValue: kind) else {
guard let declaration = declarationKind else {
return false
}
return [.extensionClass, .extension].contains(declaration)
Expand Down
Loading

0 comments on commit 0db1f9c

Please sign in to comment.