Skip to content

Commit e21878d

Browse files
committed
Remove AnySyntax, explicitly specialize SyntaxCollection nodes
1 parent ac6c8b2 commit e21878d

File tree

9 files changed

+101
-123
lines changed

9 files changed

+101
-123
lines changed

test/SwiftSyntax/SyntaxChildren.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var SyntaxChildrenAPI = TestSuite("SyntaxChildrenAPI")
2828
SyntaxChildrenAPI.test("IterateWithAllPresent") {
2929
let returnStmt = SyntaxFactory.makeReturnStmt(
3030
returnKeyword: SyntaxFactory.makeReturnKeyword(),
31-
expression: SyntaxFactory.makeBlankExpr(),
31+
expression: SyntaxFactory.makeBlankUnknownExpr(),
3232
semicolon: SyntaxFactory.makeSemicolonToken())
3333

3434
var iterator = returnStmt.children.makeIterator()

tools/SwiftSyntax/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ add_swift_library(swiftSwiftSyntax SHARED
1414
Syntax.swift
1515
SyntaxData.swift
1616
SyntaxChildren.swift
17-
SyntaxCollection.swift
17+
SyntaxCollections.swift.gyb
1818
SyntaxBuilders.swift.gyb
1919
SyntaxFactory.swift.gyb
2020
SyntaxKind.swift.gyb
Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
//===-------------- SyntaxCollection.swift - Syntax Collection ------------===//
1+
%{
2+
from gyb_syntax_support import *
3+
# -*- mode: Swift -*-
4+
# Ignore the following admonition it applies to the resulting .swift file only
5+
}%
6+
//// Automatically Generated From SyntaxCollections.swift.gyb.
7+
//// Do Not Edit Directly!
8+
//===------------ SyntaxCollections.swift.gyb - Syntax Collection ---------===//
29
//
310
// This source file is part of the Swift.org open source project
411
//
@@ -12,12 +19,15 @@
1219

1320
import Foundation
1421

22+
% for node in SYNTAX_NODES:
23+
% if node.collection_element:
24+
1525
/// Represents a collection of Syntax nodes of a specific type. SyntaxCollection
1626
/// behaves as a regular Swift collection, and has accessors that return new
1727
/// versions of the collection with different children.
18-
public class SyntaxCollection<SyntaxElement: Syntax>: _SyntaxBase {
28+
public struct ${node.name}: _SyntaxBase {
1929
var _root: SyntaxData
20-
unowned var _data: SyntaxData
30+
unowned var _data: SyntaxData
2131

2232
/// Creates a Syntax node from the provided root and data.
2333
internal init(root: SyntaxData, data: SyntaxData) {
@@ -28,52 +38,52 @@ public class SyntaxCollection<SyntaxElement: Syntax>: _SyntaxBase {
2838
#endif
2939
}
3040

31-
/// Creates a new SyntaxCollection by replacing the underlying layout with
41+
/// Creates a new `${node.name}` by replacing the underlying layout with
3242
/// a different set of raw syntax nodes.
3343
///
3444
/// - Parameter layout: The new list of raw syntax nodes underlying this
3545
/// collection.
36-
/// - Returns: A new SyntaxCollection with the new layout underlying it.
46+
/// - Returns: A new `${node.name}` with the new layout underlying it.
3747
internal func replacingLayout(
38-
_ layout: [RawSyntax]) -> SyntaxCollection<SyntaxElement> {
48+
_ layout: [RawSyntax]) -> ${node.name} {
3949
let newRaw = data.raw.replacingLayout(layout)
4050
let (newRoot, newData) = data.replacingSelf(newRaw)
41-
return SyntaxCollection<SyntaxElement>(root: newRoot, data: newData)
51+
return ${node.name}(root: newRoot, data: newData)
4252
}
4353

44-
/// Creates a new SyntaxCollection by appending the provided syntax element
54+
/// Creates a new `${node.name}` by appending the provided syntax element
4555
/// to the children.
4656
///
4757
/// - Parameter syntax: The element to append.
48-
/// - Returns: A new SyntaxCollection with that element appended to the end.
58+
/// - Returns: A new `${node.name}` with that element appended to the end.
4959
public func appending(
50-
_ syntax: SyntaxElement) -> SyntaxCollection<SyntaxElement> {
60+
_ syntax: ${node.collection_element_type}) -> ${node.name} {
5161
var newLayout = data.raw.layout
5262
newLayout.append(syntax.raw)
5363
return replacingLayout(newLayout)
5464
}
5565

56-
/// Creates a new SyntaxCollection by prepending the provided syntax element
66+
/// Creates a new `${node.name}` by prepending the provided syntax element
5767
/// to the children.
5868
///
5969
/// - Parameter syntax: The element to prepend.
60-
/// - Returns: A new SyntaxCollection with that element prepended to the
70+
/// - Returns: A new `${node.name}` with that element prepended to the
6171
/// beginning.
6272
public func prepending(
63-
_ syntax: SyntaxElement) -> SyntaxCollection<SyntaxElement> {
73+
_ syntax: ${node.collection_element_type}) -> ${node.name} {
6474
return inserting(syntax, at: 0)
6575
}
6676

67-
/// Creates a new SyntaxCollection by inserting the provided syntax element
77+
/// Creates a new `${node.name}` by inserting the provided syntax element
6878
/// at the provided index in the children.
6979
///
7080
/// - Parameters:
7181
/// - syntax: The element to insert.
7282
/// - index: The index at which to insert the element in the collection.
7383
///
74-
/// - Returns: A new SyntaxCollection with that element appended to the end.
75-
public func inserting(_ syntax: SyntaxElement,
76-
at index: Int) -> SyntaxCollection<SyntaxElement> {
84+
/// - Returns: A new `${node.name}` with that element appended to the end.
85+
public func inserting(_ syntax: ${node.collection_element_type},
86+
at index: Int) -> ${node.name} {
7787
var newLayout = data.raw.layout
7888
/// Make sure the index is a valid insertion index (0 to 1 past the end)
7989
precondition((newLayout.startIndex...newLayout.endIndex).contains(index),
@@ -82,67 +92,71 @@ public class SyntaxCollection<SyntaxElement: Syntax>: _SyntaxBase {
8292
return replacingLayout(newLayout)
8393
}
8494

85-
/// Creates a new SyntaxCollection by removing the syntax element at the
95+
/// Creates a new `${node.name}` by removing the syntax element at the
8696
/// provided index.
8797
///
8898
/// - Parameter index: The index of the element to remove from the collection.
89-
/// - Returns: A new SyntaxCollection with the element at the provided index
99+
/// - Returns: A new `${node.name}` with the element at the provided index
90100
/// removed.
91-
public func removing(childAt index: Int) -> SyntaxCollection<SyntaxElement> {
101+
public func removing(childAt index: Int) -> ${node.name} {
92102
var newLayout = data.raw.layout
93103
newLayout.remove(at: index)
94104
return replacingLayout(newLayout)
95105
}
96106

97-
/// Creates a new SyntaxCollection by removing the first element.
107+
/// Creates a new `${node.name}` by removing the first element.
98108
///
99-
/// - Returns: A new SyntaxCollection with the first element removed.
100-
public func removingFirst() -> SyntaxCollection<SyntaxElement> {
109+
/// - Returns: A new `${node.name}` with the first element removed.
110+
public func removingFirst() -> ${node.name} {
101111
var newLayout = data.raw.layout
102112
newLayout.removeFirst()
103113
return replacingLayout(newLayout)
104114
}
105115

106-
/// Creates a new SyntaxCollection by removing the last element.
116+
/// Creates a new `${node.name}` by removing the last element.
107117
///
108-
/// - Returns: A new SyntaxCollection with the last element removed.
109-
public func removingLast() -> SyntaxCollection<SyntaxElement> {
118+
/// - Returns: A new `${node.name}` with the last element removed.
119+
public func removingLast() -> ${node.name} {
110120
var newLayout = data.raw.layout
111121
newLayout.removeLast()
112122
return replacingLayout(newLayout)
113123
}
114124

115125
/// Returns an iterator over the elements of this syntax collection.
116-
public func makeIterator() -> SyntaxCollectionIterator<SyntaxElement> {
117-
return SyntaxCollectionIterator(collection: self)
126+
public func makeIterator() -> ${node.name}Iterator {
127+
return ${node.name}Iterator(collection: self)
118128
}
119129
}
120130

121-
/// Conformance for SyntaxCollection to the Collection protocol.
122-
extension SyntaxCollection: Collection {
131+
/// Conformance for `${node.name}`` to the Collection protocol.
132+
extension ${node.name}: Collection {
123133
public var startIndex: Int {
124134
return data.childCaches.startIndex
125135
}
126-
136+
127137
public var endIndex: Int {
128138
return data.childCaches.endIndex
129139
}
130-
140+
131141
public func index(after i: Int) -> Int {
132142
return data.childCaches.index(after: i)
133143
}
134-
135-
public subscript(_ index: Int) -> SyntaxElement {
136-
return child(at: index)! as! SyntaxElement
144+
145+
public subscript(_ index: Int) -> ${node.collection_element_type} {
146+
% cast = '' if node.collection_element_type == 'Syntax' \
147+
% else 'as! ' + node.collection_element_type
148+
return child(at: index)! ${cast}
137149
}
138150
}
139151

140-
/// A type that iterates over a syntax collection using its indices.
141-
public struct SyntaxCollectionIterator<Element: Syntax>: IteratorProtocol {
142-
private let collection: SyntaxCollection<Element>
143-
private var index: SyntaxCollection<Element>.Index
152+
/// A type that iterates over a `${node.name}` using its indices.
153+
public struct ${node.name}Iterator: IteratorProtocol {
154+
public typealias Element = ${node.collection_element_type}
155+
156+
private let collection: ${node.name}
157+
private var index: ${node.name}.Index
144158

145-
fileprivate init(collection: SyntaxCollection<Element>) {
159+
fileprivate init(collection: ${node.name}) {
146160
self.collection = collection
147161
self.index = collection.startIndex
148162
}
@@ -160,3 +174,5 @@ public struct SyntaxCollectionIterator<Element: Syntax>: IteratorProtocol {
160174
}
161175
}
162176

177+
% end
178+
% end

tools/SwiftSyntax/SyntaxFactory.swift.gyb

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ public enum SyntaxFactory {
4040
let data = SyntaxData(raw: .node(.unknown,
4141
tokens.map { $0.data.raw },
4242
.present))
43-
return AnySyntax(root: data, data: data)
43+
return UnknownSyntax(root: data, data: data)
4444
}
4545

4646
/// MARK: Syntax Node Creation APIs
4747

4848
% for node in SYNTAX_NODES:
49-
% if node.children:
49+
% if node.is_base():
50+
% pass
51+
% elif node.children:
5052
% child_params = []
5153
% for child in node.children:
5254
% param_type = child.type_name
@@ -64,25 +66,27 @@ public enum SyntaxFactory {
6466
% end
6567
% end
6668
], .present))
67-
return ${node.swift_type_name}(root: data, data: data)
69+
return ${node.name}(root: data, data: data)
6870
}
6971
% elif node.is_syntax_collection():
7072
public static func make${node.syntax_kind}(
7173
_ elements: [${node.collection_element_type}]) -> ${node.name} {
7274
let data = SyntaxData(raw: .node(.${node.swift_syntax_kind},
7375
elements.map { $0.data.raw }, .present))
74-
return ${node.swift_type_name}(root: data, data: data)
76+
return ${node.name}(root: data, data: data)
7577
}
7678
% end
7779

80+
% if not node.is_base():
7881
public static func makeBlank${node.syntax_kind}() -> ${node.name} {
7982
let data = SyntaxData(raw: .node(.${node.swift_syntax_kind}, [
80-
% for child in node.children:
83+
% for child in node.children:
8184
${make_missing_swift_child(child)},
82-
% end
85+
% end
8386
], .present))
84-
return ${node.swift_type_name}(root: data, data: data)
87+
return ${node.name}(root: data, data: data)
8588
}
89+
% end
8690
% end
8791

8892
/// MARK: Token Creation APIs

tools/SwiftSyntax/SyntaxKind.swift.gyb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,14 @@ internal func makeSyntax(root: SyntaxData?, data: SyntaxData) -> Syntax {
7171
let root = root ?? data
7272
switch data.raw.kind {
7373
case .token: return TokenSyntax(root: root, data: data)
74-
case .unknown: return AnySyntax(root: root, data: data)
74+
case .unknown: return UnknownSyntax(root: root, data: data)
7575
% for node in SYNTAX_NODES:
7676
case .${node.swift_syntax_kind}:
77-
return ${node.swift_type_name}(root: root, data: data)
77+
% if node.is_base():
78+
return Unknown${node.name}(root: root, data: data)
79+
% else:
80+
return ${node.name}(root: root, data: data)
81+
% end
7882
% end
7983
}
8084
}

tools/SwiftSyntax/SyntaxNodes.swift.gyb

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -38,51 +38,28 @@ Each node will have:
3838
"""
3939
}%
4040

41-
public struct AnySyntax: _SyntaxBase, Hashable {
41+
/// A wrapper around a raw Syntax layout.
42+
public struct UnknownSyntax: _SyntaxBase {
4243
var _root: SyntaxData
43-
unowned var _data: SyntaxData
44+
unowned var _data: SyntaxData
4445

45-
/// Creates an `AnySyntax`` node from the provided root and data.
46+
/// Creates an `UnknownSyntax` node from the provided root and data.
4647
internal init(root: SyntaxData, data: SyntaxData) {
4748
self._root = root
4849
self._data = data
49-
}
50-
51-
public static func ==(lhs: AnySyntax, rhs: AnySyntax) -> Bool {
52-
return lhs._data === rhs._data
53-
}
54-
55-
public var hashValue: Int {
56-
return ObjectIdentifier(_data).hashValue
50+
#if DEBUG
51+
validate()
52+
#endif
5753
}
5854
}
5955

6056
% for node in SYNTAX_NODES:
6157
% base_type = node.base_type
6258
% if node.is_base():
6359
public protocol ${node.name}: Syntax {}
64-
public struct ${node.swift_type_name}: ${node.name}, _SyntaxBase, Hashable {
65-
var _root: SyntaxData
66-
unowned var _data: SyntaxData
67-
68-
/// Creates an `${node.swift_type_name}` node from the provided root and data.
69-
internal init(root: SyntaxData, data: SyntaxData) {
70-
self._root = root
71-
self._data = data
72-
}
73-
74-
public static func ==(lhs: ${node.swift_type_name},
75-
rhs: ${node.swift_type_name}) -> Bool {
76-
return lhs._data === rhs._data
77-
}
78-
79-
public var hashValue: Int {
80-
return ObjectIdentifier(_data).hashValue
81-
}
82-
}
8360

8461
% elif node.collection_element:
85-
public typealias ${node.name} = SyntaxCollection<${node.swift_collection_element_type}>
62+
% pass
8663
% else:
8764
public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable {
8865
% if node.children:
@@ -141,18 +118,21 @@ public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable {
141118
#endif
142119
% end
143120
% for child in node.children:
121+
% ret_type = child.type_name
122+
% cast_symbol = 'as!'
123+
% if child.is_optional:
124+
% ret_type += '?'
125+
% cast_symbol = 'as?'
126+
% end
127+
% cast = '' if child.type_name == 'Syntax' \
128+
% else '%s %s' % (cast_symbol, child.type_name)
129+
public var ${child.swift_name}: ${ret_type} {
144130
% if child.is_optional:
145-
public var ${child.swift_name}: ${child.swift_type_name}? {
146131
guard raw[Cursor.${child.swift_name}].isPresent else { return nil }
147-
return ${child.swift_type_name}(root: _root,
148-
data: data.cachedChild(at: Cursor.${child.swift_name}))
149-
}
150-
% else:
151-
public var ${(child.swift_name)}: ${child.swift_type_name} {
152-
return ${child.swift_type_name}(root: _root,
153-
data: data.cachedChild(at: Cursor.${child.swift_name}))
154-
}
155132
% end
133+
let child = data.cachedChild(at: Cursor.${child.swift_name})
134+
return makeSyntax(root: _root, data: child) ${cast}
135+
}
156136
% child_node = NODE_MAP.get(child.syntax_kind)
157137
% if child_node and child_node.is_syntax_collection():
158138
% child_elt = child_node.collection_element_name
@@ -167,16 +147,15 @@ public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable {
167147
% end
168148

169149
public func with${child.name}(
170-
_ newChild: ${child.swift_type_name}?) -> ${node.name} {
150+
_ newChild: ${child.type_name}?) -> ${node.name} {
171151
let raw = newChild?.raw ?? ${make_missing_swift_child(child)}
172152
let (root, newData) = data.replacingChild(raw,
173153
at: Cursor.${child.swift_name})
174154
return ${node.name}(root: root, data: newData)
175155
}
176156
% end
177157

178-
public static func ==(lhs: ${node.swift_type_name},
179-
rhs: ${node.swift_type_name}) -> Bool {
158+
public static func ==(lhs: ${node.name}, rhs: ${node.name}) -> Bool {
180159
return lhs._data === rhs._data
181160
}
182161

0 commit comments

Comments
 (0)