@@ -24,9 +24,11 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
24
24
// For root node.
25
25
struct Root : Sendable {
26
26
private let arena : RetainedSyntaxArena
27
+ var syntaxTracking : SyntaxTracking ?
27
28
28
- init ( arena: RetainedSyntaxArena ) {
29
+ init ( arena: RetainedSyntaxArena , syntaxTracking : SyntaxTracking ? ) {
29
30
self . arena = arena
31
+ self . syntaxTracking = syntaxTracking
30
32
}
31
33
}
32
34
@@ -52,6 +54,17 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
52
54
fileprivate var pointer : UnsafePointer < Root > {
53
55
return withUnsafePointer ( to: & value) { $0 }
54
56
}
57
+
58
+ /// Get a reference to the root info which can be mutated.
59
+ ///
60
+ /// - Warning: This must only be used if the caller is guaranteed to have exclusive access to the tree and no
61
+ /// concurrent accesses can happen. Effectively, this can only be guaranteed if the tree has just been created,
62
+ /// and it hasn't been returned to any function which might concurrently access it.
63
+ /// In practice, this should only be used to set the `SyntaxTracking` on the root after a new tree has been
64
+ /// created (eg. by replacing a child in an existing tree) but before that new tree is returned to the client.
65
+ fileprivate var mutablePointer : UnsafeMutablePointer < Root > {
66
+ return withUnsafeMutablePointer ( to: & value) { $0 }
67
+ }
55
68
}
56
69
57
70
// For non-root nodes.
@@ -111,6 +124,20 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
111
124
}
112
125
}
113
126
127
+ /// Get a reference to the root info which can be mutated.
128
+ ///
129
+ /// - Warning: This must only be used if the caller is guaranteed to have exclusive access to the tree and no
130
+ /// concurrent accesses can happen. Effectively, this can only be guaranteed if the tree has just been created,
131
+ /// and it hasn't been returned to any function which might concurrently access it.
132
+ /// In practice, this should only be used to set the `SyntaxTracking` on the root after a new tree has been
133
+ /// created (eg. by replacing a child in an existing tree) but before that new tree is returned to the client.
134
+ var mutableRootInfo : UnsafeMutablePointer < Info . Root > {
135
+ switch info. info! {
136
+ case . root( let info) : return info. mutablePointer
137
+ case . nonRoot( let info) : return info. parent. mutableRootInfo
138
+ }
139
+ }
140
+
114
141
private var nonRootInfo : Info . NonRoot ? {
115
142
switch info. info! {
116
143
case . root( _) : return nil
@@ -145,6 +172,20 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
145
172
absoluteInfo. nodeId
146
173
}
147
174
175
+ var syntaxTracking : SyntaxTracking ? {
176
+ rootInfo. pointee. syntaxTracking
177
+ }
178
+
179
+ /// Set the translation ranges of the entire tree.
180
+ ///
181
+ /// - Warning: This must only be used if the caller is guaranteed to have exclusive access to the tree and no
182
+ /// concurrent accesses can happen. Effectively, this can only be guaranteed if the tree has just been created,
183
+ /// and it hasn't been returned to any function which might concurrently access it.
184
+ func setSyntaxTrackingOfTree( _ syntaxTracking: SyntaxTracking ? ) {
185
+ precondition ( rootInfo. pointee. syntaxTracking == nil )
186
+ mutableRootInfo. pointee. syntaxTracking = syntaxTracking
187
+ }
188
+
148
189
/// The position of the start of this node's leading trivia
149
190
public var position : AbsolutePosition {
150
191
AbsolutePosition ( utf8Offset: Int ( absoluteInfo. offset) )
@@ -192,14 +233,21 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
192
233
/// has a chance to retain it.
193
234
static func forRoot( _ raw: RawSyntax , rawNodeArena: RetainedSyntaxArena ) -> Syntax {
194
235
precondition ( rawNodeArena == raw. arenaReference)
195
- return Syntax ( raw, info: Info ( . root( Syntax . Info. RefCountedRoot ( Syntax . Info. Root ( arena: rawNodeArena) ) ) ) )
236
+ return Syntax (
237
+ raw,
238
+ info: Info ( . root( Syntax . Info. RefCountedRoot ( Syntax . Info. Root ( arena: rawNodeArena, syntaxTracking: nil ) ) ) )
239
+ )
196
240
}
197
241
198
242
static func forRoot( _ raw: RawSyntax , rawNodeArena: SyntaxArena ) -> Syntax {
199
243
precondition ( rawNodeArena == raw. arenaReference)
200
244
return Syntax (
201
245
raw,
202
- info: Info ( . root( Syntax . Info. RefCountedRoot ( Syntax . Info. Root ( arena: RetainedSyntaxArena ( rawNodeArena) ) ) ) )
246
+ info: Info (
247
+ . root(
248
+ Syntax . Info. RefCountedRoot ( Syntax . Info. Root ( arena: RetainedSyntaxArena ( rawNodeArena) , syntaxTracking: nil ) )
249
+ )
250
+ )
203
251
)
204
252
}
205
253
@@ -296,12 +344,23 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
296
344
/// `newChild` has been addded to the result.
297
345
func replacingChild( at index: Int , with newChild: Syntax ? , arena: SyntaxArena ) -> Syntax {
298
346
return withExtendedLifetime ( newChild) {
299
- return replacingChild (
347
+ let result = replacingChild (
300
348
at: index,
301
349
with: newChild? . raw,
302
350
rawNodeArena: newChild? . raw. arenaReference. retained,
303
351
allocationArena: arena
304
352
)
353
+ if trackedTree != nil {
354
+ var iter = RawSyntaxChildren ( absoluteRaw) . makeIterator ( )
355
+ for _ in 0 ..< index { _ = iter. next ( ) }
356
+ let ( raw, info) = iter. next ( ) !
357
+ result. mutableRootInfo. pointee. syntaxTracking = syntaxTracking? . replacing (
358
+ oldIndexInTree: info. nodeId. indexInTree,
359
+ oldTotalNodes: raw? . totalNodes ?? 0 ,
360
+ by: newChild
361
+ )
362
+ }
363
+ return result
305
364
}
306
365
}
307
366
0 commit comments