@@ -24,12 +24,34 @@ extension SyntaxProtocol {
24
24
}
25
25
26
26
@_spi ( Experimental) extension SourceFileSyntax : ScopeSyntax {
27
+ /// All names introduced in the file scope
28
+ /// according to the default strategy: `memberBlockUpToLastDecl`.
27
29
public var introducedNames : [ LookupName ] {
28
30
introducedNames ( using: . memberBlockUpToLastDecl)
29
31
}
30
32
31
- public func introducedNames( using nameIntroductionStrategy: FileScopeNameIntroductionStrategy ) -> [ LookupName ] {
32
- switch nameIntroductionStrategy {
33
+ /// All names introduced in the file scope
34
+ /// using the provided configuration.
35
+ ///
36
+ /// Example usage:
37
+ /// ```swift
38
+ /// class a {}
39
+ /// class b {
40
+ /// // <--
41
+ /// }
42
+ /// let c = 0
43
+ /// class d {}
44
+ /// if true {}
45
+ /// class e {}
46
+ /// let f = 0
47
+ /// ```
48
+ /// During lookup, according to different configurations,
49
+ /// names available at the marked place are:
50
+ /// - for `fileScopeNameIntroductionStrategy` - a, b, c, d
51
+ /// - for `memberBlock` - a, b, c, d, e, f
52
+ /// - for `codeBlock` - a
53
+ public func introducedNames( using fileScopeHandling: FileScopeHandlingConfig ) -> [ LookupName ] {
54
+ switch fileScopeHandling {
33
55
case . memberBlockUpToLastDecl:
34
56
var encounteredNonDeclaration = false
35
57
@@ -58,23 +80,43 @@ extension SyntaxProtocol {
58
80
}
59
81
}
60
82
83
+ /// Returns names matching lookup using provided file
84
+ /// scope handling configuration (by default: `memberBlockUpToLastDecl`).
85
+ ///
86
+ /// Example usage:
87
+ /// ```swift
88
+ /// class a {}
89
+ /// class b {
90
+ /// // <--
91
+ /// }
92
+ /// let c = 0
93
+ /// class d {}
94
+ /// if true {}
95
+ /// class e {}
96
+ /// let f = 0
97
+ /// ```
98
+ /// According to different configurations,
99
+ /// names available at the marked place are:
100
+ /// - for `fileScopeNameIntroductionStrategy` - a, b, c, d
101
+ /// - for `memberBlock` - a, b, c, d, e, f
102
+ /// - for `codeBlock` - a
61
103
public func lookup(
62
104
for name: String ? ,
63
105
at syntax: SyntaxProtocol ,
64
- with configDict : LookupConfigDictionary
106
+ with config : LookupConfig
65
107
) -> [ LookupResult ] {
66
- let nameIntroductionStrategy = configDict [ FileScopeNameIntroductionStrategy . self] ?? . memberBlockUpToLastDecl
67
-
68
- let names = introducedNames ( using: nameIntroductionStrategy)
108
+ let names = introducedNames ( using: config. fileScopeHandling)
69
109
. filter { introducedName in
70
110
introducedName. isAccessible ( at: syntax) && ( name == nil || introducedName. refersTo ( name!) )
71
111
}
72
112
73
- return [ . fromFileScope( self , withNames: names, nameIntroductionStrategy : nameIntroductionStrategy ) ]
113
+ return [ . fromFileScope( self , withNames: names) ]
74
114
}
75
115
}
76
116
77
117
@_spi ( Experimental) extension CodeBlockSyntax : ScopeSyntax {
118
+ /// Names introduced in the code block scope
119
+ /// accessible after their declaration.
78
120
public var introducedNames : [ LookupName ] {
79
121
statements. flatMap { codeBlockItem in
80
122
LookupName . getNames ( from: codeBlockItem. item, accessibleAfter: codeBlockItem. endPosition)
@@ -83,12 +125,24 @@ extension SyntaxProtocol {
83
125
}
84
126
85
127
@_spi ( Experimental) extension ForStmtSyntax : ScopeSyntax {
128
+ /// Names introduced in the `for` body.
86
129
public var introducedNames : [ LookupName ] {
87
130
LookupName . getNames ( from: pattern)
88
131
}
89
132
}
90
133
91
134
@_spi ( Experimental) extension ClosureExprSyntax : ScopeSyntax {
135
+ /// All names introduced by the closure signature.
136
+ /// Could be closure captures or (shorthand) parameters.
137
+ ///
138
+ /// Example:
139
+ /// ```swift
140
+ /// let x = { [weak self, a] b, _ in
141
+ /// // <--
142
+ /// }
143
+ /// ```
144
+ /// During lookup, names available at the marked place are:
145
+ /// `self`, a, b.
92
146
public var introducedNames : [ LookupName ] {
93
147
let captureNames =
94
148
signature? . capture? . children ( viewMode: . sourceAccurate) . flatMap { child in
@@ -117,6 +171,7 @@ extension SyntaxProtocol {
117
171
}
118
172
119
173
@_spi ( Experimental) extension WhileStmtSyntax : ScopeSyntax {
174
+ /// Names introduced by the `while` loop by its conditions.
120
175
public var introducedNames : [ LookupName ] {
121
176
conditions. flatMap { element in
122
177
LookupName . getNames ( from: element. condition)
@@ -125,11 +180,28 @@ extension SyntaxProtocol {
125
180
}
126
181
127
182
@_spi ( Experimental) extension IfExprSyntax : ScopeSyntax {
183
+ /// Parent scope, omitting ancestor `if` statements if part of their `else if` clause.
128
184
public var parentScope : ScopeSyntax ? {
129
185
getParent ( for: self . parent, previousIfElse: self . elseKeyword == nil )
130
186
}
131
187
132
- /// Finds the parent scope, omitting parent `if` statements if part of their `else if` clause.
188
+ /// Finds parent scope, omitting ancestor `if` statements if part of their `else if` clause.
189
+ ///
190
+ /// Example:
191
+ /// ```swift
192
+ /// func foo() {
193
+ /// if let a = x {
194
+ /// // <--
195
+ /// } else if let b {
196
+ /// // <--
197
+ /// } else if y == 1 {
198
+ /// // <--
199
+ /// }
200
+ /// }
201
+ /// ```
202
+ /// For each of the marked scopes, resulting parent
203
+ /// is the enclosing code block scope associated with
204
+ /// the function body.
133
205
private func getParent( for syntax: Syntax ? , previousIfElse: Bool ) -> ScopeSyntax ? {
134
206
guard let syntax else { return nil }
135
207
@@ -144,26 +216,40 @@ extension SyntaxProtocol {
144
216
}
145
217
}
146
218
219
+ /// Names introduced by the `if` optional binding conditions.
147
220
public var introducedNames : [ LookupName ] {
148
221
conditions. flatMap { element in
149
222
LookupName . getNames ( from: element. condition, accessibleAfter: element. endPosition)
150
223
}
151
224
}
152
225
226
+ /// Returns names matching lookup.
227
+ /// Lookup triggered from inside of `else`
228
+ /// clause is immediately forwarded to parent scope.
229
+ ///
230
+ /// Example:
231
+ /// ```swift
232
+ /// if let a = x {
233
+ /// // <-- a is visible here
234
+ /// } else {
235
+ /// // <-- a is not visible here
236
+ /// }
237
+ /// ```
153
238
public func lookup(
154
239
for name: String ? ,
155
240
at syntax: SyntaxProtocol ,
156
- with configDict : LookupConfigDictionary
241
+ with config : LookupConfig
157
242
) -> [ LookupResult ] {
158
243
if let elseBody, elseBody. position <= syntax. position, elseBody. endPosition >= syntax. position {
159
- lookupInParent ( for: name, at: syntax, with: configDict )
244
+ lookupInParent ( for: name, at: syntax, with: config )
160
245
} else {
161
- defaultLookupImplementation ( for: name, at: syntax, with: configDict )
246
+ defaultLookupImplementation ( for: name, at: syntax, with: config )
162
247
}
163
248
}
164
249
}
165
250
166
251
@_spi ( Experimental) extension MemberBlockSyntax : ScopeSyntax {
252
+ /// All names introduced by members of this member scope.
167
253
public var introducedNames : [ LookupName ] {
168
254
members. flatMap { member in
169
255
LookupName . getNames ( from: member. decl)
@@ -172,19 +258,32 @@ extension SyntaxProtocol {
172
258
}
173
259
174
260
@_spi ( Experimental) extension GuardStmtSyntax : ScopeSyntax {
261
+ /// Guard doesn't introduce any names to its children.
262
+ /// It's always empty.
175
263
public var introducedNames : [ LookupName ] {
176
264
[ ]
177
265
}
178
266
267
+ /// Returns names matching lookup.
268
+ /// Lookup triggered from inside of `else`
269
+ /// clause is immediately forwarded to parent scope.
270
+ ///
271
+ /// Example:
272
+ /// ```swift
273
+ /// guard let a = x else {
274
+ /// return // a is not visible here
275
+ /// }
276
+ /// // a is visible here
277
+ /// ```
179
278
public func lookup(
180
279
for name: String ? ,
181
280
at syntax: SyntaxProtocol ,
182
- with configDict : LookupConfigDictionary
281
+ with config : LookupConfig
183
282
) -> [ LookupResult ] {
184
283
if body. position <= syntax. position && body. endPosition >= syntax. position {
185
- lookupInParent ( for: name, at: self , with: configDict )
284
+ lookupInParent ( for: name, at: self , with: config )
186
285
} else {
187
- defaultLookupImplementation ( for: name, at: syntax, with: configDict )
286
+ defaultLookupImplementation ( for: name, at: syntax, with: config )
188
287
}
189
288
}
190
289
}
0 commit comments