From 6b1895bb2b2ee2ba575c31f8b96b2e864bf23123 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 31 Aug 2023 14:30:57 -0700 Subject: [PATCH] Improve documentation of `SyntaxProtocol.tracked` and write entry in release notes --- Release Notes/510.md | 4 +++ Sources/SwiftSyntax/SyntaxTracking.swift | 31 ++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Release Notes/510.md b/Release Notes/510.md index 65e28280066..a041ae54ef8 100644 --- a/Release Notes/510.md +++ b/Release Notes/510.md @@ -20,6 +20,10 @@ - `DiagnosticSeverity` and `PluginMessage.Diagnostic.Severity` now have new case named `remark` - Description: Remarks are used by the Swift compiler and other tools to describe some aspect of translation that doesn't reflect correctness, but may be useful for the user. Remarks have been added to the diagnostic severity enums to align with the Swift compiler. - Pull Request: https://github.com/apple/swift-syntax/pull/2143 +- `SyntaxProtocol.tracked` / `SyntaxProtocol.originalNode(in:)` + - Description: `tracked` enables node tracking of a tree. For every tree derived from a tracked tree, `originalNode(in:)` returns the original node in the tracked tree. This allows clients to e.g. get the original location of a node in a source file after a tree has been modified. + - Issue: rdar://112679655 + - Pull Request: https://github.com/apple/swift-syntax/pull/2118 ## API Behavior Changes diff --git a/Sources/SwiftSyntax/SyntaxTracking.swift b/Sources/SwiftSyntax/SyntaxTracking.swift index f20390d01ff..58421612ded 100644 --- a/Sources/SwiftSyntax/SyntaxTracking.swift +++ b/Sources/SwiftSyntax/SyntaxTracking.swift @@ -226,7 +226,7 @@ extension SyntaxData { fileprivate var tracked: SyntaxData { if let parent { let parentTracked = parent.tracked - return parentTracked.child(at: self.indexInParent, parent: Syntax(parentTracked))! + return parentTracked.child(at: self.indexInParent)! } else { let result = SyntaxData.forRoot(self.raw, rawNodeArena: self.raw.arena) let syntaxTracking = SyntaxTracking( @@ -267,18 +267,39 @@ class IndexInTreeFinder: SyntaxAnyVisitor { } extension SyntaxProtocol { - /// The same `SyntaxData` but with tracking enabled in the entire tree. + /// Start tracking this syntax tree as the original tree for all trees derived + /// from it. /// - /// All syntax nodes derived from this will be able to find their - /// corresponding location in this original tree. + /// All syntax nodes derived from the returned, tracked, tree will be able to + /// find the corresponding node in the original tree by calling + /// ``SyntaxProtocol/originalNode(in:)``. + /// + /// Derived nodes are + /// - Nodes that contain a node from this tree as a subtree. + /// - Nodes that resulted from modification of a node in this tree (e.g. + /// modification of a child node or insertion of an element into a + /// collection). + /// - Detached subtrees of this tree (see ``SyntaxProtocol/detached``). + /// + /// Node tracking is not enabled by default because maintaining the mapping + /// back to the tracked tree has a performance cost that. + /// + /// A tree can only track a single original tree. I.e. it is not possible to + /// create a node that has one child in tracked tree A and another child in + /// tracked tree B. In practice, this should seldom pose an issue because the + /// most common use case is to mark the tree obtained from a file on disk as + /// the tracked tree and trees from separate source files will rarely be + /// merged. /// + /// - SeeAlso: ``SyntaxProtocol/originalNode(in:)`` /// - Complexity: O(number of ancestors) public var tracked: Self { return Syntax(self.data.tracked).cast(Self.self) } /// If this syntax node is tracking `originalTree` and this node originated - /// in that tree, return the corresponding corresponding node in `originalTree`. + /// from that tree, return the corresponding corresponding node in + /// `originalTree`. /// /// The original node will have the same structure as this node but the parent /// might be different since it's anchored in `originalTree`.