Skip to content

Commit fae4d0e

Browse files
committed
Fix ordering of implicit self introduction by subscript accessors.
1 parent 7521e4e commit fae4d0e

File tree

1 file changed

+85
-10
lines changed

1 file changed

+85
-10
lines changed

Sources/SwiftLexicalLookup/Scopes/ScopeImplementations.swift

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ import SwiftSyntax
112112
at lookUpPosition: AbsolutePosition,
113113
with config: LookupConfig
114114
) -> [LookupResult] {
115-
guard config.includeMembers else { return [] }
116-
117115
switch config.fileScopeHandling {
118116
case .memberBlock:
117+
guard config.includeMembers else { return [] }
118+
119119
let names = introducedNames(using: .memberBlock)
120120
.filter { lookupName in
121121
checkIdentifier(identifier, refersTo: lookupName, at: lookUpPosition)
@@ -150,7 +150,7 @@ import SwiftSyntax
150150
with: config
151151
)
152152

153-
return (members.isEmpty ? [] : [.fromFileScope(self, withNames: members)]) + sequentialNames
153+
return (members.isEmpty || !config.includeMembers ? [] : [.fromFileScope(self, withNames: members)]) + sequentialNames
154154
}
155155
}
156156
}
@@ -522,16 +522,38 @@ import SwiftSyntax
522522
}
523523
}
524524

525-
if let parentScope, parentScope.is(AccessorBlockSyntax.self) {
526-
return names + [.implicit(.self(self))]
527-
} else {
528-
return names
529-
}
525+
return names
530526
}
531527

532528
@_spi(Experimental) public var scopeDebugName: String {
533529
"AccessorDeclScope"
534530
}
531+
532+
/// Returns result with matching names from
533+
/// this scope and passes result with implicit `self`
534+
/// to be introduced after the `subscript`
535+
/// declaration scope grandparent.
536+
@_spi(Experimental) public func lookup(
537+
_ identifier: Identifier?,
538+
at lookUpPosition: AbsolutePosition,
539+
with config: LookupConfig
540+
) -> [LookupResult] {
541+
guard let parentAccessorBlockScope = parentScope?.as(AccessorBlockSyntax.self) else {
542+
return defaultLookupImplementation(identifier, at: lookUpPosition, with: config)
543+
}
544+
545+
return defaultLookupImplementation(
546+
identifier,
547+
at: lookUpPosition,
548+
with: config,
549+
propagateToParent: false
550+
) + parentAccessorBlockScope.interleaveAccessorResultsAfterSubscriptLookup(
551+
identifier,
552+
at: lookUpPosition,
553+
with: config,
554+
resultsToInterleave: [.fromScope(self, withNames: [.implicit(.self(self))])]
555+
)
556+
}
535557
}
536558

537559
@_spi(Experimental) extension CatchClauseSyntax: ScopeSyntax {
@@ -584,7 +606,7 @@ import SwiftSyntax
584606
with: config,
585607
propagateToParent: false
586608
) + (filteredNamesFromLabel.isEmpty ? [] : [.fromScope(self, withNames: filteredNamesFromLabel)])
587-
+ lookupInParent(identifier, at: lookUpPosition, with: config)
609+
+ (config.finishInSequentialScope ? [] : lookupInParent(identifier, at: lookUpPosition, with: config))
588610
}
589611
}
590612

@@ -713,6 +735,39 @@ import SwiftSyntax
713735
_ identifier: Identifier?,
714736
at lookUpPosition: AbsolutePosition,
715737
with config: LookupConfig
738+
) -> [LookupResult] {
739+
interleaveResultsAfterThisSubscriptLookup(
740+
identifier,
741+
at: lookUpPosition,
742+
with: config,
743+
resultsToInterleave: []
744+
)
745+
}
746+
747+
/// Lookup names in this scope and add `resultsToInterleave`
748+
/// after results from this scope.
749+
///
750+
/// It's used to handle implicit `self` introduction
751+
/// at the boundaries of accessors in this subscript.
752+
/// ```swift
753+
/// class X {
754+
/// subscript(self: Int) -> Int {
755+
/// get {
756+
/// self // <-- lookup here
757+
/// }
758+
/// }
759+
/// }
760+
/// ```
761+
/// In this case, the `self` reference references the `self`
762+
/// function parameter which shadows implicit `self`
763+
/// introduced at the boundary of the getter. That's why
764+
/// this function needs to ensure the implicit `self` passed
765+
/// from inside the accessor block is added after `subscript` parameters.
766+
func interleaveResultsAfterThisSubscriptLookup(
767+
_ identifier: Identifier?,
768+
at lookUpPosition: AbsolutePosition,
769+
with config: LookupConfig,
770+
resultsToInterleave: [LookupResult]
716771
) -> [LookupResult] {
717772
var thisScopeResults: [LookupResult] = []
718773

@@ -725,7 +780,7 @@ import SwiftSyntax
725780
)
726781
}
727782

728-
return thisScopeResults
783+
return thisScopeResults + resultsToInterleave
729784
+ lookupThroughGenericParameterScope(
730785
identifier,
731786
at: lookUpPosition,
@@ -767,6 +822,26 @@ import SwiftSyntax
767822
return lookupInParent(identifier, at: lookUpPosition, with: config)
768823
}
769824
}
825+
826+
/// Used by children accessors to interleave
827+
/// their results with parent `subscript` declaration scope.
828+
func interleaveAccessorResultsAfterSubscriptLookup(
829+
_ identifier: Identifier?,
830+
at lookUpPosition: AbsolutePosition,
831+
with config: LookupConfig,
832+
resultsToInterleave: [LookupResult]
833+
) -> [LookupResult] {
834+
guard let parentSubscriptScope = parentScope?.as(SubscriptDeclSyntax.self) else {
835+
return lookupInParent(identifier, at: lookUpPosition, with: config)
836+
}
837+
838+
return parentSubscriptScope.interleaveResultsAfterThisSubscriptLookup(
839+
identifier,
840+
at: lookUpPosition,
841+
with: config,
842+
resultsToInterleave: resultsToInterleave
843+
)
844+
}
770845
}
771846

772847
@_spi(Experimental) extension TypeAliasDeclSyntax: WithGenericParametersScopeSyntax {

0 commit comments

Comments
 (0)