Skip to content

Commit 3cfcb55

Browse files
authored
Merge pull request #3752 from parkera/foundation_reflection
2 parents 0712ffc + dab81e8 commit 3cfcb55

16 files changed

+406
-133
lines changed

stdlib/public/SDK/Foundation/Calendar.swift

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ internal func __NSCalendarInit(_ identifier : NSString) -> NSCalendar?
2727
/**
2828
`Calendar` encapsulates information about systems of reckoning time in which the beginning, length, and divisions of a year are defined. It provides information about the calendar and support for calendrical computations such as determining the range of a given calendrical unit and adding units to a given absolute time.
2929
*/
30-
public struct Calendar : CustomStringConvertible, CustomDebugStringConvertible, Hashable, Equatable, ReferenceConvertible, _MutableBoxing {
30+
public struct Calendar : Hashable, Equatable, ReferenceConvertible, _MutableBoxing {
3131
public typealias ReferenceType = NSCalendar
3232

3333
private var _autoupdating: Bool
@@ -908,14 +908,6 @@ public struct Calendar : CustomStringConvertible, CustomDebugStringConvertible,
908908

909909
// MARK: -
910910

911-
public var description: String {
912-
return _handle.map { $0.description }
913-
}
914-
915-
public var debugDescription : String {
916-
return _handle.map { $0.debugDescription }
917-
}
918-
919911
public var hashValue : Int {
920912
// We implement hash ourselves, because we need to make sure autoupdating calendars have the same hash
921913
if _autoupdating {
@@ -1081,6 +1073,37 @@ public struct Calendar : CustomStringConvertible, CustomDebugStringConvertible,
10811073

10821074
}
10831075

1076+
extension Calendar : CustomDebugStringConvertible, CustomStringConvertible, CustomReflectable {
1077+
private var _kindDescription : String {
1078+
if (self == Calendar.autoupdatingCurrent) {
1079+
return "autoupdatingCurrent"
1080+
} else if (self == Calendar.current) {
1081+
return "current"
1082+
} else {
1083+
return "fixed"
1084+
}
1085+
}
1086+
1087+
public var description: String {
1088+
return "\(identifier) (\(_kindDescription))"
1089+
}
1090+
1091+
public var debugDescription : String {
1092+
return "\(identifier) (\(_kindDescription))"
1093+
}
1094+
1095+
public var customMirror : Mirror {
1096+
var c: [(label: String?, value: Any)] = []
1097+
c.append((label: "identifier", value: identifier))
1098+
c.append((label: "kind", value: _kindDescription))
1099+
c.append((label: "locale", value: locale))
1100+
c.append((label: "timeZone", value: timeZone))
1101+
c.append((label: "firstWeekday", value: firstWeekday))
1102+
c.append((label: "minimumDaysInFirstWeek", value: minimumDaysInFirstWeek))
1103+
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
1104+
}
1105+
}
1106+
10841107
extension Calendar : _ObjectiveCBridgeable {
10851108
@_semantics("convertToObjectiveC")
10861109
public func _bridgeToObjectiveC() -> NSCalendar {

stdlib/public/SDK/Foundation/Data.swift

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,15 @@ internal final class _SwiftNSData : _SwiftNativeNSData, _SwiftNativeFoundationTy
6262
}
6363
}
6464

65+
6566
/**
6667
`Data` is a `MutableCollection` of bytes.
6768

6869
This type provides "copy-on-write" behavior, and is also bridged to the Objective-C `NSData` class. You can wrap an instance of a custom subclass of `NSData` in `struct Data` by converting it using `myData as Data`.
6970

7071
`Data` can be initialized with an `UnsafePointer` and count, an array of `UInt8` (the primitive byte type), or an `UnsafeBufferPointer`. The buffer-oriented functions provide an extra measure of safety by automatically performing the size calculation, as the type is known at compile time.
7172
*/
72-
public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection, _MutablePairBoxing {
73+
public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection, _MutablePairBoxing {
7374
/// The Objective-C bridged type of `Data`.
7475
public typealias ReferenceType = NSData
7576

@@ -588,16 +589,6 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
588589
return _mapUnmanaged { $0.hashValue }
589590
}
590591

591-
/// A human-readable description for the data.
592-
public var description: String {
593-
return _mapUnmanaged { $0.description }
594-
}
595-
596-
/// A human-readable debug description for the data.
597-
public var debugDescription: String {
598-
return _mapUnmanaged { $0.debugDescription }
599-
}
600-
601592
// MARK: -
602593

603594
// MARK: -
@@ -676,6 +667,37 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
676667
}
677668
}
678669

670+
extension Data : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
671+
/// A human-readable description for the data.
672+
public var description: String {
673+
return "\(self.count) bytes"
674+
}
675+
676+
/// A human-readable debug description for the data.
677+
public var debugDescription: String {
678+
return self.description
679+
}
680+
681+
public var customMirror: Mirror {
682+
let nBytes = self.count
683+
var children: [(label: String?, value: Any)] = []
684+
children.append((label: "count", value: nBytes))
685+
686+
self.withUnsafeBytes { (bytes : UnsafePointer<UInt8>) in
687+
children.append((label: "pointer", value: bytes))
688+
}
689+
690+
// Minimal size data is output as an array
691+
if nBytes < 64 {
692+
children.append((label: "bytes", value: self[0..<nBytes].map { $0 }))
693+
}
694+
695+
let m = Mirror(self, children:children, displayStyle: Mirror.DisplayStyle.struct)
696+
return m
697+
}
698+
}
699+
700+
679701
/// Provides bridging functionality for struct Data to class NSData and vice-versa.
680702
extension Data : _ObjectiveCBridgeable {
681703
@_semantics("convertToObjectiveC")

stdlib/public/SDK/Foundation/Date.swift

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import CoreFoundation
1818

1919
A `Date` is independent of a particular calendar or time zone. To represent a `Date` to a user, you must interpret it in the context of a `Calendar`.
2020
*/
21-
public struct Date : ReferenceConvertible, Comparable, Equatable, CustomStringConvertible {
21+
public struct Date : ReferenceConvertible, Comparable, Equatable {
2222
public typealias ReferenceType = NSDate
2323

2424
fileprivate var _time : TimeInterval
@@ -160,33 +160,6 @@ public struct Date : ReferenceConvertible, Comparable, Equatable, CustomStringCo
160160
}
161161
}
162162

163-
/**
164-
A string representation of the date object (read-only).
165-
166-
The representation is useful for debugging only.
167-
168-
There are a number of options to acquire a formatted string for a date including: date formatters (see
169-
[NSDateFormatter](//apple_ref/occ/cl/NSDateFormatter) and [Data Formatting Guide](//apple_ref/doc/uid/10000029i)), and the `Date` functions `description(locale:)`.
170-
*/
171-
public var description: String {
172-
// Defer to NSDate for description
173-
return NSDate(timeIntervalSinceReferenceDate: _time).description
174-
}
175-
176-
/**
177-
Returns a string representation of the receiver using the given
178-
locale.
179-
180-
- Parameter locale: A `Locale` object. If you pass `nil`, `NSDate` formats the date in the same way as the `description` property.
181-
182-
- Returns: A string representation of the receiver, using the given locale, or if the locale argument is `nil`, in the international format `YYYY-MM-DD HH:MM:SS ±HHMM`, where `±HHMM` represents the time zone offset in hours and minutes from UTC (for example, "`2001-03-24 10:45:32 +0600`").
183-
*/
184-
public func description(with locale: Locale?) -> String {
185-
return NSDate(timeIntervalSinceReferenceDate: _time).description(with: locale)
186-
}
187-
188-
public var debugDescription: String { return description }
189-
190163
/// Returns true if the two `Date` values represent the same point in time.
191164
public static func ==(lhs: Date, rhs: Date) -> Bool {
192165
return lhs.timeIntervalSinceReferenceDate == rhs.timeIntervalSinceReferenceDate
@@ -228,6 +201,43 @@ public struct Date : ReferenceConvertible, Comparable, Equatable, CustomStringCo
228201

229202
}
230203

204+
extension Date : CustomDebugStringConvertible, CustomStringConvertible, CustomReflectable {
205+
/**
206+
A string representation of the date object (read-only).
207+
208+
The representation is useful for debugging only.
209+
210+
There are a number of options to acquire a formatted string for a date including: date formatters (see
211+
[NSDateFormatter](//apple_ref/occ/cl/NSDateFormatter) and [Data Formatting Guide](//apple_ref/doc/uid/10000029i)), and the `Date` function `description(locale:)`.
212+
*/
213+
public var description: String {
214+
// Defer to NSDate for description
215+
return NSDate(timeIntervalSinceReferenceDate: _time).description
216+
}
217+
218+
/**
219+
Returns a string representation of the receiver using the given
220+
locale.
221+
222+
- Parameter locale: A `Locale`. If you pass `nil`, `Date` formats the date in the same way as the `description` property.
223+
224+
- Returns: A string representation of the `Date`, using the given locale, or if the locale argument is `nil`, in the international format `YYYY-MM-DD HH:MM:SS ±HHMM`, where `±HHMM` represents the time zone offset in hours and minutes from UTC (for example, "`2001-03-24 10:45:32 +0600`").
225+
*/
226+
public func description(with locale: Locale?) -> String {
227+
return NSDate(timeIntervalSinceReferenceDate: _time).description(with: locale)
228+
}
229+
230+
public var debugDescription: String {
231+
return description
232+
}
233+
234+
public var customMirror: Mirror {
235+
var c: [(label: String?, value: Any)] = []
236+
c.append((label: "timeIntervalSinceReferenceDate", value: timeIntervalSinceReferenceDate))
237+
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
238+
}
239+
}
240+
231241
extension Date : _ObjectiveCBridgeable {
232242
@_semantics("convertToObjectiveC")
233243
public func _bridgeToObjectiveC() -> NSDate {

stdlib/public/SDK/Foundation/DateComponents.swift

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,6 @@ public struct DateComponents : ReferenceConvertible, Hashable, Equatable, _Mutab
267267
return _handle.map { $0.hash }
268268
}
269269

270-
public var description: String {
271-
return _handle.map { $0.description }
272-
}
273-
274-
public var debugDescription: String {
275-
return _handle.map { $0.debugDescription }
276-
}
277-
278270
// MARK: - Bridging Helpers
279271

280272
fileprivate init(reference: NSDateComponents) {
@@ -288,6 +280,40 @@ public struct DateComponents : ReferenceConvertible, Hashable, Equatable, _Mutab
288280

289281
}
290282

283+
extension DateComponents : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
284+
285+
public var description: String {
286+
return self.customMirror.children.reduce("") {
287+
$0.appending("\($1.label ?? ""): \($1.value) ")
288+
}
289+
}
290+
291+
public var debugDescription: String {
292+
return self.description
293+
}
294+
295+
public var customMirror: Mirror {
296+
var c: [(label: String?, value: Any)] = []
297+
if let r = calendar { c.append((label: "calendar", value: r)) }
298+
if let r = timeZone { c.append((label: "timeZone", value: r)) }
299+
if let r = era { c.append((label: "era", value: r)) }
300+
if let r = year { c.append((label: "year", value: r)) }
301+
if let r = month { c.append((label: "month", value: r)) }
302+
if let r = day { c.append((label: "day", value: r)) }
303+
if let r = hour { c.append((label: "hour", value: r)) }
304+
if let r = minute { c.append((label: "minute", value: r)) }
305+
if let r = second { c.append((label: "second", value: r)) }
306+
if let r = nanosecond { c.append((label: "nanosecond", value: r)) }
307+
if let r = weekday { c.append((label: "weekday", value: r)) }
308+
if let r = weekdayOrdinal { c.append((label: "weekdayOrdinal", value: r)) }
309+
if let r = quarter { c.append((label: "quarter", value: r)) }
310+
if let r = weekOfMonth { c.append((label: "weekOfMonth", value: r)) }
311+
if let r = weekOfYear { c.append((label: "weekOfYear", value: r)) }
312+
if let r = yearForWeekOfYear { c.append((label: "yearForWeekOfYear", value: r)) }
313+
if let r = isLeapMonth { c.append((label: "isLeapMonth", value: r)) }
314+
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
315+
}
316+
}
291317

292318
// MARK: - Bridging
293319

stdlib/public/SDK/Foundation/DateInterval.swift

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,6 @@ public struct DateInterval : ReferenceConvertible, Comparable, Hashable {
161161
}
162162
}
163163

164-
public var description: String {
165-
return "(Start Date) \(start) + (Duration) \(duration) seconds = (End Date) \(end)"
166-
}
167-
168-
public var debugDescription: String {
169-
return description
170-
}
171-
172164
@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
173165
public static func ==(lhs: DateInterval, rhs: DateInterval) -> Bool {
174166
return lhs.start == rhs.start && lhs.duration == rhs.duration
@@ -178,7 +170,25 @@ public struct DateInterval : ReferenceConvertible, Comparable, Hashable {
178170
public static func <(lhs: DateInterval, rhs: DateInterval) -> Bool {
179171
return lhs.compare(rhs) == .orderedAscending
180172
}
173+
}
181174

175+
@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
176+
extension DateInterval : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
177+
public var description: String {
178+
return "\(start) to \(end)"
179+
}
180+
181+
public var debugDescription: String {
182+
return description
183+
}
184+
185+
public var customMirror: Mirror {
186+
var c: [(label: String?, value: Any)] = []
187+
c.append((label: "start", value: start))
188+
c.append((label: "end", value: end))
189+
c.append((label: "duration", value: duration))
190+
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
191+
}
182192
}
183193

184194
@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)

