mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The demangling tree for a symbolic reference doesn't indicate the generic context depth of the referenced type, so we have to form the type metadata from whole cloth without incrementally building up nested types as we do for concrete mangled types. Notice when DecodedMetadataBuilder is passed a context descriptor ref without a parent and directly form the entire type in this case. Fixes rdar://problem/38891999.
802 lines
22 KiB
Swift
802 lines
22 KiB
Swift
//===--- 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: 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 %s -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror; \
|
|
// RUN: else \
|
|
// RUN: %target-build-swift %s -o %t/Mirror; \
|
|
// RUN: fi
|
|
// 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.index(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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#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("field with generic nested type") {
|
|
let x = e<d>()
|
|
|
|
expectTrue(type(of: Mirror(reflecting: x).children.first!.value)
|
|
== [Int: a<d>.c].self)
|
|
}
|
|
|
|
runAllTests()
|