Skip to content

Commit 8b5fbd2

Browse files
committed
Separate lookup state from config.
1 parent c31046a commit 8b5fbd2

File tree

6 files changed

+74
-36
lines changed

6 files changed

+74
-36
lines changed

Sources/SwiftLexicalLookup/Configurations/LookupConfig.swift

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,9 @@ import Foundation
1717
/// `memberBlockUpToLastDecl` by default.
1818
public var fileScopeHandling: FileScopeHandlingConfig
1919

20-
/// Specifies scopes that introduce names to their parent and
21-
/// should be skipped during lookup in sequential scopes.
22-
public var ignoreChildrenToSequentialParentIntroductionsFrom: [IntroducingToSequentialParentScopeSyntax]
23-
2420
public init(
25-
fileScopeHandling: FileScopeHandlingConfig = .memberBlockUpToLastDecl,
26-
ignoreChildrenToSequentialParentIntroductionsFrom: [IntroducingToSequentialParentScopeSyntax] = []
21+
fileScopeHandling: FileScopeHandlingConfig = .memberBlockUpToLastDecl
2722
) {
2823
self.fileScopeHandling = fileScopeHandling
29-
self.ignoreChildrenToSequentialParentIntroductionsFrom = ignoreChildrenToSequentialParentIntroductionsFrom
3024
}
3125
}

Sources/SwiftLexicalLookup/IntroducingToSequentialParentScopeSyntax.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import SwiftSyntax
1818
func introducesToSequentialParent(
1919
for name: String?,
2020
at syntax: SyntaxProtocol,
21-
with config: LookupConfig
21+
with config: LookupConfig,
22+
state: LookupState
2223
) -> [LookupResult]
2324
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
@_spi(Experimental) public struct LookupState {
16+
/// Specifies scopes that introduce names to their parent and
17+
/// should be skipped during lookup in sequential scopes.
18+
var skipSequentialIntroductionFrom: IntroducingToSequentialParentScopeSyntax?
19+
20+
@_spi(Experimental) public init() {}
21+
}

