%{ from gyb_syntax_support import * # -*- mode: Swift -*- # Ignore the following admonition it applies to the resulting .swift file only }% //// Automatically Generated From SyntaxCollections.swift.gyb. //// Do Not Edit Directly! //===------------ SyntaxCollections.swift.gyb - Syntax Collection ---------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import Foundation % for node in SYNTAX_NODES: % if node.collection_element: /// `${node.name}` represents a collection of one or more /// `${node.collection_element_type}` nodes. ${node.name} behaves /// as a regular Swift collection, and has accessors that return new /// versions of the collection with different children. public struct ${node.name}: _SyntaxBase { let _root: SyntaxData unowned let _data: SyntaxData /// Creates a Syntax node from the provided root and data. internal init(root: SyntaxData, data: SyntaxData) { self._root = root self._data = data #if DEBUG validate() #endif } /// Creates a new `${node.name}` by replacing the underlying layout with /// a different set of raw syntax nodes. /// /// - Parameter layout: The new list of raw syntax nodes underlying this /// collection. /// - Returns: A new `${node.name}` with the new layout underlying it. internal func replacingLayout( _ layout: [RawSyntax?]) -> ${node.name} { let newRaw = data.raw.replacingLayout(layout) let (newRoot, newData) = data.replacingSelf(newRaw) return ${node.name}(root: newRoot, data: newData) } /// Creates a new `${node.name}` by appending the provided syntax element /// to the children. /// /// - Parameter syntax: The element to append. /// - Returns: A new `${node.name}` with that element appended to the end. public func appending( _ syntax: ${node.collection_element_type}) -> ${node.name} { var newLayout = data.raw.layout newLayout.append(syntax.raw) return replacingLayout(newLayout) } /// Creates a new `${node.name}` by prepending the provided syntax element /// to the children. /// /// - Parameter syntax: The element to prepend. /// - Returns: A new `${node.name}` with that element prepended to the /// beginning. public func prepending( _ syntax: ${node.collection_element_type}) -> ${node.name} { return inserting(syntax, at: 0) } /// Creates a new `${node.name}` by inserting the provided syntax element /// at the provided index in the children. /// /// - Parameters: /// - syntax: The element to insert. /// - index: The index at which to insert the element in the collection. /// /// - Returns: A new `${node.name}` with that element appended to the end. public func inserting(_ syntax: ${node.collection_element_type}, at index: Int) -> ${node.name} { var newLayout = data.raw.layout /// Make sure the index is a valid insertion index (0 to 1 past the end) precondition((newLayout.startIndex...newLayout.endIndex).contains(index), "inserting node at invalid index \(index)") newLayout.insert(syntax.raw, at: index) return replacingLayout(newLayout) } /// Creates a new `${node.name}` by replacing the syntax element /// at the provided index. /// /// - Parameters: /// - index: The index at which to replace the element in the collection. /// - syntax: The element to replace with. /// /// - Returns: A new `${node.name}` with the new element at the provided index. public func replacing(childAt index: Int, with syntax: ${node.collection_element_type}) -> ${node.name} { var newLayout = data.raw.layout /// Make sure the index is a valid index for replacing precondition((newLayout.startIndex.. ${node.name} { var newLayout = data.raw.layout newLayout.remove(at: index) return replacingLayout(newLayout) } /// Creates a new `${node.name}` by removing the first element. /// /// - Returns: A new `${node.name}` with the first element removed. public func removingFirst() -> ${node.name} { var newLayout = data.raw.layout newLayout.removeFirst() return replacingLayout(newLayout) } /// Creates a new `${node.name}` by removing the last element. /// /// - Returns: A new `${node.name}` with the last element removed. public func removingLast() -> ${node.name} { var newLayout = data.raw.layout newLayout.removeLast() return replacingLayout(newLayout) } /// Returns an iterator over the elements of this syntax collection. public func makeIterator() -> ${node.name}Iterator { return ${node.name}Iterator(collection: self) } } /// Conformance for `${node.name}`` to the Collection protocol. extension ${node.name}: Collection { public var startIndex: Int { return data.childCaches.startIndex } public var endIndex: Int { return data.childCaches.endIndex } public func index(after i: Int) -> Int { return data.childCaches.index(after: i) } public subscript(_ index: Int) -> ${node.collection_element_type} { % cast = '' if node.collection_element_type == 'Syntax' \ % else 'as! ' + node.collection_element_type return child(at: index)! ${cast} } } /// A type that iterates over a `${node.name}` using its indices. public struct ${node.name}Iterator: IteratorProtocol { public typealias Element = ${node.collection_element_type} private let collection: ${node.name} private var index: ${node.name}.Index fileprivate init(collection: ${node.name}) { 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 } } % end % end