Skip to content

Commit 65a976c

Browse files
authored
Add Attribute+Debug support (#169)
1 parent efcf4c2 commit 65a976c

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//
2+
// Attribute+Debug.swift
3+
// OpenGraphShims
4+
5+
#if canImport(Darwin) && DEBUG // Compiler crash for Darwin + release and non-Darwin build
6+
7+
// Use 4 spaces instead of \t for bettern test case expect
8+
private let tab = " "
9+
10+
extension Attribute: Swift.CustomDebugStringConvertible {
11+
public var debugDescription: String {
12+
_debugDescription(indent: 0)
13+
}
14+
15+
func _debugDescription(indent: Int) -> String {
16+
let tabs = String(repeating: tab, count: indent)
17+
return #"""
18+
\#(tabs)Attribute<\#(Value.self)> {
19+
\#(identifier._debugDescription(indent: indent + 1))
20+
\#(tabs)}
21+
"""#
22+
}
23+
}
24+
25+
extension AnyAttribute: Swift.CustomDebugStringConvertible {
26+
public var debugDescription: String {
27+
_debugDescription(indent: 0)
28+
}
29+
30+
func _debugDescription(indent: Int) -> String {
31+
let tabs = String(repeating: tab, count: indent)
32+
33+
guard self != .nil else {
34+
return "\(tabs)AnyAttribute.nil"
35+
}
36+
37+
var description = #"""
38+
\#(tabs)rawValue: \#(rawValue)
39+
\#(tabs)graph: \#(graph)
40+
"""#
41+
42+
if rawValue % 2 == 0 { // direct
43+
description.append("\n\(tabs)(direct attribute)")
44+
45+
let valueType = valueType
46+
description.append("\n\(tabs)valueType: \(valueType)")
47+
48+
var value: Any!
49+
func project1<T>(type: T.Type) {
50+
value = unsafeCast(to: type).value
51+
}
52+
_openExistential(valueType, do: project1)
53+
description.append("\n\(tabs)value: \(value!)")
54+
55+
let bodyType = _bodyType
56+
description.append("\n\(tabs)bodyType: \(bodyType)")
57+
58+
var bodyValue: Any!
59+
func project2<T>(type: T.Type) {
60+
bodyValue = _bodyPointer.assumingMemoryBound(to: type).pointee
61+
}
62+
_openExistential(bodyType, do: project2)
63+
64+
let bodyValueDescription = _formatBodyValue(bodyValue!, indent: indent)
65+
description.append("\n\(tabs)bodyValue:\n\(bodyValueDescription)")
66+
67+
} else { // indirect
68+
description.append("\n\(tabs)(indirect attribute)")
69+
description.append("\n\(tabs)source attribute:")
70+
description.append("\n\(source._debugDescription(indent: indent + 1))")
71+
}
72+
return description
73+
}
74+
75+
private func _formatBodyValue(_ bodyValue: Any, indent: Int) -> String {
76+
let bodyValueString = String(describing: bodyValue)
77+
let nextTabs = String(repeating: tab, count: indent + 1)
78+
79+
// Check if the body value contains attributes
80+
if bodyValueString.contains("Attribute<") {
81+
// Split lines and add proper indentation
82+
let lines = bodyValueString.components(separatedBy: .newlines)
83+
return lines.enumerated().map { index, line in
84+
return "\(nextTabs)\(line)"
85+
}.joined(separator: "\n")
86+
}
87+
88+
return "\(nextTabs)\(bodyValueString)"
89+
}
90+
}
91+
#endif
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//
2+
// Attribute+DebugTests.swift
3+
// OpenGraphShimsTests
4+
5+
#if canImport(Darwin) && DEBUG
6+
7+
import Testing
8+
import OpenGraphShims
9+
10+
@MainActor
11+
@Suite(.disabled(if: !attributeGraphEnabled, "Subgraph is not implemented on OG"), .graphScope)
12+
struct Attribute_DebugTests {
13+
@Test
14+
func directAttribute() {
15+
let attribute = Attribute(value: 3)
16+
17+
#expect(attribute.debugDescription == #"""
18+
Attribute<Int> {
19+
rawValue: \#(attribute.identifier.rawValue)
20+
graph: \#(attribute.graph)
21+
(direct attribute)
22+
valueType: Int
23+
value: 3
24+
bodyType: External<Int>
25+
bodyValue:
26+
Int
27+
}
28+
"""#)
29+
}
30+
31+
@Test
32+
func indirectAttribute() {
33+
let tuple = Attribute(value: Tuple(first: 1, second: "2"))
34+
let second = tuple[keyPath: \.second]
35+
#expect(second.debugDescription == #"""
36+
Attribute<String> {
37+
rawValue: \#(second.identifier.rawValue)
38+
graph: \#(second.graph)
39+
(indirect attribute)
40+
source attribute:
41+
rawValue: \#(tuple.identifier.rawValue)
42+
graph: \#(tuple.graph)
43+
(direct attribute)
44+
valueType: Tuple<Int, String>
45+
value: Tuple<Int, String>(first: 1, second: "2")
46+
bodyType: External<Tuple<Int, String>>
47+
bodyValue:
48+
Tuple<Int, String>
49+
}
50+
"""#)
51+
}
52+
}
53+
#endif

0 commit comments

Comments
 (0)