Skip to content

Commit 862b526

Browse files
committed
Fix ordering of closure capture names and filtering of names in switch case and variable declaration scopes.
1 parent 3c0ee18 commit 862b526

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

Sources/SwiftLexicalLookup/LookupName.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ import SwiftSyntax
103103
?? subscriptDecl.endPositionBeforeTrailingTrivia
104104
case .variableDecl(let variableDecl):
105105
return variableDecl.bindings.first?.accessorBlock?.positionAfterSkippingLeadingTrivia
106-
?? variableDecl.endPosition
106+
?? variableDecl.bindings.positionAfterSkippingLeadingTrivia
107107
case .accessorDecl(let accessorDecl):
108108
return accessorDecl.accessorSpecifier.positionAfterSkippingLeadingTrivia
109109
case .deinitializerDecl(let deinitializerDecl):
@@ -139,14 +139,14 @@ import SwiftSyntax
139139
case implicit(ImplicitDecl)
140140
/// Dollar identifier introduced by a closure without parameters.
141141
case dollarIdentifier(ClosureExprSyntax, strRepresentation: String)
142-
/// Equivalent identifiers grouped together.
143-
/// The associated array of names is always non-empty.
142+
/// Represents equivalent identifiers grouped together.
143+
/// - Important: The array should be non-empty.
144144
///
145145
/// ### Example:
146146
/// ```swift
147-
/// switch x {
148-
/// case .a(let smth), .b(let smth):
149-
/// print(smth) // <-- lookup here
147+
/// switch X {
148+
/// case .a(let x), .b(let x):
149+
/// print(x) // <-- lookup here
150150
/// }
151151
/// ```
152152
/// For lookup at the given position, the result

Sources/SwiftLexicalLookup/Scopes/ScopeImplementations.swift

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ import SwiftSyntax
144144

145145
/// Capture, parameter and body names introduced in this scope.
146146
@_spi(Experimental) public var defaultIntroducedNames: [LookupName] {
147-
captureNames + parameterNames + introducedNamesInBody
147+
parameterNames + captureNames + introducedNamesInBody
148148
}
149149

150150
@_spi(Experimental) public var scopeDebugName: String {
@@ -202,7 +202,7 @@ import SwiftSyntax
202202
} else {
203203
signatureResults = LookupResult.getResultArray(
204204
for: self,
205-
withNames: (captureNames + parameterNames).filter { name in
205+
withNames: (parameterNames + captureNames).filter { name in
206206
checkIdentifier(identifier, refersTo: name, at: lookUpPosition)
207207
}
208208
)
@@ -638,7 +638,7 @@ import SwiftSyntax
638638
checkIdentifier(identifier, refersTo: name, at: lookUpPosition)
639639
}
640640

641-
if label.range.contains(lookUpPosition) {
641+
if label.range.contains(lookUpPosition) && !isInWhereClause(lookUpPosition: lookUpPosition) {
642642
return config.finishInSequentialScope ? [] : lookupInParent(identifier, at: lookUpPosition, with: config)
643643
} else if config.finishInSequentialScope {
644644
return sequentialLookup(
@@ -660,6 +660,20 @@ import SwiftSyntax
660660
+ lookupInParent(identifier, at: lookUpPosition, with: config)
661661
}
662662
}
663+
664+
/// Returns `true` if `lookUpPosition` is inside a `where`
665+
/// clause associated with one of the case items of this scope.
666+
private func isInWhereClause(lookUpPosition: AbsolutePosition) -> Bool {
667+
guard let switchCaseItemList = label.as(SwitchCaseLabelSyntax.self)?.caseItems else { return false }
668+
669+
for item in switchCaseItemList {
670+
if item.whereClause?.range.contains(lookUpPosition) ?? false {
671+
return true
672+
}
673+
}
674+
675+
return false
676+
}
663677
}
664678

665679
@_spi(Experimental) extension ProtocolDeclSyntax: ScopeSyntax, LookInMembersScopeSyntax {
@@ -934,7 +948,9 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
934948
at lookUpPosition: AbsolutePosition,
935949
with config: LookupConfig
936950
) -> [LookupResult] {
937-
if bindings.first?.accessorBlock?.range.contains(lookUpPosition) ?? false {
951+
if (bindings.first?.accessorBlock?.range.contains(lookUpPosition) ?? false)
952+
|| shouldIntroduceSelfIfLazy(lookUpPosition: lookUpPosition)
953+
{
938954
return defaultLookupImplementation(
939955
in: (isMember ? [.implicit(.self(self))] : LookupName.getNames(from: self)),
940956
identifier,
@@ -960,6 +976,16 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
960976

961977
return resultsToInterleave + lookupInParent(identifier, at: lookUpPosition, with: config)
962978
}
979+
980+
/// Returns `true`, if `lookUpPosition` is in initializer of
981+
/// this variable declaration and the declaration is lazy.
982+
private func shouldIntroduceSelfIfLazy(lookUpPosition: AbsolutePosition) -> Bool {
983+
guard bindings.first?.initializer?.range.contains(lookUpPosition) ?? false else { return false }
984+
985+
return modifiers.contains {
986+
$0.name.tokenKind == .keyword(.lazy)
987+
}
988+
}
963989
}
964990

965991
@_spi(Experimental) extension DeinitializerDeclSyntax: ScopeSyntax {

0 commit comments

Comments
 (0)