@@ -314,7 +314,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
314314
315315 // newLayout is nil until the first child node is rewritten and rewritten
316316 // nodes are being collected.
317- var newLayout: ContiguousArray <RawSyntax?>?
317+ var newLayout: UnsafeMutableBufferPointer <RawSyntax?> = .init(start: nil, count: 0)
318318
319319 // Keep 'SyntaxArena' of rewritten nodes alive until they are wrapped
320320 // with 'Syntax'
@@ -328,12 +328,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
328328 defer { childIndex += 1 }
329329
330330 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.
337332 continue
338333 }
339334
@@ -343,44 +338,31 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
343338 dispatchVisit(&childNode)
344339 if childNode.raw.id != child.id {
345340 // The node was rewritten, let's handle it
346- if newLayout == nil {
341+
342+ if newLayout.baseAddress == nil {
347343 // 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)
358347 }
359348
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.
362352 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- }
370353 }
371354
372355 // Recycle 'childNode.info'
373356 nodeFactory.dispose(&childNode)
374357 }
375358
376- if let newLayout {
359+ if newLayout.baseAddress != nil {
377360 // A child node was rewritten. Build the updated node.
378361
379- // Sanity check, ensure the new children are the same length.
380- precondition(newLayout.count == node.raw.layoutView!.children.count)
381-
382362 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()
384366 // 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here.
385367 return withExtendedLifetime(rewrittens) {
386368 Syntax(raw: newRaw, rawNodeArena: arena).cast(SyntaxType.self)
0 commit comments