mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* [SwiftSyntax] Add replace method SyntaxCollections * Change replaceSubrange method call to subscript setter call * [SwiftSyntax] Add test for SyntaxCollections * Fix mistakes in SyntaxCollections tests * Use syntax's raw value instead of syntax itself in replacing method * Update SyntaxCollections tests
198 lines
6.6 KiB
Swift
198 lines
6.6 KiB
Swift
%{
|
|
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..<newLayout.endIndex).contains(index),
|
|
"replacing node at invalid index \(index)")
|
|
newLayout[index] = syntax.raw
|
|
return replacingLayout(newLayout)
|
|
}
|
|
|
|
/// Creates a new `${node.name}` by removing the syntax element at the
|
|
/// provided index.
|
|
///
|
|
/// - Parameter index: The index of the element to remove from the collection.
|
|
/// - Returns: A new `${node.name}` with the element at the provided index
|
|
/// removed.
|
|
public func removing(childAt index: Int) -> ${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
|