|
2 | 2 | //
|
3 | 3 | // This source file is part of the Swift.org open source project
|
4 | 4 | //
|
5 |
| -// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors |
| 5 | +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors |
6 | 6 | // Licensed under Apache License v2.0 with Runtime Library Exception
|
7 | 7 | //
|
8 | 8 | // See https://swift.org/LICENSE.txt for license information
|
9 | 9 | // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
10 | 10 | //
|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 |
| -struct AbsoluteSyntaxPosition: Sendable { |
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 | 13 | /// `AbsoluteSyntaxInfo` represents the information that relates a `RawSyntax`
|
34 | 14 | /// to a source file tree, like its absolute source offset.
|
35 | 15 | struct AbsoluteSyntaxInfo: Sendable {
|
36 |
| - let position: AbsoluteSyntaxPosition |
37 |
| - let nodeId: SyntaxIdentifier |
| 16 | + /// The UTF-8 offset at which the syntax node’s leading trivia start in the source file. |
| 17 | + let offset: UInt32 |
| 18 | + |
| 19 | + /// Index in parent's layout. Note that this counts `nil` children. |
| 20 | + let layoutIndexInParent: UInt32 |
38 | 21 |
|
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 } |
| 22 | + /// Index of the node when traversing the syntax tree using a depth-first traversal. |
| 23 | + /// This skips `nil` children in the parent's layout. |
| 24 | + let indexInTree: UInt32 |
42 | 25 |
|
43 | 26 | func advancedBySibling(_ raw: RawSyntax?) -> AbsoluteSyntaxInfo {
|
44 |
| - let newPosition = position.advancedBySibling(raw) |
45 |
| - let newNodeId = nodeId.advancedBySibling(raw) |
46 |
| - return .init(position: newPosition, nodeId: newNodeId) |
| 27 | + if let raw { |
| 28 | + // '&+' operations are safe because we have the preconditions in 'forRoot(_:)'. |
| 29 | + return AbsoluteSyntaxInfo( |
| 30 | + offset: offset &+ UInt32(truncatingIfNeeded: raw.totalLength.utf8Length), |
| 31 | + layoutIndexInParent: layoutIndexInParent &+ 1, |
| 32 | + indexInTree: indexInTree &+ UInt32(truncatingIfNeeded: raw.totalNodes) |
| 33 | + ) |
| 34 | + } else { |
| 35 | + return AbsoluteSyntaxInfo( |
| 36 | + offset: offset, |
| 37 | + layoutIndexInParent: layoutIndexInParent &+ 1, |
| 38 | + indexInTree: indexInTree |
| 39 | + ) |
| 40 | + } |
47 | 41 | }
|
48 | 42 |
|
49 | 43 | func advancedToFirstChild() -> AbsoluteSyntaxInfo {
|
50 |
| - let newPosition = position.advancedToFirstChild() |
51 |
| - let newNodeId = nodeId.advancedToFirstChild() |
52 |
| - return .init(position: newPosition, nodeId: newNodeId) |
| 44 | + return AbsoluteSyntaxInfo( |
| 45 | + offset: offset, |
| 46 | + layoutIndexInParent: 0, |
| 47 | + indexInTree: indexInTree &+ 1 |
| 48 | + ) |
53 | 49 | }
|
54 | 50 |
|
55 | 51 | static func forRoot(_ raw: RawSyntax) -> AbsoluteSyntaxInfo {
|
56 |
| - return .init(position: .forRoot, nodeId: .forRoot(raw)) |
| 52 | + // These checks ensure the safety of the unchecked arithmetic operations in 'advancedBySibling(_:)'. |
| 53 | + precondition(raw.totalLength.utf8Length <= UInt32.max, "too long") |
| 54 | + precondition(raw.totalNodes <= UInt32.max, "too many nodes") |
| 55 | + return AbsoluteSyntaxInfo( |
| 56 | + offset: 0, |
| 57 | + layoutIndexInParent: 0, |
| 58 | + indexInTree: 0 |
| 59 | + ) |
57 | 60 | }
|
58 | 61 | }
|
0 commit comments