Skip to content

Commit 584d1ab

Browse files
committed
Eliminate SyntaxArena.default
SyntaxArena.default was a global arena which just leaked. Eliminate it, and make all Syntax factory/modifier API use a new arena. rdar://101894396
1 parent e44e18c commit 584d1ab

20 files changed

+12537
-10730
lines changed

Sources/SwiftSyntax/Raw/RawSyntax.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ extension RawSyntax {
219219
/// If the syntax tree did not contain a token and thus no trivia could be attached to it, `nil` is returned.
220220
/// - Parameters:
221221
/// - leadingTrivia: The trivia to attach.
222-
func withLeadingTrivia(_ leadingTrivia: Trivia) -> RawSyntax? {
222+
/// - arena: SyntaxArena to the result node data resides.
223+
func withLeadingTrivia(_ leadingTrivia: Trivia, arena: SyntaxArena) -> RawSyntax? {
223224
switch view {
224225
case .token(let tokenView):
225226
return .makeMaterializedToken(
@@ -229,7 +230,7 @@ extension RawSyntax {
229230
arena: arena)
230231
case .layout(let layoutView):
231232
for (index, child) in layoutView.children.enumerated() {
232-
if let replaced = child?.withLeadingTrivia(leadingTrivia) {
233+
if let replaced = child?.withLeadingTrivia(leadingTrivia, arena: arena) {
233234
return layoutView.replacingChild(at: index, with: replaced, arena: arena)
234235
}
235236
}
@@ -241,7 +242,8 @@ extension RawSyntax {
241242
/// If the syntax tree did not contain a token and thus no trivia could be attached to it, `nil` is returned.
242243
/// - Parameters:
243244
/// - trailingTrivia: The trivia to attach.
244-
func withTrailingTrivia(_ trailingTrivia: Trivia) -> RawSyntax? {
245+
/// - arena: SyntaxArena to the result node data resides.
246+
func withTrailingTrivia(_ trailingTrivia: Trivia, arena: SyntaxArena) -> RawSyntax? {
245247
switch view {
246248
case .token(let tokenView):
247249
return .makeMaterializedToken(
@@ -251,7 +253,7 @@ extension RawSyntax {
251253
arena: arena)
252254
case .layout(let layoutView):
253255
for (index, child) in layoutView.children.enumerated().reversed() {
254-
if let replaced = child?.withTrailingTrivia(trailingTrivia) {
256+
if let replaced = child?.withTrailingTrivia(trailingTrivia, arena: arena) {
255257
return layoutView.replacingChild(at: index, with: replaced, arena: arena)
256258
}
257259
}

Sources/SwiftSyntax/Raw/RawSyntaxTokenView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,24 +151,24 @@ public struct RawSyntaxTokenView {
151151
/// Returns a `RawSyntax` node with the same source text but with the token
152152
/// kind changed to `newValue`.
153153
@_spi(RawSyntax)
154-
public func withKind(_ newValue: TokenKind) -> RawSyntax {
154+
public func withKind(_ newValue: TokenKind, arena: SyntaxArena) -> RawSyntax {
155155
switch raw.rawData.payload {
156156
case .parsedToken(_):
157157
// The wholeText can't be continuous anymore. Make a materialized token.
158158
return .makeMaterializedToken(
159159
kind: newValue,
160160
leadingTrivia: formLeadingTrivia(),
161161
trailingTrivia: formTrailingTrivia(),
162-
arena: raw.arena)
162+
arena: arena)
163163
case .materializedToken(var payload):
164164
let decomposed = newValue.decomposeToRaw()
165165
let rawKind = decomposed.rawKind
166-
let text: SyntaxText = (decomposed.string.map({raw.arena.intern($0)}) ??
166+
let text: SyntaxText = (decomposed.string.map({arena.intern($0)}) ??
167167
decomposed.rawKind.defaultText ??
168168
"")
169169
payload.tokenKind = rawKind
170170
payload.tokenText = text
171-
return RawSyntax(arena: raw.arena, payload: .materializedToken(payload))
171+
return RawSyntax(arena: arena, payload: .materializedToken(payload))
172172
default:
173173
preconditionFailure("'withTokenKind()' is called on non-token raw syntax")
174174
}

Sources/SwiftSyntax/Syntax.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,13 +482,13 @@ public extension SyntaxProtocol {
482482
/// Returns a new syntax node with its leading trivia replaced
483483
/// by the provided trivia.
484484
func withLeadingTrivia(_ leadingTrivia: Trivia) -> Self {
485-
return Self(Syntax(data.withLeadingTrivia(leadingTrivia)))!
485+
return Self(Syntax(data.withLeadingTrivia(leadingTrivia, arena: SyntaxArena())))!
486486
}
487487

488488
/// Returns a new syntax node with its trailing trivia replaced
489489
/// by the provided trivia.
490490
func withTrailingTrivia(_ trailingTrivia: Trivia) -> Self {
491-
return Self(Syntax(data.withTrailingTrivia(trailingTrivia)))!
491+
return Self(Syntax(data.withTrailingTrivia(trailingTrivia, arena: SyntaxArena())))!
492492
}
493493

494494
/// Returns a new syntax node with its leading trivia removed.

Sources/SwiftSyntax/SyntaxArena.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,6 @@ struct SyntaxArenaRef: Equatable {
250250
}
251251
}
252252

253-
extension SyntaxArena {
254-
// FIXME: This is only for migration. All clients should move to "arena" model.
255-
//@available(*, deprecated, message: ".default SyntaxArena is subject to remove soon")
256-
public static let `default` = SyntaxArena()
257-
}
258-
259253
private func _defaultParseTriviaFunction(_ source: SyntaxText, _ position: TriviaPosition) -> [RawTriviaPiece] {
260254
preconditionFailure("Trivia parsing not supported")
261255
}

Sources/SwiftSyntax/SyntaxCollections.swift.gyb

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
118118
}
119119

120120
public init(_ children: [Element]) {
121-
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
122-
from: children.map { $0.raw }, arena: .default)
123-
let data = SyntaxData.forRoot(raw)
121+
let data: SyntaxData = withExtendedLifetime(SyntaxArena()) { arena in
122+
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
123+
from: children.map { $0.raw }, arena: arena)
124+
return SyntaxData.forRoot(raw)
125+
}
124126
self.init(data)
125127
}
126128

@@ -135,8 +137,9 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
135137
/// - Returns: A new `${node.name}` with the new layout underlying it.
136138
internal func replacingLayout(
137139
_ layout: [RawSyntax?]) -> ${node.name} {
138-
let newRaw = layoutView.replacingLayout(with: layout, arena: .default)
139-
let newData = data.replacingSelf(newRaw)
140+
let arena = SyntaxArena()
141+
let newRaw = layoutView.replacingLayout(with: layout, arena: arena)
142+
let newData = data.replacingSelf(newRaw, arena: arena)
140143
return ${node.name}(newData)
141144
}
142145

@@ -228,13 +231,13 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
228231
/// Returns a new `${node.name}` with its leading trivia replaced
229232
/// by the provided trivia.
230233
public func withLeadingTrivia(_ leadingTrivia: Trivia) -> ${node.name} {
231-
return ${node.name}(data.withLeadingTrivia(leadingTrivia))
234+
return ${node.name}(data.withLeadingTrivia(leadingTrivia, arena: SyntaxArena()))
232235
}
233236

234237
/// Returns a new `${node.name}` with its trailing trivia replaced
235238
/// by the provided trivia.
236239
public func withTrailingTrivia(_ trailingTrivia: Trivia) -> ${node.name} {
237-
return ${node.name}(data.withTrailingTrivia(trailingTrivia))
240+
return ${node.name}(data.withTrailingTrivia(trailingTrivia, arena: SyntaxArena()))
238241
}
239242

240243
/// Returns a new `${node.name}` with its leading trivia removed.

Sources/SwiftSyntax/SyntaxData.swift

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -322,15 +322,16 @@ struct SyntaxData {
322322

323323
/// Creates a copy of `self` and recursively creates `SyntaxData` nodes up to
324324
/// the root.
325-
/// - parameter newRaw: The new RawSyntax that will back the new `Data`
326-
/// - returns: A tuple of both the new root node and the new data with the raw
325+
/// - Parameters:
326+
/// - newRaw: The new RawSyntax that will back the new `Data`
327+
/// - arena: SyntaxArena to the result RawSyntax node data resides.
328+
/// - Returns: A tuple of both the new root node and the new data with the raw
327329
/// layout replaced.
328-
func replacingSelf(
329-
_ newRaw: RawSyntax) -> SyntaxData {
330+
func replacingSelf(_ newRaw: RawSyntax, arena: SyntaxArena) -> SyntaxData {
330331
// If we have a parent already, then ask our current parent to copy itself
331332
// recursively up to the root.
332333
if let parent = parent {
333-
let parentData = parent.replacingChild(newRaw, at: indexInParent)
334+
let parentData = parent.replacingChild(newRaw, at: indexInParent, arena: arena)
334335
let newParent = Syntax(parentData)
335336
return SyntaxData(absoluteRaw.replacingSelf(newRaw, newRootId: parentData.nodeId.rootId), parent: newParent)
336337
} else {
@@ -346,25 +347,26 @@ struct SyntaxData {
346347
/// - child: The raw syntax for the new child to replace.
347348
/// - index: The index pointing to where in the raw layout to place this
348349
/// child.
350+
/// - arena: SyntaxArena to the result RawSyntax node data resides.
349351
/// - Returns: The new root node created by this operation, and the new child
350352
/// syntax data.
351353
/// - SeeAlso: replacingSelf(_:)
352-
func replacingChild(_ child: RawSyntax?, at index: Int) -> SyntaxData {
353-
let newRaw = raw.layoutView!.replacingChild(at: index, with: child, arena: .default)
354-
return replacingSelf(newRaw)
354+
func replacingChild(_ child: RawSyntax?, at index: Int, arena: SyntaxArena) -> SyntaxData {
355+
let newRaw = raw.layoutView!.replacingChild(at: index, with: child, arena: arena)
356+
return replacingSelf(newRaw, arena: arena)
355357
}
356358

357-
func withLeadingTrivia(_ leadingTrivia: Trivia) -> SyntaxData {
358-
if let raw = raw.withLeadingTrivia(leadingTrivia) {
359-
return replacingSelf(raw)
359+
func withLeadingTrivia(_ leadingTrivia: Trivia, arena: SyntaxArena) -> SyntaxData {
360+
if let raw = raw.withLeadingTrivia(leadingTrivia, arena: arena) {
361+
return replacingSelf(raw, arena: arena)
360362
} else {
361363
return self
362364
}
363365
}
364366

365-
func withTrailingTrivia(_ trailingTrivia: Trivia) -> SyntaxData {
366-
if let raw = raw.withTrailingTrivia(trailingTrivia) {
367-
return replacingSelf(raw)
367+
func withTrailingTrivia(_ trailingTrivia: Trivia, arena: SyntaxArena) -> SyntaxData {
368+
if let raw = raw.withTrailingTrivia(trailingTrivia, arena: arena) {
369+
return replacingSelf(raw, arena: arena)
368370
} else {
369371
return self
370372
}

Sources/SwiftSyntax/SyntaxFactory.swift.gyb

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,16 @@ public enum SyntaxFactory {
3232
public static func makeToken(_ kind: TokenKind, presence: SourcePresence,
3333
leadingTrivia: Trivia = [],
3434
trailingTrivia: Trivia = []) -> TokenSyntax {
35-
let raw = RawSyntax.makeMaterializedToken(kind: kind, leadingTrivia: leadingTrivia,
36-
trailingTrivia: trailingTrivia, presence: presence, arena: .default)
37-
let data = SyntaxData.forRoot(raw)
38-
return TokenSyntax(data)
35+
TokenSyntax(
36+
kind,
37+
leadingTrivia: leadingTrivia,
38+
trailingTrivia: trailingTrivia,
39+
presence: presence)
3940
}
4041

4142
@available(*, deprecated, message: "Use initializer on UnknownSyntax")
4243
public static func makeUnknownSyntax(tokens: [TokenSyntax]) -> UnknownSyntax {
43-
let raw = RawSyntax.makeLayout(kind: .unknown,
44-
from: tokens.map { $0.raw }, arena: .default)
45-
let data = SyntaxData.forRoot(raw)
46-
return UnknownSyntax(data)
44+
UnknownSyntax(tokens: tokens)
4745
}
4846

4947
/// MARK: Syntax Node Creation APIs
@@ -78,37 +76,43 @@ public enum SyntaxFactory {
7876
% end
7977
% end
8078
]
81-
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
82-
from: layout, arena: .default)
83-
let data = SyntaxData.forRoot(raw)
84-
return ${node.name}(data)
79+
return withExtendedLifetime(SyntaxArena()) { arena in
80+
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
81+
from: layout, arena: arena)
82+
let data = SyntaxData.forRoot(raw)
83+
return ${node.name}(data)
84+
}
8585
}
8686
% elif node.is_syntax_collection():
8787
@available(*, deprecated, message: "Use initializer on ${node.name}")
8888
public static func make${node.syntax_kind}(
8989
_ elements: [${node.collection_element_type}]) -> ${node.name} {
90-
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
91-
from: elements.map { $0.raw }, arena: .default)
92-
let data = SyntaxData.forRoot(raw)
93-
return ${node.name}(data)
90+
return withExtendedLifetime(SyntaxArena()) { arena in
91+
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
92+
from: elements.map { $0.raw }, arena: arena)
93+
let data = SyntaxData.forRoot(raw)
94+
return ${node.name}(data)
95+
}
9496
}
9597
% end
9698

9799
% if not node.is_base():
98100
% default_presence = 'missing' if node.is_missing() else 'present'
99101
@available(*, deprecated, message: "Use initializer on ${node.name}")
100102
public static func makeBlank${node.syntax_kind}(presence: SourcePresence = .${default_presence}) -> ${node.name} {
101-
let data = SyntaxData.forRoot(RawSyntax.makeLayout(kind: .${node.swift_syntax_kind},
102-
from: [
103+
return withExtendedLifetime(SyntaxArena()) { arena in
104+
let data = SyntaxData.forRoot(RawSyntax.makeLayout(kind: .${node.swift_syntax_kind},
105+
from: [
103106
% for child in node.children:
104107
% if child.is_optional:
105-
nil,
108+
nil,
106109
% else:
107-
${make_missing_swift_child(child)},
110+
${make_missing_swift_child(child)},
108111
% end
109112
% end
110-
], arena: .default))
111-
return ${node.name}(data)
113+
], arena: arena))
114+
return ${node.name}(data)
115+
}
112116
}
113117
% end
114118
% end

Sources/SwiftSyntax/SyntaxNodes.swift.gyb.template

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
126126
% else:
127127
${child.swift_name}: ${param_type}${comma}
128128
% end
129-
% end
129+
% end
130130
) {
131131
let layout: [RawSyntax?] = [
132132
% for child in node.children:
@@ -137,9 +137,11 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
137137
% end
138138
% end
139139
]
140-
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
141-
from: layout, arena: .default)
142-
let data = SyntaxData.forRoot(raw)
140+
let data: SyntaxData = withExtendedLifetime(SyntaxArena()) { arena in
141+
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
142+
from: layout, arena: arena)
143+
return SyntaxData.forRoot(raw)
144+
}
143145
self.init(data)
144146
}
145147
% for (idx, child) in enumerate(node.children):
@@ -190,13 +192,14 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
190192
/// appended to its `${child.swift_name}` collection.
191193
public func add${child_elt}(_ element: ${child_elt_type}) -> ${node.name} {
192194
var collection: RawSyntax
195+
let arena = SyntaxArena()
193196
if let col = raw.layoutView!.children[${idx}] {
194-
collection = col.layoutView!.appending(element.raw, arena: .default)
197+
collection = col.layoutView!.appending(element.raw, arena: arena)
195198
} else {
196199
collection = RawSyntax.makeLayout(kind: SyntaxKind.${child_node.swift_syntax_kind},
197-
from: [element.raw], arena: .default)
200+
from: [element.raw], arena: arena)
198201
}
199-
let newData = data.replacingChild(collection, at: ${idx})
202+
let newData = data.replacingChild(collection, at: ${idx}, arena: arena)
200203
return ${node.name}(newData)
201204
}
202205
% end
@@ -207,14 +210,14 @@ public struct ${node.name}: ${base_type}Protocol, SyntaxHashable {
207210
/// Returns a copy of the receiver with its `${child.swift_name}` replaced.
208211
/// - param newChild: The new `${child.swift_name}` to replace the node's
209212
/// current `${child.swift_name}`, if present.
210-
public func with${child.name}(
211-
_ newChild: ${child_type}?) -> ${node.name} {
213+
public func with${child.name}(_ newChild: ${child_type}?) -> ${node.name} {
214+
let arena = SyntaxArena()
212215
% if child.is_optional:
213216
let raw = newChild?.raw
214217
% else:
215218
let raw = newChild?.raw ?? ${make_missing_swift_child(child)}
216219
% end
217-
let newData = data.replacingChild(raw, at: ${idx})
220+
let newData = data.replacingChild(raw, at: ${idx}, arena: arena)
218221
return ${node.name}(newData)
219222
}
220223
% end

0 commit comments

Comments
 (0)