breaking change: change spelling of Entity subscript accessor that returns values of properties within Attributes without digging into the AttributeType. This change will make it possible for the compiler to unambiguously determine the type of subscript access being made before the value is stored, cast, or compared.

This commit is contained in:
Mathew Polzin
2019-04-18 22:40:12 -07:00
parent 14bd29bf42
commit 6b6f40c968
3 changed files with 13 additions and 10 deletions
+9 -6
View File
@@ -440,31 +440,34 @@ public extension Entity where EntityRawIdType: CreatableRawIdType {
public extension EntityProxy {
/// Access the attribute at the given keypath. This just
/// allows you to write `entity[\.propertyName]` instead
/// of `entity.relationships.propertyName`.
/// of `entity.attributes.propertyName`.
subscript<T: AttributeType>(_ path: KeyPath<Description.Attributes, T>) -> T.ValueType {
return attributes[keyPath: path].value
}
/// Access the attribute at the given keypath. This just
/// allows you to write `entity[\.propertyName]` instead
/// of `entity.relationships.propertyName`.
/// of `entity.attributes.propertyName`.
subscript<T: AttributeType>(_ path: KeyPath<Description.Attributes, T?>) -> T.ValueType? {
return attributes[keyPath: path]?.value
}
/// Access the attribute at the given keypath. This just
/// allows you to write `entity[\.propertyName]` instead
/// of `entity.relationships.propertyName`.
/// of `entity.attributes.propertyName`.
subscript<T: AttributeType, U>(_ path: KeyPath<Description.Attributes, T?>) -> U? where T.ValueType == U? {
// Implementation Note: Handles Transform that returns optional
// type.
return attributes[keyPath: path].flatMap { $0.value }
}
/// Access the computed attribute at the given keypath. This just
/// Access the storage of the attribute at the given keypath. This just
/// allows you to write `entity[\.propertyName]` instead
/// of `entity.relationships.propertyName`.
subscript<T>(_ path: KeyPath<Description.Attributes, T>) -> T {
/// of `entity.attributes.propertyName`.
/// Most of the subscripts dig into an `AttributeType`. This subscript
/// returns the `AttributeType` (or another type, if you are accessing
/// an attribute that is not stored in an `AttributeType`).
subscript<T>(direct path: KeyPath<Description.Attributes, T>) -> T {
// Implementation Note: Handles attributes that are not
// AttributeType. These should only exist as computed properties.
return attributes[keyPath: path]
@@ -27,13 +27,13 @@ class ComputedPropertiesTests: XCTestCase {
let entity = decoded(type: TestType.self, data: computed_property_attribute)
XCTAssertEqual(entity[\.computed], "Sarah2")
XCTAssertEqual(entity[\.secretsOut], "shhhh")
XCTAssertEqual(entity[direct: \.secretsOut], "shhhh")
}
func test_ComputedNonAttributeAccess() {
let entity = decoded(type: TestType.self, data: computed_property_attribute)
XCTAssertEqual(entity[\.computed2], "Sarah2")
XCTAssertEqual(entity[direct: \.computed2], "Sarah2")
}
func test_ComputedRelationshipAccess() {
+2 -2
View File
@@ -24,7 +24,7 @@ public class PolyProxyTests: XCTestCase {
XCTAssertEqual(polyUserA[\.name], "Ken Moore")
XCTAssertEqual(polyUserA.id, "1")
XCTAssertEqual(polyUserA.relationships, .none)
XCTAssertEqual(polyUserA[\.x], .init(x: "y"))
XCTAssertEqual(polyUserA[direct: \.x], .init(x: "y"))
}
func test_UserAAndBEncodeEquality() {
@@ -59,7 +59,7 @@ public class PolyProxyTests: XCTestCase {
XCTAssertEqual(polyUserB[\.name], "Ken Less")
XCTAssertEqual(polyUserB.id, "2")
XCTAssertEqual(polyUserB.relationships, .none)
XCTAssertEqual(polyUserB[\.x], .init(x: "y"))
XCTAssertEqual(polyUserB[direct: \.x], .init(x: "y"))
}
}