Skip to content

Commit e7db129

Browse files
authored
Merge pull request #1880 from ahoppen/ahoppen/syntax-collection-index
Deprecate `SyntaxCollection.replacing(childAt:with:)` in favor of a writable subscript
2 parents c4b8c2f + b852e3c commit e7db129

File tree

5 files changed

+34
-16
lines changed

5 files changed

+34
-16
lines changed

Sources/SwiftSyntax/SyntaxChildren.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
/// The data for an index in a syntax children collection that is not the end
1616
/// index. See ``SyntaxChildrenIndex`` for the representation of the end index.
17-
struct SyntaxChildrenIndexData: Comparable {
17+
struct SyntaxChildrenIndexData: Hashable, Comparable {
1818
/// The UTF-8 offset of the item at this index in the source file
1919
/// See `AbsoluteSyntaxPosition.offset`
2020
let offset: UInt32
@@ -50,7 +50,7 @@ struct SyntaxChildrenIndexData: Comparable {
5050
}
5151

5252
/// An index in a syntax children collection.
53-
public struct SyntaxChildrenIndex: Comparable, ExpressibleByNilLiteral {
53+
public struct SyntaxChildrenIndex: Hashable, Comparable, ExpressibleByNilLiteral {
5454
/// Construct the `endIndex` of a ``SyntaxChildren`` collection.
5555
public init(nilLiteral: ()) {
5656
self.data = nil

Sources/SwiftSyntax/SyntaxCollection.swift

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
public protocol SyntaxCollection: SyntaxProtocol, BidirectionalCollection where Element: SyntaxProtocol {
13+
public protocol SyntaxCollection: SyntaxProtocol, BidirectionalCollection, MutableCollection where Element: SyntaxProtocol {
1414
associatedtype Iterator = SyntaxCollectionIterator<Element>
1515

1616
/// The ``SyntaxKind`` of the syntax node that conforms to ``SyntaxCollection``.
@@ -116,6 +116,7 @@ extension SyntaxCollection {
116116
/// - syntax: The element to replace with.
117117
///
118118
/// - Returns: A new collection with the new element at the provided index.
119+
@available(*, deprecated, message: "Use .with(\\.[index], newValue) instead")
119120
public func replacing(childAt index: Int, with syntax: Element) -> Self {
120121
var newLayout = layoutView.formLayoutArray()
121122
/// Make sure the index is a valid index for replacing
@@ -217,9 +218,24 @@ extension SyntaxCollection {
217218
}
218219

219220
public subscript(position: SyntaxChildrenIndex) -> Element {
220-
let (raw, info) = rawChildren[position]
221-
let absoluteRaw = AbsoluteRawSyntax(raw: raw!, info: info)
222-
let data = SyntaxData(absoluteRaw, parent: Syntax(self))
223-
return Syntax(data).cast(Element.self)
221+
get {
222+
let (raw, info) = rawChildren[position]
223+
let absoluteRaw = AbsoluteRawSyntax(raw: raw!, info: info)
224+
let data = SyntaxData(absoluteRaw, parent: Syntax(self))
225+
return Syntax(data).cast(Element.self)
226+
}
227+
set {
228+
guard let indexToReplace = (position.data?.indexInParent).map(Int.init) else {
229+
preconditionFailure("Cannot replace element at the end index")
230+
}
231+
var newLayout = layoutView.formLayoutArray()
232+
/// Make sure the index is a valid index for replacing
233+
precondition(
234+
(newLayout.startIndex..<newLayout.endIndex).contains(indexToReplace),
235+
"replacing node at invalid index \(index)"
236+
)
237+
newLayout[indexToReplace] = newValue.raw
238+
self = replacingLayout(newLayout)
239+
}
224240
}
225241
}

Sources/SwiftSyntaxMacroExpansion/MacroSystem.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,9 +340,9 @@ class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
340340
return DeclSyntax(
341341
visitedVarDecl.with(
342342
\.bindings,
343-
visitedVarDecl.bindings.replacing(
344-
childAt: 0,
345-
with: binding.with(
343+
visitedVarDecl.bindings.with(
344+
\.[visitedVarDecl.bindings.startIndex],
345+
binding.with(
346346
\.accessor,
347347
.accessors(
348348
.init(

Tests/SwiftSyntaxMacroExpansionTest/MacroSystemTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ private func replaceFirstLabel(
5858
return tuple
5959
}
6060

61-
return tuple.replacing(
62-
childAt: 0,
63-
with: firstElement.with(\.label, .identifier(newLabel))
61+
return tuple.with(
62+
\.[tuple.startIndex],
63+
firstElement.with(\.label, .identifier(newLabel))
6464
)
6565
}
6666

Tests/SwiftSyntaxTest/SyntaxCollectionsTests.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,11 @@ public class SyntaxCollectionsTests: XCTestCase {
110110
integerLiteralElement(2),
111111
])
112112

113-
let newArrayElementList = arrayElementList.replacing(
114-
childAt: 2,
115-
with: integerLiteralElement(3)
113+
let lastElementIndex = arrayElementList.index(arrayElementList.startIndex, offsetBy: 2)
114+
115+
let newArrayElementList = arrayElementList.with(
116+
\.[lastElementIndex],
117+
integerLiteralElement(3)
116118
)
117119

118120
XCTAssertNotNil(newArrayElementList.child(at: 2))

0 commit comments

Comments
 (0)