Skip to content

Commit 0aaea2a

Browse files
committed
Switch ConfiguredRegions.isActive(_:) to a binary search
1 parent 98aeb44 commit 0aaea2a

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

Sources/SwiftIfConfig/ConfiguredRegions.swift

+29-7
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,41 @@ public struct ConfiguredRegions {
4444

4545
/// Determine whether the given syntax node is active within the configured
4646
/// regions.
47+
///
48+
/// Any given node within the range of configured regions can either be
49+
/// "active" (it is part of the program), "inactive" (it is not part of the
50+
/// program), or "unparsed" (it is not part of the program and shouldn't
51+
/// produce any syntax errors).
52+
///
53+
/// This operation takes time that is logarthmic in the number of regions
54+
/// in the syntax tree.
4755
public func isActive(_ node: some SyntaxProtocol) -> IfConfigRegionState {
48-
var currentState: IfConfigRegionState = .active
49-
for (ifClause, state) in regions {
50-
if node.position < ifClause.position {
51-
return currentState
56+
// Find the slice of the regions in which this node lands.
57+
var currentSlice = regions[...]
58+
while !currentSlice.isEmpty {
59+
let middle = currentSlice.startIndex + currentSlice.count / 2
60+
61+
// If the node is prior to the start of the middle, take the left-hand side.
62+
if node.position < currentSlice[middle].0.regionStart {
63+
currentSlice = currentSlice[..<middle]
64+
continue
5265
}
5366

54-
if node.position >= ifClause.regionStart && node.position <= ifClause.endPosition {
55-
currentState = state
67+
// If the node is after the end of the middle, take the right-hand side.
68+
if node.position > currentSlice[middle].0.endPosition {
69+
currentSlice = currentSlice[(middle + 1)...]
70+
continue
5671
}
72+
73+
// We cannot narrow the range any further.
74+
break
5775
}
5876

59-
return currentState
77+
// Find the last region in which this node lands. If there is no such
78+
// region, this is active.
79+
return currentSlice.last { region in
80+
node.position >= region.0.regionStart && node.position <= region.0.endPosition
81+
}?.1 ?? .active
6082
}
6183
}
6284

0 commit comments

Comments
 (0)