Skip to content

Commit 5d10772

Browse files
committed
Replace most generated code in SyntaxCollections.swift by default protocol implementations
This has two advantages. 1. It reduces the amout of code in swift-syntax 2. It actually makes all the functions defined in every `SyntaxCollection` accessible for existentials or generics over `SyntaxCollection`.
1 parent 8a75944 commit 5d10772

File tree

5 files changed

+812
-10200
lines changed

5 files changed

+812
-10200
lines changed

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxCollectionsFile.swift

Lines changed: 2 additions & 304 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,10 @@ import SyntaxSupport
1616
import Utils
1717

1818
let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
19-
DeclSyntax(
20-
"""
21-
public protocol SyntaxCollection: SyntaxProtocol, Sequence where Element: SyntaxProtocol {
22-
/// Creates a new collection with the elements.
23-
init(_ children: [Element])
24-
/// The number of elements, `present` or `missing`, in this collection.
25-
var count: Int { get }
26-
}
27-
"""
28-
)
29-
30-
DeclSyntax(
31-
"""
32-
public extension SyntaxCollection {
33-
static var structure: SyntaxNodeStructure {
34-
return .collection(Element.self)
35-
}
36-
}
37-
"""
38-
)
39-
4019
for node in SYNTAX_NODES.compactMap(\.collectionNode) {
41-
let documentation =
42-
!node.documentation.isEmpty
43-
? node.documentation
44-
: """
45-
/// ``\(node.kind.syntaxType)`` represents a collection of one or more
46-
/// ``\(node.collectionElementType.syntaxBaseName)`` nodes. ``\(node.kind.syntaxType)`` behaves
47-
/// as a regular Swift collection, and has accessors that return new
48-
/// versions of the collection with different children.
49-
"""
50-
5120
try! StructDeclSyntax(
5221
"""
53-
\(raw: documentation)
22+
\(raw: node.documentation)
5423
public struct \(raw: node.kind.syntaxType): SyntaxCollection, SyntaxHashable
5524
"""
5625
) {
@@ -136,14 +105,6 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
136105

137106
DeclSyntax("public let _syntaxNode: Syntax")
138107

139-
DeclSyntax(
140-
"""
141-
private var layoutView: RawSyntaxLayoutView {
142-
data.raw.layoutView!
143-
}
144-
"""
145-
)
146-
147108
DeclSyntax(
148109
"""
149110
public init?(_ node: some SyntaxProtocol) {
@@ -153,270 +114,7 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
153114
"""
154115
)
155116

156-
DeclSyntax(
157-
"""
158-
/// Creates a Syntax node from the provided root and data. This assumes
159-
/// that the `SyntaxData` is of the correct kind. If it is not, the behaviour
160-
/// is undefined.
161-
internal init(_ data: SyntaxData) {
162-
precondition(data.raw.kind == .\(node.varOrCaseName))
163-
self._syntaxNode = Syntax(data)
164-
}
165-
"""
166-
)
167-
168-
DeclSyntax(
169-
"""
170-
public init(_ children: [Element]) {
171-
let data: SyntaxData = withExtendedLifetime(SyntaxArena()) { arena in
172-
let raw = RawSyntax.makeLayout(kind: SyntaxKind.\(node.varOrCaseName),
173-
from: children.map { $0.raw }, arena: arena)
174-
return SyntaxData.forRoot(raw)
175-
}
176-
self.init(data)
177-
}
178-
"""
179-
)
180-
181-
DeclSyntax(
182-
"""
183-
/// The number of elements, `present` or `missing`, in this collection.
184-
public var count: Int { return layoutView.children.count }
185-
"""
186-
)
187-
188-
DeclSyntax(
189-
"""
190-
/// Creates a new ``\(node.kind.syntaxType)`` by replacing the underlying layout with
191-
/// a different set of raw syntax nodes.
192-
///
193-
/// - Parameter layout: The new list of raw syntax nodes underlying this
194-
/// collection.
195-
/// - Returns: A new ``\(node.kind.syntaxType)`` with the new layout underlying it.
196-
internal func replacingLayout(_ layout: [RawSyntax?]) -> \(node.kind.syntaxType) {
197-
let arena = SyntaxArena()
198-
let newRaw = layoutView.replacingLayout(with: layout, arena: arena)
199-
let newData = data.replacingSelf(newRaw, arena: arena)
200-
return \(node.kind.syntaxType)(newData)
201-
}
202-
"""
203-
)
204-
205-
DeclSyntax(
206-
"""
207-
/// Creates a new ``\(node.kind.syntaxType)`` by appending the provided syntax element
208-
/// to the children.
209-
///
210-
/// - Parameter syntax: The element to append.
211-
/// - Returns: A new ``\(node.kind.syntaxType)`` with that element appended to the end.
212-
public func appending(_ syntax: Element) -> \(node.kind.syntaxType) {
213-
var newLayout = layoutView.formLayoutArray()
214-
newLayout.append(syntax.raw)
215-
return replacingLayout(newLayout)
216-
}
217-
"""
218-
)
219-
220-
DeclSyntax(
221-
"""
222-
/// Creates a new ``\(node.kind.syntaxType)`` by prepending the provided syntax element
223-
/// to the children.
224-
///
225-
/// - Parameter syntax: The element to prepend.
226-
/// - Returns: A new ``\(node.kind.syntaxType)`` with that element prepended to the
227-
/// beginning.
228-
public func prepending(_ syntax: Element) -> \(node.kind.syntaxType) {
229-
return inserting(syntax, at: 0)
230-
}
231-
"""
232-
)
233-
234-
DeclSyntax(
235-
"""
236-
/// Creates a new ``\(node.kind.syntaxType)`` by inserting the provided syntax element
237-
/// at the provided index in the children.
238-
///
239-
/// - Parameters:
240-
/// - syntax: The element to insert.
241-
/// - index: The index at which to insert the element in the collection.
242-
///
243-
/// - Returns: A new ``\(node.kind.syntaxType)`` with that element appended to the end.
244-
public func inserting(_ syntax: Element, at index: Int) -> \(node.kind.syntaxType) {
245-
var newLayout = layoutView.formLayoutArray()
246-
/// Make sure the index is a valid insertion index (0 to 1 past the end)
247-
precondition((newLayout.startIndex...newLayout.endIndex).contains(index),
248-
"inserting node at invalid index \\(index)")
249-
newLayout.insert(syntax.raw, at: index)
250-
return replacingLayout(newLayout)
251-
}
252-
"""
253-
)
254-
255-
DeclSyntax(
256-
"""
257-
/// Creates a new ``\(node.kind.syntaxType)`` by replacing the syntax element
258-
/// at the provided index.
259-
///
260-
/// - Parameters:
261-
/// - index: The index at which to replace the element in the collection.
262-
/// - syntax: The element to replace with.
263-
///
264-
/// - Returns: A new ``\(node.kind.syntaxType)`` with the new element at the provided index.
265-
public func replacing(childAt index: Int, with syntax: Element) -> \(node.kind.syntaxType) {
266-
var newLayout = layoutView.formLayoutArray()
267-
/// Make sure the index is a valid index for replacing
268-
precondition((newLayout.startIndex..<newLayout.endIndex).contains(index),
269-
"replacing node at invalid index \\(index)")
270-
newLayout[index] = syntax.raw
271-
return replacingLayout(newLayout)
272-
}
273-
"""
274-
)
275-
276-
DeclSyntax(
277-
"""
278-
/// Creates a new ``\(node.kind.syntaxType)`` by removing the syntax element at the
279-
/// provided index.
280-
///
281-
/// - Parameter index: The index of the element to remove from the collection.
282-
/// - Returns: A new ``\(node.kind.syntaxType)`` with the element at the provided index
283-
/// removed.
284-
public func removing(childAt index: Int) -> \(node.kind.syntaxType) {
285-
var newLayout = layoutView.formLayoutArray()
286-
newLayout.remove(at: index)
287-
return replacingLayout(newLayout)
288-
}
289-
"""
290-
)
291-
292-
DeclSyntax(
293-
"""
294-
/// Creates a new ``\(node.kind.syntaxType)`` by removing the first element.
295-
///
296-
/// - Returns: A new ``\(node.kind.syntaxType)`` with the first element removed.
297-
public func removingFirst() -> \(node.kind.syntaxType) {
298-
var newLayout = layoutView.formLayoutArray()
299-
newLayout.removeFirst()
300-
return replacingLayout(newLayout)
301-
}
302-
"""
303-
)
304-
305-
DeclSyntax(
306-
"""
307-
/// Creates a new ``\(node.kind.syntaxType)`` by removing the last element.
308-
///
309-
/// - Returns: A new ``\(node.kind.syntaxType)`` with the last element removed.
310-
public func removingLast() -> \(node.kind.syntaxType) {
311-
var newLayout = layoutView.formLayoutArray()
312-
newLayout.removeLast()
313-
return replacingLayout(newLayout)
314-
}
315-
"""
316-
)
317-
}
318-
319-
try! ExtensionDeclSyntax(
320-
"""
321-
/// Conformance for ``\(node.kind.syntaxType)`` to the `BidirectionalCollection` protocol.
322-
extension \(node.kind.syntaxType): BidirectionalCollection
323-
"""
324-
) {
325-
DeclSyntax("public typealias Index = SyntaxChildrenIndex")
326-
327-
DeclSyntax(
328-
"""
329-
public struct Iterator: IteratorProtocol {
330-
private let parent: Syntax
331-
private var iterator: RawSyntaxChildren.Iterator
332-
333-
init(parent: Syntax, rawChildren: RawSyntaxChildren) {
334-
self.parent = parent
335-
self.iterator = rawChildren.makeIterator()
336-
}
337-
338-
public mutating func next() -> Element? {
339-
guard let (raw, info) = self.iterator.next() else {
340-
return nil
341-
}
342-
let absoluteRaw = AbsoluteRawSyntax(raw: raw!, info: info)
343-
let data = SyntaxData(absoluteRaw, parent: parent)
344-
return Element(data)
345-
}
346-
}
347-
"""
348-
)
349-
350-
DeclSyntax(
351-
"""
352-
public func makeIterator() -> Iterator {
353-
return Iterator(parent: Syntax(self), rawChildren: rawChildren)
354-
}
355-
"""
356-
)
357-
358-
DeclSyntax(
359-
"""
360-
private var rawChildren: RawSyntaxChildren {
361-
// We know children in a syntax collection cannot be missing. So we can
362-
// use the low-level and faster RawSyntaxChildren collection instead of
363-
// NonNilRawSyntaxChildren.
364-
return RawSyntaxChildren(self.data.absoluteRaw)
365-
}
366-
"""
367-
)
368-
369-
DeclSyntax(
370-
"""
371-
public var startIndex: SyntaxChildrenIndex {
372-
return rawChildren.startIndex
373-
}
374-
"""
375-
)
376-
377-
DeclSyntax(
378-
"""
379-
public var endIndex: SyntaxChildrenIndex {
380-
return rawChildren.endIndex
381-
}
382-
"""
383-
)
384-
385-
DeclSyntax(
386-
"""
387-
public func index(after index: SyntaxChildrenIndex) -> SyntaxChildrenIndex {
388-
return rawChildren.index(after: index)
389-
}
390-
"""
391-
)
392-
393-
DeclSyntax(
394-
"""
395-
public func index(before index: SyntaxChildrenIndex) -> SyntaxChildrenIndex {
396-
return rawChildren.index(before: index)
397-
}
398-
"""
399-
)
400-
401-
DeclSyntax(
402-
"""
403-
public func distance(from start: SyntaxChildrenIndex, to end: SyntaxChildrenIndex)
404-
-> Int {
405-
return rawChildren.distance(from: start, to: end)
406-
}
407-
"""
408-
)
409-
410-
DeclSyntax(
411-
"""
412-
public subscript(position: SyntaxChildrenIndex) -> Element {
413-
let (raw, info) = rawChildren[position]
414-
let absoluteRaw = AbsoluteRawSyntax(raw: raw!, info: info)
415-
let data = SyntaxData(absoluteRaw, parent: Syntax(self))
416-
return Element(data)
417-
}
418-
"""
419-
)
117+
DeclSyntax("public static let syntaxKind = SyntaxKind.\(node.varOrCaseName)")
420118
}
421119
}
422120
}

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntaxbuilder/BuildableCollectionNodesFile.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ let buildableCollectionNodesFile = SourceFileSyntax(leadingTrivia: copyrightHead
4040
public init(_ elements: \(ArrayTypeSyntax(elementType: elementType.parameterType))) {
4141
self = \(raw: node.type.syntaxBaseName)(elements.map {
4242
\(elementType.syntax)(fromProtocol: $0)
43-
})
43+
} as [\(elementType.syntax)])
4444
}
4545
"""
4646
)

0 commit comments

Comments
 (0)