Skip to content

Add CustomReflectable implementation to most Foundation value types. #3752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions stdlib/public/SDK/Foundation/Calendar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal func __NSCalendarInit(_ identifier : NSString) -> NSCalendar?
/**
`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.
*/
public struct Calendar : CustomStringConvertible, CustomDebugStringConvertible, Hashable, Equatable, ReferenceConvertible, _MutableBoxing {
public struct Calendar : Hashable, Equatable, ReferenceConvertible, _MutableBoxing {
public typealias ReferenceType = NSCalendar

private var _autoupdating: Bool
Expand Down Expand Up @@ -908,14 +908,6 @@ public struct Calendar : CustomStringConvertible, CustomDebugStringConvertible,

// MARK: -

public var description: String {
return _handle.map { $0.description }
}

public var debugDescription : String {
return _handle.map { $0.debugDescription }
}

public var hashValue : Int {
// We implement hash ourselves, because we need to make sure autoupdating calendars have the same hash
if _autoupdating {
Expand Down Expand Up @@ -1081,6 +1073,37 @@ public struct Calendar : CustomStringConvertible, CustomDebugStringConvertible,

}

extension Calendar : CustomDebugStringConvertible, CustomStringConvertible, CustomReflectable {
private var _kindDescription : String {
if (self == Calendar.autoupdatingCurrent) {
return "autoupdatingCurrent"
} else if (self == Calendar.current) {
return "current"
} else {
return "fixed"
}
}

public var description: String {
return "\(identifier) (\(_kindDescription))"
}

public var debugDescription : String {
return "\(identifier) (\(_kindDescription))"
}

public var customMirror : Mirror {
var c: [(label: String?, value: Any)] = []
c.append((label: "identifier", value: identifier))
c.append((label: "kind", value: _kindDescription))
c.append((label: "locale", value: locale))
c.append((label: "timeZone", value: timeZone))
c.append((label: "firstWeekday", value: firstWeekday))
c.append((label: "minimumDaysInFirstWeek", value: minimumDaysInFirstWeek))
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
}
}

extension Calendar : _ObjectiveCBridgeable {
public static func _isBridgedToObjectiveC() -> Bool {
return true
Expand Down
44 changes: 33 additions & 11 deletions stdlib/public/SDK/Foundation/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,15 @@ internal final class _SwiftNSData : _SwiftNativeNSData, _SwiftNativeFoundationTy
}
}


/**
`Data` is a `MutableCollection` of bytes.

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`.

`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.
*/
public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection, _MutablePairBoxing {
public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection, _MutablePairBoxing {
/// The Objective-C bridged type of `Data`.
public typealias ReferenceType = NSData

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

/// A human-readable description for the data.
public var description: String {
return _mapUnmanaged { $0.description }
}

/// A human-readable debug description for the data.
public var debugDescription: String {
return _mapUnmanaged { $0.debugDescription }
}

// MARK: -

// MARK: -
Expand Down Expand Up @@ -676,6 +667,37 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
}
}

extension Data : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
/// A human-readable description for the data.
public var description: String {
return "\(self.count) bytes"
}

/// A human-readable debug description for the data.
public var debugDescription: String {
return self.description
}

public var customMirror: Mirror {
let nBytes = self.count
var children: [(label: String?, value: Any)] = []
children.append((label: "count", value: nBytes))

self.withUnsafeBytes { (bytes : UnsafePointer<UInt8>) in
children.append((label: "pointer", value: bytes))
}

// Minimal size data is output as an array
if nBytes < 64 {
children.append((label: "bytes", value: self[0..<nBytes].map { $0 }))
}

let m = Mirror(self, children:children, displayStyle: Mirror.DisplayStyle.struct)
return m
}
}


/// Provides bridging functionality for struct Data to class NSData and vice-versa.
extension Data : _ObjectiveCBridgeable {
public static func _isBridgedToObjectiveC() -> Bool {
Expand Down
66 changes: 38 additions & 28 deletions stdlib/public/SDK/Foundation/Date.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import CoreFoundation

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`.
*/
public struct Date : ReferenceConvertible, Comparable, Equatable, CustomStringConvertible {
public struct Date : ReferenceConvertible, Comparable, Equatable {
public typealias ReferenceType = NSDate

private var _time : TimeInterval
Expand Down Expand Up @@ -160,33 +160,6 @@ public struct Date : ReferenceConvertible, Comparable, Equatable, CustomStringCo
}
}

/**
A string representation of the date object (read-only).

The representation is useful for debugging only.

There are a number of options to acquire a formatted string for a date including: date formatters (see
[NSDateFormatter](//apple_ref/occ/cl/NSDateFormatter) and [Data Formatting Guide](//apple_ref/doc/uid/10000029i)), and the `Date` functions `description(locale:)`.
*/
public var description: String {
// Defer to NSDate for description
return NSDate(timeIntervalSinceReferenceDate: _time).description
}

/**
Returns a string representation of the receiver using the given
locale.

- Parameter locale: A `Locale` object. If you pass `nil`, `NSDate` formats the date in the same way as the `description` property.

- 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`").
*/
public func description(with locale: Locale?) -> String {
return NSDate(timeIntervalSinceReferenceDate: _time).description(with: locale)
}

public var debugDescription: String { return description }

/// Returns true if the two `Date` values represent the same point in time.
public static func ==(lhs: Date, rhs: Date) -> Bool {
return lhs.timeIntervalSinceReferenceDate == rhs.timeIntervalSinceReferenceDate
Expand Down Expand Up @@ -228,6 +201,43 @@ public struct Date : ReferenceConvertible, Comparable, Equatable, CustomStringCo

}

extension Date : CustomDebugStringConvertible, CustomStringConvertible, CustomReflectable {
/**
A string representation of the date object (read-only).

The representation is useful for debugging only.

There are a number of options to acquire a formatted string for a date including: date formatters (see
[NSDateFormatter](//apple_ref/occ/cl/NSDateFormatter) and [Data Formatting Guide](//apple_ref/doc/uid/10000029i)), and the `Date` function `description(locale:)`.
*/
public var description: String {
// Defer to NSDate for description
return NSDate(timeIntervalSinceReferenceDate: _time).description
}

/**
Returns a string representation of the receiver using the given
locale.

- Parameter locale: A `Locale`. If you pass `nil`, `Date` formats the date in the same way as the `description` property.

- 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`").
*/
public func description(with locale: Locale?) -> String {
return NSDate(timeIntervalSinceReferenceDate: _time).description(with: locale)
}

public var debugDescription: String {
return description
}

public var customMirror: Mirror {
var c: [(label: String?, value: Any)] = []
c.append((label: "timeIntervalSinceReferenceDate", value: timeIntervalSinceReferenceDate))
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
}
}

extension Date : _ObjectiveCBridgeable {
public static func _isBridgedToObjectiveC() -> Bool {
return true
Expand Down
42 changes: 34 additions & 8 deletions stdlib/public/SDK/Foundation/DateComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,6 @@ public struct DateComponents : ReferenceConvertible, Hashable, Equatable, _Mutab
return _handle.map { $0.hash }
}

public var description: String {
return _handle.map { $0.description }
}

public var debugDescription: String {
return _handle.map { $0.debugDescription }
}

// MARK: - Bridging Helpers

private init(reference: NSDateComponents) {
Expand All @@ -288,6 +280,40 @@ public struct DateComponents : ReferenceConvertible, Hashable, Equatable, _Mutab

}

extension DateComponents : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {

public var description: String {
return self.customMirror.children.reduce("") {
$0.appending("\($1.label ?? ""): \($1.value) ")
}
}

public var debugDescription: String {
return self.description
}

public var customMirror: Mirror {
var c: [(label: String?, value: Any)] = []
if let r = calendar { c.append((label: "calendar", value: r)) }
if let r = timeZone { c.append((label: "timeZone", value: r)) }
if let r = era { c.append((label: "era", value: r)) }
if let r = year { c.append((label: "year", value: r)) }
if let r = month { c.append((label: "month", value: r)) }
if let r = day { c.append((label: "day", value: r)) }
if let r = hour { c.append((label: "hour", value: r)) }
if let r = minute { c.append((label: "minute", value: r)) }
if let r = second { c.append((label: "second", value: r)) }
if let r = nanosecond { c.append((label: "nanosecond", value: r)) }
if let r = weekday { c.append((label: "weekday", value: r)) }
if let r = weekdayOrdinal { c.append((label: "weekdayOrdinal", value: r)) }
if let r = quarter { c.append((label: "quarter", value: r)) }
if let r = weekOfMonth { c.append((label: "weekOfMonth", value: r)) }
if let r = weekOfYear { c.append((label: "weekOfYear", value: r)) }
if let r = yearForWeekOfYear { c.append((label: "yearForWeekOfYear", value: r)) }
if let r = isLeapMonth { c.append((label: "isLeapMonth", value: r)) }
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
}
}

// MARK: - Bridging

Expand Down
26 changes: 18 additions & 8 deletions stdlib/public/SDK/Foundation/DateInterval.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,6 @@ public struct DateInterval : ReferenceConvertible, Comparable, Hashable {
}
}

public var description: String {
return "(Start Date) \(start) + (Duration) \(duration) seconds = (End Date) \(end)"
}

public var debugDescription: String {
return description
}

@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
public static func ==(lhs: DateInterval, rhs: DateInterval) -> Bool {
return lhs.start == rhs.start && lhs.duration == rhs.duration
Expand All @@ -178,7 +170,25 @@ public struct DateInterval : ReferenceConvertible, Comparable, Hashable {
public static func <(lhs: DateInterval, rhs: DateInterval) -> Bool {
return lhs.compare(rhs) == .orderedAscending
}
}

@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
extension DateInterval : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
public var description: String {
return "\(start) to \(end)"
}

public var debugDescription: String {
return description
}

public var customMirror: Mirror {
var c: [(label: String?, value: Any)] = []
c.append((label: "start", value: start))
c.append((label: "end", value: end))
c.append((label: "duration", value: duration))
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
}
}

@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
Expand Down
24 changes: 15 additions & 9 deletions stdlib/public/SDK/Foundation/IndexPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,7 @@ public struct IndexPath : ReferenceConvertible, Equatable, Hashable, MutableColl
let me = self.makeReference()
return me.hash
}

public var description: String {
return _indexes.description
}

public var debugDescription: String {
return _indexes.debugDescription
}


// MARK: - Bridging Helpers

private init(nsIndexPath: ReferenceType) {
Expand Down Expand Up @@ -208,6 +200,20 @@ public struct IndexPath : ReferenceConvertible, Equatable, Hashable, MutableColl
}
}

extension IndexPath : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
public var description: String {
return _indexes.description
}

public var debugDescription: String {
return _indexes.debugDescription
}

public var customMirror: Mirror {
return _indexes.customMirror
}
}

extension IndexPath : _ObjectiveCBridgeable {
public static func _isBridgedToObjectiveC() -> Bool {
return true
Expand Down
24 changes: 16 additions & 8 deletions stdlib/public/SDK/Foundation/IndexSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -724,14 +724,6 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
public mutating func shift(startingAt integer: Element, by delta: IndexSet.IndexDistance) {
_applyMutation { $0.shiftIndexesStarting(at: integer, by: delta) }
}

public var description: String {
return _handle.map { $0.description }
}

public var debugDescription: String {
return _handle.map { $0.debugDescription }
}

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

extension IndexSet : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
public var description: String {
return "\(count) indexes"
}

public var debugDescription: String {
return "\(count) indexes"
}

public var customMirror: Mirror {
var c: [(label: String?, value: Any)] = []
c.append((label: "ranges", value: rangeView.map { $0 }))
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
}
}

/// Iterate two index sets on the boundaries of their ranges. This is where all of the interesting stuff happens for exclusive or, intersect, etc.
private struct IndexSetBoundaryIterator : IteratorProtocol {
private typealias Element = IndexSet.Element
Expand Down
Loading