1212
1313import SwiftSyntax
1414
15+ @_spi ( Experimental) public enum LookupImplicitNameKind {
16+ /// `self` keyword representing object instance.
17+ case `self`( SyntaxProtocol )
18+ /// `Self` keyword representing object type.
19+ case `Self`( DeclSyntaxProtocol )
20+ /// `self` captured by a closure.
21+ case error( CatchClauseSyntax )
22+ /// `newValue` available by default inside `set` and `willSet`.
23+ case newValue( AccessorDeclSyntax )
24+ /// `oldValue` available by default inside `didSet`.
25+ case oldValue( AccessorDeclSyntax )
26+
27+ /// Syntax associated with this name.
28+ @_spi ( Experimental) public var syntax : SyntaxProtocol {
29+ switch self {
30+ case . self ( let syntax) :
31+ syntax
32+ case . Self( let syntax) :
33+ syntax
34+ case . error( let syntax) :
35+ syntax
36+ case . newValue( let syntax) :
37+ syntax
38+ case . oldValue( let syntax) :
39+ syntax
40+ }
41+ }
42+
43+ /// Used for name comparison.
44+ var name : String {
45+ switch self {
46+ case . self :
47+ " self "
48+ case . Self:
49+ " Self "
50+ case . error:
51+ " error "
52+ case . newValue:
53+ " newValue "
54+ case . oldValue:
55+ " oldValue "
56+ }
57+ }
58+ }
59+
1560@_spi ( Experimental) public enum LookupName {
1661 /// Identifier associated with the name.
17- /// Could be an identifier of a variable, function or closure parameter and more
62+ /// Could be an identifier of a variable, function or closure parameter and more.
1863 case identifier( IdentifiableSyntax , accessibleAfter: AbsolutePosition ? )
1964 /// Declaration associated with the name.
20- /// Could be class, struct, actor, protocol, function and more
65+ /// Could be class, struct, actor, protocol, function and more.
2166 case declaration( NamedDeclSyntax , accessibleAfter: AbsolutePosition ? )
67+ /// Name introduced implicitly certain syntax nodes.
68+ case implicit( LookupImplicitNameKind )
2269
2370 /// Syntax associated with this name.
2471 @_spi ( Experimental) public var syntax : SyntaxProtocol {
@@ -27,6 +74,8 @@ import SwiftSyntax
2774 syntax
2875 case . declaration( let syntax, _) :
2976 syntax
77+ case . implicit( let implicitName) :
78+ implicitName. syntax
3079 }
3180 }
3281
@@ -37,6 +86,8 @@ import SwiftSyntax
3786 Identifier ( syntax. identifier)
3887 case . declaration( let syntax, _) :
3988 Identifier ( syntax. name)
89+ default :
90+ nil
4091 }
4192 }
4293
@@ -46,6 +97,18 @@ import SwiftSyntax
4697 switch self {
4798 case . identifier( _, let absolutePosition) , . declaration( _, let absolutePosition) :
4899 absolutePosition
100+ default :
101+ nil
102+ }
103+ }
104+
105+ /// Used for name comparison.
106+ var name : String ? {
107+ switch self {
108+ case . identifier, . declaration:
109+ identifier? . name
110+ case . implicit( let implicitName) :
111+ implicitName. name
49112 }
50113 }
51114
@@ -57,12 +120,15 @@ import SwiftSyntax
57120
58121 /// Checks if this name refers to the looked up phrase.
59122 func refersTo( _ lookedUpName: String ) -> Bool {
60- guard let name = identifier ? . name else { return false }
123+ guard let name else { return false }
61124 return name == lookedUpName
62125 }
63126
64- /// Extracts names introduced by the given `from` structure.
65- static func getNames( from syntax: SyntaxProtocol , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ] {
127+ /// Extracts names introduced by the given `syntax` structure.
128+ static func getNames(
129+ from syntax: SyntaxProtocol ,
130+ accessibleAfter: AbsolutePosition ? = nil
131+ ) -> [ LookupName ] {
66132 switch Syntax ( syntax) . as ( SyntaxEnum . self) {
67133 case . variableDecl( let variableDecl) :
68134 variableDecl. bindings. flatMap { binding in
@@ -90,10 +156,6 @@ import SwiftSyntax
90156 functionCallExpr. arguments. flatMap { argument in
91157 getNames ( from: argument. expression, accessibleAfter: accessibleAfter)
92158 }
93- case . guardStmt( let guardStmt) :
94- guardStmt. conditions. flatMap { cond in
95- getNames ( from: cond. condition, accessibleAfter: cond. endPosition)
96- }
97159 default :
98160 if let namedDecl = Syntax ( syntax) . asProtocol ( SyntaxProtocol . self) as? NamedDeclSyntax {
99161 handle ( namedDecl: namedDecl, accessibleAfter: accessibleAfter)
@@ -106,17 +168,26 @@ import SwiftSyntax
106168 }
107169
108170 /// Extracts name introduced by `IdentifiableSyntax` node.
109- private static func handle( identifiable: IdentifiableSyntax , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ]
110- {
111- if identifiable. identifier. text != " _ " {
171+ private static func handle(
172+ identifiable: IdentifiableSyntax ,
173+ accessibleAfter: AbsolutePosition ? = nil
174+ ) -> [ LookupName ] {
175+ if let closureCapture = identifiable as? ClosureCaptureSyntax ,
176+ closureCapture. identifier. tokenKind == . keyword( . self )
177+ {
178+ return [ . implicit( . self ( closureCapture) ) ] // Handle `self` closure capture.
179+ } else if identifiable. identifier. tokenKind != . wildcard {
112180 return [ . identifier( identifiable, accessibleAfter: accessibleAfter) ]
113181 } else {
114182 return [ ]
115183 }
116184 }
117185
118186 /// Extracts name introduced by `NamedDeclSyntax` node.
119- private static func handle( namedDecl: NamedDeclSyntax , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ] {
187+ private static func handle(
188+ namedDecl: NamedDeclSyntax ,
189+ accessibleAfter: AbsolutePosition ? = nil
190+ ) -> [ LookupName ] {
120191 [ . declaration( namedDecl, accessibleAfter: accessibleAfter) ]
121192 }
122193}
0 commit comments