Skip to content

Commit e9d9560

Browse files
committed
Add childrenKeyPaths
1 parent e621e8a commit e9d9560

13 files changed

+2919
-0
lines changed

Sources/SwiftSyntax/Syntax.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
4949
self = syntax._syntaxNode
5050
}
5151

52+
public static var childrenKeyPaths: [AnyKeyPath] {
53+
fatalError("Syntax is a base type and thus doesn't have statically known children")
54+
}
55+
5256
public func hash(into hasher: inout Hasher) {
5357
return data.nodeId.hash(into: &hasher)
5458
}
@@ -136,13 +140,28 @@ public protocol SyntaxProtocol: CustomStringConvertible,
136140
/// conversion is not possible.
137141
init?(_ syntaxNode: Syntax)
138142

143+
/// An array that maps children indicies to key paths that can be used to
144+
/// access this child. Use cases for these are:
145+
/// - To name parent-child relationships of syntax nodes (e.g. to specify that
146+
/// the right brace of a CodeBlockItem should be put on a new line)
147+
/// - To get the static type of a child of a syntax node
148+
///
149+
/// Technically, this should have type `PartialKeyPath<Self>` but we cannot do
150+
/// that because then `SyntaxProtocol` would have a Self type requirement.
151+
static var childrenKeyPaths: [AnyKeyPath] { get }
152+
139153
/// Return a name with which the child at the given `index` can be referred to
140154
/// in diagnostics.
141155
/// Typically, you want to use `childNameInParent` on the child instead of
142156
/// calling this method on the parent.
143157
func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String?
144158
}
145159

160+
public extension SyntaxProtocol {
161+
/// Returns the value of the static `childrenKeyPaths` for this node's type.
162+
var childrenKeyPaths: [AnyKeyPath] { return Self.childrenKeyPaths }
163+
}
164+
146165
public extension SyntaxProtocol {
147166
/// If the parent has a dedicated "name for diagnostics" for this node, return it.
148167
/// Otherwise, return `nil`.

Sources/SwiftSyntax/SyntaxBaseNodes.swift.gyb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ public struct ${node.name}: ${node.name}Protocol, SyntaxHashable {
138138
return Syntax(self).asProtocol(${node.name}Protocol.self)!
139139
}
140140

141+
public static var childrenKeyPaths: [AnyKeyPath] {
142+
fatalError("${node.name} is a base type and thus doesn't have statically known children")
143+
}
144+
145+
public var childrenKeyPaths: [AnyKeyPath] {
146+
return Syntax(self).childrenKeyPaths
147+
}
148+
149+
141150
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
142151
return Syntax(self).childNameForDiagnostics(index)
143152
}

Sources/SwiftSyntax/SyntaxCollections.swift.gyb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ public protocol SyntaxCollection: SyntaxProtocol, Sequence {
2323
var count: Int { get }
2424
}
2525

26+
public extension SyntaxCollection {
27+
static var childrenKeyPaths: [AnyKeyPath] { [] }
28+
}
29+
2630
% for node in SYNTAX_NODES:
2731
% if node.collection_element:
2832
% element_node = NODE_MAP.get(node.collection_element)

Sources/SwiftSyntax/SyntaxNodes.swift.gyb.template

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
172172
}
173173
% end
174174

175+
public static var childrenKeyPaths: [AnyKeyPath] {
176+
[
177+
% for (index, child) in enumerate(node.children):
178+
\Self.${child.swift_name},
179+
% end
180+
]
181+
}
182+
175183
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
176184
switch index.data?.indexInParent {
177185
% for (index, child) in enumerate(node.children):

Sources/SwiftSyntax/SyntaxOtherNodes.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public struct UnknownSyntax: SyntaxProtocol, SyntaxHashable {
3838
self.init(data)
3939
}
4040

41+
public static var childrenKeyPaths: [AnyKeyPath] { [] }
42+
4143
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
4244
return nil
4345
}
@@ -195,6 +197,8 @@ public struct TokenSyntax: SyntaxProtocol, SyntaxHashable {
195197
return raw.totalLength
196198
}
197199

