Skip to content

Commit f15005b

Browse files
committed
WIP enumerate node_choices and element_choices
1 parent b03345b commit f15005b

File tree

12 files changed

+1522
-741
lines changed

12 files changed

+1522
-741
lines changed

Sources/SwiftSyntax/Syntax.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
5959
}
6060

6161
// Casting functions to specialized syntax nodes.
62-
extension Syntax {
62+
extension SyntaxProtocol {
6363
public func `is`<S: SyntaxProtocol>(_ syntaxType: S.Type) -> Bool {
6464
return self.as(syntaxType) != nil
6565
}
6666

6767
public func `as`<S: SyntaxProtocol>(_ syntaxType: S.Type) -> S? {
68-
return S.init(self)
68+
return S.init(self._syntaxNode)
6969
}
7070
}
7171

Sources/SwiftSyntax/SyntaxCollections.swift.gyb

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,40 @@ public protocol SyntaxCollection: SyntaxProtocol, Sequence {
3838
/// versions of the collection with different children.
3939
% end
4040
public struct ${node.name}: SyntaxCollection, SyntaxHashable {
41+
% if node.collection_element_choices:
42+
public enum Element: SyntaxProtocol {
43+
% for choice_name in node.collection_element_choices:
44+
% choice = NODE_MAP[choice_name]
45+
case `${choice.swift_syntax_kind}`(${choice.name})
46+
% end
47+
public var _syntaxNode: Syntax {
48+
switch self {
49+
% for choice_name in node.collection_element_choices:
50+
% choice = NODE_MAP[choice_name]
51+
case .${choice.swift_syntax_kind}(let node): return node._syntaxNode
52+
% end
53+
}
54+
}
55+
init(_ data: SyntaxData) { self.init(Syntax(data))! }
56+
% for choice_name in node.collection_element_choices:
57+
% choice = NODE_MAP[choice_name]
58+
public init(${choice.swift_syntax_kind} node: ${choice.name}) { self = .${choice.swift_syntax_kind}(node) }
59+
% end
60+
public init?<Node: SyntaxProtocol>(_ syntaxNode: Node) {
61+
% for choice_name in node.collection_element_choices:
62+
% choice = NODE_MAP[choice_name]
63+
if let node = syntaxNode.as(${choice.name}.self) {
64+
self = .${choice.swift_syntax_kind}(node)
65+
return
66+
}
67+
% end
68+
return nil
69+
}
70+
}
71+
% else:
72+
public typealias Element = ${node.collection_element_type}
73+
% end
74+
4175
public let _syntaxNode: Syntax
4276

4377
var layoutView: RawSyntaxLayoutView {
@@ -59,7 +93,7 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
5993
self._syntaxNode = Syntax(data)
6094
}
6195

62-
public init(_ children: [${node.collection_element_type}]) {
96+
public init(_ children: [Element]) {
6397
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
6498
from: children.map { $0.raw }, arena: .default)
6599
let data = SyntaxData.forRoot(raw)
@@ -87,8 +121,7 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
87121
///
88122
/// - Parameter syntax: The element to append.
89123
/// - Returns: A new `${node.name}` with that element appended to the end.
90-
public func appending(
91-
_ syntax: ${node.collection_element_type}) -> ${node.name} {
124+
public func appending(_ syntax: Element) -> ${node.name} {
92125
var newLayout = layoutView.formLayoutArray()
93126
newLayout.append(syntax.raw)
94127
return replacingLayout(newLayout)
@@ -100,8 +133,7 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
100133
/// - Parameter syntax: The element to prepend.
101134
/// - Returns: A new `${node.name}` with that element prepended to the
102135
/// beginning.
103-
public func prepending(
104-
_ syntax: ${node.collection_element_type}) -> ${node.name} {
136+
public func prepending(_ syntax: Element) -> ${node.name} {
105137
return inserting(syntax, at: 0)
106138
}
107139

@@ -113,8 +145,7 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
113145
/// - index: The index at which to insert the element in the collection.
114146
///
115147
/// - Returns: A new `${node.name}` with that element appended to the end.
116-
public func inserting(_ syntax: ${node.collection_element_type},
117-
at index: Int) -> ${node.name} {
148+
public func inserting(_ syntax: Element, at index: Int) -> ${node.name} {
118149
var newLayout = layoutView.formLayoutArray()
119150
/// Make sure the index is a valid insertion index (0 to 1 past the end)
120151
precondition((newLayout.startIndex...newLayout.endIndex).contains(index),
@@ -131,8 +162,7 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
131162
/// - syntax: The element to replace with.
132163
///
133164
/// - Returns: A new `${node.name}` with the new element at the provided index.
134-
public func replacing(childAt index: Int,
135-
with syntax: ${node.collection_element_type}) -> ${node.name} {
165+
public func replacing(childAt index: Int, with syntax: Element) -> ${node.name} {
136166
var newLayout = layoutView.formLayoutArray()
137167
/// Make sure the index is a valid index for replacing
138168
precondition((newLayout.startIndex..<newLayout.endIndex).contains(index),
@@ -221,7 +251,6 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
221251

222252
/// Conformance for `${node.name}` to the `BidirectionalCollection` protocol.
223253
extension ${node.name}: BidirectionalCollection {
224-
public typealias Element = ${node.collection_element_type}
225254
public typealias Index = SyntaxChildrenIndex
226255

227256
public struct Iterator: IteratorProtocol {
@@ -233,13 +262,13 @@ extension ${node.name}: BidirectionalCollection {
233262
self.iterator = rawChildren.makeIterator()
234263
}
235264

236-
public mutating func next() -> ${node.collection_element_type}? {
265+
public mutating func next() -> Element? {
237266
guard let (raw, info) = self.iterator.next() else {
238267
return nil
239268
}
240269
let absoluteRaw = AbsoluteRawSyntax(raw: raw!, info: info)
241270
let data = SyntaxData(absoluteRaw, parent: parent)
242-
return ${node.collection_element_type}(data)
271+
return Element(data)
243272
}
244273
}
245274

@@ -274,11 +303,11 @@ extension ${node.name}: BidirectionalCollection {
274303
return rawChildren.distance(from: start, to: end)
275304
}
276305

277-
public subscript(position: SyntaxChildrenIndex) -> ${node.collection_element_type} {
306+
public subscript(position: SyntaxChildrenIndex) -> Element {
278307
let (raw, info) = rawChildren[position]
279308
let absoluteRaw = AbsoluteRawSyntax(raw: raw!, info: info)
280309
let data = SyntaxData(absoluteRaw, parent: Syntax(self))
281-
return ${node.collection_element_type}(data)
310+
return Element(data)
282311
}
283312
}
284313
% end

Sources/SwiftSyntax/SyntaxNodes.swift.gyb.template

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,36 @@ nodes whose base kind are that specified kind.
4747
/// ${line}
4848
% end
4949
public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
50+
% for child in node.children:
51+
% if child.node_choices:
52+
public enum ${child.name}: SyntaxProtocol {
53+
% for choice in child.node_choices:
54+
case `${choice.swift_name}`(${choice.type_name})
55+
% end
56+
public var _syntaxNode: Syntax {
57+
switch self {
58+
% for choice in child.node_choices:
59+
case .${choice.swift_name}(let node): return node._syntaxNode
60+
% end
61+
}
62+
}
63+
init(_ data: SyntaxData) { self.init(Syntax(data))! }
64+
% for choice in child.node_choices:
65+
public init(${choice.swift_name} node: ${choice.type_name}) { self = .${choice.swift_name}(node) }
66+
% end
67+
public init?<Node: SyntaxProtocol>(_ syntaxNode: Node) {
68+
% for choice in child.node_choices:
69+
if let node = syntaxNode.as(${choice.type_name}.self) {
70+
self = .${choice.swift_name}(node)
71+
return
72+
}
73+
% end
74+
return nil
75+
}
76+
}
77+
78+
% end
79+
% end
5080
% # ==============
5181
% # Initialization
5282
% # ==============
@@ -71,7 +101,7 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
71101
public init(
72102
% for (index, child) in enumerate(node.children):
73103
% comma = ',' if index != len(node.children) - 1 else ''
74-
% param_type = child.type_name
104+
% param_type = child.name if child.node_choices else child.type_name
75105
% if child.is_optional:
76106
% param_type = param_type + "?"
77107
% if child.is_unexpected_nodes():
@@ -102,21 +132,21 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
102132
% # Children properties
103133
% # ===================
104134
%
105-
% ret_type = child.type_name
106-
% if child.is_optional:
107-
% ret_type += '?'
108-
% end
135+
% child_type = child.type_name
136+
% if child.node_choices:
137+
% child_type = child.name
138+
% optional_mark = "?" if child.is_optional else ""
109139
110140
% for line in dedented_lines(child.description):
111141
/// ${line}
112142
% end
113-
public var ${child.swift_name}: ${ret_type} {
143+
public var ${child.swift_name}: ${child_type}${optional_mark} {
114144
get {
115145
let childData = data.child(at: ${idx}, parent: Syntax(self))
116146
% if child.is_optional:
117147
if childData == nil { return nil }
118148
% end
119-
return ${child.type_name}(childData!)
149+
return ${child_type}(childData!)
120150
}
121151
set(value) {
122152
self = with${child.name}(value)
@@ -161,7 +191,7 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
161191
/// - param newChild: The new `${child.swift_name}` to replace the node's
162192
/// current `${child.swift_name}`, if present.
163193
public func with${child.name}(
164-
_ newChild: ${child.type_name}?) -> ${node.name} {
194+
_ newChild: ${child_type}?) -> ${node.name} {
165195
% if child.is_optional:
166196
let raw = newChild?.raw
167197
% else:

0 commit comments

Comments
 (0)