Skip to content

Commit adef407

Browse files
authored
Use AnyKeyPath.customDebugDescription when possible (#73)
* Use `AnyKeyPath.customDebugDescription` when possible New in Swift 5.8 with implementation of [SE-0369](https://github.com/apple/swift-evolution/blob/main/proposals/0369-add-customdebugdescription-conformance-to-anykeypath.md). * Linux support. * Linux tests * Fix warning * Fix * wip * wip * wip
1 parent dd86159 commit adef407

File tree

5 files changed

+152
-18
lines changed

5 files changed

+152
-18
lines changed

Sources/CustomDump/Conformances/KeyPath.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
2-
extension AnyKeyPath: CustomDumpStringConvertible {
3-
public var customDumpDescription: String {
1+
extension AnyKeyPath: CustomDumpStringConvertible {
2+
public var customDumpDescription: String {
3+
#if swift(>=5.8)
4+
if #available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *) {
5+
return self.debugDescription
6+
}
7+
#endif
8+
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
49
guard let name = keyPathToName[self] else {
510
func reflectName() -> String {
611
var namedKeyPaths = Reflection.allNamedKeyPaths(forUnderlyingTypeOf: Self.rootType)
@@ -24,9 +29,13 @@
2429
return name
2530
}
2631
return name
27-
}
32+
#else
33+
return typeName(Self.self, genericsAbbreviated: false)
34+
#endif
2835
}
36+
}
2937

38+
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
3039
private var keyPathToName: [AnyKeyPath: String] = [:]
3140

3241
// The source code below was extracted from the "KeyPath Reflection" branch of Apple's
Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
1-
func typeName(_ type: Any.Type) -> String {
2-
var name = _typeName(type)
3-
if let index = name.firstIndex(of: ".") {
4-
name.removeSubrange(...index)
5-
}
6-
return
7-
name
1+
func typeName(
2+
_ type: Any.Type,
3+
qualified: Bool = true,
4+
genericsAbbreviated: Bool = true
5+
) -> String {
6+
var name = _typeName(type, qualified: qualified)
7+
.replacingOccurrences(
8+
of: #"\w+\.(\w+)"#,
9+
with: "$1",
10+
options: .regularExpression
11+
)
812
.replacingOccurrences(
9-
of: #"<.+>|\(unknown context at \$[[:xdigit:]]+\)\."#,
13+
of: #"\(unknown context at \$[[:xdigit:]]+\)\."#,
1014
with: "",
1115
options: .regularExpression
1216
)
17+
if genericsAbbreviated {
18+
name = name.replacingOccurrences(
19+
of: #"<.+>"#,
20+
with: "",
21+
options: .regularExpression
22+
)
23+
}
24+
return name
1325
}

Tests/CustomDumpTests/DiffTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,7 @@ final class DiffTests: XCTestCase {
957957
diff(
958958
[
959959
"value": 29.99 as Float
960-
],
960+
] as [String: Any],
961961
[
962962
"value": 29.99 as Double
963963
]

Tests/CustomDumpTests/DumpTests.swift

Lines changed: 108 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,59 @@ final class DumpTests: XCTestCase {
573573
)
574574
}
575575

576-
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
577-
func testKeyPath() {
578-
var dump = ""
576+
func testKeyPath() {
577+
var dump = ""
578+
579+
#if swift(>=5.8)
580+
if #available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *) {
581+
dump = ""
582+
customDump(\UserClass.name, to: &dump)
583+
XCTAssertNoDifference(
584+
dump,
585+
#"""
586+
\UserClass.name
587+
"""#
588+
)
579589

590+
dump = ""
591+
customDump(\Pair.driver.name, to: &dump)
592+
XCTAssertNoDifference(
593+
dump,
594+
#"""
595+
\Pair.driver.name
596+
"""#
597+
)
598+
599+
dump = ""
600+
customDump(\User.name.count, to: &dump)
601+
XCTAssertNoDifference(
602+
dump,
603+
#"""
604+
\User.name.count
605+
"""#
606+
)
607+
608+
dump = ""
609+
customDump(\(x: Double, y: Double).x, to: &dump)
610+
XCTAssertNoDifference(
611+
dump,
612+
#"""
613+
\(x: Double, y: Double).x
614+
"""#
615+
)
616+
617+
dump = ""
618+
customDump(\Item.$isInStock, to: &dump)
619+
XCTAssertNoDifference(
620+
dump,
621+
#"""
622+
\Item.$isInStock
623+
"""#
624+
)
625+
return
626+
}
627+
#endif
628+
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
580629
// Run twice to exercise cached lookup
581630
for _ in 1...2 {
582631
dump = ""
@@ -614,9 +663,63 @@ final class DumpTests: XCTestCase {
614663
WritableKeyPath<(x: Double, y: Double), Double>
615664
"""#
616665
)
666+
667+
dump = ""
668+
customDump(\Item.$isInStock, to: &dump)
669+
XCTAssertNoDifference(
670+
dump,
671+
#"""
672+
KeyPath<Item, Wrapped<Bool>>
673+
"""#
674+
)
617675
}
618-
}
619-
#endif
676+
#else
677+
dump = ""
678+
customDump(\UserClass.name, to: &dump)
679+
XCTAssertNoDifference(
680+
dump,
681+
#"""
682+
KeyPath<UserClass, String>
683+
"""#
684+
)
685+
686+
dump = ""
687+
customDump(\Pair.driver.name, to: &dump)
688+
XCTAssertNoDifference(
689+
dump,
690+
#"""
691+
KeyPath<Pair, String>
692+
"""#
693+
)
694+
695+
dump = ""
696+
customDump(\User.name.count, to: &dump)
697+
XCTAssertNoDifference(
698+
dump,
699+
#"""
700+
KeyPath<User, Int>
701+
"""#
702+
)
703+
704+
dump = ""
705+
customDump(\(x: Double, y: Double).x, to: &dump)
706+
XCTAssertNoDifference(
707+
dump,
708+
#"""
709+
WritableKeyPath<(x: Double, y: Double), Double>
710+
"""#
711+
)
712+
713+
dump = ""
714+
customDump(\Item.$isInStock, to: &dump)
715+
XCTAssertNoDifference(
716+
dump,
717+
#"""
718+
KeyPath<Item, Wrapped<Bool>>
719+
"""#
720+
)
721+
#endif
722+
}
620723

621724
func testNamespacedTypes() {
622725
var dump = ""

Tests/CustomDumpTests/Mocks.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,13 @@ struct Redacted<RawValue>: CustomDumpStringConvertible {
129129

130130
struct User: Equatable, Identifiable { var id: Int, name: String }
131131
struct HashableUser: Equatable, Identifiable, Hashable { var id: Int, name: String }
132+
133+
@propertyWrapper
134+
struct Wrapped<Value> {
135+
var wrappedValue: Value
136+
var projectedValue: Self { self }
137+
}
138+
139+
struct Item {
140+
@Wrapped var isInStock = true
141+
}

0 commit comments

Comments
 (0)