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.
This commit is contained in:
Robert Widmann
2017-11-28 15:23:35 -05:00
committed by Harlan
parent 384c1985fe
commit cd64938e6b

View File

@@ -99,6 +99,11 @@ public class SyntaxCollection<SyntaxElement: Syntax>: Syntax {
newLayout.removeLast()
return replacingLayout(newLayout)
}
/// Returns an iterator over the elements of this syntax collection.
public func makeIterator() -> SyntaxCollectionIterator<SyntaxElement> {
return SyntaxCollectionIterator(collection: self)
}
}
/// Conformance for SyntaxCollection to the Collection protocol.
@@ -118,4 +123,28 @@ extension SyntaxCollection: Collection {
public subscript(_ index: Int) -> SyntaxElement {
return child(at: index)! as! SyntaxElement
}
}
}
/// A type that iterates over a syntax collection using its indices.
public struct SyntaxCollectionIterator<Element: Syntax>: IteratorProtocol {
private let collection: SyntaxCollection<Element>
private var index: SyntaxCollection<Element>.Index
fileprivate init(collection: SyntaxCollection<Element>) {
self.collection = collection
self.index = collection.startIndex
}
public mutating func next() -> Element? {
guard
!(self.collection.isEmpty || self.index == self.collection.endIndex)
else {
return nil
}
let result = collection[index]
collection.formIndex(after: &index)
return result
}
}