Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use swift enums instead of raw values #2924

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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