//===--- Mirror.swift -----------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // RUN: rm -rf %t // RUN: mkdir -p %t // // RUN: %target-clang %S/Inputs/Mirror/Mirror.mm -c -o %t/Mirror.mm.o -g // RUN: %target-build-swift %s -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror // RUN: %target-run %t/Mirror // REQUIRES: executable_test // XFAIL: linux import StdlibUnittest // Also import modules which are used by StdlibUnittest internally. This // workaround is needed to link all required libraries in case we compile // StdlibUnittest with -sil-serialize-all. import SwiftPrivate #if _runtime(_ObjC) import ObjectiveC #endif 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.characters.count let substringCount = substring.characters.count if (domainCount < substringCount) { return nil } var sliceStart = domain.startIndex var sliceEnd = domain.startIndex.advanced(by: substringCount) var i = 0 while true { if domain[sliceStart..") { 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) expectEmpty(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 = expectNotEmpty(b.children.first) { expectEqual("b", bChild.label) expectEqual(42, bChild.value as? UInt) } if let a = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) if let aChild = expectNotEmpty(a.children.first) { expectEqual("a", aChild.label) expectEqual(1, aChild.value as? Int) expectEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) expectEqual("a", a.children.first?.label) expectEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) expectEqual("a", a.children.first!.label) expectEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) expectEqual("a", a.children.first!.label) expectEmpty(a.superclassMirror) } } 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 = expectNotEmpty(b.children.first) { expectEqual("b", bChild.label) expectEqual(42, bChild.value as? UInt) } if let a = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) if let aChild = expectNotEmpty(a.children.first) { expectEqual("a", aChild.label) expectEqual(1, aChild.value as? Int) if let o = expectNotEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) expectEqual("a", a.children.first?.label) if let o = expectNotEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) expectEqual("a", a.children.first!.label) if let o = expectNotEmpty(a.superclassMirror) { expectTrue(o.subjectType == NSObject.self) } } } mirrors.test("class/ObjCCustomizedSuper/Synthesized") { class A : NSDateFormatter, 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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) expectEqual("a", a.children.first!.label) if let d = expectNotEmpty(a.superclassMirror) { expectTrue(d.subjectType == NSDateFormatter.self) if let f = expectNotEmpty(d.superclassMirror) { expectTrue(f.subjectType == NSFormatter.self) if let o = expectNotEmpty(f.superclassMirror) { expectTrue(o.subjectType == NSObject.self) expectEmpty(o.superclassMirror) } } } } } //===--- 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) expectEmpty(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) expectEmpty(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) expectEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) expectEqual("aye", a.children.first!.label) expectEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(y.subjectType == Y.self) if let x = expectNotEmpty(y.superclassMirror) { expectTrue(x.subjectType == X.self) expectEqual(0, x.children.count) if let a = expectNotEmpty(x.superclassMirror) { expectTrue(a.subjectType == A.self) if let aye = expectNotEmpty(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 = expectNotEmpty(b.superclassMirror) { expectTrue(a.subjectType == A.self) if let aye = expectNotEmpty(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 = expectNotEmpty(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"], b: 4)) let ott0 = m1.descendant(0) as? [String] expectNotEmpty(ott0) let ott1 = m1.descendant(".0") as? [String] expectNotEmpty(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(".0", 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, ".0", 1) expectEqual("two", two as? String) expectEqual(1, m.descendant(1, 1, "bark") as? Int) expectEqual(0, m.descendant(1, 1, "bite") as? Int) expectEmpty(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): expectTrue(text.hasSuffix(".(X #1)()"), text) default: expectTrue(false) } struct Y : CustomDebugStringConvertible { var debugDescription: String { return "Why?" } } switch PlaygroundQuickLook(reflecting: Y()) { case .text("Why?"): break default: expectTrue(false) } } 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) } mirrors.test("String.init") { expectEqual("42", String(42)) expectEqual("42", String("42")) expectEqual("42", String(reflecting: 42)) expectEqual("\"42\"", String(reflecting: "42")) } runAllTests()