Skip to content

Commit e19c5f2

Browse files
committed
Eliminate SyntaxArena.default
SyntaxArena.default was a global arena which just leaked. Eliminate it, and make all Syntax factory/modifier API receive an optioal SyntaxArena parameter. If the parameter is omitted, use a new arena. rdar://101894396
1 parent ce11d7a commit e19c5f2

22 files changed

+9759
-7664
lines changed

Sources/SwiftSyntax/Raw/RawSyntax.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ 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+
func withLeadingTrivia(_ leadingTrivia: Trivia, arena: SyntaxArena) -> RawSyntax? {
223223
switch view {
224224
case .token(let tokenView):
225225
return .makeMaterializedToken(
@@ -229,7 +229,7 @@ extension RawSyntax {
229229
arena: arena)
230230
case .layout(let layoutView):
231231
for (index, child) in layoutView.children.enumerated() {
232-
if let replaced = child?.withLeadingTrivia(leadingTrivia) {
232+
if let replaced = child?.withLeadingTrivia(leadingTrivia, arena: arena) {
233233
return layoutView.replacingChild(at: index, with: replaced, arena: arena)
234234
}
235235
}
@@ -241,7 +241,7 @@ extension RawSyntax {
241241
/// If the syntax tree did not contain a token and thus no trivia could be attached to it, `nil` is returned.
242242
/// - Parameters:
243243
/// - trailingTrivia: The trivia to attach.
244-
func withTrailingTrivia(_ trailingTrivia: Trivia) -> RawSyntax? {
244+
func withTrailingTrivia(_ trailingTrivia: Trivia, arena: SyntaxArena) -> RawSyntax? {
245245
switch view {
246246
case .token(let tokenView):
247247
return .makeMaterializedToken(
@@ -251,7 +251,7 @@ extension RawSyntax {
251251
arena: arena)
252252
case .layout(let layoutView):
253253
for (index, child) in layoutView.children.enumerated().reversed() {
254-
if let replaced = child?.withTrailingTrivia(trailingTrivia) {
254+
if let replaced = child?.withTrailingTrivia(trailingTrivia, arena: arena) {
255255
return layoutView.replacingChild(at: index, with: replaced, arena: arena)
256256
}
257257
}

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: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,14 +481,14 @@ public extension SyntaxProtocol {
481481

482482
/// Returns a new syntax node with its leading trivia replaced
483483
/// by the provided trivia.
484-
func withLeadingTrivia(_ leadingTrivia: Trivia) -> Self {
485-
return Self(Syntax(data.withLeadingTrivia(leadingTrivia)))!
484+
func withLeadingTrivia(_ leadingTrivia: Trivia, arena: SyntaxArena = SyntaxArena()) -> Self {
485+
return Self(Syntax(data.withLeadingTrivia(leadingTrivia, arena: arena)))!
486486
}
487487

488488
/// Returns a new syntax node with its trailing trivia replaced
489489
/// by the provided trivia.
490-
func withTrailingTrivia(_ trailingTrivia: Trivia) -> Self {
491-
return Self(Syntax(data.withTrailingTrivia(trailingTrivia)))!
490+
func withTrailingTrivia(_ trailingTrivia: Trivia, arena: SyntaxArena = SyntaxArena()) -> Self {
491+
return Self(Syntax(data.withTrailingTrivia(trailingTrivia, arena: arena)))!
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: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,16 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
117117
self._syntaxNode = Syntax(data)
118118
}
119119

120-
public init(_ children: [Element]) {
120+
public init(_ children: [Element]) { self.init(children, arena: SyntaxArena()) }
121+
122+
% # NOTE: Don't make 'arena' defaulted because:
123+
% # * Some clients use 'XXXListSyntax.init' as a '([Element]) -> XXXListSyntax'
124+
% # function
125+
% # * SyntaxBuilder has e.g. 'init(_: [ExprSyntaxProtocol])' method that makes
126+
% # 'XXXListSyntax([ExprSyntax(node)!])' ambiguous
127+
public init(_ children: [Element], arena: SyntaxArena) {
121128
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
122-
from: children.map { $0.raw }, arena: .default)
129+
from: children.map { $0.raw }, arena: arena)
123130
let data = SyntaxData.forRoot(raw)
124131
self.init(data)
125132
}
@@ -134,9 +141,10 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
134141
/// collection.
135142
/// - Returns: A new `${node.name}` with the new layout underlying it.
136143
internal func replacingLayout(
137-
_ layout: [RawSyntax?]) -> ${node.name} {
138-
let newRaw = layoutView.replacingLayout(with: layout, arena: .default)
139-
let newData = data.replacingSelf(newRaw)
144+
_ layout: [RawSyntax?],
145+
arena: SyntaxArena) -> ${node.name} {
146+
let newRaw = layoutView.replacingLayout(with: layout, arena: arena)
147+
let newData = data.replacingSelf(newRaw, arena: arena)
140148
return ${node.name}(newData)
141149
}
142150

@@ -145,10 +153,10 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
145153
///
146154
/// - Parameter syntax: The element to append.
147155
/// - Returns: A new `${node.name}` with that element appended to the end.
148-
public func appending(_ syntax: Element) -> ${node.name} {
156+
public func appending(_ syntax: Element, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
149157
var newLayout = layoutView.formLayoutArray()
150158
newLayout.append(syntax.raw)
151-
return replacingLayout(newLayout)
159+
return replacingLayout(newLayout, arena: arena)
152160
}
153161

154162
/// Creates a new `${node.name}` by prepending the provided syntax element
@@ -157,8 +165,8 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
157165
/// - Parameter syntax: The element to prepend.
158166
/// - Returns: A new `${node.name}` with that element prepended to the
159167
/// beginning.
160-
public func prepending(_ syntax: Element) -> ${node.name} {
161-
return inserting(syntax, at: 0)
168+
public func prepending(_ syntax: Element, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
169+
return inserting(syntax, at: 0, arena: arena)
162170
}
163171

164172
/// Creates a new `${node.name}` by inserting the provided syntax element
@@ -169,13 +177,13 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
169177
/// - index: The index at which to insert the element in the collection.
170178
///
171179
/// - Returns: A new `${node.name}` with that element appended to the end.
172-
public func inserting(_ syntax: Element, at index: Int) -> ${node.name} {
180+
public func inserting(_ syntax: Element, at index: Int, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
173181
var newLayout = layoutView.formLayoutArray()
174182
/// Make sure the index is a valid insertion index (0 to 1 past the end)
175183
precondition((newLayout.startIndex...newLayout.endIndex).contains(index),
176184
"inserting node at invalid index \(index)")
177185
newLayout.insert(syntax.raw, at: index)
178-
return replacingLayout(newLayout)
186+
return replacingLayout(newLayout, arena: arena)
179187
}
180188

181189
/// Creates a new `${node.name}` by replacing the syntax element
@@ -186,13 +194,13 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
186194
/// - syntax: The element to replace with.
187195
///
188196
/// - Returns: A new `${node.name}` with the new element at the provided index.
189-
public func replacing(childAt index: Int, with syntax: Element) -> ${node.name} {
197+
public func replacing(childAt index: Int, with syntax: Element, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
190198
var newLayout = layoutView.formLayoutArray()
191199
/// Make sure the index is a valid index for replacing
192200
precondition((newLayout.startIndex..<newLayout.endIndex).contains(index),
193201
"replacing node at invalid index \(index)")
194202
newLayout[index] = syntax.raw
195-
return replacingLayout(newLayout)
203+
return replacingLayout(newLayout, arena: arena)
196204
}
197205

198206
/// Creates a new `${node.name}` by removing the syntax element at the
@@ -201,55 +209,55 @@ public struct ${node.name}: SyntaxCollection, SyntaxHashable {
201209
/// - Parameter index: The index of the element to remove from the collection.
202210
/// - Returns: A new `${node.name}` with the element at the provided index
203211
/// removed.
204-
public func removing(childAt index: Int) -> ${node.name} {
212+
public func removing(childAt index: Int, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
205213
var newLayout = layoutView.formLayoutArray()
206214
newLayout.remove(at: index)
207-
return replacingLayout(newLayout)
215+
return replacingLayout(newLayout, arena: arena)
208216
}
209217

210218
/// Creates a new `${node.name}` by removing the first element.
211219
///
212220
/// - Returns: A new `${node.name}` with the first element removed.
213-
public func removingFirst() -> ${node.name} {
221+
public func removingFirst(arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
214222
var newLayout = layoutView.formLayoutArray()
215223
newLayout.removeFirst()
216-
return replacingLayout(newLayout)
224+
return replacingLayout(newLayout, arena: arena)
217225
}
218226

219227
/// Creates a new `${node.name}` by removing the last element.
220228
///
221229
/// - Returns: A new `${node.name}` with the last element removed.
222-
public func removingLast() -> ${node.name} {
230+
public func removingLast(arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
223231
var newLayout = layoutView.formLayoutArray()
224232
newLayout.removeLast()
225-
return replacingLayout(newLayout)
233+
return replacingLayout(newLayout, arena: arena)
226234
}
227235

228236
/// Returns a new `${node.name}` with its leading trivia replaced
229237
/// by the provided trivia.
230-
public func withLeadingTrivia(_ leadingTrivia: Trivia) -> ${node.name} {
231-
return ${node.name}(data.withLeadingTrivia(leadingTrivia))
238+
public func withLeadingTrivia(_ leadingTrivia: Trivia, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
239+
return ${node.name}(data.withLeadingTrivia(leadingTrivia, arena: arena))
232240
}
233241

234242
/// Returns a new `${node.name}` with its trailing trivia replaced
235243
/// by the provided trivia.
236-
public func withTrailingTrivia(_ trailingTrivia: Trivia) -> ${node.name} {
237-
return ${node.name}(data.withTrailingTrivia(trailingTrivia))
244+
public func withTrailingTrivia(_ trailingTrivia: Trivia, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
245+
return ${node.name}(data.withTrailingTrivia(trailingTrivia, arena: arena))
238246
}
239247

240248
/// Returns a new `${node.name}` with its leading trivia removed.
241-
public func withoutLeadingTrivia() -> ${node.name} {
242-
return withLeadingTrivia([])
249+
public func withoutLeadingTrivia(arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
250+
return withLeadingTrivia([], arena: arena)
243251
}
244252

245253
/// Returns a new `${node.name}` with its trailing trivia removed.
246-
public func withoutTrailingTrivia() -> ${node.name} {
247-
return withTrailingTrivia([])
254+
public func withoutTrailingTrivia(arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
255+
return withTrailingTrivia([], arena: arena)
248256
}
249257

250258
/// Returns a new `${node.name}` with all trivia removed.
251-
public func withoutTrivia() -> ${node.name} {
252-
return withoutLeadingTrivia().withoutTrailingTrivia()
259+
public func withoutTrivia(arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
260+
return withoutLeadingTrivia(arena: arena).withoutTrailingTrivia(arena: arena)
253261
}
254262

255263
/// The leading trivia (spaces, newlines, etc.) associated with this `${node.name}`.

Sources/SwiftSyntax/SyntaxData.swift

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -325,12 +325,11 @@ struct SyntaxData {
325325
/// - parameter newRaw: The new RawSyntax that will back the new `Data`
326326
/// - returns: A tuple of both the new root node and the new data with the raw
327327
/// layout replaced.
328-
func replacingSelf(
329-
_ newRaw: RawSyntax) -> SyntaxData {
328+
func replacingSelf(_ newRaw: RawSyntax, arena: SyntaxArena) -> SyntaxData {
330329
// If we have a parent already, then ask our current parent to copy itself
331330
// recursively up to the root.
332331
if let parent = parent {
333-
let parentData = parent.replacingChild(newRaw, at: indexInParent)
332+
let parentData = parent.replacingChild(newRaw, at: indexInParent, arena: arena)
334333
let newParent = Syntax(parentData)
335334
return SyntaxData(absoluteRaw.replacingSelf(newRaw, newRootId: parentData.nodeId.rootId), parent: newParent)
336335
} else {
@@ -349,22 +348,22 @@ struct SyntaxData {
349348
/// - Returns: The new root node created by this operation, and the new child
350349
/// syntax data.
351350
/// - 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)
351+
func replacingChild(_ child: RawSyntax?, at index: Int, arena: SyntaxArena) -> SyntaxData {
352+
let newRaw = raw.layoutView!.replacingChild(at: index, with: child, arena: arena)
353+
return replacingSelf(newRaw, arena: arena)
355354
}
356355

357-
func withLeadingTrivia(_ leadingTrivia: Trivia) -> SyntaxData {
358-
if let raw = raw.withLeadingTrivia(leadingTrivia) {
359-
return replacingSelf(raw)
356+
func withLeadingTrivia(_ leadingTrivia: Trivia, arena: SyntaxArena) -> SyntaxData {
357+
if let raw = raw.withLeadingTrivia(leadingTrivia, arena: arena) {
358+
return replacingSelf(raw, arena: arena)
360359
} else {
361360
return self
362361
}
363362
}
364363

365-
func withTrailingTrivia(_ trailingTrivia: Trivia) -> SyntaxData {
366-
if let raw = raw.withTrailingTrivia(trailingTrivia) {
367-
return replacingSelf(raw)
364+
func withTrailingTrivia(_ trailingTrivia: Trivia, arena: SyntaxArena) -> SyntaxData {
365+
if let raw = raw.withTrailingTrivia(trailingTrivia, arena: arena) {
366+
return replacingSelf(raw, arena: arena)
368367
} else {
369368
return self
370369
}

Sources/SwiftSyntax/SyntaxFactory.swift.gyb

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,19 @@ public enum SyntaxFactory {
3131
@available(*, deprecated, message: "Use initializer on TokenSyntax")
3232
public static func makeToken(_ kind: TokenKind, presence: SourcePresence,
3333
leadingTrivia: Trivia = [],
34-
trailingTrivia: Trivia = []) -> TokenSyntax {
34+
trailingTrivia: Trivia = [],
35+
arena: SyntaxArena = SyntaxArena()) -> TokenSyntax {
3536
let raw = RawSyntax.makeMaterializedToken(kind: kind, leadingTrivia: leadingTrivia,
36-
trailingTrivia: trailingTrivia, presence: presence, arena: .default)
37+
trailingTrivia: trailingTrivia, presence: presence, arena: arena)
3738
let data = SyntaxData.forRoot(raw)
3839
return TokenSyntax(data)
3940
}
4041

4142
@available(*, deprecated, message: "Use initializer on UnknownSyntax")
42-
public static func makeUnknownSyntax(tokens: [TokenSyntax]) -> UnknownSyntax {
43+
public static func makeUnknownSyntax(tokens: [TokenSyntax],
44+
arena: SyntaxArena = SyntaxArena()) -> UnknownSyntax {
4345
let raw = RawSyntax.makeLayout(kind: .unknown,
44-
from: tokens.map { $0.raw }, arena: .default)
46+
from: tokens.map { $0.raw }, arena: arena)
4547
let data = SyntaxData.forRoot(raw)
4648
return UnknownSyntax(data)
4749
}
@@ -68,7 +70,7 @@ public enum SyntaxFactory {
6870
% end
6971
% child_params = ', '.join(child_params)
7072
@available(*, deprecated, message: "Use initializer on ${node.name}")
71-
public static func make${node.syntax_kind}(${child_params}) -> ${node.name} {
73+
public static func make${node.syntax_kind}(${child_params}, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
7274
let layout: [RawSyntax?] = [
7375
% for child in node.children:
7476
% if child.is_optional:
@@ -79,16 +81,17 @@ public enum SyntaxFactory {
7981
% end
8082
]
8183
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
82-
from: layout, arena: .default)
84+
from: layout, arena: arena)
8385
let data = SyntaxData.forRoot(raw)
8486
return ${node.name}(data)
8587
}
8688
% elif node.is_syntax_collection():
8789
@available(*, deprecated, message: "Use initializer on ${node.name}")
8890
public static func make${node.syntax_kind}(
89-
_ elements: [${node.collection_element_type}]) -> ${node.name} {
91+
_ elements: [${node.collection_element_type}],
92+
arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
9093
let raw = RawSyntax.makeLayout(kind: SyntaxKind.${node.swift_syntax_kind},
91-
from: elements.map { $0.raw }, arena: .default)
94+
from: elements.map { $0.raw }, arena: arena)
9295
let data = SyntaxData.forRoot(raw)
9396
return ${node.name}(data)
9497
}
@@ -97,7 +100,7 @@ public enum SyntaxFactory {
97100
% if not node.is_base():
98101
% default_presence = 'missing' if node.is_missing() else 'present'
99102
@available(*, deprecated, message: "Use initializer on ${node.name}")
100-
public static func makeBlank${node.syntax_kind}(presence: SourcePresence = .${default_presence}) -> ${node.name} {
103+
public static func makeBlank${node.syntax_kind}(presence: SourcePresence = .${default_presence}, arena: SyntaxArena = SyntaxArena()) -> ${node.name} {
101104
let data = SyntaxData.forRoot(RawSyntax.makeLayout(kind: .${node.swift_syntax_kind},
102105
from: [
103106
% for child in node.children:
@@ -107,7 +110,7 @@ public enum SyntaxFactory {
107110
${make_missing_swift_child(child)},
108111
% end
109112
% end
110-
], arena: .default))
113+
], arena: arena))
111114
return ${node.name}(data)
112115
}
113116
% end

0 commit comments

Comments
 (0)