blob: df2803b4083ec96d9fae1884606915c1c6c5fe01 [file] [log] [blame]
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -disable-objc-attr-requires-foundation-module -typecheck -primary-file %s %S/Inputs/property_helper.swift -verify -swift-version 4
import ObjectiveC
// REQUIRES: objc_interop
@objc class HelperClass: NSObject {}
struct Wrapper {
var objcInstance = ObjCClass()
}
class ObjCClass {
@objc var myProperty = HelperClass()
@objc let myConstant = HelperClass() // expected-note 4{{'myConstant' declared here}}
@objc var myComputedReadOnlyProperty: HelperClass { // expected-note 2{{'myComputedReadOnlyProperty' declared here}}
get {
return HelperClass()
}
}
@objc var myComputedReadWriteProperty: HelperClass {
get {
return HelperClass()
}
set {
}
}
@objc func myFunc() {}
@objc class func myClassFunc() {}
func instanceMethod() {
let _ = #selector(myFunc)
let _ = #selector(getter: myProperty)
let _ = #selector(setter: myProperty)
let _ = #selector(setter: myComputedReadWriteProperty)
let _ = #selector(setter: myConstant) // expected-error {{argument of '#selector(setter:)' refers to non-settable let 'myConstant'}}
let _ = #selector(setter: myComputedReadOnlyProperty) // expected-error {{argument of '#selector(setter:)' refers to non-settable var 'myComputedReadOnlyProperty'}}
let _ = #selector(myClassFunc) // expected-error{{static member 'myClassFunc' cannot be used on instance of type 'ObjCClass'}}
}
class func classMethod() {
let _ = #selector(myFunc)
let _ = #selector(getter: myProperty)
let _ = #selector(setter: myProperty)
let _ = #selector(setter: myComputedReadWriteProperty)
let _ = #selector(setter: myConstant) // expected-error {{argument of '#selector(setter:)' refers to non-settable let 'myConstant'}}
let _ = #selector(setter: myComputedReadOnlyProperty) // expected-error {{argument of '#selector(setter:)' refers to non-settable var 'myComputedReadOnlyProperty'}}
let _ = #selector(myClassFunc)
}
}
let myObjcInstance = ObjCClass()
let myWrapperInstance = Wrapper()
func testSimple(myObjcInstance: ObjCClass, myWrapperInstance: Wrapper) {
// Check cases that should work
let _ = #selector(ObjCClass.myFunc)
let _ = #selector(getter: ObjCClass.myProperty)
let _ = #selector(setter: ObjCClass.myProperty)
let _ = #selector(myObjcInstance.myFunc)
let _ = #selector(getter: myObjcInstance.myProperty)
let _ = #selector(setter: myObjcInstance.myProperty)
let _ = #selector(myWrapperInstance.objcInstance.myFunc)
let _ = #selector(getter: myWrapperInstance.objcInstance.myProperty)
let _ = #selector(setter: myWrapperInstance.objcInstance.myProperty)
}
func testWrongKind(myObjcInstance: ObjCClass, myWrapperInstance: Wrapper) {
// Referring to a property with a method selector or a method with a
// property selector
let _ = #selector(myObjcInstance.myProperty) // expected-error{{use 'getter:' or 'setter:' to refer to the Objective-C getter or setter of property 'myProperty', respectively}}
// expected-note@-1{{add 'getter:' to reference the Objective-C getter for 'myProperty'}}{{21-21=getter: }}
// expected-note@-2{{add 'setter:' to reference the Objective-C setter for 'myProperty'}}{{21-21=setter: }}
let _ = #selector(myObjcInstance.myComputedReadOnlyProperty) // expected-error{{use 'getter:' to refer to the Objective-C getter of property 'myComputedReadOnlyProperty'}}{{21-21=getter: }}
let _ = #selector(ObjCClass.myProperty) // expected-error{{use 'getter:' or 'setter:' to refer to the Objective-C getter or setter of property 'myProperty', respectively}}
// expected-note@-1{{add 'setter:' to reference the Objective-C setter for 'myProperty'}}{{21-21=setter: }}
// expected-note@-2{{add 'getter:' to reference the Objective-C getter for 'myProperty'}}{{21-21=getter: }}
// Referring to a method with a property selector
let _ = #selector(getter: myObjcInstance.myFunc) // expected-error{{cannot reference instance method 'myFunc()' as a property; remove 'getter:'}} {{21-29=}}
let _ = #selector(setter: myObjcInstance.myFunc) // expected-error{{cannot reference instance method 'myFunc()' as a property; remove 'setter:'}} {{21-29=}}
let _ = #selector(getter: ObjCClass.myFunc) // expected-error{{cannot reference instance method 'myFunc()' as a property; remove 'getter:'}} {{21-29=}}
let _ = #selector(setter: ObjCClass.myFunc) // expected-error{{cannot reference instance method 'myFunc()' as a property; remove 'setter:'}} {{21-29=}}
// Referring to a let property with a setter
let _ = #selector(setter: myObjcInstance.myConstant) // expected-error {{argument of '#selector(setter:)' refers to non-settable let 'myConstant'}}
let _ = #selector(setter: ObjCClass.myConstant) // expected-error {{argument of '#selector(setter:)' refers to non-settable let 'myConstant'}}
}
// Referring to non ObjC members
class NonObjCClass {
var nonObjCPropertyForGetter = HelperClass() // expected-note{{add '@objc' to expose this var to Objective-C}} {{3-3=@objc }}
var nonObjCPropertyForSetter = HelperClass() // expected-note{{add '@objc' to expose this var to Objective-C}} {{3-3=@objc }}
}
func testNonObjCMembers(nonObjCInstance: NonObjCClass) {
let _ = #selector(getter: nonObjCInstance.nonObjCPropertyForGetter) // expected-error{{argument of '#selector' refers to var 'nonObjCPropertyForGetter' that is not exposed to Objective-C}}
let _ = #selector(setter: nonObjCInstance.nonObjCPropertyForSetter) // expected-error{{argument of '#selector' refers to var 'nonObjCPropertyForSetter' that is not exposed to Objective-C}}
// Referencing undefined symbols
let _ = #selector(getter: UndefinedClass.myVariable) // expected-error{{use of unresolved identifier 'UndefinedClass'}}
let _ = #selector(getter: ObjCClass.undefinedProperty) // expected-error{{type 'ObjCClass' has no member 'undefinedProperty'}}
let _ = #selector(getter: myObjcInstance.undefinedProperty) // expected-error{{value of type 'ObjCClass' has no member 'undefinedProperty'}}
}
// Ambiguous expressions
func testAmbiguous(myObjcInstance: ObjCClass) { // expected-note{{'myObjcInstance' declared here}}
// Referring to a properties not within a type.
let myOtherObjcInstance = ObjCClass(); // expected-note{{'myOtherObjcInstance' declared here}}
let _ = #selector(getter: myObjcInstance) // expected-error{{argument of '#selector' cannot refer to parameter 'myObjcInstance'}}
let _ = #selector(getter: myOtherObjcInstance) // expected-error{{argument of '#selector' cannot refer to variable 'myOtherObjcInstance'}}
}
// Getter/setter is no keyword
let getter = HelperClass()
let setter = HelperClass()
// Referencing methods named getter and setter
class ObjCClassWithGetterSetter: NSObject {
@objc func getter() {
}
@objc func setter() {
}
func referenceGetterSetter() {
let _ = #selector(getter)
let _ = #selector(setter)
}
}
// Looking up inherited members
class BaseClass: NSObject {
var myVar = 1
func myFunc() {
}
}
class SubClass: BaseClass {
}
func testInherited() {
let _ = #selector(getter: SubClass.myVar)
let _ = #selector(SubClass.myFunc)
let subInstance = SubClass()
let _ = #selector(getter: subInstance.myVar)
let _ = #selector(subInstance.myFunc)
}
// Looking up instance/static methods on instance/static contexts
class InstanceStaticTestClass {
@objc static let staticProperty = HelperClass()
@objc let instanceProperty = HelperClass()
@objc class func classMethod() {}
@objc static func staticMethod() {}
@objc func instanceMethod() {}
@objc func instanceAndStaticMethod() {}
@objc class func instanceAndStaticMethod() {}
class func testClass() {
let _ = #selector(getter: instanceProperty)
let _ = #selector(instanceMethod)
let _ = #selector(classMethod)
let _ = #selector(staticMethod)
let _ = #selector(getter: staticProperty)
let _ = #selector(instanceAndStaticMethod)
}
static func testStatic() {
let _ = #selector(getter: instanceProperty)
let _ = #selector(getter: staticProperty)
let _ = #selector(instanceMethod)
let _ = #selector(classMethod)
let _ = #selector(staticMethod)
let _ = #selector(instanceAndStaticMethod)
}
func testInstance() {
let _ = #selector(getter: instanceProperty)
let _ = #selector(instanceMethod)
let _ = #selector(getter: staticProperty) // expected-error{{static member 'staticProperty' cannot be used on instance of type 'InstanceStaticTestClass'}}
let _ = #selector(classMethod) // expected-error{{static member 'classMethod' cannot be used on instance of type 'InstanceStaticTestClass'}}
let _ = #selector(staticMethod) // expected-error{{static member 'staticMethod' cannot be used on instance of type 'InstanceStaticTestClass'}}
let _ = #selector(instanceAndStaticMethod)
}
}
// Accessibility
let otherObjCInstance = OtherObjCClass()
let v11 = #selector(getter: OtherObjCClass.privateVar) // expected-error{{'privateVar' is inaccessible due to 'private' protection level}}
let v12 = #selector(setter: OtherObjCClass.privateVar) // expected-error{{'privateVar' is inaccessible due to 'private' protection level}}
let v13 = #selector(getter: otherObjCInstance.privateVar) // expected-error{{}}
let v14 = #selector(setter: otherObjCInstance.privateVar) // expected-error{{privateVar' is inaccessible due to 'private' protection level}}
let v21 = #selector(getter: OtherObjCClass.privateSetVar)
let v22 = #selector(setter: OtherObjCClass.privateSetVar) // expected-error{{setter of var 'privateSetVar' is inaccessible}}
let v23 = #selector(getter: otherObjCInstance.privateSetVar)
let v24 = #selector(setter: otherObjCInstance.privateSetVar) // expected-error{{setter of var 'privateSetVar' is inaccessible}}
let v31 = #selector(getter: OtherObjCClass.internalVar)
let v32 = #selector(setter: OtherObjCClass.internalVar)
let v33 = #selector(getter: otherObjCInstance.internalVar)
let v34 = #selector(setter: otherObjCInstance.internalVar)
let v41 = #selector(OtherObjCClass.internalFunc)
let v42 = #selector(otherObjCInstance.internalFunc)
let v51 = #selector(OtherObjCClass.privateFunc) // expected-error{{'privateFunc' is inaccessible due to 'private' protection level}}
let v52 = #selector(otherObjCInstance.privateFunc) // expected-error{{'privateFunc' is inaccessible due to 'private' protection level}}