|
10 | 10 | // |
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
13 | | -struct AbsoluteSyntaxPosition { |
14 | | - /// The UTF-8 offset of the syntax node in the source file |
15 | | - let offset: UInt32 |
16 | | - let indexInParent: UInt32 |
17 | | - |
18 | | - func advancedBySibling(_ raw: RawSyntax?) -> AbsoluteSyntaxPosition { |
19 | | - let newOffset = self.offset + UInt32(truncatingIfNeeded: raw?.totalLength.utf8Length ?? 0) |
20 | | - let newIndexInParent = self.indexInParent + 1 |
21 | | - return .init(offset: newOffset, indexInParent: newIndexInParent) |
22 | | - } |
23 | | - |
24 | | - func advancedToFirstChild() -> AbsoluteSyntaxPosition { |
25 | | - return .init(offset: self.offset, indexInParent: 0) |
26 | | - } |
27 | | - |
28 | | - static var forRoot: AbsoluteSyntaxPosition { |
29 | | - return .init(offset: 0, indexInParent: 0) |
30 | | - } |
31 | | -} |
32 | | - |
33 | | -/// AbsoluteSyntaxInfo represents the information that relates a RawSyntax to a |
34 | | -/// source file tree, like its absolute source offset. |
35 | | -struct AbsoluteSyntaxInfo { |
36 | | - let position: AbsoluteSyntaxPosition |
37 | | - let nodeId: SyntaxIdentifier |
38 | | - |
39 | | - /// The UTF-8 offset of the syntax node in the source file |
40 | | - var offset: UInt32 { return position.offset } |
41 | | - var indexInParent: UInt32 { return position.indexInParent } |
42 | | - |
43 | | - func advancedBySibling(_ raw: RawSyntax?) -> AbsoluteSyntaxInfo { |
44 | | - let newPosition = position.advancedBySibling(raw) |
45 | | - let newNodeId = nodeId.advancedBySibling(raw) |
46 | | - return .init(position: newPosition, nodeId: newNodeId) |
47 | | - } |
48 | | - |
49 | | - func advancedToFirstChild() -> AbsoluteSyntaxInfo { |
50 | | - let newPosition = position.advancedToFirstChild() |
51 | | - let newNodeId = nodeId.advancedToFirstChild() |
52 | | - return .init(position: newPosition, nodeId: newNodeId) |
53 | | - } |
54 | | - |
55 | | - static func forRoot(_ raw: RawSyntax) -> AbsoluteSyntaxInfo { |
56 | | - return .init(position: .forRoot, nodeId: .forRoot(raw)) |
57 | | - } |
58 | | -} |
59 | | - |
60 | | -/// Represents a unique value for a node within its own tree. |
61 | | -@_spi(RawSyntax) |
62 | | -public struct SyntaxIndexInTree: Comparable, Hashable { |
63 | | - let indexInTree: UInt32 |
64 | | - |
65 | | - static var zero: SyntaxIndexInTree = SyntaxIndexInTree(indexInTree: 0) |
66 | | - |
67 | | - /// Assuming that this index points to the start of ``Raw``, so that it points |
68 | | - /// to the next sibling of ``Raw``. |
69 | | - func advancedBy(_ raw: RawSyntax?) -> SyntaxIndexInTree { |
70 | | - let newIndexInTree = self.indexInTree + UInt32(truncatingIfNeeded: raw?.totalNodes ?? 0) |
71 | | - return .init(indexInTree: newIndexInTree) |
72 | | - } |
73 | | - |
74 | | - /// Assuming that this index points to the next sibling of ``Raw``, reverse it |
75 | | - /// so that it points to the start of ``Raw``. |
76 | | - func reversedBy(_ raw: RawSyntax?) -> SyntaxIndexInTree { |
77 | | - let newIndexInTree = self.indexInTree - UInt32(truncatingIfNeeded: raw?.totalNodes ?? 0) |
78 | | - return .init(indexInTree: newIndexInTree) |
79 | | - } |
80 | | - |
81 | | - func advancedToFirstChild() -> SyntaxIndexInTree { |
82 | | - let newIndexInTree = self.indexInTree + 1 |
83 | | - return .init(indexInTree: newIndexInTree) |
84 | | - } |
85 | | - |
86 | | - init(indexInTree: UInt32) { |
87 | | - self.indexInTree = indexInTree |
88 | | - } |
89 | | - |
90 | | - /// Returns `true` if `lhs` occurs before `rhs` in the tree. |
91 | | - public static func < (lhs: SyntaxIndexInTree, rhs: SyntaxIndexInTree) -> Bool { |
92 | | - return lhs.indexInTree < rhs.indexInTree |
93 | | - } |
94 | | -} |
95 | | - |
96 | | -/// Provides a stable and unique identity for ``Syntax`` nodes. |
97 | | -/// |
98 | | -/// Note that two nodes might have the same contents even if their IDs are |
99 | | -/// different. For example two different ``FunctionDeclSyntax`` nodes in the |
100 | | -/// might have the exact same contents but if they occur at a different |
101 | | -/// location in the source file, they have different IDs. |
102 | | -/// |
103 | | -/// Also note that the ID of a syntax node changes when it is anchored in a |
104 | | -/// different syntax tree. Modifying any node in the syntax tree a node is |
105 | | -/// contained in generates a copy of that tree and thus changes the IDs of all |
106 | | -/// nodes in the tree, not just the modified node's children. |
107 | | -public struct SyntaxIdentifier: Hashable { |
108 | | - /// Unique value for the root node. |
109 | | - /// |
110 | | - /// Multiple trees may have the same 'rootId' if their root RawSyntax is the |
111 | | - /// same instance. This guarantees that the trees with the same 'rootId' have |
112 | | - /// exact the same structure. But, two trees with exactly the same structure |
113 | | - /// might still have different 'rootId's. |
114 | | - let rootId: UInt |
115 | | - /// Unique value for a node within its own tree. |
116 | | - @_spi(RawSyntax) |
117 | | - public let indexInTree: SyntaxIndexInTree |
118 | | - |
119 | | - func advancedBySibling(_ raw: RawSyntax?) -> SyntaxIdentifier { |
120 | | - let newIndexInTree = indexInTree.advancedBy(raw) |
121 | | - return .init(rootId: self.rootId, indexInTree: newIndexInTree) |
122 | | - } |
123 | | - |
124 | | - func advancedToFirstChild() -> SyntaxIdentifier { |
125 | | - let newIndexInTree = self.indexInTree.advancedToFirstChild() |
126 | | - return .init(rootId: self.rootId, indexInTree: newIndexInTree) |
127 | | - } |
128 | | - |
129 | | - static func forRoot(_ raw: RawSyntax) -> SyntaxIdentifier { |
130 | | - return .init( |
131 | | - rootId: UInt(bitPattern: raw.pointer), |
132 | | - indexInTree: .zero |
133 | | - ) |
134 | | - } |
135 | | -} |
136 | | - |
137 | | -struct AbsoluteRawSyntax { |
138 | | - let raw: RawSyntax |
139 | | - let info: AbsoluteSyntaxInfo |
140 | | - |
141 | | - /// Returns first `present` child. |
142 | | - func firstChild(viewMode: SyntaxTreeViewMode) -> AbsoluteRawSyntax? { |
143 | | - guard let layoutView = raw.layoutView else { return nil } |
144 | | - var curInfo = info.advancedToFirstChild() |
145 | | - for childOpt in layoutView.children { |
146 | | - if let child = childOpt, viewMode.shouldTraverse(node: child) { |
147 | | - return AbsoluteRawSyntax(raw: child, info: curInfo) |
148 | | - } |
149 | | - curInfo = curInfo.advancedBySibling(childOpt) |
150 | | - } |
151 | | - return nil |
152 | | - } |
153 | | - |
154 | | - /// Returns next `present` sibling. |
155 | | - func nextSibling(parent: AbsoluteRawSyntax, viewMode: SyntaxTreeViewMode) -> AbsoluteRawSyntax? { |
156 | | - var curInfo = info.advancedBySibling(raw) |
157 | | - for siblingOpt in parent.raw.layoutView!.children.dropFirst(Int(info.indexInParent + 1)) { |
158 | | - if let sibling = siblingOpt, viewMode.shouldTraverse(node: sibling) { |
159 | | - return AbsoluteRawSyntax(raw: sibling, info: curInfo) |
160 | | - } |
161 | | - curInfo = curInfo.advancedBySibling(siblingOpt) |
162 | | - } |
163 | | - return nil |
164 | | - } |
165 | | - |
166 | | - func replacingSelf(_ newRaw: RawSyntax, newRootId: UInt) -> AbsoluteRawSyntax { |
167 | | - let nodeId = SyntaxIdentifier(rootId: newRootId, indexInTree: info.nodeId.indexInTree) |
168 | | - let newInfo = AbsoluteSyntaxInfo(position: info.position, nodeId: nodeId) |
169 | | - return .init(raw: newRaw, info: newInfo) |
170 | | - } |
171 | | -} |
172 | | - |
173 | 13 | /// SyntaxData is the underlying storage for each Syntax node. |
174 | 14 | /// |
175 | 15 | /// SyntaxData is an implementation detail, and should not be exposed to clients |
|
0 commit comments