@@ -314,7 +314,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
314
314
315
315
// newLayout is nil until the first child node is rewritten and rewritten
316
316
// nodes are being collected.
317
- var newLayout: ContiguousArray <RawSyntax?>?
317
+ var newLayout: UnsafeMutableBufferPointer <RawSyntax?> = .init(start: nil, count: 0)
318
318
319
319
// Keep 'SyntaxArena' of rewritten nodes alive until they are wrapped
320
320
// with 'Syntax'
@@ -328,12 +328,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
328
328
defer { childIndex += 1 }
329
329
330
330
guard let child = raw, viewMode.shouldTraverse(node: child) else {
331
- // Node does not exist or should not be visited. If we are collecting
332
- // rewritten nodes, we need to collect this one as well, otherwise we
333
- // can ignore it.
334
- if newLayout != nil {
335
- newLayout!.append(raw)
336
- }
331
+ // Node does not exist or should not be visited.
337
332
continue
338
333
}
339
334
@@ -343,44 +338,31 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
343
338
dispatchVisit(&childNode)
344
339
if childNode.raw.id != child.id {
345
340
// The node was rewritten, let's handle it
346
- if newLayout == nil {
341
+
342
+ if newLayout.baseAddress == nil {
347
343
// We have not yet collected any previous rewritten nodes. Initialize
348
- // the new layout with the previous nodes of the parent. This is
349
- // possible, since we know they were not rewritten.
350
-
351
- // The below implementation is based on Collection.map but directly
352
- // reserves enough capacity for the entire layout.
353
- newLayout = ContiguousArray<RawSyntax?>()
354
- newLayout!.reserveCapacity(node.raw.layoutView!.children.count)
355
- for j in 0..<childIndex {
356
- newLayout!.append(node.raw.layoutView!.children[j])
357
- }
344
+ // the new layout with the previous nodes of the parent.
345
+ newLayout = .allocate(capacity: node.raw.layoutView!.children.count)
346
+ _ = newLayout.initialize(fromContentsOf: node.raw.layoutView!.children)
358
347
}
359
348
360
- // Now that we know we have a new layout in which we collect rewritten
361
- // nodes, add it.
349
+ // Update the rewritten child.
350
+ newLayout[childIndex] = childNode.raw
351
+ // Retain the syntax arena of the new node until it's wrapped with Syntax node.
362
352
rewrittens.append(childNode.raw.arenaReference.retained)
363
- newLayout!.append(childNode.raw)
364
- } else {
365
- // The node was not changed by the rewriter. Only store it if a previous
366
- // node has been rewritten and we are collecting a rewritten layout.
367
- if newLayout != nil {
368
- newLayout!.append(raw)
369
- }
370
353
}
371
354
372
355
// Recycle 'childNode.info'
373
356
nodeFactory.dispose(&childNode)
374
357
}
375
358
376
- if let newLayout {
359
+ if newLayout.baseAddress != nil {
377
360
// A child node was rewritten. Build the updated node.
378
361
379
- // Sanity check, ensure the new children are the same length.
380
- precondition(newLayout.count == node.raw.layoutView!.children.count)
381
-
382
362
let arena = self.arena ?? SyntaxArena()
383
- let newRaw = node.raw.layoutView!.replacingLayout(with: Array(newLayout), arena: arena)
363
+ let newRaw = node.raw.layoutView!.replacingLayout(with: newLayout, arena: arena)
364
+ newLayout.deinitialize()
365
+ newLayout.deallocate()
384
366
// 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here.
385
367
return withExtendedLifetime(rewrittens) {
386
368
Syntax(raw: newRaw, rawNodeArena: arena).cast(SyntaxType.self)
0 commit comments