1+ @_spi ( Experimental)
2+ import SwiftLexicalLookup
13import SwiftLintCore
24import SwiftSyntax
35
@@ -22,6 +24,14 @@ struct EmptyCountRule: Rule {
2224 Example ( " order.discount == 0 " ) ,
2325 Example ( " let rule = #Rule(Tips.Event(id: \" someTips \" )) { $0.donations.count == 0 } " ) ,
2426 Example ( " #Rule(param1: \" param1 \" ) " , excludeFromDocumentation: true ) ,
27+ Example ( " func isEmpty(count: Int) -> Bool { count == 0 } " ) ,
28+ Example ( """
29+ var isEmpty: Bool {
30+ let count = 0
31+ return count == 0
32+ }
33+ """ ) ,
34+ Example ( " { count in count == 0 }() " ) ,
2535 ] ,
2636 triggeringExamples: [
2737 Example ( " [Int]().↓count == 0 " ) ,
@@ -50,7 +60,18 @@ struct EmptyCountRule: Rule {
5060 doSomething()
5161 return $0.donations.↓count == 0
5262 }
53- """ , excludeFromDocumentation: true ) ,
63+ """ , excludeFromDocumentation: true ) ,
64+ Example ( """
65+ extension E {
66+ var isEmpty: Bool { ↓count == 0 }
67+ }
68+ """ , excludeFromDocumentation: true ) ,
69+ Example (
70+ """
71+ struct S {
72+ var isEmpty: Bool { ↓count == 0 }
73+ }
74+ """ , excludeFromDocumentation: true ) ,
5475 ] ,
5576 corrections: [
5677 Example ( " [].↓count == 0 " ) :
@@ -146,19 +167,31 @@ private extension EmptyCountRule {
146167}
147168
148169private extension ExprSyntax {
170+ var isNonLocalCountIdentifier : Bool {
171+ guard let declRef = self . as ( DeclReferenceExprSyntax . self) ,
172+ declRef. argumentNames == nil ,
173+ declRef. baseName. tokenKind == . identifier( " count " ) else {
174+ return false
175+ }
176+ let result = lookup ( Identifier ( canonicalName: " count " ) )
177+ return result. isEmpty || !result. contains { result in
178+ switch result {
179+ case . fromScope: true
180+ default : false
181+ }
182+ }
183+ }
184+
149185 func countCallPosition( onlyAfterDot: Bool ) -> AbsolutePosition ? {
150186 if let expr = self . as ( MemberAccessExprSyntax . self) {
151187 if expr. declName. argumentNames == nil , expr. declName. baseName. tokenKind == . identifier( " count " ) {
152188 return expr. declName. baseName. positionAfterSkippingLeadingTrivia
153189 }
154-
155190 return nil
156191 }
157-
158- if !onlyAfterDot, let expr = self . as ( DeclReferenceExprSyntax . self) {
159- return expr. baseName. tokenKind == . identifier( " count " ) ? expr. positionAfterSkippingLeadingTrivia : nil
192+ if !onlyAfterDot, isNonLocalCountIdentifier {
193+ return positionAfterSkippingLeadingTrivia
160194 }
161-
162195 return nil
163196 }
164197}
0 commit comments