Sources/SwiftLexicalLookup/ScopeImplementations.swift

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ extension SyntaxProtocol {
103103
public func lookup(
104104
for name: String?,
105105
at syntax: SyntaxProtocol,
106-
with config: LookupConfig
106+
with config: LookupConfig,
107+
state: LookupState
107108
) -> [LookupResult] {
108109
switch config.fileScopeHandling {
109110
case .codeBlock:
@@ -112,6 +113,7 @@ extension SyntaxProtocol {
112113
for: name,
113114
at: syntax,
114115
with: config,
116+
state: state,
115117
createResultsForThisScopeWith: { .fromFileScope(self, withNames: $0) }
116118
)
117119
case .memberBlock:
@@ -148,6 +150,7 @@ extension SyntaxProtocol {
148150
for: name,
149151
at: syntax,
150152
with: config,
153+
state: state,
151154
createResultsForThisScopeWith: { .fromFileScope(self, withNames: $0) }
152155
)
153156

@@ -165,18 +168,24 @@ extension SyntaxProtocol {
165168
}
166169
}
167170

168-
public func lookup(for name: String?, at syntax: SyntaxProtocol, with config: LookupConfig) -> [LookupResult] {
171+
public func lookup(
172+
for name: String?,
173+
at syntax: SyntaxProtocol,
174+
with config: LookupConfig,
175+
state: LookupState
176+
) -> [LookupResult] {
169177
sequentialLookup(
170178
in: statements,
171179
for: name,
172180
at: syntax,
173181
with: config,
182+
state: state,
174183
createResultsForThisScopeWith: { .fromScope(self, withNames: $0) }
175184
)
176185
}
177186
}
178187

179-
@_spi(Experimental) extension ForStmtSyntax: ScopeSyntax {
188+
@_spi(Experimental) extension ForStmtSyntax: ScopeSyntax {
180189
/// Names introduced in the `for` body.
181190
public var introducedNames: [LookupName] {
182191
LookupName.getNames(from: pattern)
@@ -290,12 +299,13 @@ extension SyntaxProtocol {
290299
public func lookup(
291300
for name: String?,
292301
at syntax: SyntaxProtocol,
293-
with config: LookupConfig
302+
with config: LookupConfig,
303+
state: LookupState
294304
) -> [LookupResult] {
295305
if let elseBody, elseBody.position <= syntax.position, elseBody.endPosition >= syntax.position {
296-
lookupInParent(for: name, at: syntax, with: config)
306+
lookupInParent(for: name, at: syntax, with: config, state: state)
297307
} else {
298-
defaultLookupImplementation(for: name, at: syntax, with: config)
308+
defaultLookupImplementation(for: name, at: syntax, with: config, state: state)
299309
}
300310
}
301311
}
@@ -313,7 +323,8 @@ extension SyntaxProtocol {
313323
public func introducesToSequentialParent(
314324
for name: String?,
315325
at syntax: SwiftSyntax.SyntaxProtocol,
316-
with config: LookupConfig
326+
with config: LookupConfig,
327+
state: LookupState
317328
) -> [LookupResult] {
318329
let names = conditions.flatMap { element in
319330
LookupName.getNames(from: element.condition, accessibleAfter: element.endPosition)
@@ -342,14 +353,15 @@ extension SyntaxProtocol {
342353
public func lookup(
343354
for name: String?,
344355
at syntax: SyntaxProtocol,
345-
with config: LookupConfig
356+
with config: LookupConfig,
357+
state: LookupState
346358
) -> [LookupResult] {
347359
if body.position <= syntax.position && body.endPosition >= syntax.position {
348-
var newConfig = config
349-
newConfig.ignoreChildrenToSequentialParentIntroductionsFrom.append(self)
350-
return lookupInParent(for: name, at: syntax, with: newConfig)
360+
var newState = state
361+
newState.skipSequentialIntroductionFrom = self
362+
return lookupInParent(for: name, at: syntax, with: config, state: newState)
351363
} else {
352-
return defaultLookupImplementation(for: name, at: syntax, with: config)
364+
return defaultLookupImplementation(for: name, at: syntax, with: config, state: state)
353365
}
354366
}
355367
}

Sources/SwiftLexicalLookup/ScopeSyntax.swift

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ extension SyntaxProtocol {
4747
for name: String?,
4848
with config: LookupConfig = LookupConfig()
4949
) -> [LookupResult] {
50-
scope?.lookup(for: name, at: self, with: config) ?? []
50+
scope?.lookup(for: name, at: self, with: config, state: LookupState()) ?? []
5151
}
5252
}
5353

@@ -58,7 +58,10 @@ extension SyntaxProtocol {
5858
var introducedNames: [LookupName] { get }
5959
/// Finds all declarations `name` refers to. `at` specifies the node lookup was triggered with.
6060
/// If `name` set to `nil`, returns all available names at the given node.
61-
func lookup(for name: String?, at syntax: SyntaxProtocol, with config: LookupConfig) -> [LookupResult]
61+
func lookup(for name: String?,
62+
at syntax: SyntaxProtocol,
63+
with config: LookupConfig,
64+
state: LookupState) -> [LookupResult]
6265
}
6366

6467
@_spi(Experimental) extension ScopeSyntax {
@@ -72,9 +75,10 @@ extension SyntaxProtocol {
7275
public func lookup(
7376
for name: String?,
7477
at syntax: SyntaxProtocol,
75-
with config: LookupConfig
78+
with config: LookupConfig,
79+
state: LookupState
7680
) -> [LookupResult] {
77-
defaultLookupImplementation(for: name, at: syntax, with: config)
81+
defaultLookupImplementation(for: name, at: syntax, with: config, state: state)
7882
}
7983

8084
/// Returns `LookupResult` of all names introduced in this scope that `name`
@@ -83,7 +87,8 @@ extension SyntaxProtocol {
8387
func defaultLookupImplementation(
8488
for name: String?,
8589
at syntax: SyntaxProtocol,
86-
with config: LookupConfig
90+
with config: LookupConfig,
91+
state: LookupState
8792
) -> [LookupResult] {
8893
let filteredNames =
8994
introducedNames
@@ -92,19 +97,20 @@ extension SyntaxProtocol {
9297
}
9398

9499
if filteredNames.isEmpty {
95-
return lookupInParent(for: name, at: syntax, with: config)
100+
return lookupInParent(for: name, at: syntax, with: config, state: state)
96101
} else {
97-
return [.fromScope(self, withNames: filteredNames)] + lookupInParent(for: name, at: syntax, with: config)
102+
return [.fromScope(self, withNames: filteredNames)] + lookupInParent(for: name, at: syntax, with: config, state: state)
98103
}
99104
}
100105

101106
/// Looks up in parent scope.
102107
func lookupInParent(
103108
for name: String?,
104109
at syntax: SyntaxProtocol,
105-
with config: LookupConfig
110+
with config: LookupConfig,
111+
state: LookupState
106112
) -> [LookupResult] {
107-
parentScope?.lookup(for: name, at: syntax, with: config) ?? []
113+
parentScope?.lookup(for: name, at: syntax, with: config, state: state) ?? []
108114
}
109115

110116
func does(name: String?, referTo introducedName: LookupName, at syntax: SyntaxProtocol) -> Bool {

Sources/SwiftLexicalLookup/SequentialScopeSyntax.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import SwiftSyntax
2424
for name: String?,
2525
at syntax: SyntaxProtocol,
2626
with config: LookupConfig,
27+
state: LookupState,
2728
createResultsForThisScopeWith getResults: ([LookupName]) -> (LookupResult)
2829
) -> [LookupResult]
2930
}
@@ -34,6 +35,7 @@ import SwiftSyntax
3435
for name: String?,
3536
at syntax: SyntaxProtocol,
3637
with config: LookupConfig,
38+
state: LookupState,
3739
createResultsForThisScopeWith getResults: ([LookupName]) -> (LookupResult)
3840
) -> [LookupResult] {
3941
var result = [LookupResult]()
@@ -43,23 +45,24 @@ import SwiftSyntax
4345
if let introducingToParentScope = Syntax(codeBlockItem.item).asProtocol(SyntaxProtocol.self)
4446
as? IntroducingToSequentialParentScopeSyntax
4547
{
46-
guard
47-
!config.ignoreChildrenToSequentialParentIntroductionsFrom.contains(where: {
48-
$0.id == introducingToParentScope.id
49-
})
50-
else {
48+
// Check if the enocountered scope should be ignored.
49+
if let scopeToSkip = state.skipSequentialIntroductionFrom,
50+
scopeToSkip.id == introducingToParentScope.id {
5151
continue
5252
}
5353

54+
// If there are some names collected, create a new result for this scope.
5455
if !currentChunk.isEmpty {
5556
result.append(getResults(currentChunk))
5657
currentChunk = []
5758
}
5859

60+
// Add names introduced by the encountered scope.
5961
result.append(
60-
contentsOf: introducingToParentScope.introducesToSequentialParent(for: name, at: syntax, with: config)
62+
contentsOf: introducingToParentScope.introducesToSequentialParent(for: name, at: syntax, with: config, state: state)
6163
)
6264
} else {
65+
// Extract new names from encountered node.
6366
currentChunk.append(
6467
contentsOf:
6568
LookupName.getNames(
@@ -72,11 +75,12 @@ import SwiftSyntax
7275
}
7376
}
7477

78+
// If there are some names collected, create a new result for this scope.
7579
if !currentChunk.isEmpty {
7680
result.append(getResults(currentChunk))
7781
currentChunk = []
7882
}
7983

80-
return (result.isEmpty ? [] : result.reversed()) + lookupInParent(for: name, at: syntax, with: config)
84+
return (result.isEmpty ? [] : result.reversed()) + lookupInParent(for: name, at: syntax, with: config, state: state)
8185
}
8286
}

0 commit comments

Comments
 (0)