13
13
/// Represent an index in a layout.
14
14
public struct SyntaxLayoutIndex : Equatable , Comparable {
15
15
let value : UInt32
16
+
17
+ @_spi ( RawSyntax)
16
18
public init ( _ value: UInt32 ) {
17
19
self . value = value
18
20
}
21
+
19
22
public static func == ( lhs: Self , rhs: Self ) -> Bool {
20
23
lhs. value == rhs. value
21
24
}
25
+
22
26
public static func < ( lhs: Self , rhs: Self ) -> Bool {
23
27
lhs. value < rhs. value
24
28
}
@@ -27,68 +31,80 @@ public struct SyntaxLayoutIndex: Equatable, Comparable {
27
31
/// Represent a property in a layout syntax.
28
32
public struct SyntaxLayoutProperty : Equatable {
29
33
/// 'SyntaxKind' of the parent layout node.
30
- let baseKind : SyntaxKind
34
+ let syntaxKind : SyntaxKind
31
35
/// Index in the parent node layout.
32
36
let index : SyntaxLayoutIndex
33
37
34
- public init ( baseKind: SyntaxKind , index: SyntaxLayoutIndex ) {
35
- self . baseKind = baseKind
38
+ @_spi ( RawSyntax)
39
+ public init ( syntaxKind: SyntaxKind , index: SyntaxLayoutIndex ) {
40
+ self . syntaxKind = syntaxKind
36
41
self . index = index
37
42
}
38
43
39
44
public static func == ( lhs: Self , rhs: Self ) -> Bool {
40
- lhs. baseKind == rhs. baseKind && lhs. index == rhs. index
45
+ lhs. syntaxKind == rhs. syntaxKind && lhs. index == rhs. index
41
46
}
42
47
}
43
48
49
+ /// Protocol for concrete layout syntax nodes.
50
+ public protocol _LayoutSyntaxProtocol : SyntaxProtocol {
51
+ static var layout : SyntaxLayout < Self > { get }
52
+ }
53
+
44
54
/// Describes the layout of a `_LayoutSyntaxProtocol` syntax node.
45
55
public struct SyntaxLayout < Base: _LayoutSyntaxProtocol > {
46
- let baseKind : SyntaxKind
56
+ let syntaxKind : SyntaxKind
47
57
let _count : UInt32
48
58
49
59
// SyntaxLayout can only be constructed by `_LayoutSyntaxProtocol.layout`
50
60
private init ( ) { fatalError ( ) }
51
61
}
52
62
53
- #if false // Not needed at this point.
54
- extension SyntaxLayout : Collection {
55
- public typealias Index = SyntaxLayoutIndex
56
- public typealias Element = SyntaxLayoutProperty
57
-
58
- public var count : Int { Int ( _count) }
59
- public var startIndex : Index { Index ( 0 ) }
60
- public var endIndex : Index { Index ( _count) }
61
- public func index( after i: Index ) -> Index { Index ( i. value + 1 ) }
62
-
63
- public subscript( position: SyntaxLayoutIndex ) -> SyntaxLayoutProperty {
64
- return SyntaxLayoutProperty ( baseKind: baseKind, index: position)
65
- }
66
- }
67
- #endif
68
-
69
- public protocol _LayoutSyntaxProtocol : SyntaxProtocol {
70
- static var layout : SyntaxLayout < Self > { get }
71
- }
72
-
73
- public struct ConcreteSyntaxProperty < Base: SyntaxProtocol , Value> {
63
+ /// Represent a typed property in a layout syntax.
64
+ ///
65
+ /// Specialized types have static properties to instantiate this type. E.g.:
66
+ ///
67
+ /// let exprProperty: ConcreteSyntaxProperty<ReturnStmtSyntax, ExprSyntax?> = .expression
68
+ ///
69
+ /// The property can be used similar to 'KeyPath'.
70
+ ///
71
+ /// let expr/*: ExprSyntax?*/ = returnStmt[property: exprProperty]
72
+ /// let newReturnStmt = returnStmt.with(.expression, expr)
73
+ ///
74
+ public struct ConcreteSyntaxProperty < Base: _LayoutSyntaxProtocol , Value> {
74
75
let index : SyntaxLayoutIndex
75
76
76
- // ConcreteSyntaxProperty can only be constructed by
77
- // `ConcreteSyntaxProperty<Base, Value>.${name}`
77
+ // ConcreteSyntaxProperty can only be constructed by `ConcreteSyntaxProperty<Base, Value>.${name}`
78
78
private init ( ) { fatalError ( ) }
79
79
}
80
80
81
81
extension SyntaxLayout {
82
- /// Get `AnySyntaxProperty ` from `ConcreteSyntaxProperty` of the `Base` type.
82
+ /// Get `AnySyntaxLayoutProperty ` from `ConcreteSyntaxProperty` of the `Base` type.
83
83
/// This is convenient for comparing '.propertyInParent'. E.g.
84
84
///
85
85
/// if node.propertyInParent == FunctionDeclSyntax.layout[.name] { ... }
86
86
///
87
87
public subscript< T> ( property: ConcreteSyntaxProperty < Base , T > ) -> SyntaxLayoutProperty {
88
- return SyntaxLayoutProperty ( baseKind : baseKind , index: property. index)
88
+ return SyntaxLayoutProperty ( syntaxKind : syntaxKind , index: property. index)
89
89
}
90
90
}
91
91
92
+ #if false // Not needed at this point.
93
+ extension SyntaxLayout : Collection {
94
+ public typealias Index = SyntaxLayoutIndex
95
+ public typealias Element = SyntaxLayoutProperty
96
+
97
+ public var count : Int { Int ( _count) }
98
+ public var startIndex : Index { Index ( 0 ) }
99
+ public var endIndex : Index { Index ( _count) }
100
+ public func index( after i: Index ) -> Index { Index ( i. value + 1 ) }
101
+
102
+ public subscript( position: SyntaxLayoutIndex ) -> SyntaxLayoutProperty {
103
+ return SyntaxLayoutProperty ( syntaxKind: syntaxKind, index: position)
104
+ }
105
+ }
106
+ #endif
107
+
92
108
extension SyntaxProtocol {
93
109
/// Return 'SyntaxLayoutProperty' in the parent node, if this node is a child
94
110
/// of a layout node. 'nil' otherwise.
@@ -101,13 +117,29 @@ extension SyntaxProtocol {
101
117
return nil
102
118
}
103
119
return SyntaxLayoutProperty (
104
- baseKind : parent. kind,
120
+ syntaxKind : parent. kind,
105
121
index: . init( self . _syntaxNode. absoluteInfo. indexInParent)
106
122
)
107
123
}
124
+ }
125
+
126
+ extension SyntaxProtocol {
127
+ /// Get a property value.
128
+ /// The property must be retrieved from the correct 'SyntaxLayout'
129
+ public subscript( property: SyntaxLayoutProperty ) -> Syntax ? {
130
+ precondition ( property. syntaxKind == Syntax ( self ) . kind)
131
+ return Syntax ( self ) . child ( at: Int ( property. index. value) )
132
+ }
133
+
134
+ /// Get a property value.
135
+ public subscript< T: SyntaxProtocol > ( property: ConcreteSyntaxProperty < Self , T > ) -> T {
136
+ return Syntax ( self ) . child ( at: Int ( property. index. value) ) !. cast ( T . self)
137
+ }
138
+ public subscript< T: SyntaxProtocol > ( property: ConcreteSyntaxProperty < Self , T ? > ) -> T ? {
139
+ return Syntax ( self ) . child ( at: Int ( property. index. value) ) ? . cast ( T . self)
140
+ }
108
141
109
- /// Returns a new syntax node that has the child at `property` replaced by
110
- /// `value`.
142
+ /// Returns a new syntax node that has the child at `property` replaced by `value`.
111
143
public func with< T: SyntaxProtocol > ( _ property: ConcreteSyntaxProperty < Self , T > , _ value: T ) -> Self {
112
144
Syntax ( self )
113
145
. replacingChild ( at: Int ( property. index. value) , with: Syntax ( value) , arena: SyntaxArena ( ) )
0 commit comments