diff --git a/Sources/CustomDump/Conformances/SwiftUI.swift b/Sources/CustomDump/Conformances/SwiftUI.swift index a922c48..65f8a5d 100644 --- a/Sources/CustomDump/Conformances/SwiftUI.swift +++ b/Sources/CustomDump/Conformances/SwiftUI.swift @@ -51,17 +51,14 @@ let arguments: [CVarArg] = Array(Mirror(reflecting: children[2].value).children) .compactMap { let children = Array(Mirror(reflecting: $0.value).children) - let value: Any - let formatter: Formatter? // `LocalizedStringKey.FormatArgument` differs depending on OS/platform. if children[0].label == "storage" { - (value, formatter) = - Array(Mirror(reflecting: children[0].value).children)[0].value as! (Any, Formatter?) + return formattedArgumentFromStorage(children[0]) } else { - value = children[0].value - formatter = children[1].value as? Formatter + let value = children[0].value + let formatter = children[1].value as? Formatter + return formatter?.string(for: value) ?? value as! CVarArg } - return formatter?.string(for: value) ?? value as! CVarArg } let format = NSLocalizedString( @@ -73,5 +70,25 @@ ) return String(format: format, locale: locale, arguments: arguments) } + + private func formattedArgumentFromStorage(_ storage: Mirror.Child) -> CVarArg { + let storage = Array(Mirror(reflecting: storage.value).children)[0].value + + // Check if storage is a FormatStyle + if #available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) { + let formatStyleBoxChildren = Array(Mirror(reflecting: storage).children) + if formatStyleBoxChildren.count == 2, let formatStyle = formatStyleBoxChildren[1].value as? (any FormatStyle) { + func formatValue(style: S, input: Any) -> String { + let input = input as! S.FormatInput + return style.format(input) as! String + } + return formatValue(style: formatStyle, input: formatStyleBoxChildren[0].value) + } + } + + // Fallback to Formatter + let (value, formatter) = storage as! (Any, Formatter?) + return formatter?.string(for: value) ?? value as! CVarArg + } } #endif diff --git a/Tests/CustomDumpTests/DiffTests.swift b/Tests/CustomDumpTests/DiffTests.swift index cb4797f..cdff920 100644 --- a/Tests/CustomDumpTests/DiffTests.swift +++ b/Tests/CustomDumpTests/DiffTests.swift @@ -1,5 +1,8 @@ import CustomDump import XCTest +#if canImport(SwiftUI) +import SwiftUI +#endif @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) final class DiffTests: XCTestCase { @@ -1088,6 +1091,46 @@ final class DiffTests: XCTestCase { ) } +#if canImport(SwiftUI) + @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) + func testLocalizedStringKey() { + XCTAssertNoDifference( + diff( + "My name is Jack" as LocalizedStringKey, + "My name is Jill" as LocalizedStringKey + ), + """ + - "My name is Jack" + + "My name is Jill" + """ + ) + + let name1 = "Jack" + let name2 = "Jill" + XCTAssertNoDifference( + diff( + "My name is \(name1)" as LocalizedStringKey, + "My name is \(name2)" as LocalizedStringKey + ), + """ + - "My name is Jack" + + "My name is Jill" + """ + ) + + XCTAssertNoDifference( + diff( + "Time remaining: \(Duration.seconds(10), format: .time(pattern: .minuteSecond))" as LocalizedStringKey, + "Time remaining: \(Duration.seconds(9), format: .time(pattern: .minuteSecond))" as LocalizedStringKey + ), + """ + - "Time remaining: 0:10" + + "Time remaining: 0:09" + """ + ) + } +#endif + func testCustomDictionary() { XCTAssertEqual( String(customDumping: Stack(elements: [(.init(rawValue: 0), "Hello")])),