@@ -14,38 +14,40 @@ import SwiftSyntax
1414
1515@_spi ( Experimental) public enum LookupName {
1616 /// Identifier associated with the name.
17- /// Could be an identifier of a variable, function or closure parameter and more
17+ /// Could be an identifier of a variable, function or closure parameter and more.
1818 case identifier( IdentifiableSyntax , accessibleAfter: AbsolutePosition ? )
1919 /// Declaration associated with the name.
20- /// Could be class, struct, actor, protocol, function and more
21- case declaration( NamedDeclSyntax , accessibleAfter : AbsolutePosition ? )
20+ /// Could be class, struct, actor, protocol, function and more.
21+ case declaration( NamedDeclSyntax )
2222
2323 /// Syntax associated with this name.
2424 @_spi ( Experimental) public var syntax : SyntaxProtocol {
2525 switch self {
2626 case . identifier( let syntax, _) :
27- syntax
28- case . declaration( let syntax, _ ) :
29- syntax
27+ return syntax
28+ case . declaration( let syntax) :
29+ return syntax
3030 }
3131 }
3232
3333 /// Introduced name.
3434 @_spi ( Experimental) public var identifier : Identifier ? {
3535 switch self {
3636 case . identifier( let syntax, _) :
37- Identifier ( syntax. identifier)
38- case . declaration( let syntax, _ ) :
39- Identifier ( syntax. name)
37+ return Identifier ( syntax. identifier)
38+ case . declaration( let syntax) :
39+ return Identifier ( syntax. name)
4040 }
4141 }
4242
4343 /// Point, after which the name is available in scope.
4444 /// If set to `nil`, the name is available at any point in scope.
4545 var accessibleAfter : AbsolutePosition ? {
4646 switch self {
47- case . identifier( _, let absolutePosition) , . declaration( _, let absolutePosition) :
48- absolutePosition
47+ case . identifier( _, let absolutePosition) :
48+ return absolutePosition
49+ default :
50+ return nil
4951 }
5052 }
5153
@@ -61,62 +63,78 @@ import SwiftSyntax
6163 return name == lookedUpName
6264 }
6365
64- /// Extracts names introduced by the given `from` structure.
65- static func getNames( from syntax: SyntaxProtocol , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ] {
66+ /// Extracts names introduced by the given `syntax` structure.
67+ ///
68+ /// When e.g. looking up a variable declaration like `let a = a`,
69+ /// we expect `a` to be visible after the whole declaration.
70+ /// That's why we can't just use `syntax.endPosition` for the `a` identifier pattern,
71+ /// as the name would already be visible at the `a` reference withing the declaration.
72+ /// That’s why code block and file scopes have to set
73+ /// `accessibleAfter` to be the end position of the entire declaration syntax node.
74+ static func getNames(
75+ from syntax: SyntaxProtocol ,
76+ accessibleAfter: AbsolutePosition ? = nil
77+ ) -> [ LookupName ] {
6678 switch Syntax ( syntax) . as ( SyntaxEnum . self) {
6779 case . variableDecl( let variableDecl) :
68- variableDecl. bindings. flatMap { binding in
69- getNames ( from: binding. pattern, accessibleAfter: accessibleAfter)
80+ return variableDecl. bindings. flatMap { binding in
81+ getNames (
82+ from: binding. pattern,
83+ accessibleAfter: accessibleAfter != nil ? binding. endPositionBeforeTrailingTrivia : nil
84+ )
7085 }
7186 case . tuplePattern( let tuplePattern) :
72- tuplePattern. elements. flatMap { tupleElement in
87+ return tuplePattern. elements. flatMap { tupleElement in
7388 getNames ( from: tupleElement. pattern, accessibleAfter: accessibleAfter)
7489 }
7590 case . valueBindingPattern( let valueBindingPattern) :
76- getNames ( from: valueBindingPattern. pattern, accessibleAfter: accessibleAfter)
91+ return getNames ( from: valueBindingPattern. pattern, accessibleAfter: accessibleAfter)
7792 case . expressionPattern( let expressionPattern) :
78- getNames ( from: expressionPattern. expression, accessibleAfter: accessibleAfter)
93+ return getNames ( from: expressionPattern. expression, accessibleAfter: accessibleAfter)
7994 case . sequenceExpr( let sequenceExpr) :
80- sequenceExpr. elements. flatMap { expression in
95+ return sequenceExpr. elements. flatMap { expression in
8196 getNames ( from: expression, accessibleAfter: accessibleAfter)
8297 }
8398 case . patternExpr( let patternExpr) :
84- getNames ( from: patternExpr. pattern, accessibleAfter: accessibleAfter)
99+ return getNames ( from: patternExpr. pattern, accessibleAfter: accessibleAfter)
85100 case . optionalBindingCondition( let optionalBinding) :
86- getNames ( from: optionalBinding. pattern, accessibleAfter: accessibleAfter)
101+ return getNames ( from: optionalBinding. pattern, accessibleAfter: accessibleAfter)
87102 case . matchingPatternCondition( let matchingPatternCondition) :
88- getNames ( from: matchingPatternCondition. pattern, accessibleAfter: accessibleAfter)
103+ return getNames ( from: matchingPatternCondition. pattern, accessibleAfter: accessibleAfter)
89104 case . functionCallExpr( let functionCallExpr) :
90- functionCallExpr. arguments. flatMap { argument in
105+ return functionCallExpr. arguments. flatMap { argument in
91106 getNames ( from: argument. expression, accessibleAfter: accessibleAfter)
92107 }
93108 case . guardStmt( let guardStmt) :
94- guardStmt. conditions. flatMap { cond in
109+ return guardStmt. conditions. flatMap { cond in
95110 getNames ( from: cond. condition, accessibleAfter: cond. endPosition)
96111 }
97112 default :
98113 if let namedDecl = Syntax ( syntax) . asProtocol ( SyntaxProtocol . self) as? NamedDeclSyntax {
99- handle ( namedDecl: namedDecl, accessibleAfter: accessibleAfter)
114+ return handle ( namedDecl: namedDecl, accessibleAfter: accessibleAfter)
100115 } else if let identifiable = Syntax ( syntax) . asProtocol ( SyntaxProtocol . self) as? IdentifiableSyntax {
101- handle ( identifiable: identifiable, accessibleAfter: accessibleAfter)
116+ return handle ( identifiable: identifiable, accessibleAfter: accessibleAfter)
102117 } else {
103- [ ]
118+ return [ ]
104119 }
105120 }
106121 }
107122
108123 /// Extracts name introduced by `IdentifiableSyntax` node.
109124 private static func handle( identifiable: IdentifiableSyntax , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ]
110125 {
111- if identifiable. identifier. text != " _ " {
126+ if identifiable. identifier. tokenKind != . wildcard {
112127 return [ . identifier( identifiable, accessibleAfter: accessibleAfter) ]
113128 } else {
114129 return [ ]
115130 }
116131 }
117132
118133 /// Extracts name introduced by `NamedDeclSyntax` node.
119- private static func handle( namedDecl: NamedDeclSyntax , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ] {
120- [ . declaration( namedDecl, accessibleAfter: accessibleAfter) ]
134+ private static func handle(
135+ namedDecl: NamedDeclSyntax ,
136+ accessibleAfter: AbsolutePosition ? = nil
137+ ) -> [ LookupName ] {
138+ [ . declaration( namedDecl) ]
121139 }
122140}
0 commit comments