stdlib/public/SDK/Foundation/IndexPath.swift

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,7 @@ public struct IndexPath : ReferenceConvertible, Equatable, Hashable, MutableColl
145145
let me = self.makeReference()
146146
return me.hash
147147
}
148-
149-
public var description: String {
150-
return _indexes.description
151-
}
152-
153-
public var debugDescription: String {
154-
return _indexes.debugDescription
155-
}
156-
148+
157149
// MARK: - Bridging Helpers
158150

159151
fileprivate init(nsIndexPath: ReferenceType) {
@@ -208,6 +200,20 @@ public struct IndexPath : ReferenceConvertible, Equatable, Hashable, MutableColl
208200
}
209201
}
210202

203+
extension IndexPath : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
204+
public var description: String {
205+
return _indexes.description
206+
}
207+
208+
public var debugDescription: String {
209+
return _indexes.debugDescription
210+
}
211+
212+
public var customMirror: Mirror {
213+
return _indexes.customMirror
214+
}
215+
}
216+
211217
extension IndexPath : _ObjectiveCBridgeable {
212218
public static func _getObjectiveCType() -> Any.Type {
213219
return NSIndexPath.self

stdlib/public/SDK/Foundation/IndexSet.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -724,14 +724,6 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
724724
public mutating func shift(startingAt integer: Element, by delta: IndexSet.IndexDistance) {
725725
_applyMutation { $0.shiftIndexesStarting(at: integer, by: delta) }
726726
}
727-
728-
public var description: String {
729-
return _handle.map { $0.description }
730-
}
731-
732-
public var debugDescription: String {
733-
return _handle.map { $0.debugDescription }
734-
}
735727

736728
// Temporary boxing function, until we can get a native Swift type for NSIndexSet
737729
@inline(__always)
@@ -777,6 +769,22 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
777769
}
778770
}
779771

772+
extension IndexSet : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
773+
public var description: String {
774+
return "\(count) indexes"
775+
}
776+
777+
public var debugDescription: String {
778+
return "\(count) indexes"
779+
}
780+
781+
public var customMirror: Mirror {
782+
var c: [(label: String?, value: Any)] = []
783+
c.append((label: "ranges", value: rangeView.map { $0 }))
784+
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
785+
}
786+
}
787+
780788
/// Iterate two index sets on the boundaries of their ranges. This is where all of the interesting stuff happens for exclusive or, intersect, etc.
781789
private struct IndexSetBoundaryIterator : IteratorProtocol {
782790
private typealias Element = IndexSet.Element

0 commit comments

Comments
 (0)