diff --git a/Sources/CustomDump/Conformances/KeyPath.swift b/Sources/CustomDump/Conformances/KeyPath.swift index 01c615f..3788f12 100644 --- a/Sources/CustomDump/Conformances/KeyPath.swift +++ b/Sources/CustomDump/Conformances/KeyPath.swift @@ -1,6 +1,11 @@ -#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS) - extension AnyKeyPath: CustomDumpStringConvertible { - public var customDumpDescription: String { +extension AnyKeyPath: CustomDumpStringConvertible { + public var customDumpDescription: String { + #if swift(>=5.8) + if #available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *) { + return self.debugDescription + } + #endif + #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS) guard let name = keyPathToName[self] else { func reflectName() -> String { var namedKeyPaths = Reflection.allNamedKeyPaths(forUnderlyingTypeOf: Self.rootType) @@ -24,9 +29,13 @@ return name } return name - } + #else + return typeName(Self.self, genericsAbbreviated: false) + #endif } +} +#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS) private var keyPathToName: [AnyKeyPath: String] = [:] // The source code below was extracted from the "KeyPath Reflection" branch of Apple's diff --git a/Sources/CustomDump/Internal/AnyType.swift b/Sources/CustomDump/Internal/AnyType.swift index 22cc21d..0ef3481 100644 --- a/Sources/CustomDump/Internal/AnyType.swift +++ b/Sources/CustomDump/Internal/AnyType.swift @@ -1,13 +1,25 @@ -func typeName(_ type: Any.Type) -> String { - var name = _typeName(type) - if let index = name.firstIndex(of: ".") { - name.removeSubrange(...index) - } - return - name +func typeName( + _ type: Any.Type, + qualified: Bool = true, + genericsAbbreviated: Bool = true +) -> String { + var name = _typeName(type, qualified: qualified) + .replacingOccurrences( + of: #"\w+\.(\w+)"#, + with: "$1", + options: .regularExpression + ) .replacingOccurrences( - of: #"<.+>|\(unknown context at \$[[:xdigit:]]+\)\."#, + of: #"\(unknown context at \$[[:xdigit:]]+\)\."#, with: "", options: .regularExpression ) + if genericsAbbreviated { + name = name.replacingOccurrences( + of: #"<.+>"#, + with: "", + options: .regularExpression + ) + } + return name } diff --git a/Tests/CustomDumpTests/DiffTests.swift b/Tests/CustomDumpTests/DiffTests.swift index ca9239a..875afba 100644 --- a/Tests/CustomDumpTests/DiffTests.swift +++ b/Tests/CustomDumpTests/DiffTests.swift @@ -957,7 +957,7 @@ final class DiffTests: XCTestCase { diff( [ "value": 29.99 as Float - ], + ] as [String: Any], [ "value": 29.99 as Double ] diff --git a/Tests/CustomDumpTests/DumpTests.swift b/Tests/CustomDumpTests/DumpTests.swift index 5a04821..acc102b 100644 --- a/Tests/CustomDumpTests/DumpTests.swift +++ b/Tests/CustomDumpTests/DumpTests.swift @@ -573,10 +573,59 @@ final class DumpTests: XCTestCase { ) } - #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS) - func testKeyPath() { - var dump = "" + func testKeyPath() { + var dump = "" + + #if swift(>=5.8) + if #available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *) { + dump = "" + customDump(\UserClass.name, to: &dump) + XCTAssertNoDifference( + dump, + #""" + \UserClass.name + """# + ) + dump = "" + customDump(\Pair.driver.name, to: &dump) + XCTAssertNoDifference( + dump, + #""" + \Pair.driver.name + """# + ) + + dump = "" + customDump(\User.name.count, to: &dump) + XCTAssertNoDifference( + dump, + #""" + \User.name.count + """# + ) + + dump = "" + customDump(\(x: Double, y: Double).x, to: &dump) + XCTAssertNoDifference( + dump, + #""" + \(x: Double, y: Double).x + """# + ) + + dump = "" + customDump(\Item.$isInStock, to: &dump) + XCTAssertNoDifference( + dump, + #""" + \Item.$isInStock + """# + ) + return + } + #endif + #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS) // Run twice to exercise cached lookup for _ in 1...2 { dump = "" @@ -614,9 +663,63 @@ final class DumpTests: XCTestCase { WritableKeyPath<(x: Double, y: Double), Double> """# ) + + dump = "" + customDump(\Item.$isInStock, to: &dump) + XCTAssertNoDifference( + dump, + #""" + KeyPath> + """# + ) } - } - #endif + #else + dump = "" + customDump(\UserClass.name, to: &dump) + XCTAssertNoDifference( + dump, + #""" + KeyPath + """# + ) + + dump = "" + customDump(\Pair.driver.name, to: &dump) + XCTAssertNoDifference( + dump, + #""" + KeyPath + """# + ) + + dump = "" + customDump(\User.name.count, to: &dump) + XCTAssertNoDifference( + dump, + #""" + KeyPath + """# + ) + + dump = "" + customDump(\(x: Double, y: Double).x, to: &dump) + XCTAssertNoDifference( + dump, + #""" + WritableKeyPath<(x: Double, y: Double), Double> + """# + ) + + dump = "" + customDump(\Item.$isInStock, to: &dump) + XCTAssertNoDifference( + dump, + #""" + KeyPath> + """# + ) + #endif + } func testNamespacedTypes() { var dump = "" diff --git a/Tests/CustomDumpTests/Mocks.swift b/Tests/CustomDumpTests/Mocks.swift index 4ac66ee..d3491d7 100644 --- a/Tests/CustomDumpTests/Mocks.swift +++ b/Tests/CustomDumpTests/Mocks.swift @@ -129,3 +129,13 @@ struct Redacted: CustomDumpStringConvertible { struct User: Equatable, Identifiable { var id: Int, name: String } struct HashableUser: Equatable, Identifiable, Hashable { var id: Int, name: String } + +@propertyWrapper +struct Wrapped { + var wrappedValue: Value + var projectedValue: Self { self } +} + +struct Item { + @Wrapped var isInStock = true +}