blob: c3fca5b6ae8cfa959f17b22195746bae2c8d4743 [file] [log] [blame]
//===--- Mirror.swift -----------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// FIXME: ExistentialCollection needs to be supported before this will work
// without the ObjC Runtime.
/// A representation of the substructure and display style of an instance of
/// any type.
///
/// A mirror describes the parts that make up a particular instance, such as
/// the instance's stored properties, collection or tuple elements, or its
/// active enumeration case. Mirrors also provide a "display style" property
/// that suggests how this mirror might be rendered.
///
/// Playgrounds and the debugger use the `Mirror` type to display
/// representations of values of any type. For example, when you pass an
/// instance to the `dump(_:_:_:_:)` function, a mirror is used to render that
/// instance's runtime contents.
///
/// struct Point {
/// let x: Int, y: Int
/// }
///
/// let p = Point(x: 21, y: 30)
/// print(String(reflecting: p))
/// // Prints "▿ Point
/// // - x: 21
/// // - y: 30"
///
/// To customize the mirror representation of a custom type, add conformance to
/// the `CustomReflectable` protocol.
@_fixed_layout // FIXME(sil-serialize-all)
public struct Mirror {
/// Representation of descendant classes that don't override
/// `customMirror`.
///
/// Note that the effect of this setting goes no deeper than the
/// nearest descendant class that overrides `customMirror`, which
/// in turn can determine representation of *its* descendants.
@_versioned // FIXME(sil-serialize-all)
internal enum _DefaultDescendantRepresentation {
/// Generate a default mirror for descendant classes that don't
/// override `customMirror`.
///
/// This case is the default.
case generated
/// Suppress the representation of descendant classes that don't
/// override `customMirror`.
///
/// This option may be useful at the root of a class cluster, where
/// implementation details of descendants should generally not be
/// visible to clients.
case suppressed
}
/// The representation to use for ancestor classes.
///
/// A class that conforms to the `CustomReflectable` protocol can control how
/// its mirror represents ancestor classes by initializing the mirror
/// with an `AncestorRepresentation`. This setting has no effect on mirrors
/// reflecting value type instances.
public enum AncestorRepresentation {
/// Generates a default mirror for all ancestor classes.
///
/// This case is the default when initializing a `Mirror` instance.
///
/// When you use this option, a subclass's mirror generates default mirrors
/// even for ancestor classes that conform to the `CustomReflectable`
/// protocol. To avoid dropping the customization provided by ancestor
/// classes, an override of `customMirror` should pass
/// `.customized({ super.customMirror })` as `ancestorRepresentation` when
/// initializing its mirror.
case generated
/// Uses the nearest ancestor's implementation of `customMirror` to create
/// a mirror for that ancestor.
///
/// Other classes derived from such an ancestor are given a default mirror.
/// The payload for this option should always be `{ super.customMirror }`:
///
/// var customMirror: Mirror {
/// return Mirror(
/// self,
/// children: ["someProperty": self.someProperty],
/// ancestorRepresentation: .customized({ super.customMirror })) // <==
/// }
case customized(() -> Mirror)
/// Suppresses the representation of all ancestor classes.
///
/// In a mirror created with this ancestor representation, the
/// `superclassMirror` property is `nil`.
case suppressed
}
/// Creates a mirror that reflects on the given instance.
///
/// If the dynamic type of `subject` conforms to `CustomReflectable`, the
/// resulting mirror is determined by its `customMirror` property.
/// Otherwise, the result is generated by the language.
///
/// If the dynamic type of `subject` has value semantics, subsequent
/// mutations of `subject` will not observable in `Mirror`. In general,
/// though, the observability of mutations is unspecified.
///
/// - Parameter subject: The instance for which to create a mirror.
@_inlineable // FIXME(sil-serialize-all)
public init(reflecting subject: Any) {
if case let customized as CustomReflectable = subject {
self = customized.customMirror
} else {
self = Mirror(
legacy: _reflect(subject),
subjectType: type(of: subject))
}
}
/// An element of the reflected instance's structure.
///
/// When the `label` component in not `nil`, it may represent the name of a
/// stored property or an active `enum` case. If you pass strings to the
/// `descendant(_:_:)` method, labels are used for lookup.
public typealias Child = (label: String?, value: Any)
/// The type used to represent substructure.
///
/// When working with a mirror that reflects a bidirectional or random access
/// collection, you may find it useful to "upgrade" instances of this type
/// to `AnyBidirectionalCollection` or `AnyRandomAccessCollection`. For
/// example, to display the last twenty children of a mirror if they can be
/// accessed efficiently, you write the following code:
///
/// if let b = AnyBidirectionalCollection(someMirror.children) {
/// for element in b.suffix(20) {
/// print(element)
/// }
/// }
public typealias Children = AnyCollection<Child>
/// A suggestion of how a mirror's subject is to be interpreted.
///
/// Playgrounds and the debugger will show a representation similar
/// to the one used for instances of the kind indicated by the
/// `DisplayStyle` case name when the mirror is used for display.
@_fixed_layout // FIXME(sil-serialize-all)
public enum DisplayStyle {
case `struct`, `class`, `enum`, tuple, optional, collection
case dictionary, `set`
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal static func _noSuperclassMirror() -> Mirror? { return nil }
/// Returns the legacy mirror representing the part of `subject`
/// corresponding to the superclass of `staticSubclass`.
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal static func _legacyMirror(
_ subject: AnyObject, asClass targetSuperclass: AnyClass) -> _Mirror? {
// get a legacy mirror and the most-derived type
var cls: AnyClass = type(of: subject)
var clsMirror = _reflect(subject)
// Walk up the chain of mirrors/classes until we find staticSubclass
while let superclass: AnyClass = _getSuperclass(cls) {
guard let superclassMirror = clsMirror._superMirror() else { break }
if superclass == targetSuperclass { return superclassMirror }
clsMirror = superclassMirror
cls = superclass
}
return nil
}
@_semantics("optimize.sil.specialize.generic.never")
@inline(never)
@_inlineable // FIXME(sil-serialize-all)
@_versioned
internal static func _superclassIterator<Subject>(
_ subject: Subject, _ ancestorRepresentation: AncestorRepresentation
) -> () -> Mirror? {
if let subjectClass = Subject.self as? AnyClass,
let superclass = _getSuperclass(subjectClass) {
switch ancestorRepresentation {
case .generated:
return {
self._legacyMirror(_unsafeDowncastToAnyObject(fromAny: subject), asClass: superclass).map {
Mirror(legacy: $0, subjectType: superclass)
}
}
case .customized(let makeAncestor):
return {
Mirror(_unsafeDowncastToAnyObject(fromAny: subject), subjectClass: superclass,
ancestor: makeAncestor())
}
case .suppressed:
break
}
}
return Mirror._noSuperclassMirror
}
/// Creates a mirror representing the given subject with a specified
/// structure.
///
/// You use this initializer from within your type's `customMirror`
/// implementation to create a customized mirror.
///
/// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
/// `customMirror` implementations will be used. By default, the
/// `customMirror` implementation of any ancestors is ignored. To prevent
/// bypassing customized ancestors, pass
/// `.customized({ super.customMirror })` as the `ancestorRepresentation`
/// parameter when implementing your type's `customMirror` property.
///
/// - Parameters:
/// - subject: The instance to represent in the new mirror.
/// - children: The structure to use for the mirror. The collection
/// traversal modeled by `children` is captured so that the resulting
/// mirror's children may be upgraded to a bidirectional or random
/// access collection later. See the `children` property for details.
/// - displayStyle: The preferred display style for the mirror when
/// presented in the debugger or in a playground. The default is `nil`.
/// - ancestorRepresentation: The means of generating the subject's
/// ancestor representation. `ancestorRepresentation` is ignored if
/// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject, C : Collection>(
_ subject: Subject,
children: C,
displayStyle: DisplayStyle? = nil,
ancestorRepresentation: AncestorRepresentation = .generated
) where C.Element == Child
{
self.subjectType = Subject.self
self._makeSuperclassMirror = Mirror._superclassIterator(
subject, ancestorRepresentation)
self.children = Children(children)
self.displayStyle = displayStyle
self._defaultDescendantRepresentation
= subject is CustomLeafReflectable ? .suppressed : .generated
}
/// Creates a mirror representing the given subject with unlabeled children.
///
/// You use this initializer from within your type's `customMirror`
/// implementation to create a customized mirror, particularly for custom
/// types that are collections. The labels of the resulting mirror's
/// `children` collection are all `nil`.
///
/// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
/// `customMirror` implementations will be used. By default, the
/// `customMirror` implementation of any ancestors is ignored. To prevent
/// bypassing customized ancestors, pass
/// `.customized({ super.customMirror })` as the `ancestorRepresentation`
/// parameter when implementing your type's `customMirror` property.
///
/// - Parameters:
/// - subject: The instance to represent in the new mirror.
/// - unlabeledChildren: The children to use for the mirror. The collection
/// traversal modeled by `unlabeledChildren` is captured so that the
/// resulting mirror's children may be upgraded to a bidirectional or
/// random access collection later. See the `children` property for
/// details.
/// - displayStyle: The preferred display style for the mirror when
/// presented in the debugger or in a playground. The default is `nil`.
/// - ancestorRepresentation: The means of generating the subject's
/// ancestor representation. `ancestorRepresentation` is ignored if
/// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject, C : Collection>(
_ subject: Subject,
unlabeledChildren: C,
displayStyle: DisplayStyle? = nil,
ancestorRepresentation: AncestorRepresentation = .generated
)
{
self.subjectType = Subject.self
self._makeSuperclassMirror = Mirror._superclassIterator(
subject, ancestorRepresentation)
let lazyChildren =
unlabeledChildren.lazy.map { Child(label: nil, value: $0) }
self.children = Children(lazyChildren)
self.displayStyle = displayStyle
self._defaultDescendantRepresentation
= subject is CustomLeafReflectable ? .suppressed : .generated
}
/// Creates a mirror representing the given subject using a dictionary
/// literal for the structure.
///
/// You use this initializer from within your type's `customMirror`
/// implementation to create a customized mirror. Pass a dictionary literal
/// with string keys as `children`. Although an *actual* dictionary is
/// arbitrarily-ordered, when you create a mirror with a dictionary literal,
/// the ordering of the mirror's `children` will exactly match that of the
/// literal you pass.
///
/// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
/// `customMirror` implementations will be used. By default, the
/// `customMirror` implementation of any ancestors is ignored. To prevent
/// bypassing customized ancestors, pass
/// `.customized({ super.customMirror })` as the `ancestorRepresentation`
/// parameter when implementing your type's `customMirror` property.
///
/// - Parameters:
/// - subject: The instance to represent in the new mirror.
/// - children: A dictionary literal to use as the structure for the
/// mirror. The `children` collection of the resulting mirror may be
/// upgraded to a random access collection later. See the `children`
/// property for details.
/// - displayStyle: The preferred display style for the mirror when
/// presented in the debugger or in a playground. The default is `nil`.
/// - ancestorRepresentation: The means of generating the subject's
/// ancestor representation. `ancestorRepresentation` is ignored if
/// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject>(
_ subject: Subject,
children: DictionaryLiteral<String, Any>,
displayStyle: DisplayStyle? = nil,
ancestorRepresentation: AncestorRepresentation = .generated
) {
self.subjectType = Subject.self
self._makeSuperclassMirror = Mirror._superclassIterator(
subject, ancestorRepresentation)
let lazyChildren = children.lazy.map { Child(label: $0.0, value: $0.1) }
self.children = Children(lazyChildren)
self.displayStyle = displayStyle
self._defaultDescendantRepresentation
= subject is CustomLeafReflectable ? .suppressed : .generated
}
/// The static type of the subject being reflected.
///
/// This type may differ from the subject's dynamic type when this mirror
/// is the `superclassMirror` of another mirror.
public let subjectType: Any.Type
/// A collection of `Child` elements describing the structure of the
/// reflected subject.
public let children: Children
/// A suggested display style for the reflected subject.
public let displayStyle: DisplayStyle?
/// A mirror of the subject's superclass, if one exists.
@_inlineable // FIXME(sil-serialize-all)
public var superclassMirror: Mirror? {
return _makeSuperclassMirror()
}
@_versioned // FIXME(sil-serialize-all)
internal let _makeSuperclassMirror: () -> Mirror?
@_versioned // FIXME(sil-serialize-all)
internal let _defaultDescendantRepresentation: _DefaultDescendantRepresentation
}
/// A type that explicitly supplies its own mirror.
///
/// You can create a mirror for any type using the `Mirror(reflecting:)`
/// initializer, but if you are not satisfied with the mirror supplied for
/// your type by default, you can make it conform to `CustomReflectable` and
/// return a custom `Mirror` instance.
public protocol CustomReflectable {
/// The custom mirror for this instance.
///
/// If this type has value semantics, the mirror should be unaffected by
/// subsequent mutations of the instance.
var customMirror: Mirror { get }
}
/// A type that explicitly supplies its own mirror, but whose
/// descendant classes are not represented in the mirror unless they
/// also override `customMirror`.
public protocol CustomLeafReflectable : CustomReflectable {}
//===--- Addressing -------------------------------------------------------===//
/// A protocol for legitimate arguments to `Mirror`'s `descendant`
/// method.
///
/// Do not declare new conformances to this protocol; they will not
/// work as expected.
public protocol MirrorPath {
// FIXME(ABI)#49 (Sealed Protocols): this protocol should be "non-open" and
// you shouldn't be able to create conformances.
}
extension Int : MirrorPath {}
extension String : MirrorPath {}
extension Mirror {
@_fixed_layout // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal struct _Dummy : CustomReflectable {
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init(mirror: Mirror) {
self.mirror = mirror
}
@_versioned // FIXME(sil-serialize-all)
internal var mirror: Mirror
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal var customMirror: Mirror { return mirror }
}
/// Returns a specific descendant of the reflected subject, or `nil` if no
/// such descendant exists.
///
/// Pass a variadic list of string and integer arguments. Each string
/// argument selects the first child with a matching label. Each integer
/// argument selects the child at that offset. For example, passing
/// `1, "two", 3` as arguments to `myMirror.descendant(_:_:)` is equivalent
/// to:
///
/// var result: Any? = nil
/// let children = myMirror.children
/// if let i0 = children.index(
/// children.startIndex, offsetBy: 1, limitedBy: children.endIndex),
/// i0 != children.endIndex
/// {
/// let grandChildren = Mirror(reflecting: children[i0].value).children
/// if let i1 = grandChildren.index(where: { $0.label == "two" }) {
/// let greatGrandChildren =
/// Mirror(reflecting: grandChildren[i1].value).children
/// if let i2 = greatGrandChildren.index(
/// greatGrandChildren.startIndex,
/// offsetBy: 3,
/// limitedBy: greatGrandChildren.endIndex),
/// i2 != greatGrandChildren.endIndex
/// {
/// // Success!
/// result = greatGrandChildren[i2].value
/// }
/// }
/// }
///
/// This function is suitable for exploring the structure of a mirror in a
/// REPL or playground, but is not intended to be efficient. The efficiency
/// of finding each element in the argument list depends on the argument
/// type and the capabilities of the each level of the mirror's `children`
/// collections. Each string argument requires a linear search, and unless
/// the underlying collection supports random-access traversal, each integer
/// argument also requires a linear operation.
///
/// - Parameters:
/// - first: The first mirror path component to access.
/// - rest: Any remaining mirror path components.
/// - Returns: The descendant of this mirror specified by the given mirror
/// path components if such a descendant exists; otherwise, `nil`.
@_inlineable // FIXME(sil-serialize-all)
public func descendant(
_ first: MirrorPath, _ rest: MirrorPath...
) -> Any? {
var result: Any = _Dummy(mirror: self)
for e in [first] + rest {
let children = Mirror(reflecting: result).children
let position: Children.Index
if case let label as String = e {
position = children.index { $0.label == label } ?? children.endIndex
}
else if let offset = e as? Int {
position = children.index(children.startIndex,
offsetBy: offset,
limitedBy: children.endIndex) ?? children.endIndex
}
else {
_preconditionFailure(
"Someone added a conformance to MirrorPath; that privilege is reserved to the standard library")
}
if position == children.endIndex { return nil }
result = children[position].value
}
return result
}
}
//===--- Legacy _Mirror Support -------------------------------------------===//
extension Mirror.DisplayStyle {
/// Construct from a legacy `_MirrorDisposition`
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init?(legacy: _MirrorDisposition) {
switch legacy {
case .`struct`: self = .`struct`
case .`class`: self = .`class`
case .`enum`: self = .`enum`
case .tuple: self = .tuple
case .aggregate: return nil
case .indexContainer: self = .collection
case .keyContainer: self = .dictionary
case .membershipContainer: self = .`set`
case .container: preconditionFailure("unused!")
case .optional: self = .optional
case .objCObject: self = .`class`
}
}
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal func _isClassSuperMirror(_ t: Any.Type) -> Bool {
#if _runtime(_ObjC)
return t == _ClassSuperMirror.self || t == _ObjCSuperMirror.self
#else
return t == _ClassSuperMirror.self
#endif
}
extension _Mirror {
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal func _superMirror() -> _Mirror? {
if self.count > 0 {
let childMirror = self[0].1
if _isClassSuperMirror(type(of: childMirror)) {
return childMirror
}
}
return nil
}
}
/// When constructed using the legacy reflection infrastructure, the
/// resulting `Mirror`'s `children` collection will always be
/// upgradable to `AnyRandomAccessCollection` even if it doesn't
/// exhibit appropriate performance. To avoid this pitfall, convert
/// mirrors to use the new style, which only present forward
/// traversal in general.
internal extension Mirror {
/// An adapter that represents a legacy `_Mirror`'s children as
/// a `Collection` with integer `Index`. Note that the performance
/// characteristics of the underlying `_Mirror` may not be
/// appropriate for random access! To avoid this pitfall, convert
/// mirrors to use the new style, which only present forward
/// traversal in general.
@_fixed_layout // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal struct LegacyChildren : RandomAccessCollection {
internal typealias Indices = CountableRange<Int>
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init(_ oldMirror: _Mirror) {
self._oldMirror = oldMirror
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal var startIndex: Int {
return _oldMirror._superMirror() == nil ? 0 : 1
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal var endIndex: Int { return _oldMirror.count }
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal subscript(position: Int) -> Child {
let (label, childMirror) = _oldMirror[position]
return (label: label, value: childMirror.value)
}
@_versioned // FIXME(sil-serialize-all)
internal let _oldMirror: _Mirror
}
/// Initialize for a view of `subject` as `subjectClass`.
///
/// - parameter ancestor: A Mirror for a (non-strict) ancestor of
/// `subjectClass`, to be injected into the resulting hierarchy.
///
/// - parameter legacy: Either `nil`, or a legacy mirror for `subject`
/// as `subjectClass`.
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init(
_ subject: AnyObject,
subjectClass: AnyClass,
ancestor: Mirror,
legacy legacyMirror: _Mirror? = nil
) {
if ancestor.subjectType == subjectClass
|| ancestor._defaultDescendantRepresentation == .suppressed {
self = ancestor
}
else {
let legacyMirror = legacyMirror ?? Mirror._legacyMirror(
subject, asClass: subjectClass)!
self = Mirror(
legacy: legacyMirror,
subjectType: subjectClass,
makeSuperclassMirror: {
_getSuperclass(subjectClass).map {
Mirror(
subject,
subjectClass: $0,
ancestor: ancestor,
legacy: legacyMirror._superMirror())
}
})
}
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init(
legacy legacyMirror: _Mirror,
subjectType: Any.Type,
makeSuperclassMirror: (() -> Mirror?)? = nil
) {
if let makeSuperclassMirror = makeSuperclassMirror {
self._makeSuperclassMirror = makeSuperclassMirror
}
else if let subjectSuperclass = _getSuperclass(subjectType) {
self._makeSuperclassMirror = {
legacyMirror._superMirror().map {
Mirror(legacy: $0, subjectType: subjectSuperclass) }
}
}
else {
self._makeSuperclassMirror = Mirror._noSuperclassMirror
}
self.subjectType = subjectType
self.children = Children(LegacyChildren(legacyMirror))
self.displayStyle = DisplayStyle(legacy: legacyMirror.disposition)
self._defaultDescendantRepresentation = .generated
}
}
//===--- QuickLooks -------------------------------------------------------===//
/// The sum of types that can be used as a Quick Look representation.
@_fixed_layout // FIXME(sil-serialize-all)
public enum PlaygroundQuickLook {
/// Plain text.
case text(String)
/// An integer numeric value.
case int(Int64)
/// An unsigned integer numeric value.
case uInt(UInt64)
/// A single precision floating-point numeric value.
case float(Float32)
/// A double precision floating-point numeric value.
case double(Float64)
// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
/// An image.
case image(Any)
// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
/// A sound.
case sound(Any)
// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
/// A color.
case color(Any)
// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
/// A bezier path.
case bezierPath(Any)
// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
/// An attributed string.
case attributedString(Any)
// FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
/// A rectangle.
case rectangle(Float64, Float64, Float64, Float64)
// FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
/// A point.
case point(Float64, Float64)
// FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
/// A size.
case size(Float64, Float64)
/// A boolean value.
case bool(Bool)
// FIXME: Uses explicit values to avoid coupling a particular Cocoa type.
/// A range.
case range(Int64, Int64)
// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
/// A GUI view.
case view(Any)
// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
/// A graphical sprite.
case sprite(Any)
/// A Uniform Resource Locator.
case url(String)
/// Raw data that has already been encoded in a format the IDE understands.
case _raw([UInt8], String)
}
extension PlaygroundQuickLook {
/// Creates a new Quick Look for the given instance.
///
/// If the dynamic type of `subject` conforms to
/// `CustomPlaygroundQuickLookable`, the result is found by calling its
/// `customPlaygroundQuickLook` property. Otherwise, the result is
/// synthesized by the language. In some cases, the synthesized result may
/// be `.text(String(reflecting: subject))`.
///
/// - Note: If the dynamic type of `subject` has value semantics, subsequent
/// mutations of `subject` will not observable in the Quick Look. In
/// general, though, the observability of such mutations is unspecified.
///
/// - Parameter subject: The instance to represent with the resulting Quick
/// Look.
@_inlineable // FIXME(sil-serialize-all)
public init(reflecting subject: Any) {
if let customized = subject as? CustomPlaygroundQuickLookable {
self = customized.customPlaygroundQuickLook
}
else if let customized = subject as? _DefaultCustomPlaygroundQuickLookable {
self = customized._defaultCustomPlaygroundQuickLook
}
else {
if let q = _reflect(subject).quickLookObject {
self = q
}
else {
self = .text(String(reflecting: subject))
}
}
}
}
/// A type that explicitly supplies its own playground Quick Look.
///
/// A Quick Look can be created for an instance of any type by using the
/// `PlaygroundQuickLook(reflecting:)` initializer. If you are not satisfied
/// with the representation supplied for your type by default, you can make it
/// conform to the `CustomPlaygroundQuickLookable` protocol and provide a
/// custom `PlaygroundQuickLook` instance.
public protocol CustomPlaygroundQuickLookable {
/// A custom playground Quick Look for this instance.
///
/// If this type has value semantics, the `PlaygroundQuickLook` instance
/// should be unaffected by subsequent mutations.
var customPlaygroundQuickLook: PlaygroundQuickLook { get }
}
// A workaround for <rdar://problem/26182650>
// FIXME(ABI)#50 (Dynamic Dispatch for Class Extensions) though not if it moves out of stdlib.
public protocol _DefaultCustomPlaygroundQuickLookable {
var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook { get }
}
//===--- General Utilities ------------------------------------------------===//
// This component could stand alone, but is used in Mirror's public interface.
/// A lightweight collection of key-value pairs.
///
/// Use a `DictionaryLiteral` instance when you need an ordered collection of
/// key-value pairs and don't require the fast key lookup that the
/// `Dictionary` type provides. Unlike key-value pairs in a true dictionary,
/// neither the key nor the value of a `DictionaryLiteral` instance must
/// conform to the `Hashable` protocol.
///
/// You initialize a `DictionaryLiteral` instance using a Swift dictionary
/// literal. Besides maintaining the order of the original dictionary literal,
/// `DictionaryLiteral` also allows duplicates keys. For example:
///
/// let recordTimes: DictionaryLiteral = ["Florence Griffith-Joyner": 10.49,
/// "Evelyn Ashford": 10.76,
/// "Evelyn Ashford": 10.79,
/// "Marlies Gohr": 10.81]
/// print(recordTimes.first!)
/// // Prints "("Florence Griffith-Joyner", 10.49)"
///
/// Some operations that are efficient on a dictionary are slower when using
/// `DictionaryLiteral`. In particular, to find the value matching a key, you
/// must search through every element of the collection. The call to
/// `index(where:)` in the following example must traverse the whole
/// collection to find the element that matches the predicate:
///
/// let runner = "Marlies Gohr"
/// if let index = recordTimes.index(where: { $0.0 == runner }) {
/// let time = recordTimes[index].1
/// print("\(runner) set a 100m record of \(time) seconds.")
/// } else {
/// print("\(runner) couldn't be found in the records.")
/// }
/// // Prints "Marlies Gohr set a 100m record of 10.81 seconds."
///
/// Dictionary Literals as Function Parameters
/// ------------------------------------------
///
/// When calling a function with a `DictionaryLiteral` parameter, you can pass
/// a Swift dictionary literal without causing a `Dictionary` to be created.
/// This capability can be especially important when the order of elements in
/// the literal is significant.
///
/// For example, you could create an `IntPairs` structure that holds a list of
/// two-integer tuples and use an initializer that accepts a
/// `DictionaryLiteral` instance.
///
/// struct IntPairs {
/// var elements: [(Int, Int)]
///
/// init(_ elements: DictionaryLiteral<Int, Int>) {
/// self.elements = Array(elements)
/// }
/// }
///
/// When you're ready to create a new `IntPairs` instance, use a dictionary
/// literal as the parameter to the `IntPairs` initializer. The
/// `DictionaryLiteral` instance preserves the order of the elements as
/// passed.
///
/// let pairs = IntPairs([1: 2, 1: 1, 3: 4, 2: 1])
/// print(pairs.elements)
/// // Prints "[(1, 2), (1, 1), (3, 4), (2, 1)]"
@_fixed_layout // FIXME(sil-serialize-all)
public struct DictionaryLiteral<Key, Value> : ExpressibleByDictionaryLiteral {
/// Creates a new `DictionaryLiteral` instance from the given dictionary
/// literal.
///
/// The order of the key-value pairs is kept intact in the resulting
/// `DictionaryLiteral` instance.
@_inlineable // FIXME(sil-serialize-all)
public init(dictionaryLiteral elements: (Key, Value)...) {
self._elements = elements
}
@_versioned // FIXME(sil-serialize-all)
internal let _elements: [(Key, Value)]
}
/// `Collection` conformance that allows `DictionaryLiteral` to
/// interoperate with the rest of the standard library.
extension DictionaryLiteral : RandomAccessCollection {
public typealias Indices = CountableRange<Int>
/// The position of the first element in a nonempty collection.
///
/// If the `DictionaryLiteral` instance is empty, `startIndex` is equal to
/// `endIndex`.
@_inlineable // FIXME(sil-serialize-all)
public var startIndex: Int { return 0 }
/// The collection's "past the end" position---that is, the position one
/// greater than the last valid subscript argument.
///
/// If the `DictionaryLiteral` instance is empty, `endIndex` is equal to
/// `startIndex`.
@_inlineable // FIXME(sil-serialize-all)
public var endIndex: Int { return _elements.endIndex }
// FIXME(ABI)#174 (Type checker): a typealias is needed to prevent <rdar://20248032>
/// The element type of a `DictionaryLiteral`: a tuple containing an
/// individual key-value pair.
public typealias Element = (key: Key, value: Value)
/// Accesses the element at the specified position.
///
/// - Parameter position: The position of the element to access. `position`
/// must be a valid index of the collection that is not equal to the
/// `endIndex` property.
/// - Returns: The key-value pair at position `position`.
@_inlineable // FIXME(sil-serialize-all)
public subscript(position: Int) -> Element {
return _elements[position]
}
}
extension String {
/// Creates a string representing the given value.
///
/// Use this initializer to convert an instance of any type to its preferred
/// representation as a `String` instance. The initializer creates the
/// string representation of `instance` in one of the following ways,
/// depending on its protocol conformance:
///
/// - If `instance` conforms to the `TextOutputStreamable` protocol, the
/// result is obtained by calling `instance.write(to: s)` on an empty
/// string `s`.
/// - If `instance` conforms to the `CustomStringConvertible` protocol, the
/// result is `instance.description`.
/// - If `instance` conforms to the `CustomDebugStringConvertible` protocol,
/// the result is `instance.debugDescription`.
/// - An unspecified result is supplied automatically by the Swift standard
/// library.
///
/// For example, this custom `Point` struct uses the default representation
/// supplied by the standard library.
///
/// struct Point {
/// let x: Int, y: Int
/// }
///
/// let p = Point(x: 21, y: 30)
/// print(String(describing: p))
/// // Prints "Point(x: 21, y: 30)"
///
/// After adding `CustomStringConvertible` conformance by implementing the
/// `description` property, `Point` provides its own custom representation.
///
/// extension Point: CustomStringConvertible {
/// var description: String {
/// return "(\(x), \(y))"
/// }
/// }
///
/// print(String(describing: p))
/// // Prints "(21, 30)"
@_inlineable // FIXME(sil-serialize-all)
public init<Subject>(describing instance: Subject) {
self.init()
_print_unlocked(instance, &self)
}
/// Creates a string with a detailed representation of the given value,
/// suitable for debugging.
///
/// Use this initializer to convert an instance of any type to its custom
/// debugging representation. The initializer creates the string
/// representation of `instance` in one of the following ways, depending on
/// its protocol conformance:
///
/// - If `subject` conforms to the `CustomDebugStringConvertible` protocol,
/// the result is `subject.debugDescription`.
/// - If `subject` conforms to the `CustomStringConvertible` protocol, the
/// result is `subject.description`.
/// - If `subject` conforms to the `TextOutputStreamable` protocol, the
/// result is obtained by calling `subject.write(to: s)` on an empty
/// string `s`.
/// - An unspecified result is supplied automatically by the Swift standard
/// library.
///
/// For example, this custom `Point` struct uses the default representation
/// supplied by the standard library.
///
/// struct Point {
/// let x: Int, y: Int
/// }
///
/// let p = Point(x: 21, y: 30)
/// print(String(reflecting: p))
/// // Prints "p: Point = {
/// // x = 21
/// // y = 30
/// // }"
///
/// After adding `CustomDebugStringConvertible` conformance by implementing
/// the `debugDescription` property, `Point` provides its own custom
/// debugging representation.
///
/// extension Point: CustomDebugStringConvertible {
/// var debugDescription: String {
/// return "Point(x: \(x), y: \(y))"
/// }
/// }
///
/// print(String(reflecting: p))
/// // Prints "Point(x: 21, y: 30)"
@_inlineable // FIXME(sil-serialize-all)
public init<Subject>(reflecting subject: Subject) {
self.init()
_debugPrint_unlocked(subject, &self)
}
}
/// Reflection for `Mirror` itself.
extension Mirror : CustomStringConvertible {
@_inlineable // FIXME(sil-serialize-all)
public var description: String {
return "Mirror for \(self.subjectType)"
}
}
extension Mirror : CustomReflectable {
@_inlineable // FIXME(sil-serialize-all)
public var customMirror: Mirror {
return Mirror(self, children: [:])
}
}