blob: 5c1fc0941fd6a51cb6b97b5bccace495372bb9ec [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
//
//===----------------------------------------------------------------------===//
// RUN: %empty-directory(%t)
// RUN: cp %s %t/main.swift
//
// RUN: if [ %target-runtime == "objc" ]; \
// RUN: then \
// RUN: %target-clang %S/Inputs/Mirror/Mirror.mm -c -o %t/Mirror.mm.o -g && \
// RUN: %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror; \
// RUN: else \
// RUN: %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -o %t/Mirror; \
// RUN: fi
// RUN: %target-codesign %t/Mirror
// RUN: %target-run %t/Mirror
// REQUIRES: executable_test
import StdlibUnittest
var mirrors = TestSuite("Mirrors")
extension Mirror {
public var testDescription: String {
let nil_ = "nil"
return "[" +
children.lazy
.map { "\($0.0 ?? nil_): \(String(reflecting: $0.1))" }
.joined(separator: ", ")
+ "]"
}
}
mirrors.test("RandomAccessStructure") {
struct Eggs : CustomReflectable {
var customMirror: Mirror {
return Mirror(self, unlabeledChildren: ["aay", "bee", "cee"])
}
}
let x = Eggs().customMirror
expectEqual("[nil: \"aay\", nil: \"bee\", nil: \"cee\"]", x.testDescription)
}
let letters = "abcdefghijklmnopqrstuvwxyz "
func find(_ substring: String, within domain: String) -> String.Index? {
let domainCount = domain.count
let substringCount = substring.count
if (domainCount < substringCount) { return nil }
var sliceStart = domain.startIndex
var sliceEnd = domain.index(sliceStart, offsetBy: substringCount)
var i = 0
while true {
if domain[sliceStart..<sliceEnd] == substring {
return sliceStart
}
if i == domainCount - substringCount { break }
sliceStart = domain.index(after: sliceStart)
sliceEnd = domain.index(after: sliceEnd)
i += 1
}
return nil
}
mirrors.test("ForwardStructure") {
struct DoubleYou : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self,
unlabeledChildren: Set(letters),
displayStyle: .`set`)
}
}
let w = DoubleYou().customMirror
expectEqual(.`set`, w.displayStyle)
expectEqual(letters.count, numericCast(w.children.count))
// Because we don't control the order of a Set, we need to do a
// fancy dance in order to validate the result.
let description = w.testDescription
for c in letters {
let expected = "nil: \"\(c)\""
expectNotNil(find(expected, within: description))
}
}
mirrors.test("BidirectionalStructure") {
struct Why : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self,
unlabeledChildren: letters,
displayStyle: .collection)
}
}
// Test that the basics seem to work
let y = Why().customMirror
expectEqual(.`collection`, y.displayStyle)
let description = y.testDescription
expectEqual(
"[nil: \"a\", nil: \"b\", nil: \"c\", nil: \"",
description[description.startIndex..<description.firstIndex(of: "d")!])
}
mirrors.test("LabeledStructure") {
struct Zee : CustomReflectable, CustomStringConvertible {
var customMirror: Mirror {
return Mirror(self, children: ["bark": 1, "bite": 0])
}
var description: String { return "Zee" }
}
let z = Zee().customMirror
expectEqual("[bark: 1, bite: 0]", z.testDescription)
expectNil(z.displayStyle)
struct Zee2 : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self, children: ["bark": 1, "bite": 0], displayStyle: .dictionary)
}
}
let z2 = Zee2().customMirror
expectEqual(.dictionary, z2.displayStyle)
expectEqual("[bark: 1, bite: 0]", z2.testDescription)
struct Heterogeny : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self, children: ["bark": 1, "bite": Zee()])
}
}
let h = Heterogeny().customMirror
expectEqual("[bark: 1, bite: Zee]", h.testDescription)
}
mirrors.test("Legacy") {
let m = Mirror(reflecting: [1, 2, 3])
expectTrue(m.subjectType == [Int].self)
let x0: [Mirror.Child] = [
(label: nil, value: 1),
(label: nil, value: 2),
(label: nil, value: 3)
]
expectFalse(
zip(x0, m.children).contains {
$0.0.value as! Int != $0.1.value as! Int
})
class B { let bx: Int = 0 }
class D : B { let dx: Int = 1 }
let mb = Mirror(reflecting: B())
func expectBMirror(
_ mb: Mirror, stackTrace: SourceLocStack = SourceLocStack(),
file: String = #file, line: UInt = #line
) {
expectTrue(mb.subjectType == B.self,
stackTrace: stackTrace, file: file, line: line)
expectNil(
mb.superclassMirror,
stackTrace: stackTrace, file: file, line: line)
expectEqual(
1, mb.children.count,
stackTrace: stackTrace, file: file, line: line)
expectEqual(
"bx", mb.children.first?.label,
stackTrace: stackTrace, file: file, line: line)
expectEqual(
0, mb.children.first?.value as? Int,
stackTrace: stackTrace, file: file, line: line)
}
expectBMirror(mb)
// Ensure that the base class instance is properly filtered out of
// the child list
do {
let md = Mirror(reflecting: D())
expectTrue(md.subjectType == D.self)
expectEqual(1, md.children.count)
expectEqual("dx", md.children.first?.label)
expectEqual(1, md.children.first?.value as? Int)
expectNotNil(md.superclassMirror)
if let mb2 = md.superclassMirror { expectBMirror(mb2) }
}
do {
// Ensure that we reflect on the dynamic type of the subject
let md = Mirror(reflecting: D() as B)
expectTrue(md.subjectType == D.self)
expectEqual(1, md.children.count)
expectEqual("dx", md.children.first?.label)
expectEqual(1, md.children.first?.value as? Int)
expectNotNil(md.superclassMirror)
if let mb2 = md.superclassMirror { expectBMirror(mb2) }
}
}
//===----------------------------------------------------------------------===//
//===--- Class Support ----------------------------------------------------===//
mirrors.test("Class/Root/Uncustomized") {
class A { var a: Int = 1 }
let a = Mirror(reflecting: A())
expectTrue(a.subjectType == A.self)
expectNil(a.superclassMirror)
expectEqual(1, a.children.count)
expectEqual("a", a.children.first!.label)
}
//===--- Generated Superclass Mirrors -------------------------------------===//
mirrors.test("Class/Root/superclass:.generated") {
class B : CustomReflectable {
var b: String = "two"
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .generated)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
expectEqual(1, b.children.count)
expectEqual("bee", b.children.first!.label)
expectEqual("two", b.children.first!.value as? String)
}
mirrors.test("class/Root/superclass:<default>") {
class C : CustomReflectable {
var c: UInt = 3
var customMirror: Mirror {
return Mirror(self, children: ["sea": c + 1])
}
}
let c = Mirror(reflecting: C())
expectTrue(c.subjectType == C.self)
expectNil(c.superclassMirror)
expectEqual(1, c.children.count)
expectEqual("sea", c.children.first!.label)
expectEqual(4, c.children.first!.value as? UInt)
}
mirrors.test("class/Plain/Plain") {
class A { var a: Int = 1 }
class B : A { var b: UInt = 42 }
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let bChild = expectNotNil(b.children.first) {
expectEqual("b", bChild.label)
expectEqual(42, bChild.value as? UInt)
}
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aChild = expectNotNil(a.children.first) {
expectEqual("a", aChild.label)
expectEqual(1, aChild.value as? Int)
expectNil(a.superclassMirror)
}
}
}
mirrors.test("class/UncustomizedSuper/Synthesized/Implicit") {
class A { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first?.label)
expectNil(a.superclassMirror)
}
}
mirrors.test("class/UncustomizedSuper/Synthesized/Explicit") {
class A { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .generated)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
expectNil(a.superclassMirror)
}
}
mirrors.test("class/CustomizedSuper/Synthesized") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class B : A {
var b: UInt = 42
// This is an unusual case: when writing override on a
// customMirror implementation you would typically want to pass
// ancestorRepresentation: .customized(super.customMirror) or, in
// rare cases, ancestorRepresentation: .Suppressed. However, it
// has an expected behavior, which we test here.
override var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
expectNil(a.superclassMirror)
}
}
#if _runtime(_ObjC)
import Foundation
//===--- ObjC Base Classes ------------------------------------------------===//
mirrors.test("class/ObjCPlain/Plain") {
class A : NSObject { var a: Int = 1 }
class B : A { var b: UInt = 42 }
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let bChild = expectNotNil(b.children.first) {
expectEqual("b", bChild.label)
expectEqual(42, bChild.value as? UInt)
}
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aChild = expectNotNil(a.children.first) {
expectEqual("a", aChild.label)
expectEqual(1, aChild.value as? Int)
if let o = expectNotNil(a.superclassMirror) {
expectEqual("NSObject", String(reflecting: o.subjectType))
}
}
}
}
mirrors.test("class/ObjCUncustomizedSuper/Synthesized/Implicit") {
class A : NSObject { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first?.label)
if let o = expectNotNil(a.superclassMirror) {
expectTrue(o.subjectType == NSObject.self)
}
}
}
mirrors.test("class/ObjCUncustomizedSuper/Synthesized/Explicit") {
class A : NSObject { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .generated)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
if let o = expectNotNil(a.superclassMirror) {
expectTrue(o.subjectType == NSObject.self)
}
}
}
mirrors.test("class/ObjCCustomizedSuper/Synthesized") {
class A : DateFormatter, CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class B : A {
var b: UInt = 42
// This is an unusual case: when writing override on a
// customMirror implementation you would typically want to pass
// ancestorRepresentation: .customized(super.customMirror) or, in
// rare cases, ancestorRepresentation: .Suppressed. However, it
// has an expected behavior, which we test here.
override var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
if let d = expectNotNil(a.superclassMirror) {
expectTrue(d.subjectType == DateFormatter.self)
if let f = expectNotNil(d.superclassMirror) {
expectTrue(f.subjectType == Formatter.self)
if let o = expectNotNil(f.superclassMirror) {
expectTrue(o.subjectType == NSObject.self)
expectNil(o.superclassMirror)
}
}
}
}
}
// rdar://problem/39629937
@objc class ObjCClass : NSObject {
let value: Int
init(value: Int) { self.value = value }
override var description: String {
return "\(value)"
}
}
struct WrapObjCClassArray {
var array: [ObjCClass]
}
mirrors.test("struct/WrapNSArray") {
let nsArray: NSArray = [
ObjCClass(value: 1), ObjCClass(value: 2),
ObjCClass(value: 3), ObjCClass(value: 4)
]
let s = String(describing: WrapObjCClassArray(array: nsArray as! [ObjCClass]))
expectEqual("WrapObjCClassArray(array: [1, 2, 3, 4])", s)
}
#endif // _runtime(_ObjC)
//===--- Suppressed Superclass Mirrors ------------------------------------===//
mirrors.test("Class/Root/NoSuperclassMirror") {
class B : CustomReflectable {
var b: String = "two"
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .suppressed)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
expectEqual(1, b.children.count)
expectEqual("bee", b.children.first!.label)
}
mirrors.test("class/UncustomizedSuper/NoSuperclassMirror") {
class A { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .suppressed)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
}
mirrors.test("class/CustomizedSuper/NoSuperclassMirror") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class B : A {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .suppressed)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
}
//===--- Override Superclass Mirrors --------------------------------------===//
mirrors.test("class/CustomizedSuper/SuperclassCustomMirror/Direct") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
// B inherits A directly
class B : A {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self,
children: ["bee": b],
ancestorRepresentation: .customized({ super.customMirror }))
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("aye", a.children.first!.label)
expectNil(a.superclassMirror)
}
}
mirrors.test("class/CustomizedSuper/SuperclassCustomMirror/Indirect") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class X : A {}
class Y : X {}
// B inherits A indirectly through X and Y
class B : Y {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self,
children: ["bee": b],
ancestorRepresentation: .customized({ super.customMirror }))
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let y = expectNotNil(b.superclassMirror) {
expectTrue(y.subjectType == Y.self)
if let x = expectNotNil(y.superclassMirror) {
expectTrue(x.subjectType == X.self)
expectEqual(0, x.children.count)
if let a = expectNotNil(x.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aye = expectNotNil(a.children.first) {
expectEqual("aye", aye.label)
}
}
}
}
}
mirrors.test("class/CustomizedSuper/SuperclassCustomMirror/Indirect2") {
class A : CustomLeafReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(
self, children: ["aye": a])
}
}
class X : A {}
class Y : X {}
// B inherits A indirectly through X and Y
class B : Y {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self,
children: ["bee": b],
ancestorRepresentation: .customized({ super.customMirror }))
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aye = expectNotNil(a.children.first) {
expectEqual("aye", aye.label)
}
}
}
mirrors.test("class/Cluster") {
class A : CustomLeafReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(
self, children: ["aye": a])
}
}
class X : A {}
class Y : X {}
let a = Mirror(reflecting: Y())
expectTrue(a.subjectType == A.self)
if let aye = expectNotNil(a.children.first) {
expectEqual("aye", aye.label)
}
}
//===--- End Class Support ------------------------------------------------===//
//===----------------------------------------------------------------------===//
mirrors.test("Addressing") {
let m0 = Mirror(reflecting: [1, 2, 3])
expectEqual(1, m0.descendant(0) as? Int)
expectEqual(2, m0.descendant(1) as? Int)
expectEqual(3, m0.descendant(2) as? Int)
let m1 = Mirror(reflecting: (a: ["one", "two", "three"], 4))
let ott0 = m1.descendant(0) as? [String]
expectNotNil(ott0)
let ott1 = m1.descendant("a") as? [String]
expectNotNil(ott1)
if ott0 != nil && ott1 != nil {
expectEqualSequence(ott0!, ott1!)
}
expectEqual(4, m1.descendant(1) as? Int)
expectEqual(4, m1.descendant(".1") as? Int)
expectEqual("one", m1.descendant(0, 0) as? String)
expectEqual("two", m1.descendant(0, 1) as? String)
expectEqual("three", m1.descendant(0, 2) as? String)
expectEqual("one", m1.descendant("a", 0) as? String)
struct Zee : CustomReflectable {
var customMirror: Mirror {
return Mirror(self, children: ["bark": 1, "bite": 0])
}
}
let x = [
(a: ["one", "two", "three"], b: Zee()),
(a: ["five"], b: Zee()),
(a: [], b: Zee())]
let m = Mirror(reflecting: x)
let two = m.descendant(0, "a", 1)
expectEqual("two", two as? String)
expectEqual(1, m.descendant(1, 1, "bark") as? Int)
expectEqual(0, m.descendant(1, 1, "bite") as? Int)
expectNil(m.descendant(1, 1, "bork"))
}
mirrors.test("Invalid Path Type")
.skip(.custom(
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
struct X : MirrorPath {}
let m = Mirror(reflecting: [1, 2, 3])
expectEqual(1, m.descendant(0) as? Int)
expectCrashLater()
_ = m.descendant(X())
}
mirrors.test("PlaygroundQuickLook") {
// Customization works.
struct CustomQuickie : CustomPlaygroundQuickLookable {
var customPlaygroundQuickLook: PlaygroundQuickLook {
return .point(1.25, 42)
}
}
switch PlaygroundQuickLook(reflecting: CustomQuickie()) {
case .point(1.25, 42): break
default: expectTrue(false)
}
// PlaygroundQuickLook support from Legacy Mirrors works.
switch PlaygroundQuickLook(reflecting: true) {
case .bool(true): break
default: expectTrue(false)
}
// With no Legacy Mirror QuickLook support, we fall back to
// String(reflecting: ).
struct X {}
switch PlaygroundQuickLook(reflecting: X()) {
case .text(let text):
#if _runtime(_ObjC)
// FIXME: Enable if non-objc hasSuffix is implemented.
expectTrue(text.contains(").X"), text)
#endif
default:
expectTrue(false)
}
struct Y : CustomDebugStringConvertible {
var debugDescription: String { return "Why?" }
}
switch PlaygroundQuickLook(reflecting: Y()) {
case .text("Why?"): break
default: expectTrue(false)
}
}
class Parent {}
extension Parent : _DefaultCustomPlaygroundQuickLookable {
var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
return .text("base")
}
}
class Child : Parent { }
class FancyChild : Parent, CustomPlaygroundQuickLookable {
var customPlaygroundQuickLook: PlaygroundQuickLook {
return .text("child")
}
}
mirrors.test("_DefaultCustomPlaygroundQuickLookable") {
// testing the workaround for custom quicklookables in subclasses
switch PlaygroundQuickLook(reflecting: Child()) {
case .text("base"): break
default: expectUnreachable("Base custom quicklookable was expected")
}
switch PlaygroundQuickLook(reflecting: FancyChild()) {
case .text("child"): break
default: expectUnreachable("FancyChild custom quicklookable was expected")
}
}
#if _runtime(_ObjC)
import MirrorObjC
mirrors.test("ObjC") {
// Some Foundation classes lie about their ivars, which would crash
// a mirror; make sure we are not automatically exposing ivars of
// Objective-C classes from the default mirror implementation.
expectEqual(0, Mirror(reflecting: HasIVars()).children.count)
}
#endif
mirrors.test("String.init") {
expectEqual("42", String(42))
expectEqual("42", String("42"))
expectEqual("42", String(reflecting: 42))
expectEqual("\"42\"", String(reflecting: "42"))
}
struct a<b> {
enum c{}
}
class d {}
struct e<f> {
var constraints: [Int: a<f>.c] = [:]
}
mirrors.test("GenericNestedTypeField") {
let x = e<d>()
expectTrue(type(of: Mirror(reflecting: x).children.first!.value)
== [Int: a<d>.c].self)
}
extension OtherOuter {
struct Inner {}
}
extension OtherOuterGeneric {
struct Inner<U> {}
}
mirrors.test("SymbolicReferenceInsideType") {
let s = OtherStruct(a: OtherOuter.Inner(),
b: OtherOuterGeneric<Int>.Inner<String>())
var output = ""
dump(s, to: &output)
let expected =
"▿ Mirror.OtherStruct\n" +
" - a: Mirror.OtherOuter.Inner\n" +
" - b: Mirror.OtherOuterGeneric<Swift.Int>.Inner<Swift.String>\n"
expectEqual(expected, output)
}
runAllTests()