Skip to content

Commit 9e88e2f

Browse files
committed
Factor out the Hashable conformance for syntax nodes to separate protocol
This allows us to use SyntaxProtocol as a return value again and provide nice functions that check if type-erased note conforms to a protocol.
1 parent 897ac41 commit 9e88e2f

13 files changed

+249
-242
lines changed

Sources/SwiftSyntax/Syntax.swift

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===-------------------- Syntax.swift - Syntax Protocol ------------------===//
1+
//===--------------- Syntax.swift - Base Syntax Type eraser --------------===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -13,7 +13,7 @@
1313
/// A Syntax node represents a tree of nodes with tokens at the leaves.
1414
/// Each node has accessors for its known children, and allows efficient
1515
/// iteration over the children through its `children` property.
16-
public struct Syntax: SyntaxProtocol {
16+
public struct Syntax: SyntaxProtocol, SyntaxHashable {
1717
let data: SyntaxData
1818

1919
public var _syntaxNode: Syntax {
@@ -57,11 +57,26 @@ extension Syntax: CustomReflectable {
5757
}
5858
}
5959

60+
/// Protocol that provides a common Hashable implementation for all syntax nodes
61+
public protocol SyntaxHashable: Hashable {
62+
var _syntaxNode: Syntax { get }
63+
}
64+
65+
public extension SyntaxHashable {
66+
func hash(into hasher: inout Hasher) {
67+
return _syntaxNode.data.nodeId.hash(into: &hasher)
68+
}
69+
70+
static func ==(lhs: Self, rhs: Self) -> Bool {
71+
return lhs._syntaxNode.data.nodeId == rhs._syntaxNode.data.nodeId
72+
}
73+
}
74+
6075
/// Provide common functionality for specialized syntax nodes. Extend this
6176
/// protocol to provide common functionality for all syntax nodes.
6277
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
6378
public protocol SyntaxProtocol: CustomStringConvertible,
64-
CustomDebugStringConvertible, TextOutputStreamable, Hashable {
79+
CustomDebugStringConvertible, TextOutputStreamable {
6580

6681
/// Retrieve the generic syntax node that is represented by this node.
6782
/// Do not retrieve this property directly. Use `Syntax(self)` instead.
@@ -415,14 +430,6 @@ public extension SyntaxProtocol {
415430
where Target: TextOutputStream {
416431
data.raw.write(to: &target)
417432
}
418-
419-
func hash(into hasher: inout Hasher) {
420-
return data.nodeId.hash(into: &hasher)
421-
}
422-
423-
static func ==(lhs: Self, rhs: Self) -> Bool {
424-
return lhs.data.nodeId == rhs.data.nodeId
425-
}
426433
}
427434

428435
/// Sequence of tokens that are part of the provided Syntax node.

Sources/SwiftSyntax/SyntaxBaseNodes.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public protocol ${node.name}Protocol: ${base_type}Protocol {}
3232
% for line in dedented_lines(node.description):
3333
/// ${line}
3434
% end
35-
public struct ${node.name}: ${node.name}Protocol {
35+
public struct ${node.name}: ${node.name}Protocol, SyntaxHashable {
3636
public let _syntaxNode: Syntax
3737

3838
public init<S: ${node.name}Protocol>(_ syntax: S) {

Sources/SwiftSyntax/SyntaxCollections.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public protocol SyntaxCollection: SyntaxProtocol, Sequence {
3131
/// `${node.collection_element_type}` nodes. ${node.name} behaves
3232
/// as a regular Swift collection, and has accessors that return new
3333
/// versions of the collection with different children.
34-
public struct ${node.name}: SyntaxCollection {
34+
public struct ${node.name}: SyntaxCollection, SyntaxHashable {
3535
public let _syntaxNode: Syntax
3636

3737
/// Converts the given `Syntax` node to a `${node.name}` if possible. Returns

Sources/SwiftSyntax/SyntaxNodes.swift.gyb.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ nodes whose base kind are that specified kind.
4646
% for line in dedented_lines(node.description):
4747
/// ${line}
4848
% end
49-
public struct ${node.name}: ${base_type}Protocol {
49+
public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
5050
% # ======
5151
% # Cursor
5252
% # ======

Sources/SwiftSyntax/SyntaxOtherNodes.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// MARK: UnknownSyntax
1616

1717
/// A wrapper around a raw Syntax layout.
18-
public struct UnknownSyntax: SyntaxProtocol {
18+
public struct UnknownSyntax: SyntaxProtocol, SyntaxHashable {
1919
public let _syntaxNode: Syntax
2020

2121
/// Convert the given `Syntax` node to an `UnknownSyntax` if possible. Return
@@ -43,7 +43,7 @@ extension UnknownSyntax: CustomReflectable {
4343
// MARK: TokenSyntax
4444

4545
/// A Syntax node representing a single token.
46-
public struct TokenSyntax: SyntaxProtocol {
46+
public struct TokenSyntax: SyntaxProtocol, SyntaxHashable {
4747
public let _syntaxNode: Syntax
4848

4949
/// Converts the given `Syntax` node to a `TokenSyntax` if possible. Returns

Sources/SwiftSyntax/gyb_generated/SyntaxBaseNodes.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
2020
public protocol DeclSyntaxProtocol: SyntaxProtocol {}
2121

22-
public struct DeclSyntax: DeclSyntaxProtocol {
22+
public struct DeclSyntax: DeclSyntaxProtocol, SyntaxHashable {
2323
public let _syntaxNode: Syntax
2424

2525
public init<S: DeclSyntaxProtocol>(_ syntax: S) {
@@ -81,7 +81,7 @@ extension DeclSyntax: CustomReflectable {
8181
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
8282
public protocol ExprSyntaxProtocol: SyntaxProtocol {}
8383

84-
public struct ExprSyntax: ExprSyntaxProtocol {
84+
public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
8585
public let _syntaxNode: Syntax
8686

8787
public init<S: ExprSyntaxProtocol>(_ syntax: S) {
@@ -143,7 +143,7 @@ extension ExprSyntax: CustomReflectable {
143143
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
144144
public protocol StmtSyntaxProtocol: SyntaxProtocol {}
145145

146-
public struct StmtSyntax: StmtSyntaxProtocol {
146+
public struct StmtSyntax: StmtSyntaxProtocol, SyntaxHashable {
147147
public let _syntaxNode: Syntax
148148

149149
public init<S: StmtSyntaxProtocol>(_ syntax: S) {
@@ -205,7 +205,7 @@ extension StmtSyntax: CustomReflectable {
205205
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
206206
public protocol TypeSyntaxProtocol: SyntaxProtocol {}
207207

208-
public struct TypeSyntax: TypeSyntaxProtocol {
208+
public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable {
209209
public let _syntaxNode: Syntax
210210

211211
public init<S: TypeSyntaxProtocol>(_ syntax: S) {
@@ -267,7 +267,7 @@ extension TypeSyntax: CustomReflectable {
267267
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
268268
public protocol PatternSyntaxProtocol: SyntaxProtocol {}
269269

270-
public struct PatternSyntax: PatternSyntaxProtocol {
270+
public struct PatternSyntax: PatternSyntaxProtocol, SyntaxHashable {
271271
public let _syntaxNode: Syntax
272272

273273
public init<S: PatternSyntaxProtocol>(_ syntax: S) {

0 commit comments

Comments
 (0)