@@ -29,6 +29,16 @@ extension CodingUserInfoKey {
29
29
struct SyntaxNodeId : Hashable , Codable {
30
30
private let rawValue : UInt
31
31
32
+ // Start creating fresh node IDs for user generated nodes on in the upper
33
+ // half of the UInt value range so that they don't easily collide with node
34
+ // ids generated by the C++ side of libSyntax
35
+ private static var highestUsedId : UInt = UInt . max / 2
36
+
37
+ /// Generates a syntax node ID that has not been used yet
38
+ fileprivate static func generateFreshId( ) -> SyntaxNodeId {
39
+ return SyntaxNodeId ( rawValue: highestUsedId + 1 )
40
+ }
41
+
32
42
fileprivate init ( rawValue: UInt ) {
33
43
self . rawValue = rawValue
34
44
}
@@ -43,53 +53,57 @@ struct SyntaxNodeId: Hashable, Codable {
43
53
}
44
54
}
45
55
56
+ /// The data that is specific to a tree or token node
57
+ fileprivate indirect enum RawSyntaxData {
58
+ /// A tree node with a kind and an array of children
59
+ case node( kind: SyntaxKind , layout: [ RawSyntax ? ] )
60
+ /// A token with a token kind, leading trivia, and trailing trivia
61
+ case token( kind: TokenKind , leadingTrivia: Trivia , trailingTrivia: Trivia )
62
+ }
63
+
46
64
/// Represents the raw tree structure underlying the syntax tree. These nodes
47
65
/// have no notion of identity and only provide structure to the tree. They
48
66
/// are immutable and can be freely shared between syntax nodes.
49
- indirect enum RawSyntax : Codable {
50
- /// A tree node with a kind, an array of children, and a source presence.
51
- case node( SyntaxKind , [ RawSyntax ? ] , SourcePresence , SyntaxNodeId ? )
67
+ struct RawSyntax : Codable {
68
+ fileprivate let data : RawSyntaxData
69
+ let presence : SourcePresence
70
+ let id : SyntaxNodeId
71
+
72
+ init ( kind: SyntaxKind , layout: [ RawSyntax ? ] , presence: SourcePresence ,
73
+ id: SyntaxNodeId ? = nil ) {
74
+ self . data = . node( kind: kind, layout: layout)
75
+ self . presence = presence
76
+ self . id = id ?? SyntaxNodeId . generateFreshId ( )
77
+ }
52
78
53
- /// A token with a token kind, leading trivia, trailing trivia, and a source
54
- /// presence.
55
- case token( TokenKind , Trivia , Trivia , SourcePresence , SyntaxNodeId ? )
79
+ init ( kind: TokenKind , leadingTrivia: Trivia , trailingTrivia: Trivia ,
80
+ presence: SourcePresence , id: SyntaxNodeId ? = nil ) {
81
+ self . data = . token( kind: kind, leadingTrivia: leadingTrivia,
82
+ trailingTrivia: trailingTrivia)
83
+ self . presence = presence
84
+ self . id = id ?? SyntaxNodeId . generateFreshId ( )
85
+ }
56
86
57
87
/// The syntax kind of this raw syntax.
58
88
var kind : SyntaxKind {
59
- switch self {
60
- case . node( let kind, _, _ , _ ) : return kind
61
- case . token( _, _, _, _ , _ ) : return . token
89
+ switch data {
90
+ case . node( let kind, _) : return kind
91
+ case . token( _, _, _) : return . token
62
92
}
63
93
}
64
94
65
95
var tokenKind : TokenKind ? {
66
- switch self {
67
- case . node( _, _, _ , _ ) : return nil
68
- case . token( let kind, _, _, _ , _ ) : return kind
96
+ switch data {
97
+ case . node( _, _) : return nil
98
+ case . token( let kind, _, _) : return kind
69
99
}
70
100
}
71
101
72
102
/// The layout of the children of this Raw syntax node.
73
103
var layout : [ RawSyntax ? ] {
74
- switch self {
75
- case . node( _, let layout, _, _) : return layout
76
- case . token( _, _, _, _, _) : return [ ]
77
- }
78
- }
79
-
80
- /// The source presence of this node.
81
- var presence : SourcePresence {
82
- switch self {
83
- case . node( _, _, let presence, _) : return presence
84
- case . token( _, _, _, let presence, _) : return presence
85
- }
86
- }
87
-
88
- /// The ID of this node
89
- var id : SyntaxNodeId ? {
90
- switch self {
91
- case . node( _, _, _, let id) : return id
92
- case . token( _, _, _, _, let id) : return id
104
+ switch data {
105
+ case . node( _, let layout) : return layout
106
+ case . token( _, _, _) : return [ ]
93
107
}
94
108
}
95
109
@@ -152,12 +166,13 @@ indirect enum RawSyntax: Codable {
152
166
let presence = try container. decode ( SourcePresence . self, forKey: . presence)
153
167
if let kind = try container. decodeIfPresent ( SyntaxKind . self, forKey: . kind) {
154
168
let layout = try container. decode ( [ RawSyntax ? ] . self, forKey: . layout)
155
- self = . node ( kind, layout, presence, id)
169
+ self . init ( kind: kind , layout: layout , presence: presence , id : id)
156
170
} else {
157
171
let kind = try container. decode ( TokenKind . self, forKey: . tokenKind)
158
172
let leadingTrivia = try container. decode ( Trivia . self, forKey: . leadingTrivia)
159
173
let trailingTrivia = try container. decode ( Trivia . self, forKey: . trailingTrivia)
160
- self = . token( kind, leadingTrivia, trailingTrivia, presence, id)
174
+ self . init ( kind: kind, leadingTrivia: leadingTrivia,
175
+ trailingTrivia: trailingTrivia, presence: presence, id: id)
161
176
}
162
177
if let callback = decoder. userInfo [ . rawSyntaxDecodedCallback] as?
163
178
( RawSyntax ) -> Void {
@@ -168,23 +183,18 @@ indirect enum RawSyntax: Codable {
168
183
/// Encodes the RawSyntax to the provided Foundation Encoder.
169
184
func encode( to encoder: Encoder ) throws {
170
185
var container = encoder. container ( keyedBy: CodingKeys . self)
171
- switch self {
172
- case let . node( kind, layout, presence, id) :
173
- if let id = id {
174
- try container. encode ( id, forKey: . id)
175
- }
186
+ switch self . data {
187
+ case let . node( kind, layout) :
188
+ try container. encode ( id, forKey: . id)
176
189
try container. encode ( kind, forKey: . kind)
177
190
try container. encode ( layout, forKey: . layout)
178
- try container. encode ( presence, forKey: . presence)
179
- case let . token( kind, leadingTrivia, trailingTrivia, presence, id) :
180
- if let id = id {
181
- try container. encode ( id, forKey: . id)
182
- }
191
+ case let . token( kind, leadingTrivia, trailingTrivia) :
192
+ try container. encode ( id, forKey: . id)
183
193
try container. encode ( kind, forKey: . tokenKind)
184
194
try container. encode ( leadingTrivia, forKey: . leadingTrivia)
185
195
try container. encode ( trailingTrivia, forKey: . trailingTrivia)
186
- try container. encode ( presence, forKey: . presence)
187
196
}
197
+ try container. encode ( presence, forKey: . presence)
188
198
}
189
199
190
200
/// Creates a RawSyntax node that's marked missing in the source with the
@@ -195,7 +205,7 @@ indirect enum RawSyntax: Codable {
195
205
/// - Returns: A new RawSyntax `.node` with the provided kind and layout, with
196
206
/// `.missing` source presence.
197
207
static func missing( _ kind: SyntaxKind ) -> RawSyntax {
198
- return . node ( kind, [ ] , . missing, nil )
208
+ return RawSyntax ( kind: kind , layout : [ ] , presence : . missing)
199
209
}
200
210
201
211
/// Creates a RawSyntax token that's marked missing in the source with the
@@ -204,7 +214,7 @@ indirect enum RawSyntax: Codable {
204
214
/// - Returns: A new RawSyntax `.token` with the provided kind, no
205
215
/// leading/trailing trivia, and `.missing` source presence.
206
216
static func missingToken( _ kind: TokenKind ) -> RawSyntax {
207
- return . token ( kind, [ ] , [ ] , . missing, nil )
217
+ return RawSyntax ( kind: kind , leadingTrivia : [ ] , trailingTrivia : [ ] , presence : . missing)
208
218
}
209
219
210
220
/// Returns a new RawSyntax node with the provided layout instead of the
@@ -213,10 +223,10 @@ indirect enum RawSyntax: Codable {
213
223
/// is returned.
214
224
/// - Parameter newLayout: The children of the new node you're creating.
215
225
func replacingLayout( _ newLayout: [ RawSyntax ? ] ) -> RawSyntax {
216
- switch self {
217
- case let . node( kind, _, presence , _ ) :
218
- return . node ( kind, newLayout, presence, nil )
219
- case . token( _, _, _, _ , _ ) : return self
226
+ switch data {
227
+ case let . node( kind, _) :
228
+ return RawSyntax ( kind: kind , layout : newLayout, presence: presence )
229
+ case . token( _, _, _) : return self
220
230
}
221
231
}
222
232
@@ -259,14 +269,14 @@ extension RawSyntax: TextOutputStreamable {
259
269
/// - Parameter stream: The stream on which to output this node.
260
270
func write< Target> ( to target: inout Target )
261
271
where Target: TextOutputStream {
262
- switch self {
263
- case . node( _, let layout, _ , _ ) :
272
+ switch data {
273
+ case . node( _, let layout) :
264
274
for child in layout {
265
275
guard let child = child else { continue }
266
276
child. write ( to: & target)
267
277
}
268
- case let . token( kind, leadingTrivia, trailingTrivia, presence , _ ) :
269
- guard case . present = presence else { return }
278
+ case let . token( kind, leadingTrivia, trailingTrivia) :
279
+ guard isPresent else { return }
270
280
for piece in leadingTrivia {
271
281
piece. write ( to: & target)
272
282
}
@@ -280,14 +290,14 @@ extension RawSyntax: TextOutputStreamable {
280
290
281
291
extension RawSyntax {
282
292
func accumulateAbsolutePosition( _ pos: AbsolutePosition ) {
283
- switch self {
284
- case . node( _, let layout, _ , _ ) :
293
+ switch data {
294
+ case . node( _, let layout) :
285
295
for child in layout {
286
296
guard let child = child else { continue }
287
297
child. accumulateAbsolutePosition ( pos)
288
298
}
289
- case let . token( kind, leadingTrivia, trailingTrivia, presence , _ ) :
290
- guard case . present = presence else { return }
299
+ case let . token( kind, leadingTrivia, trailingTrivia) :
300
+ guard isPresent else { return }
291
301
for piece in leadingTrivia {
292
302
piece. accumulateAbsolutePosition ( pos)
293
303
}
@@ -299,31 +309,29 @@ extension RawSyntax {
299
309
}
300
310
301
311
var leadingTrivia : Trivia ? {
302
- switch self {
303
- case . node( _, let layout, _ , _ ) :
312
+ switch data {
313
+ case . node( _, let layout) :
304
314
for child in layout {
305
315
guard let child = child else { continue }
306
316
guard let result = child. leadingTrivia else { continue }
307
317
return result
308
318
}
309
319
return nil
310
- case let . token( _, leadingTrivia, _, presence, _) :
311
- guard case . present = presence else { return nil }
320
+ case let . token( _, leadingTrivia, _) :
312
321
return leadingTrivia
313
322
}
314
323
}
315
324
316
325
var trailingTrivia : Trivia ? {
317
- switch self {
318
- case . node( _, let layout, _ , _ ) :
326
+ switch data {
327
+ case . node( _, let layout) :
319
328
for child in layout. reversed ( ) {
320
329
guard let child = child else { continue }
321
330
guard let result = child. trailingTrivia else { continue }
322
331
return result
323
332
}
324
333
return nil
325
- case let . token( _, _, trailingTrivia, presence, _) :
326
- guard case . present = presence else { return nil }
334
+ case let . token( _, _, trailingTrivia) :
327
335
return trailingTrivia
328
336
}
329
337
}
0 commit comments