Skip to content

Commit

Permalink
Add helper protocols for the properties included in the dump
Browse files Browse the repository at this point in the history
The current method of using the CustomDumpReflectable can work to produce this but it requires a lot more work to implement for each type that needs it.
  • Loading branch information
tahirmt committed Oct 3, 2022
1 parent 8a93a47 commit c7c66d9
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 23 deletions.
97 changes: 97 additions & 0 deletions Sources/CustomDump/CustomDumpChildren.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/// Implement this protocol to exclude superclass nodes
public protocol CustomDumpExcludeSuperclass {}

/// Implement this protocol to ignore dumping child nodes
///
/// Using this protocol will make the type ignore the children completly and only print out the type name.
/// This can be useful when something is irrelevant
public protocol CustomDumpIgnoreChildNodes {}

/// Properties to include child nodes. By default all child nodes are included but when this is implemented, only the values passed will be included in the dump
///
/// ```
/// struct Human {
/// let name = "Jimmy"
/// }
///
/// struct User: CustomDumpIncludedChildNodesProvider {
/// static var includedNodes: [String]? {
/// [
/// "name",
/// "email",
/// "friends",
/// ]
/// }
/// let name = "John"
/// let email = "[email protected]"
/// let age = 97
/// let friends = [
/// "James",
/// "Lilly",
/// "Peter",
/// "Remus",
/// ]
/// let human = Human()
/// }
/// ```
/// The dump for this will produce
/// ```
/// User(
/// name: "John",
/// email: "[email protected]",
/// friends: [
/// [0]: "James",
/// [1]: "Lilly",
/// [2]: "Peter",
/// [3]: "Remus"
/// ]
/// )
/// ```
public protocol CustomDumpIncludedChildNodesProvider {
/// Which nodes to include in the dump
static var includedNodes: [String]? { get }
}

/// Properties to exclude child nodes. This can be helpful when one or more fields are not relevant
///
/// ```
/// struct Human {
/// let name = "Jimmy"
/// }
///
/// struct User: CustomDumpExcludedChildNodesProvider {
/// static var excludedNodes: [String] {
/// [
/// "age",
/// "friends"
/// ]
/// }
/// let name = "John"
/// let email = "[email protected]"
/// let age = 97
/// let friends = [
/// "James",
/// "Lilly",
/// "Peter",
/// "Remus",
/// ]
/// let human = Human()
/// }
/// ```
/// The dump for this will produce
/// ```
/// User(
/// name: "John",
/// email: "[email protected]",
/// friends: [
/// [0]: "James",
/// [1]: "Lilly",
/// [2]: "Peter",
/// [3]: "Remus"
/// ]
/// )
/// ```
public protocol CustomDumpExcludedChildNodesProvider {
/// Which nodes to exclude from the dump
static var excludedNodes: [String] { get }
}
34 changes: 27 additions & 7 deletions Sources/CustomDump/Dump.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,28 @@ public func customDump<T, TargetStream>(
_ transform: (inout Mirror.Child, Int) -> Void = { _, _ in }
) {
out.write(prefix)
if !mirror.children.isEmpty {
var children = mirror.children
if value is CustomDumpIgnoreChildNodes {
out.write("...")
out.write(suffix)
return
}
if let value = value as? CustomDumpIncludedChildNodesProvider, let nodes = type(of: value).includedNodes {
children = Mirror.Children(children.filter {
$0.label.map { nodes.contains($0) } ?? false
})
}
if let value = value as? CustomDumpExcludedChildNodesProvider {
let nodes = type(of: value).excludedNodes
children = Mirror.Children(children.filter {
$0.label.map { !nodes.contains($0) } ?? true
})
}

if !children.isEmpty {
if mirror.isSingleValueContainer {
var childOut = ""
let child = mirror.children.first!
let child = children.first!
customDumpHelp(
child.value, to: &childOut, name: child.label, indent: 0, maxDepth: maxDepth - 1
)
Expand All @@ -104,7 +122,7 @@ public func customDump<T, TargetStream>(
out.write("")
} else {
out.write("\n")
var children = Array(mirror.children)
var children = Array(children)
if let areInIncreasingOrder = areInIncreasingOrder {
children.sort(by: areInIncreasingOrder)
}
Expand Down Expand Up @@ -140,10 +158,12 @@ public func customDump<T, TargetStream>(
visitedItems.insert(item)
var children = Array(mirror.children)

var superclassMirror = mirror.superclassMirror
while let mirror = superclassMirror {
children.insert(contentsOf: mirror.children, at: 0)
superclassMirror = mirror.superclassMirror
if !(value is CustomDumpExcludeSuperclass) {
var superclassMirror = mirror.superclassMirror
while let mirror = superclassMirror {
children.insert(contentsOf: mirror.children, at: 0)
superclassMirror = mirror.superclassMirror
}
}
dumpChildren(
of: Mirror(value, children: children),
Expand Down
104 changes: 88 additions & 16 deletions Tests/CustomDumpTests/DumpTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,77 @@ final class DumpTests: XCTestCase {
)
}

func testIncludedNodes() {
var dump = ""
class Human: CustomDumpIncludedChildNodesProvider {
static var includedNodes: [String]? {
[
"name",
"email",
]
}
let name = "John"
let email = "[email protected]"
let age = 97
}

customDump(Human(), to: &dump)

XCTAssertNoDifference(
dump,
"""
DumpTests.Human(
name: "John",
email: "[email protected]"
)
"""
)
}

func testExcludedNodes() {
var dump = ""
class Human: CustomDumpExcludedChildNodesProvider {
static var excludedNodes: [String] {
[
"name",
]
}
let name = "John"
let email = "[email protected]"
let age = 97
}

customDump(Human(), to: &dump)

XCTAssertNoDifference(
dump,
"""
DumpTests.Human(
email: "[email protected]",
age: 97
)
"""
)
}

func testIgnoreChildNodes() {
var dump = ""
class Human: CustomDumpIgnoreChildNodes {
let name = "John"
let email = "[email protected]"
let age = 97
}

customDump(Human(), to: &dump)

XCTAssertNoDifference(
dump,
"""
DumpTests.Human(...)
"""
)
}

func testRepeatition() {
class Human {
let name = "John"
Expand All @@ -871,25 +942,26 @@ final class DumpTests: XCTestCase {

XCTAssertNoDifference(
dump,
"""
[
[0]: DumpTests.Human(
name: "John",
email: "[email protected]",
age: 97
),
[1]: DumpTests.Human(↩︎),
[2]: DumpTests.Human(
name: "John",
email: "[email protected]",
age: 97
),
[3]: DumpTests.Human(↩︎)
]
"""
"""
[
[0]: DumpTests.Human(
name: "John",
email: "[email protected]",
age: 97
),
[1]: DumpTests.Human(↩︎),
[2]: DumpTests.Human(
name: "John",
email: "[email protected]",
age: 97
),
[3]: DumpTests.Human(↩︎)
]
"""
)
}


#if canImport(CoreGraphics)
func testCoreGraphics() {
var dump = ""
Expand Down

0 comments on commit c7c66d9

Please sign in to comment.