|
1 | 1 | import SwiftTreeSitter |
| 2 | +import SwiftUI |
2 | 3 |
|
3 | 4 | public extension ASTTree { |
4 | 5 | /// Dumps the syntax tree as a string, for debugging purposes. |
5 | | - func dump() -> String { |
| 6 | + func dump() -> AttributedString { |
6 | 7 | guard let tree, let root = tree.rootNode else { return "" } |
7 | | - var result = "" |
| 8 | + var result: AttributedString = "" |
8 | 9 |
|
9 | | - let appendNode: (_ level: Int, _ node: Node) -> Void = { level, node in |
| 10 | + let appendNode: (_ level: Int, _ node: Node, _ name: String) -> Void = { |
| 11 | + level, node, name in |
10 | 12 | let range = node.pointRange |
11 | 13 | let lowerBoundL = range.lowerBound.row |
12 | 14 | let lowerBoundC = range.lowerBound.column / 2 |
13 | 15 | let upperBoundL = range.upperBound.row |
14 | 16 | let upperBoundC = range.upperBound.column / 2 |
15 | | - let line = |
16 | | - "\(String(repeating: " ", count: level))\(node.nodeType ?? "N/A") [\(lowerBoundL), \(lowerBoundC)] - [\(upperBoundL), \(upperBoundC)]" |
17 | | - result += line + "\n" |
| 17 | + let indentation = AttributedString(String(repeating: " ", count: level)) |
| 18 | + let nodeInfo = { |
| 19 | + if name.isEmpty { |
| 20 | + return AttributedString(node.nodeType ?? "N/A", attributes: .init([ |
| 21 | + .foregroundColor: NSColor.blue, |
| 22 | + ])) |
| 23 | + } else { |
| 24 | + var string = AttributedString("\(name): ", attributes: .init([ |
| 25 | + .foregroundColor: NSColor.brown, |
| 26 | + ])) |
| 27 | + string.append(AttributedString(node.nodeType ?? "N/A", attributes: .init([ |
| 28 | + .foregroundColor: NSColor.blue, |
| 29 | + ]))) |
| 30 | + return string |
| 31 | + } |
| 32 | + }() |
| 33 | + let rangeText = "[\(lowerBoundL), \(lowerBoundC)] - [\(upperBoundL), \(upperBoundC)]" |
| 34 | + |
| 35 | + var line: AttributedString = "" |
| 36 | + line.append(indentation) |
| 37 | + line.append(nodeInfo) |
| 38 | + line.append(AttributedString(" \(rangeText)\n")) |
| 39 | + |
| 40 | + result.append(line) |
18 | 41 | } |
19 | 42 |
|
20 | | - guard let node = root.descendant(in: root.byteRange) else { return result } |
21 | | - |
22 | | - appendNode(0, node) |
23 | | - |
24 | | - let cursor = node.treeCursor |
25 | | - let level = 0 |
26 | | - |
27 | | - if cursor.goToFirstChild(for: node.byteRange.lowerBound) == false { |
28 | | - return result |
29 | | - } |
30 | | - |
31 | | - cursor.enumerateCurrentAndDescendents(level: level + 1) { level, node in |
32 | | - appendNode(level, node) |
33 | | - } |
34 | | - |
35 | | - while cursor.goToNextSibling() { |
36 | | - guard let node = cursor.currentNode else { |
37 | | - assertionFailure("no current node when gotoNextSibling succeeded") |
38 | | - break |
39 | | - } |
40 | | - |
41 | | - // once we are past the interesting range, stop |
42 | | - if node.byteRange.lowerBound > root.byteRange.upperBound { |
43 | | - break |
44 | | - } |
45 | | - |
46 | | - cursor.enumerateCurrentAndDescendents(level: level + 1) { level, node in |
47 | | - appendNode(level, node) |
| 43 | + func enumerate(_ node: Node, level: Int, name: String) { |
| 44 | + appendNode(level, node, name) |
| 45 | + for i in 0..<node.childCount { |
| 46 | + let n = node.child(at: i)! |
| 47 | + enumerate(n, level: level + 1, name: node.fieldNameForChild(at: i) ?? "") |
48 | 48 | } |
49 | 49 | } |
50 | 50 |
|
| 51 | + enumerate(root, level: 0, name: "root") |
51 | 52 | return result |
52 | 53 | } |
53 | 54 | } |
54 | 55 |
|
55 | | -private extension TreeCursor { |
56 | | - func enumerateCurrentAndDescendents(level: Int, block: (Int, Node) throws -> Void) rethrows { |
57 | | - if let node = currentNode { |
58 | | - try block(level, node) |
59 | | - } |
60 | | - |
61 | | - if goToFirstChild() == false { |
62 | | - return |
63 | | - } |
64 | | - |
65 | | - try enumerateCurrentAndDescendents(level: level + 1, block: block) |
66 | | - |
67 | | - while goToNextSibling() { |
68 | | - try enumerateCurrentAndDescendents(level: level + 1, block: block) |
69 | | - } |
70 | | - |
71 | | - let success = gotoParent() |
72 | | - |
73 | | - assert(success) |
74 | | - } |
75 | | -} |
76 | | - |
0 commit comments