@@ -24,12 +24,34 @@ extension SyntaxProtocol {
2424}
2525
2626@_spi ( Experimental) extension SourceFileSyntax : ScopeSyntax {
27+ /// All names introduced in the file scope
28+ /// according to the default strategy: `memberBlockUpToLastDecl`.
2729 public var introducedNames : [ LookupName ] {
2830 introducedNames ( using: . memberBlockUpToLastDecl)
2931 }
3032
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 {
3355 case . memberBlockUpToLastDecl:
3456 var encounteredNonDeclaration = false
3557
@@ -58,24 +80,43 @@ extension SyntaxProtocol {
5880 }
5981 }
6082
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
61103 public func lookup(
62104 for name: String ? ,
63105 at syntax: SyntaxProtocol ,
64- with configDict : LookupConfigDictionary
106+ with config : LookupConfig
65107 ) -> [ LookupResult ] {
66- let nameIntroductionStrategy = configDict [ FileScopeNameIntroductionStrategy . self] ?? . memberBlockUpToLastDecl
67-
68- let names = introducedNames ( using: nameIntroductionStrategy)
108+ let names = introducedNames ( using: config. fileScopeHandling)
69109 . filter { introducedName in
70110 does ( name: name, referTo: introducedName, at: syntax)
71111 }
72112
73- return names. isEmpty
74- ? [ ] : [ . fromFileScope( self , withNames: names, nameIntroductionStrategy: nameIntroductionStrategy) ]
113+ return names. isEmpty ? [ ] : [ . fromFileScope( self , withNames: names) ]
75114 }
76115}
77116
78117@_spi ( Experimental) extension CodeBlockSyntax : ScopeSyntax {
118+ /// Names introduced in the code block scope
119+ /// accessible after their declaration.
79120 public var introducedNames : [ LookupName ] {
80121 statements. flatMap { codeBlockItem in
81122 LookupName . getNames ( from: codeBlockItem. item, accessibleAfter: codeBlockItem. endPosition)
@@ -123,12 +164,24 @@ extension SyntaxProtocol {
123164}
124165
125166@_spi ( Experimental) extension ForStmtSyntax : ScopeSyntax {
167+ /// Names introduced in the `for` body.
126168 public var introducedNames : [ LookupName ] {
127169 LookupName . getNames ( from: pattern)
128170 }
129171}
130172
131173@_spi ( Experimental) extension ClosureExprSyntax : ScopeSyntax {
174+ /// All names introduced by the closure signature.
175+ /// Could be closure captures or (shorthand) parameters.
176+ ///
177+ /// Example:
178+ /// ```swift
179+ /// let x = { [weak self, a] b, _ in
180+ /// // <--
181+ /// }
182+ /// ```
183+ /// During lookup, names available at the marked place are:
184+ /// `self`, a, b.
132185 public var introducedNames : [ LookupName ] {
133186 let captureNames =
134187 signature? . capture? . children ( viewMode: . sourceAccurate) . flatMap { child in
@@ -157,6 +210,7 @@ extension SyntaxProtocol {
157210}
158211
159212@_spi ( Experimental) extension WhileStmtSyntax : ScopeSyntax {
213+ /// Names introduced by the `while` loop by its conditions.
160214 public var introducedNames : [ LookupName ] {
161215 conditions. flatMap { element in
162216 LookupName . getNames ( from: element. condition)
@@ -165,11 +219,28 @@ extension SyntaxProtocol {
165219}
166220
167221@_spi ( Experimental) extension IfExprSyntax : ScopeSyntax {
222+ /// Parent scope, omitting ancestor `if` statements if part of their `else if` clause.
168223 public var parentScope : ScopeSyntax ? {
169224 getParent ( for: self . parent, previousIfElse: self . elseKeyword == nil )
170225 }
171226
172- /// Finds the parent scope, omitting parent `if` statements if part of their `else if` clause.
227+ /// Finds parent scope, omitting ancestor `if` statements if part of their `else if` clause.
228+ ///
229+ /// Example:
230+ /// ```swift
231+ /// func foo() {
232+ /// if let a = x {
233+ /// // <--
234+ /// } else if let b {
235+ /// // <--
236+ /// } else if y == 1 {
237+ /// // <--
238+ /// }
239+ /// }
240+ /// ```
241+ /// For each of the marked scopes, resulting parent
242+ /// is the enclosing code block scope associated with
243+ /// the function body.
173244 private func getParent( for syntax: Syntax ? , previousIfElse: Bool ) -> ScopeSyntax ? {
174245 guard let syntax else { return nil }
175246
@@ -184,26 +255,40 @@ extension SyntaxProtocol {
184255 }
185256 }
186257
258+ /// Names introduced by the `if` optional binding conditions.
187259 public var introducedNames : [ LookupName ] {
188260 conditions. flatMap { element in
189261 LookupName . getNames ( from: element. condition, accessibleAfter: element. endPosition)
190262 }
191263 }
192264
265+ /// Returns names matching lookup.
266+ /// Lookup triggered from inside of `else`
267+ /// clause is immediately forwarded to parent scope.
268+ ///
269+ /// Example:
270+ /// ```swift
271+ /// if let a = x {
272+ /// // <-- a is visible here
273+ /// } else {
274+ /// // <-- a is not visible here
275+ /// }
276+ /// ```
193277 public func lookup(
194278 for name: String ? ,
195279 at syntax: SyntaxProtocol ,
196- with configDict : LookupConfigDictionary
280+ with config : LookupConfig
197281 ) -> [ LookupResult ] {
198282 if let elseBody, elseBody. position <= syntax. position, elseBody. endPosition >= syntax. position {
199- lookupInParent ( for: name, at: syntax, with: configDict )
283+ lookupInParent ( for: name, at: syntax, with: config )
200284 } else {
201- defaultLookupImplementation ( for: name, at: syntax, with: configDict )
285+ defaultLookupImplementation ( for: name, at: syntax, with: config )
202286 }
203287 }
204288}
205289
206290@_spi ( Experimental) extension MemberBlockSyntax : ScopeSyntax {
291+ /// All names introduced by members of this member scope.
207292 public var introducedNames : [ LookupName ] {
208293 members. flatMap { member in
209294 LookupName . getNames ( from: member. decl)
@@ -230,15 +315,26 @@ extension SyntaxProtocol {
230315 [ ]
231316 }
232317
318+ /// Returns names matching lookup.
319+ /// Lookup triggered from inside of `else`
320+ /// clause is immediately forwarded to parent scope.
321+ ///
322+ /// Example:
323+ /// ```swift
324+ /// guard let a = x else {
325+ /// return // a is not visible here
326+ /// }
327+ /// // a is visible here
328+ /// ```
233329 public func lookup(
234330 for name: String ? ,
235331 at syntax: SyntaxProtocol ,
236- with configDict : LookupConfigDictionary
332+ with config : LookupConfig
237333 ) -> [ LookupResult ] {
238334 if body. position <= syntax. position && body. endPosition >= syntax. position {
239- lookupInParent ( for: name, at: self , with: configDict ) // Should we add a new config that will skip certain scopes in lookup? Could be more consistent.
335+ lookupInParent ( for: name, at: self , with: config)
240336 } else {
241- defaultLookupImplementation ( for: name, at: syntax, with: configDict )
337+ defaultLookupImplementation ( for: name, at: syntax, with: config )
242338 }
243339 }
244340}
0 commit comments