mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
58928b7e40
This makes syntactically clear which types are rather expensive.
86 lines
2.5 KiB
Swift
86 lines
2.5 KiB
Swift
import SwiftSyntax
|
|
|
|
@SwiftSyntaxRule
|
|
struct NSObjectPreferIsEqualRule: ConfigurationProviderRule {
|
|
var configuration = SeverityConfiguration<Self>(.warning)
|
|
|
|
static let description = RuleDescription(
|
|
identifier: "nsobject_prefer_isequal",
|
|
name: "NSObject Prefer isEqual",
|
|
description: "NSObject subclasses should implement isEqual instead of ==",
|
|
kind: .lint,
|
|
nonTriggeringExamples: NSObjectPreferIsEqualRuleExamples.nonTriggeringExamples,
|
|
triggeringExamples: NSObjectPreferIsEqualRuleExamples.triggeringExamples
|
|
)
|
|
}
|
|
|
|
private extension NSObjectPreferIsEqualRule {
|
|
final class Visitor: ViolationsSyntaxVisitor {
|
|
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .extensionsAndProtocols }
|
|
|
|
override func visitPost(_ node: FunctionDeclSyntax) {
|
|
if node.isSelfEqualFunction, node.isInObjcClass {
|
|
violations.append(node.positionAfterSkippingLeadingTrivia)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension ClassDeclSyntax {
|
|
var isObjC: Bool {
|
|
if attributes.isObjc {
|
|
return true
|
|
}
|
|
|
|
guard let inheritanceList = inheritanceClause?.inheritedTypes else {
|
|
return false
|
|
}
|
|
return inheritanceList.contains { type in
|
|
type.type.as(IdentifierTypeSyntax.self)?.name.text == "NSObject"
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension FunctionDeclSyntax {
|
|
var isSelfEqualFunction: Bool {
|
|
guard
|
|
modifiers.contains(keyword: .static),
|
|
name.text == "==",
|
|
returnsBool,
|
|
case let parameterList = signature.parameterClause.parameters,
|
|
parameterList.count == 2,
|
|
let lhs = parameterList.first,
|
|
let rhs = parameterList.last,
|
|
lhs.firstName.text == "lhs",
|
|
rhs.firstName.text == "rhs",
|
|
lhs.type.trimmedDescription == rhs.type.trimmedDescription
|
|
else {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
var returnsBool: Bool {
|
|
signature.returnClause?.type.as(IdentifierTypeSyntax.self)?.name.text == "Bool"
|
|
}
|
|
}
|
|
|
|
private extension SyntaxProtocol {
|
|
var isInObjcClass: Bool {
|
|
if let parentClass = parent?.as(ClassDeclSyntax.self) {
|
|
return parentClass.isObjC
|
|
} else if parent?.as(DeclSyntax.self) != nil {
|
|
return false
|
|
}
|
|
|
|
return parent?.isInObjcClass ?? false
|
|
}
|
|
}
|
|
|
|
private extension AttributeListSyntax {
|
|
var isObjc: Bool {
|
|
contains(attributeNamed: "objc") || contains(attributeNamed: "objcMembers")
|
|
}
|
|
}
|