1212
1313import SwiftSyntax
1414
15+ /// An entity that is implicitly declared based on the syntactic structure of the program.
16+ @_spi ( Experimental) public enum ImplicitDecl {
17+ /// `self` keyword representing object instance.
18+ /// Could be associated with type declaration, extension,
19+ /// or closure captures.
20+ case `self`( DeclSyntaxProtocol )
21+ /// `Self` keyword representing object type.
22+ /// Could be associated with type declaration or extension.
23+ case `Self`( DeclSyntaxProtocol )
24+ /// `error` value caught by a `catch`
25+ /// block that does not specify a catch pattern.
26+ case error( CatchClauseSyntax )
27+ /// `newValue` available by default inside `set` and `willSet`.
28+ case newValue( AccessorDeclSyntax )
29+ /// `oldValue` available by default inside `didSet`.
30+ case oldValue( AccessorDeclSyntax )
31+
32+ /// Syntax associated with this name.
33+ @_spi ( Experimental) public var syntax : SyntaxProtocol {
34+ switch self {
35+ case . self ( let syntax) :
36+ return syntax
37+ case . Self( let syntax) :
38+ return syntax
39+ case . error( let syntax) :
40+ return syntax
41+ case . newValue( let syntax) :
42+ return syntax
43+ case . oldValue( let syntax) :
44+ return syntax
45+ }
46+ }
47+
48+ /// The name of the implicit declaration.
49+ private var name : String {
50+ switch self {
51+ case . self :
52+ return " self "
53+ case . Self:
54+ return " Self "
55+ case . error:
56+ return " error "
57+ case . newValue:
58+ return " newValue "
59+ case . oldValue:
60+ return " oldValue "
61+ }
62+ }
63+
64+ /// Identifier used for name comparison.
65+ ///
66+ /// Note that `self` and `Self` are treated as identifiers for name lookup purposes
67+ /// and that a variable named `self` can shadow the `self` keyword. For example.
68+ /// ```swift
69+ /// class Foo {
70+ /// func test() {
71+ /// let `Self` = "abc"
72+ /// print(Self.self)
73+ ///
74+ /// let `self` = "def"
75+ /// print(self)
76+ /// }
77+ /// }
78+ ///
79+ /// Foo().test()
80+ /// ```
81+ /// prints:
82+ /// ```
83+ /// abc
84+ /// def
85+ /// ```
86+ /// `self` and `Self` identifers override implicit `self` and `Self` introduced by
87+ /// the `Foo` class declaration.
88+ var identifier : Identifier {
89+ switch self {
90+ case . self :
91+ return Identifier ( " self " )
92+ case . Self:
93+ return Identifier ( " Self " )
94+ case . error:
95+ return Identifier ( " error " )
96+ case . newValue:
97+ return Identifier ( " newValue " )
98+ case . oldValue:
99+ return Identifier ( " oldValue " )
100+ }
101+ }
102+ }
103+
15104@_spi ( Experimental) public enum LookupName {
16105 /// Identifier associated with the name.
17106 /// Could be an identifier of a variable, function or closure parameter and more.
18107 case identifier( IdentifiableSyntax , accessibleAfter: AbsolutePosition ? )
19108 /// Declaration associated with the name.
20109 /// Could be class, struct, actor, protocol, function and more.
21110 case declaration( NamedDeclSyntax )
111+ /// Name introduced implicitly by certain syntax nodes.
112+ case implicit( ImplicitDecl )
113+ /// Explicit `self` keyword.
114+ case `self`( IdentifiableSyntax , accessibleAfter: AbsolutePosition ? )
115+ /// Explicit `Self` keyword.
116+ case `Self`( IdentifiableSyntax , accessibleAfter: AbsolutePosition ? )
22117
23118 /// Syntax associated with this name.
24119 @_spi ( Experimental) public var syntax : SyntaxProtocol {
@@ -27,40 +122,52 @@ import SwiftSyntax
27122 return syntax
28123 case . declaration( let syntax) :
29124 return syntax
125+ case . implicit( let implicitName) :
126+ return implicitName. syntax
127+ case . self ( let syntax, _) , . Self( let syntax, _) :
128+ return syntax
30129 }
31130 }
32131
33- /// Introduced name.
132+ /// Identifier used for name comparison .
34133 @_spi ( Experimental) public var identifier : Identifier ? {
35134 switch self {
36135 case . identifier( let syntax, _) :
37136 return Identifier ( syntax. identifier)
38137 case . declaration( let syntax) :
39138 return Identifier ( syntax. name)
139+ case . implicit( let kind) :
140+ return kind. identifier
141+ case . self :
142+ return Identifier ( " self " )
143+ case . Self:
144+ return Identifier ( " Self " )
40145 }
41146 }
42147
43148 /// Point, after which the name is available in scope.
44149 /// If set to `nil`, the name is available at any point in scope.
45150 var accessibleAfter : AbsolutePosition ? {
46151 switch self {
47- case . identifier( _, let absolutePosition) :
152+ case . identifier( _, let absolutePosition) ,
153+ . self ( _, let absolutePosition) ,
154+ . Self( _, let absolutePosition) :
48155 return absolutePosition
49156 default :
50157 return nil
51158 }
52159 }
53160
54161 /// Checks if this name was introduced before the syntax used for lookup.
55- func isAccessible( at lookedUpSyntax : SyntaxProtocol ) -> Bool {
162+ func isAccessible( at origin : AbsolutePosition ) -> Bool {
56163 guard let accessibleAfter else { return true }
57- return accessibleAfter <= lookedUpSyntax . position
164+ return accessibleAfter <= origin
58165 }
59166
60167 /// Checks if this name refers to the looked up phrase.
61- func refersTo( _ lookedUpName : String ) -> Bool {
62- guard let name = identifier? . name else { return false }
63- return name == lookedUpName
168+ func refersTo( _ lookedUpIdentifier : Identifier ) -> Bool {
169+ guard let identifier else { return false }
170+ return identifier == lookedUpIdentifier
64171 }
65172
66173 /// Extracts names introduced by the given `syntax` structure.
@@ -105,10 +212,6 @@ import SwiftSyntax
105212 return functionCallExpr. arguments. flatMap { argument in
106213 getNames ( from: argument. expression, accessibleAfter: accessibleAfter)
107214 }
108- case . guardStmt( let guardStmt) :
109- return guardStmt. conditions. flatMap { cond in
110- getNames ( from: cond. condition, accessibleAfter: cond. endPosition)
111- }
112215 default :
113216 if let namedDecl = Syntax ( syntax) . asProtocol ( SyntaxProtocol . self) as? NamedDeclSyntax {
114217 return handle ( namedDecl: namedDecl, accessibleAfter: accessibleAfter)
@@ -121,12 +224,21 @@ import SwiftSyntax
121224 }
122225
123226 /// Extracts name introduced by `IdentifiableSyntax` node.
124- private static func handle( identifiable: IdentifiableSyntax , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ]
125- {
126- if identifiable. identifier. tokenKind != . wildcard {
127- return [ . identifier( identifiable, accessibleAfter: accessibleAfter) ]
128- } else {
129- return [ ]
227+ private static func handle(
228+ identifiable: IdentifiableSyntax ,
229+ accessibleAfter: AbsolutePosition ? = nil
230+ ) -> [ LookupName ] {
231+ switch identifiable. identifier. tokenKind {
232+ case . keyword( . self ) :
233+ return [ . self ( identifiable, accessibleAfter: accessibleAfter) ]
234+ case . keyword( . Self) :
235+ return [ . Self( identifiable, accessibleAfter: accessibleAfter) ]
236+ default :
237+ if identifiable. identifier. tokenKind != . wildcard {
238+ return [ . identifier( identifiable, accessibleAfter: accessibleAfter) ]
239+ } else {
240+ return [ ]
241+ }
130242 }
131243 }
132244
0 commit comments