@@ -67,10 +67,11 @@ extension SyntaxProtocol {
6767
6868 let names = introducedNames ( using: nameIntroductionStrategy)
6969 . filter { introducedName in
70- introducedName . isAccessible ( at : syntax ) && ( name == nil || introducedName . refersTo ( name! ) )
70+ does ( name : name, referTo : introducedName , at : syntax )
7171 }
7272
73- return [ . fromFileScope( self , withNames: names, nameIntroductionStrategy: nameIntroductionStrategy) ]
73+ return names. isEmpty
74+ ? [ ] : [ . fromFileScope( self , withNames: names, nameIntroductionStrategy: nameIntroductionStrategy) ]
7475 }
7576}
7677
@@ -80,6 +81,45 @@ extension SyntaxProtocol {
8081 LookupName . getNames ( from: codeBlockItem. item, accessibleAfter: codeBlockItem. endPosition)
8182 }
8283 }
84+
85+ public func lookup(
86+ for name: String ? ,
87+ at syntax: SyntaxProtocol ,
88+ with configDict: LookupConfigDictionary
89+ ) -> [ LookupResult ] {
90+ var result = [ LookupResult] ( )
91+ var currentChunk = [ LookupName] ( )
92+
93+ for codeBlockItem in statements {
94+ if let introducingToParentScope = Syntax ( codeBlockItem. item) . asProtocol ( SyntaxProtocol . self)
95+ as? IntroducingToParentScopeSyntax
96+ {
97+ if !currentChunk. isEmpty {
98+ result. append ( . fromScope( self , withNames: currentChunk) )
99+ currentChunk = [ ]
100+ }
101+
102+ result. append ( contentsOf: introducingToParentScope. introducedToParent ( for: name, at: syntax, with: configDict) )
103+ } else {
104+ currentChunk. append (
105+ contentsOf:
106+ LookupName . getNames (
107+ from: codeBlockItem. item,
108+ accessibleAfter: codeBlockItem. endPosition
109+ ) . filter { introducedName in
110+ does ( name: name, referTo: introducedName, at: syntax)
111+ }
112+ )
113+ }
114+ }
115+
116+ if !currentChunk. isEmpty {
117+ result. append ( . fromScope( self , withNames: currentChunk) )
118+ currentChunk = [ ]
119+ }
120+
121+ return result. reversed ( ) + lookupInParent( for: name, at: syntax, with: configDict)
122+ }
83123}
84124
85125@_spi ( Experimental) extension ForStmtSyntax : ScopeSyntax {
@@ -171,7 +211,21 @@ extension SyntaxProtocol {
171211 }
172212}
173213
174- @_spi ( Experimental) extension GuardStmtSyntax : ScopeSyntax {
214+ @_spi ( Experimental) extension GuardStmtSyntax : IntroducingToParentScopeSyntax {
215+ public func introducedToParent(
216+ for name: String ? ,
217+ at syntax: SwiftSyntax . SyntaxProtocol ,
218+ with configDict: LookupConfigDictionary
219+ ) -> [ LookupResult ] {
220+ let names = conditions. flatMap { element in
221+ LookupName . getNames ( from: element. condition, accessibleAfter: element. endPosition)
222+ } . filter { introducedName in
223+ does ( name: name, referTo: introducedName, at: syntax)
224+ }
225+
226+ return names. isEmpty ? [ ] : [ . fromScope( self , withNames: names) ]
227+ }
228+
175229 public var introducedNames : [ LookupName ] {
176230 [ ]
177231 }
@@ -182,7 +236,7 @@ extension SyntaxProtocol {
182236 with configDict: LookupConfigDictionary
183237 ) -> [ LookupResult ] {
184238 if body. position <= syntax. position && body. endPosition >= syntax. position {
185- lookupInParent ( for: name, at: self , with: configDict)
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.
186240 } else {
187241 defaultLookupImplementation ( for: name, at: syntax, with: configDict)
188242 }
0 commit comments