Skip to content

Commit cd64938

Browse files
CodaFiHarlan
authored andcommitted
Provide an explicit iterator for SyntaxCollection (#13112)
The default IndexingIterator for a custom collection is not suitable for subclasses that specialize the element type the way libSyntax does. Overriding it with a more specific iterator, even with something like covariant overrides, would not work because it the iterator is generic over its base collection, not its element type. Provide a custom iterator parameterized by the element type instead.
1 parent 384c198 commit cd64938

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

tools/SwiftSyntax/SyntaxCollection.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ public class SyntaxCollection<SyntaxElement: Syntax>: Syntax {
9999
newLayout.removeLast()
100100
return replacingLayout(newLayout)
101101
}
102+
103+
/// Returns an iterator over the elements of this syntax collection.
104+
public func makeIterator() -> SyntaxCollectionIterator<SyntaxElement> {
105+
return SyntaxCollectionIterator(collection: self)
106+
}
102107
}
103108

104109
/// Conformance for SyntaxCollection to the Collection protocol.
@@ -118,4 +123,28 @@ extension SyntaxCollection: Collection {
118123
public subscript(_ index: Int) -> SyntaxElement {
119124
return child(at: index)! as! SyntaxElement
120125
}
121-
}
126+
}
127+
128+
/// A type that iterates over a syntax collection using its indices.
129+
public struct SyntaxCollectionIterator<Element: Syntax>: IteratorProtocol {
130+
private let collection: SyntaxCollection<Element>
131+
private var index: SyntaxCollection<Element>.Index
132+
133+
fileprivate init(collection: SyntaxCollection<Element>) {
134+
self.collection = collection
135+
self.index = collection.startIndex
136+
}
137+
138+
public mutating func next() -> Element? {
139+
guard
140+
!(self.collection.isEmpty || self.index == self.collection.endIndex)
141+
else {
142+
return nil
143+
}
144+
145+
let result = collection[index]
146+
collection.formIndex(after: &index)
147+
return result
148+
}
149+
}
150+

0 commit comments

Comments
 (0)