Skip to content

Commit 4d28598

Browse files
committed
Check that we are actually tracking the tree passed in as originalTree to originalNode
1 parent 7940864 commit 4d28598

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

Sources/SwiftSyntax/SyntaxTracking.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ extension SyntaxProtocol {
300300
/// - SeeAlso: ``SyntaxProtocol/tracked``
301301
/// - Complexity: O(tracked ranges in this tree) + O(width * depth of original tree)
302302
public func originalNode(in originalTree: some SyntaxProtocol) -> Self? {
303+
guard Syntax(self).syntaxTracking?.trackedTree == originalTree.id.rootId else {
304+
return nil
305+
}
303306
guard let originalIndexInTree = Syntax(self).syntaxTracking?.originalIndexInTree(of: self.id.indexInTree) else {
304307
return nil
305308
}

Tests/SwiftSyntaxTest/SyntaxTrackingTests.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,45 @@ public class SyntaxTrackingTests: XCTestCase {
117117

118118
XCTAssertEqual(codeBlockItemList.last?.item.originalNode(in: originalFunction)?.id, originalFunction.id)
119119
}
120+
121+
func testTwoLayerModification() throws {
122+
let originalFunction = try FunctionDeclSyntax("func foo() {}").tracked
123+
let modifiedFunction = originalFunction.with(\.name, "bar")
124+
let secondModification = modifiedFunction.with(\.body, nil)
125+
126+
XCTAssertEqual(
127+
secondModification.funcKeyword.originalNode(in: originalFunction)?.id,
128+
originalFunction.funcKeyword.id
129+
)
130+
XCTAssertNil(secondModification.name.originalNode(in: originalFunction))
131+
XCTAssertNil(secondModification.name.originalNode(in: modifiedFunction))
132+
}
133+
134+
func testEditAndThenCreation() throws {
135+
let originalFunction = try FunctionDeclSyntax("func foo() {}").tracked
136+
let modifiedFunction = originalFunction.with(\.name, "bar")
137+
138+
let codeBlockItem = CodeBlockItemSyntax(item: .decl(DeclSyntax(modifiedFunction)))
139+
140+
XCTAssertEqual(
141+
codeBlockItem.item.as(FunctionDeclSyntax.self)?.funcKeyword.originalNode(in: originalFunction)?.id,
142+
originalFunction.funcKeyword.id
143+
)
144+
XCTAssertNil(codeBlockItem.item.as(FunctionDeclSyntax.self)?.name.originalNode(in: originalFunction)?.id)
145+
XCTAssertNil(codeBlockItem.item.as(FunctionDeclSyntax.self)?.name.originalNode(in: modifiedFunction)?.id)
146+
}
147+
148+
func testStartTrackingModifiedNode() throws {
149+
let originalFunction = try FunctionDeclSyntax("func foo() {}").tracked
150+
let modifiedFunction = originalFunction.with(\.name, "bar").tracked
151+
let secondModification = modifiedFunction.with(\.body, nil)
152+
153+
XCTAssertNil(secondModification.funcKeyword.originalNode(in: originalFunction))
154+
XCTAssertEqual(
155+
secondModification.funcKeyword.originalNode(in: modifiedFunction)?.id,
156+
modifiedFunction.funcKeyword.id
157+
)
158+
XCTAssertNil(secondModification.name.originalNode(in: originalFunction))
159+
XCTAssertEqual(secondModification.name.originalNode(in: modifiedFunction)?.id, modifiedFunction.name.id)
160+
}
120161
}

0 commit comments

Comments
 (0)