From 1585dca64fea1416bb67875200abb32268365503 Mon Sep 17 00:00:00 2001 From: YOCKOW Date: Mon, 4 Oct 2021 11:51:09 +0900 Subject: [PATCH 1/2] Add a test for SR-14913. --- .../Tests/TestNumberFormatter.swift | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Tests/Foundation/Tests/TestNumberFormatter.swift b/Tests/Foundation/Tests/TestNumberFormatter.swift index 9e69d69a25..1e8619fc06 100644 --- a/Tests/Foundation/Tests/TestNumberFormatter.swift +++ b/Tests/Foundation/Tests/TestNumberFormatter.swift @@ -1176,6 +1176,34 @@ class TestNumberFormatter: XCTestCase { #endif } + func test_copy() throws { + let original = NumberFormatter() + let copied = try XCTUnwrap(original.copy() as? NumberFormatter) + XCTAssertFalse(original === copied) + + func __assert(_ property: KeyPath, + original expectedValueOfOriginalFormatter: T, + copy expectedValueOfCopiedFormatter: T, + file: StaticString = #file, + line: UInt = #line) where T: Equatable { + XCTAssertEqual(original[keyPath: property], expectedValueOfOriginalFormatter, + "Unexpected value in `original`.", file: file, line: line) + XCTAssertEqual(copied[keyPath: property], expectedValueOfCopiedFormatter, + "Unexpected value in `copied`.", file: file, line: line) + } + + copied.numberStyle = .decimal + __assert(\.numberStyle, original: .none, copy: .decimal) + __assert(\.maximumIntegerDigits, original: 42, copy: 2_000_000_000) + __assert(\.maximumFractionDigits, original: 0, copy: 3) + __assert(\.groupingSize, original: 0, copy: 3) + + original.numberStyle = .percent + original.percentSymbol = "%" + __assert(\.numberStyle, original: .percent, copy: .decimal) + __assert(\.format, original: "#,##0%;0%;#,##0%", copy: "#,##0.###;0;#,##0.###") + } + static var allTests: [(String, (TestNumberFormatter) -> () throws -> Void)] { return [ ("test_defaultPropertyValues", test_defaultPropertyValues), @@ -1238,6 +1266,7 @@ class TestNumberFormatter: XCTestCase { ("test_usingFormat", test_usingFormat), ("test_propertyChanges", test_propertyChanges), ("test_scientificStrings", test_scientificStrings), + ("test_copy", test_copy), ] } } From 55bb3a3a85905251133e1f0560aa5776fb7137d8 Mon Sep 17 00:00:00 2001 From: YOCKOW Date: Mon, 4 Oct 2021 16:22:16 +0900 Subject: [PATCH 2/2] Implement `copy()` in `NumberFormatter`. --- Sources/Foundation/NumberFormatter.swift | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/Sources/Foundation/NumberFormatter.swift b/Sources/Foundation/NumberFormatter.swift index d1e69baa71..91b16ec477 100644 --- a/Sources/Foundation/NumberFormatter.swift +++ b/Sources/Foundation/NumberFormatter.swift @@ -66,6 +66,87 @@ open class NumberFormatter : Formatter { } } + open override func copy(with zone: NSZone? = nil) -> Any { + let copied = NumberFormatter() + + func __copy(_ keyPath: ReferenceWritableKeyPath) { + copied[keyPath: keyPath] = self[keyPath: keyPath] + } + + func __copy(_ keyPath: ReferenceWritableKeyPath) where T: NSCopying { + copied[keyPath: keyPath] = self[keyPath: keyPath].copy(with: zone) as! T + } + + func __copy(_ keyPath: ReferenceWritableKeyPath) where T: NSCopying { + copied[keyPath: keyPath] = self[keyPath: keyPath]?.copy(with: zone) as! T? + } + + __copy(\.formattingContext) + __copy(\._numberStyle) + __copy(\._locale) + __copy(\._generatesDecimalNumbers) + __copy(\._textAttributesForNegativeValues) + __copy(\._textAttributesForPositiveValues) + __copy(\._allowsFloats) + __copy(\._decimalSeparator) + __copy(\._alwaysShowsDecimalSeparator) + __copy(\._currencyDecimalSeparator) + __copy(\._usesGroupingSeparator) + __copy(\._groupingSeparator) + __copy(\._zeroSymbol) + __copy(\._textAttributesForZero) + __copy(\._nilSymbol) + __copy(\._textAttributesForNil) + __copy(\._notANumberSymbol) + __copy(\._textAttributesForNotANumber) + __copy(\._positiveInfinitySymbol) + __copy(\._textAttributesForPositiveInfinity) + __copy(\._negativeInfinitySymbol) + __copy(\._textAttributesForNegativeInfinity) + __copy(\._positivePrefix) + __copy(\._positiveSuffix) + __copy(\._negativePrefix) + __copy(\._negativeSuffix) + __copy(\._currencyCode) + __copy(\._currencySymbol) + __copy(\._internationalCurrencySymbol) + __copy(\._percentSymbol) + __copy(\._perMillSymbol) + __copy(\._minusSign) + __copy(\._plusSign) + __copy(\._exponentSymbol) + __copy(\._groupingSize) + __copy(\._secondaryGroupingSize) + __copy(\._multiplier) + __copy(\._formatWidth) + __copy(\._paddingCharacter) + __copy(\._paddingPosition) + __copy(\._roundingMode) + __copy(\._roundingIncrement) + __copy(\._minimumIntegerDigits) + __copy(\._maximumIntegerDigits) + __copy(\._minimumFractionDigits) + __copy(\._maximumFractionDigits) + __copy(\._minimum) + __copy(\._maximum) + __copy(\._currencyGroupingSeparator) + __copy(\._lenient) + __copy(\._usesSignificantDigits) + __copy(\._minimumSignificantDigits) + __copy(\._maximumSignificantDigits) + __copy(\._partialStringValidationEnabled) + __copy(\._hasThousandSeparators) + __copy(\._thousandSeparator) + __copy(\._localizesFormat) + __copy(\._positiveFormat) + __copy(\._negativeFormat) + __copy(\._attributedStringForZero) + __copy(\._attributedStringForNotANumber) + __copy(\._roundingBehavior) + + return copied + } + // this is for NSUnitFormatter open var formattingContext: Context = .unknown // default is NSFormattingContextUnknown