200+
public static var childrenKeyPaths: [AnyKeyPath] { [] }
201+
198202
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
199203
return nil
200204
}

Sources/SwiftSyntax/gyb_generated/SyntaxBaseNodes.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ public struct DeclSyntax: DeclSyntaxProtocol, SyntaxHashable {
119119
return Syntax(self).asProtocol(DeclSyntaxProtocol.self)!
120120
}
121121

122+
public static var childrenKeyPaths: [AnyKeyPath] {
123+
fatalError("DeclSyntax is a base type and thus doesn't have statically known children")
124+
}
125+
126+
public var childrenKeyPaths: [AnyKeyPath] {
127+
return Syntax(self).childrenKeyPaths
128+
}
129+
130+
122131
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
123132
return Syntax(self).childNameForDiagnostics(index)
124133
}
@@ -239,6 +248,15 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
239248
return Syntax(self).asProtocol(ExprSyntaxProtocol.self)!
240249
}
241250

251+
public static var childrenKeyPaths: [AnyKeyPath] {
252+
fatalError("ExprSyntax is a base type and thus doesn't have statically known children")
253+
}
254+
255+
public var childrenKeyPaths: [AnyKeyPath] {
256+
return Syntax(self).childrenKeyPaths
257+
}
258+
259+
242260
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
243261
return Syntax(self).childNameForDiagnostics(index)
244262
}
@@ -359,6 +377,15 @@ public struct StmtSyntax: StmtSyntaxProtocol, SyntaxHashable {
359377
return Syntax(self).asProtocol(StmtSyntaxProtocol.self)!
360378
}
361379

380+
public static var childrenKeyPaths: [AnyKeyPath] {
381+
fatalError("StmtSyntax is a base type and thus doesn't have statically known children")
382+
}
383+
384+
public var childrenKeyPaths: [AnyKeyPath] {
385+
return Syntax(self).childrenKeyPaths
386+
}
387+
388+
362389
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
363390
return Syntax(self).childNameForDiagnostics(index)
364391
}
@@ -479,6 +506,15 @@ public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable {
479506
return Syntax(self).asProtocol(TypeSyntaxProtocol.self)!
480507
}
481508

509+
public static var childrenKeyPaths: [AnyKeyPath] {
510+
fatalError("TypeSyntax is a base type and thus doesn't have statically known children")
511+
}
512+
513+
public var childrenKeyPaths: [AnyKeyPath] {
514+
return Syntax(self).childrenKeyPaths
515+
}
516+
517+
482518
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
483519
return Syntax(self).childNameForDiagnostics(index)
484520
}
@@ -599,6 +635,15 @@ public struct PatternSyntax: PatternSyntaxProtocol, SyntaxHashable {
599635
return Syntax(self).asProtocol(PatternSyntaxProtocol.self)!
600636
}
601637

638+
public static var childrenKeyPaths: [AnyKeyPath] {
639+
fatalError("PatternSyntax is a base type and thus doesn't have statically known children")
640+
}
641+
642+
public var childrenKeyPaths: [AnyKeyPath] {
643+
return Syntax(self).childrenKeyPaths
644+
}
645+
646+
602647
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
603648
return Syntax(self).childNameForDiagnostics(index)
604649
}

Sources/SwiftSyntax/gyb_generated/SyntaxCollections.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ public protocol SyntaxCollection: SyntaxProtocol, Sequence {
1717
var count: Int { get }
1818
}
1919

20+
public extension SyntaxCollection {
21+
static var childrenKeyPaths: [AnyKeyPath] { [] }
22+
}
23+
2024

2125
/// `CodeBlockItemListSyntax` represents a collection of one or more
2226
/// `CodeBlockItemSyntax` nodes. CodeBlockItemListSyntax behaves

0 commit comments

Comments
 (0)