mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
cf64c0873b
# Conflicts: # Cartfile # Cartfile.private # Cartfile.resolved # Carthage/Checkouts/SourceKitten # Package.resolved # Package.swift # Rules.md # Source/SwiftLintFramework/Extensions/Configuration+LintableFiles.swift # Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift # Source/SwiftLintFramework/Models/SwiftVersion.swift # Source/SwiftLintFramework/Rules/ModifiersOrderRule.swift # Source/SwiftLintFramework/Rules/RuleConfigurations/ModifiersOrderConfiguration.swift # SwiftLint.xcodeproj/project.pbxproj # Tests/SwiftLintFrameworkTests/LinterCacheTests.swift # Tests/SwiftLintFrameworkTests/ModifiersOrderTests.swift # circle.yml
124 lines
5.1 KiB
Swift
124 lines
5.1 KiB
Swift
//
|
|
// ModifiersOrderRule.swift
|
|
// SwiftLint
|
|
//
|
|
// Created by Jose Cheyo Jimenez on 05/06/17.
|
|
// Copyright © 2017 Realm. All rights reserved.
|
|
//
|
|
|
|
import SourceKittenFramework
|
|
|
|
public struct ModifiersOrderRule: ASTRule, OptInRule, ConfigurationProviderRule {
|
|
|
|
public var configuration = ModifiersOrderConfiguration(preferedModifiersOrder: [.override, .acl])
|
|
|
|
public init() {}
|
|
|
|
public static let description = RuleDescription(
|
|
identifier: "modifiers_order",
|
|
name: "Modifiers Order",
|
|
description: "Modifiers order should be consistent.",
|
|
kind: .style,
|
|
nonTriggeringExamples: [
|
|
"public static let nnumber = 3 \n",
|
|
"@objc \npublic final class MyClass: NSObject {\n }",
|
|
"@objc \n override public private(set) weak var foo: Bar?\n",
|
|
"@objc \npublic final class MyClass: NSObject {\n }",
|
|
"@objc \npublic final class MyClass: NSObject {\n" +
|
|
"private final func myFinal() {}\n" +
|
|
"weak var myWeak: NSString? = nil\n" +
|
|
"public static let nnumber = 3 \n }",
|
|
"public final class MyClass {}",
|
|
"class RootClass { func myFinal() {}}\n" +
|
|
"internal class MyClass: RootClass {" +
|
|
"override internal func myFinal() {}}"
|
|
],
|
|
triggeringExamples: [
|
|
"class Foo { \n static public let bar = 3 {} \n }",
|
|
"class Foo { \n class override public let bar = 3 {} \n }",
|
|
"class Foo { \n overide static final public var foo: String {} \n }",
|
|
"@objc \npublic final class MyClass: NSObject {\n" +
|
|
"final private func myFinal() {}\n}",
|
|
"@objc \nfinal public class MyClass: NSObject {}\n",
|
|
"final public class MyClass {}\n",
|
|
"class MyClass {" +
|
|
"weak internal var myWeak: NSString? = nil\n}",
|
|
"class MyClass {" +
|
|
"static public let nnumber = 3 \n }"
|
|
]
|
|
)
|
|
|
|
public func validate(file: File,
|
|
kind: SwiftDeclarationKind,
|
|
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
|
|
|
|
guard let offset = dictionary.offset else {
|
|
return []
|
|
}
|
|
|
|
let preferedOrderOfModifiers = [.objcInteroperability, .interfaceBuilder] + configuration.preferedModifiersOrder
|
|
print(preferedOrderOfModifiers)
|
|
let modifierGroupsInDeclaration = findModifierGroups(in: dictionary)
|
|
let filteredPreferedOrderOfModifiers = preferedOrderOfModifiers.filter {
|
|
return modifierGroupsInDeclaration.contains($0)
|
|
}
|
|
print(filteredPreferedOrderOfModifiers)
|
|
for (index, preferedGroup) in filteredPreferedOrderOfModifiers.enumerated()
|
|
where preferedGroup != modifierGroupsInDeclaration[index] {
|
|
return [StyleViolation(ruleDescription: type(of: self).description,
|
|
severity: configuration.severityConfiguration.severity,
|
|
location: Location(file: file, byteOffset: offset))]
|
|
}
|
|
|
|
return []
|
|
}
|
|
// swiftlint:disable line_length
|
|
private func findModifierGroups(in dictionary: [String: SourceKitRepresentable]) -> [SwiftDeclarationAttributeKind.ModifierGroup] {
|
|
|
|
var declarationAttributes = dictionary.enclosedSwiftAttributesWithMetaData
|
|
if let delcarationKinds = contains(in: dictionary,
|
|
declarationKinds: .functionMethodClass, .functionMethodStatic, .varClass, .varStatic) {
|
|
declarationAttributes.append(delcarationKinds)
|
|
}
|
|
|
|
return declarationAttributes
|
|
.sorted {
|
|
guard let rhsOffset = $0["key.offset"] as? Int64,
|
|
let lhsOffset = $1["key.offset"] as? Int64 else {
|
|
return false
|
|
|
|
}
|
|
return rhsOffset < lhsOffset
|
|
}
|
|
.compactMap {
|
|
if let attribute = $0["key.attribute"] as? String { return group(of: attribute) }
|
|
if $0["key.kind"] != nil { return .typeMethods }
|
|
return nil
|
|
}
|
|
}
|
|
|
|
private func group(of rawAttribute: String) -> SwiftDeclarationAttributeKind.ModifierGroup? {
|
|
for value in SwiftDeclarationAttributeKind.ModifierGroup.allValues {
|
|
for attributeKind in value.swiftDeclarationAttributeKinds
|
|
where attributeKind.rawValue.hasSuffix(rawAttribute) {
|
|
return value
|
|
}
|
|
}
|
|
|
|
if rawAttribute == "static" || rawAttribute == "class" {
|
|
return .typeMethods
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
private func contains(in dictionary: [String: SourceKitRepresentable],
|
|
declarationKinds: SwiftDeclarationKind...) -> [String: SourceKitRepresentable]? {
|
|
guard let rawKind = dictionary.kind,
|
|
let kind = SwiftDeclarationKind(rawValue: rawKind),
|
|
let offset = dictionary.offset else { return nil }
|
|
if declarationKinds.contains(kind) { return ["key.kind": rawKind, "key.offset": Int64(offset)] }
|
|
return nil
|
|
}
|
|
}
|