Skip to content

Commit e318cf4

Browse files
committed
Gather properties from superclasses
1 parent bdbfd3d commit e318cf4

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

Sources/Reflection/Metadata+Class.swift

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ extension Metadata {
1212
guard let superclass = pointer.pointee.superclass else { return nil }
1313
return Metadata.Class(type: superclass)
1414
}
15+
16+
func properties() throws -> [Property.Description] {
17+
guard let superclass = superclass else { return [] }
18+
return try superclass.properties() + fetchAndSaveProperties(nominalType: self, hashedType: HashedType(pointer))
19+
}
1520

1621
}
1722
}

Sources/Reflection/Properties.swift

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
private struct HashedType : Hashable {
1+
struct HashedType : Hashable {
22
let hashValue: Int
33
init(_ type: Any.Type) {
44
hashValue = unsafeBitCast(type, to: Int.self)
55
}
6+
init<T>(_ pointer: UnsafePointer<T>) {
7+
hashValue = pointer.hashValue
8+
}
69
}
710

8-
private func == (lhs: HashedType, rhs: HashedType) -> Bool {
11+
func == (lhs: HashedType, rhs: HashedType) -> Bool {
912
return lhs.hashValue == rhs.hashValue
1013
}
1114

@@ -50,13 +53,13 @@ public func properties(_ type: Any.Type) throws -> [Property.Description] {
5053
} else if let nominalType = Metadata.Struct(type: type) {
5154
return try fetchAndSaveProperties(nominalType: nominalType, hashedType: hashedType)
5255
} else if let nominalType = Metadata.Class(type: type) {
53-
return try fetchAndSaveProperties(nominalType: nominalType, hashedType: hashedType)
56+
return try nominalType.properties()
5457
} else {
5558
throw ReflectionError.notStruct(type: type)
5659
}
5760
}
5861

59-
private func fetchAndSaveProperties<T : NominalType>(nominalType: T, hashedType: HashedType) throws -> [Property.Description] {
62+
func fetchAndSaveProperties<T : NominalType>(nominalType: T, hashedType: HashedType) throws -> [Property.Description] {
6063
let properties = try propertiesForNominalType(nominalType)
6164
cachedProperties[hashedType] = properties
6265
return properties

Tests/ReflectionTests/PublicTests.swift

+30-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,20 @@ class ReferencePerson : Equatable {
3535
}
3636
}
3737

38-
class SubclassedPerson : ReferencePerson {}
38+
class SubclassedPerson : ReferencePerson {
39+
var hobby: String
40+
41+
required init() {
42+
self.hobby = ""
43+
super.init()
44+
}
45+
46+
init(firstName: String, lastName: String, age: Int, hobby: String) {
47+
self.hobby = hobby
48+
super.init(firstName: firstName, lastName: lastName, age: age)
49+
}
50+
51+
}
3952

4053
func == (lhs: ReferencePerson, rhs: ReferencePerson) -> Bool {
4154
return lhs.firstName == rhs.firstName && lhs.lastName == rhs.lastName && lhs.age == rhs.age
@@ -116,6 +129,22 @@ public class PublicTests : XCTestCase {
116129
XCTAssert(person.lastName == lastName)
117130
XCTAssert(person.age == age)
118131
}
132+
133+
func testPropertiesForSubclass() throws {
134+
var props: [Property] = []
135+
let person = SubclassedPerson(firstName: "Brad", lastName: "Hilton", age: 27, hobby: "Golf")
136+
props = try properties(person)
137+
guard props.count == 4 else {
138+
return XCTFail("Unexpected number of properties")
139+
}
140+
guard let firstName = props[0].value as? String, let lastName = props[1].value as? String, let age = props[2].value as? Int, let hobby = props[3].value as? String else {
141+
return XCTFail("Unexpected properties")
142+
}
143+
XCTAssert(person.firstName == firstName)
144+
XCTAssert(person.lastName == lastName)
145+
XCTAssert(person.age == age)
146+
XCTAssert(person.hobby == hobby)
147+
}
119148

120149
func testSetValueForKeyOfInstance() throws {
121150
var person = Person(firstName: "Brad", lastName: "Hilton", age: 27)

0 commit comments

Comments
 (0)