Skip to content

Commit b9580e4

Browse files
committed
Improve debug description of syntax nodes
This improves the description generated by the `debugDescription` function to something like the following which is easier to read IMO ``` SourceFileSyntax ├─CodeBlockItemListSyntax │ ╰─CodeBlockItemSyntax │ ╰─MacroExpansionExprSyntax │ ├─pound │ ├─identifier("stringify") │ ├─leftParen │ ├─TupleExprElementListSyntax │ │ ╰─TupleExprElementSyntax │ │ ╰─InfixOperatorExprSyntax │ │ ├─IntegerLiteralExprSyntax │ │ │ ╰─integerLiteral("2") │ │ ├─BinaryOperatorExprSyntax │ │ │ ╰─binaryOperator("+") │ │ ╰─IntegerLiteralExprSyntax │ │ ╰─integerLiteral("3") │ ╰─rightParen ╰─eof ``` Since we now have this nice representation, it also removes the conformances to `CustomReflectable` (deleting 3000 lines of code :hooray:) and doing some new `CustomReflectable` hackery to make the debugger just print `debugDescription` and not try to print the node’s children itself. This way you an now do `po node` in the debugger to get the debug description from above, instead of having to do `e print(node.recursiveDescription)`
1 parent ac4f8f3 commit b9580e4

File tree

8 files changed

+16
-3206
lines changed

8 files changed

+16
-3206
lines changed

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxNodeFile.swift

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -280,27 +280,6 @@ func syntaxNode(emitKind: String) -> SourceFileSyntax {
280280
}
281281
}
282282
}
283-
284-
try! ExtensionDeclSyntax("extension \(raw: node.name): CustomReflectable") {
285-
let children = DictionaryExprSyntax {
286-
for child in node.children {
287-
DictionaryElementSyntax(
288-
leadingTrivia: .newline,
289-
keyExpression: ExprSyntax(#""\#(raw: child.swiftName)""#),
290-
valueExpression: child.isOptional
291-
? ExprSyntax("\(raw: child.swiftName).map(Syntax.init)?.asProtocol(SyntaxProtocol.self) as Any")
292-
: ExprSyntax("Syntax(\(raw: child.swiftName)).asProtocol(SyntaxProtocol.self)")
293-
)
294-
}
295-
}
296-
DeclSyntax(
297-
"""
298-
public var customMirror: Mirror {
299-
return Mirror(self, children: \(children))
300-
}
301-
"""
302-
)
303-
}
304283
}
305284
}
306285
}

Sources/SwiftSyntax/Syntax.swift

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public extension SyntaxHashable {
161161
/// protocol to provide common functionality for all syntax nodes.
162162
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
163163
public protocol SyntaxProtocol: CustomStringConvertible,
164-
CustomDebugStringConvertible, TextOutputStreamable
164+
CustomDebugStringConvertible, TextOutputStreamable, CustomReflectable
165165
{
166166

167167
/// Retrieve the generic syntax node that is represented by this node.
@@ -598,6 +598,12 @@ public extension SyntaxProtocol {
598598
debugDescription()
599599
}
600600

601+
var customMirror: Mirror {
602+
// Suppress printing of children when doing `po node` in the debugger.
603+
// `debugDescription` already prints them in a nicer way.
604+
return Mirror(self, children: [:])
605+
}
606+
601607
/// Same as `debugDescription` but includes all children.
602608
var recursiveDescription: String {
603609
debugDescription(includeChildren: true)
@@ -615,11 +621,11 @@ public extension SyntaxProtocol {
615621
/// - indentLevel: The starting indent level, 0 by default. Each level is 2
616622
/// spaces.
617623
func debugDescription(
618-
includeChildren: Bool = false,
624+
includeChildren: Bool = true,
619625
includeTrivia: Bool = false,
620626
converter: SourceLocationConverter? = nil,
621627
mark: SyntaxProtocol? = nil,
622-
indentLevel: Int = 0
628+
indentString: String = ""
623629
) -> String {
624630
var str = ""
625631
debugWrite(
@@ -628,7 +634,7 @@ public extension SyntaxProtocol {
628634
includeTrivia: includeTrivia,
629635
converter: converter,
630636
mark: mark,
631-
indentLevel: indentLevel
637+
indentString: indentString
632638
)
633639
return str
634640
}
@@ -639,7 +645,7 @@ public extension SyntaxProtocol {
639645
includeTrivia: Bool,
640646
converter: SourceLocationConverter? = nil,
641647
mark: SyntaxProtocol? = nil,
642-
indentLevel: Int
648+
indentString: String
643649
) {
644650
if let mark = mark, self.id == mark.id {
645651
target.write("*** ")
@@ -660,11 +666,6 @@ public extension SyntaxProtocol {
660666
}
661667

662668
let allChildren = children(viewMode: .all)
663-
if includeChildren {
664-
if !allChildren.isEmpty {
665-
target.write(" children=\(allChildren.count)")
666-
}
667-
}
668669

669670
if let converter = converter {
670671
let range = sourceRange(converter: converter)
@@ -680,18 +681,19 @@ public extension SyntaxProtocol {
680681
}
681682

682683
if includeChildren {
683-
let childIndentLevel = indentLevel + 1
684684
for (num, child) in allChildren.enumerated() {
685+
let isLastChild = num == allChildren.count - 1
685686
target.write("\n")
686-
target.write(String(repeating: " ", count: childIndentLevel * 2))
687-
target.write("\(num): ")
687+
target.write(indentString)
688+
target.write(isLastChild ? "╰─" : "├─")
689+
let childIndentString = indentString + (isLastChild ? " " : "")
688690
child.debugWrite(
689691
to: &target,
690692
includeChildren: includeChildren,
691693
includeTrivia: includeTrivia,
692694
converter: converter,
693695
mark: mark,
694-
indentLevel: childIndentLevel
696+
indentString: childIndentString
695697
)
696698
}
697699
}

Sources/SwiftSyntax/generated/syntaxNodes/SyntaxDeclNodes.swift

Lines changed: 0 additions & 481 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)