mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This reverts commit 8247525471. While
correct, it has uncovered several issues in existing code bases that
need to be sorted out before we can land it again.
Fixes rdar://problem/57846390.
244 lines
5.7 KiB
Swift
244 lines
5.7 KiB
Swift
// RUN: %empty-directory(%t)
|
|
|
|
// RUN: %clang %target-cc-options -isysroot %sdk -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o
|
|
// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ %t/ObjCClasses.o %s -o %t/a.out
|
|
// RUN: %target-codesign %t/a.out
|
|
// RUN: %target-run %t/a.out
|
|
|
|
// REQUIRES: executable_test
|
|
// REQUIRES: objc_interop
|
|
|
|
import Foundation
|
|
import StdlibUnittest
|
|
import ObjCClasses
|
|
|
|
class SwiftClass : ProtoWithClassProperty {
|
|
static var getCount = 0
|
|
static var setCount = 0
|
|
|
|
private static var _value: CInt = 0
|
|
|
|
@objc class func reset() {
|
|
getCount = 0
|
|
setCount = 0
|
|
_value = 0
|
|
}
|
|
|
|
@objc class var value: CInt {
|
|
get {
|
|
getCount += 1
|
|
return _value
|
|
}
|
|
set {
|
|
setCount += 1
|
|
_value = newValue
|
|
}
|
|
}
|
|
|
|
@objc class var optionalClassProp: Bool {
|
|
return true
|
|
}
|
|
}
|
|
|
|
class Subclass : ClassWithClassProperty {
|
|
static var getCount = 0
|
|
static var setCount = 0
|
|
|
|
override class func reset() {
|
|
getCount = 0
|
|
setCount = 0
|
|
super.reset()
|
|
}
|
|
|
|
override class var value: CInt {
|
|
get {
|
|
getCount += 1
|
|
return super.value
|
|
}
|
|
set {
|
|
setCount += 1
|
|
super.value = newValue
|
|
}
|
|
}
|
|
|
|
override class var optionalClassProp: Bool {
|
|
return true
|
|
}
|
|
}
|
|
|
|
var ClassProperties = TestSuite("ClassProperties")
|
|
|
|
ClassProperties.test("direct") {
|
|
ClassWithClassProperty.reset()
|
|
expectEqual(0, ClassWithClassProperty.value)
|
|
ClassWithClassProperty.value = 4
|
|
expectEqual(4, ClassWithClassProperty.value)
|
|
|
|
Subclass.reset()
|
|
expectEqual(0, Subclass.value)
|
|
Subclass.value = 4
|
|
expectEqual(4, Subclass.value)
|
|
expectEqual(2, Subclass.getCount)
|
|
expectEqual(1, Subclass.setCount)
|
|
}
|
|
|
|
func testExistential(_ e: ProtoWithClassProperty.Type) {
|
|
e.reset()
|
|
expectEqual(0, e.value)
|
|
e.value = 4
|
|
expectEqual(4, e.value)
|
|
}
|
|
|
|
ClassProperties.test("existentials") {
|
|
testExistential(ClassWithClassProperty.self)
|
|
testExistential(ObjCSubclassWithClassProperty.self)
|
|
|
|
testExistential(SwiftClass.self)
|
|
expectEqual(2, SwiftClass.getCount)
|
|
expectEqual(1, SwiftClass.setCount)
|
|
|
|
testExistential(Subclass.self)
|
|
expectEqual(2, Subclass.getCount)
|
|
expectEqual(1, Subclass.setCount)
|
|
}
|
|
|
|
func testGeneric<T: ProtoWithClassProperty>(_ e: T.Type) {
|
|
e.reset()
|
|
expectEqual(0, e.value)
|
|
e.value = 4
|
|
expectEqual(4, e.value)
|
|
}
|
|
|
|
ClassProperties.test("generics") {
|
|
testGeneric(ClassWithClassProperty.self)
|
|
testGeneric(ObjCSubclassWithClassProperty.self)
|
|
|
|
testGeneric(SwiftClass.self)
|
|
expectEqual(2, SwiftClass.getCount)
|
|
expectEqual(1, SwiftClass.setCount)
|
|
|
|
testGeneric(Subclass.self)
|
|
expectEqual(2, Subclass.getCount)
|
|
expectEqual(1, Subclass.setCount)
|
|
}
|
|
|
|
func testInheritance(_ e: ClassWithClassProperty.Type) {
|
|
e.reset()
|
|
expectEqual(0, e.value)
|
|
e.value = 4
|
|
expectEqual(4, e.value)
|
|
}
|
|
|
|
ClassProperties.test("inheritance") {
|
|
testInheritance(ClassWithClassProperty.self)
|
|
testInheritance(ObjCSubclassWithClassProperty.self)
|
|
|
|
testInheritance(Subclass.self)
|
|
expectEqual(2, Subclass.getCount)
|
|
expectEqual(1, Subclass.setCount)
|
|
}
|
|
|
|
func testInheritanceGeneric<T: ClassWithClassProperty>(_ e: T.Type) {
|
|
e.reset()
|
|
expectEqual(0, e.value)
|
|
e.value = 4
|
|
expectEqual(4, e.value)
|
|
}
|
|
|
|
ClassProperties.test("inheritance/generic") {
|
|
testInheritanceGeneric(ClassWithClassProperty.self)
|
|
testInheritanceGeneric(ObjCSubclassWithClassProperty.self)
|
|
|
|
testInheritanceGeneric(Subclass.self)
|
|
expectEqual(2, Subclass.getCount)
|
|
expectEqual(1, Subclass.setCount)
|
|
}
|
|
|
|
ClassProperties.test("optionalProp") {
|
|
let noProp: ProtoWithClassProperty.Type = ClassWithClassProperty.self
|
|
expectNil(noProp.optionalClassProp)
|
|
|
|
let hasProp: ProtoWithClassProperty.Type = Subclass.self
|
|
expectNotNil(hasProp.optionalClassProp)
|
|
expectEqual(true, hasProp.optionalClassProp!)
|
|
|
|
let hasOwnProp: ProtoWithClassProperty.Type = SwiftClass.self
|
|
expectNotNil(hasOwnProp.optionalClassProp)
|
|
expectEqual(true, hasOwnProp.optionalClassProp!)
|
|
|
|
let hasPropObjC: ProtoWithClassProperty.Type = ObjCSubclassWithClassProperty.self
|
|
expectNotNil(hasPropObjC.optionalClassProp)
|
|
expectEqual(true, hasPropObjC.optionalClassProp!)
|
|
}
|
|
|
|
class NamingConflictSubclass : PropertyNamingConflict {
|
|
override var prop: Any? { return nil }
|
|
override class var prop: Any? { return NamingConflictSubclass() }
|
|
}
|
|
|
|
ClassProperties.test("namingConflict") {
|
|
let obj = PropertyNamingConflict()
|
|
expectTrue(obj === obj.prop.map { $0 as AnyObject })
|
|
expectNil(type(of: obj).prop)
|
|
expectNil(PropertyNamingConflict.prop)
|
|
|
|
let sub = NamingConflictSubclass()
|
|
expectNil(sub.prop)
|
|
expectNotNil(type(of: sub).prop)
|
|
expectNotNil(NamingConflictSubclass.prop)
|
|
}
|
|
|
|
extension NamingConflictSubclass : PropertyNamingConflictProto {
|
|
var protoProp: Any? {
|
|
get { return self }
|
|
set {}
|
|
}
|
|
class var protoProp: Any? {
|
|
get { return nil }
|
|
set {}
|
|
}
|
|
}
|
|
|
|
ClassProperties.test("namingConflict/protocol") {
|
|
let obj: PropertyNamingConflictProto = NamingConflictSubclass()
|
|
expectTrue(obj === obj.protoProp.map { $0 as AnyObject })
|
|
expectNil(type(of: obj).protoProp)
|
|
|
|
let type: PropertyNamingConflictProto.Type = NamingConflictSubclass.self
|
|
expectNil(type.protoProp)
|
|
}
|
|
|
|
var global1: Int = 0
|
|
|
|
var global2: Int = 0
|
|
|
|
class Steak : NSObject {
|
|
@objc override var thickness: Int {
|
|
get { return global1 } set { global1 = newValue }
|
|
}
|
|
}
|
|
|
|
extension NSObject : HasThickness {
|
|
@objc var thickness: Int { get { return global2 } set { global2 = newValue } }
|
|
}
|
|
|
|
protocol HasThickness : class {
|
|
var thickness: Int { get set }
|
|
}
|
|
|
|
ClassProperties.test("dynamicOverride") {
|
|
// Calls NSObject.thickness
|
|
NSObject().thickness += 1
|
|
|
|
// Calls Steak.thickness
|
|
(Steak() as NSObject).thickness += 1
|
|
Steak().thickness += 1
|
|
(Steak() as HasThickness).thickness += 1
|
|
|
|
expectEqual(3, global1)
|
|
expectEqual(1, global2)
|
|
}
|
|
|
|
runAllTests()
|
|
|