@@ -14,38 +14,40 @@ import SwiftSyntax
14
14
15
15
@_spi ( Experimental) public enum LookupName {
16
16
/// 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.
18
18
case identifier( IdentifiableSyntax , accessibleAfter: AbsolutePosition ? )
19
19
/// 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 )
22
22
23
23
/// Syntax associated with this name.
24
24
@_spi ( Experimental) public var syntax : SyntaxProtocol {
25
25
switch self {
26
26
case . identifier( let syntax, _) :
27
- syntax
28
- case . declaration( let syntax, _ ) :
29
- syntax
27
+ return syntax
28
+ case . declaration( let syntax) :
29
+ return syntax
30
30
}
31
31
}
32
32
33
33
/// Introduced name.
34
34
@_spi ( Experimental) public var identifier : Identifier ? {
35
35
switch self {
36
36
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)
40
40
}
41
41
}
42
42
43
43
/// Point, after which the name is available in scope.
44
44
/// If set to `nil`, the name is available at any point in scope.
45
45
var accessibleAfter : AbsolutePosition ? {
46
46
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
49
51
}
50
52
}
51
53
@@ -61,62 +63,78 @@ import SwiftSyntax
61
63
return name == lookedUpName
62
64
}
63
65
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 ] {
66
78
switch Syntax ( syntax) . as ( SyntaxEnum . self) {
67
79
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
+ )
70
85
}
71
86
case . tuplePattern( let tuplePattern) :
72
- tuplePattern. elements. flatMap { tupleElement in
87
+ return tuplePattern. elements. flatMap { tupleElement in
73
88
getNames ( from: tupleElement. pattern, accessibleAfter: accessibleAfter)
74
89
}
75
90
case . valueBindingPattern( let valueBindingPattern) :
76
- getNames ( from: valueBindingPattern. pattern, accessibleAfter: accessibleAfter)
91
+ return getNames ( from: valueBindingPattern. pattern, accessibleAfter: accessibleAfter)
77
92
case . expressionPattern( let expressionPattern) :
78
- getNames ( from: expressionPattern. expression, accessibleAfter: accessibleAfter)
93
+ return getNames ( from: expressionPattern. expression, accessibleAfter: accessibleAfter)
79
94
case . sequenceExpr( let sequenceExpr) :
80
- sequenceExpr. elements. flatMap { expression in
95
+ return sequenceExpr. elements. flatMap { expression in
81
96
getNames ( from: expression, accessibleAfter: accessibleAfter)
82
97
}
83
98
case . patternExpr( let patternExpr) :
84
- getNames ( from: patternExpr. pattern, accessibleAfter: accessibleAfter)
99
+ return getNames ( from: patternExpr. pattern, accessibleAfter: accessibleAfter)
85
100
case . optionalBindingCondition( let optionalBinding) :
86
- getNames ( from: optionalBinding. pattern, accessibleAfter: accessibleAfter)
101
+ return getNames ( from: optionalBinding. pattern, accessibleAfter: accessibleAfter)
87
102
case . matchingPatternCondition( let matchingPatternCondition) :
88
- getNames ( from: matchingPatternCondition. pattern, accessibleAfter: accessibleAfter)
103
+ return getNames ( from: matchingPatternCondition. pattern, accessibleAfter: accessibleAfter)
89
104
case . functionCallExpr( let functionCallExpr) :
90
- functionCallExpr. arguments. flatMap { argument in
105
+ return functionCallExpr. arguments. flatMap { argument in
91
106
getNames ( from: argument. expression, accessibleAfter: accessibleAfter)
92
107
}
93
108
case . guardStmt( let guardStmt) :
94
- guardStmt. conditions. flatMap { cond in
109
+ return guardStmt. conditions. flatMap { cond in
95
110
getNames ( from: cond. condition, accessibleAfter: cond. endPosition)
96
111
}
97
112
default :
98
113
if let namedDecl = Syntax ( syntax) . asProtocol ( SyntaxProtocol . self) as? NamedDeclSyntax {
99
- handle ( namedDecl: namedDecl, accessibleAfter: accessibleAfter)
114
+ return handle ( namedDecl: namedDecl, accessibleAfter: accessibleAfter)
100
115
} else if let identifiable = Syntax ( syntax) . asProtocol ( SyntaxProtocol . self) as? IdentifiableSyntax {
101
- handle ( identifiable: identifiable, accessibleAfter: accessibleAfter)
116
+ return handle ( identifiable: identifiable, accessibleAfter: accessibleAfter)
102
117
} else {
103
- [ ]
118
+ return [ ]
104
119
}
105
120
}
106
121
}
107
122
108
123
/// Extracts name introduced by `IdentifiableSyntax` node.
109
124
private static func handle( identifiable: IdentifiableSyntax , accessibleAfter: AbsolutePosition ? = nil ) -> [ LookupName ]
110
125
{
111
- if identifiable. identifier. text != " _ " {
126
+ if identifiable. identifier. tokenKind != . wildcard {
112
127
return [ . identifier( identifiable, accessibleAfter: accessibleAfter) ]
113
128
} else {
114
129
return [ ]
115
130
}
116
131
}
117
132
118
133
/// 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) ]
121
139
}
122
140
}
0 commit comments