mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
169 lines
6.3 KiB
Swift
169 lines
6.3 KiB
Swift
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library %s -verify
|
|
import ObjectiveC
|
|
import Foundation
|
|
|
|
// REQUIRES: objc_interop
|
|
|
|
@objc class A : NSObject {
|
|
@objc var propB: B = B()
|
|
@objc var propString: String = "" // expected-note {{did you mean 'propString'}}
|
|
@objc var propArray: [String] = []
|
|
@objc var propDict: [String: B] = [:]
|
|
@objc var propSet: Set<String> = []
|
|
@objc var propNSString: NSString?
|
|
@objc var propNSArray: NSArray?
|
|
@objc var propNSDict: NSDictionary?
|
|
@objc var propNSSet: NSSet?
|
|
@objc var propAnyObject: AnyObject?
|
|
|
|
@objc var ambiguous: String? // expected-note{{'ambiguous' declared here}}
|
|
|
|
@objc func someMethod() { }
|
|
|
|
@objc var `repeat`: String?
|
|
}
|
|
|
|
@objc class B : NSObject {
|
|
@objc var propA: A?
|
|
|
|
@objc var ambiguous: String? // expected-note{{'ambiguous' declared here}}
|
|
}
|
|
|
|
class C {
|
|
var nonObjC: String? // expected-note{{add '@objc' to expose this property to Objective-C}}{{3-3=@objc }}
|
|
}
|
|
|
|
extension NSArray {
|
|
@objc class Foo : NSObject {
|
|
@objc var propString: String = ""
|
|
}
|
|
}
|
|
|
|
extension Array {
|
|
typealias Foo = NSArray.Foo
|
|
}
|
|
|
|
func testKeyPath(a: A, b: B) {
|
|
// Property
|
|
let _: String = #keyPath(A.propB)
|
|
|
|
// Chained property
|
|
let _: String = #keyPath(A.propB.propA)
|
|
|
|
// Optional property
|
|
let _: String = #keyPath(A.propB.propA.propB)
|
|
|
|
// String property
|
|
let _: String = #keyPath(A.propString)
|
|
|
|
// Property of String property (which looks on NSString)
|
|
let _: String = #keyPath(A.propString.URLsInText) // expected-warning{{'URLsInText' has been renamed to 'urlsInText'}}
|
|
|
|
// String property with a suffix
|
|
let _: String = #keyPath(A.propString).description
|
|
let _ = #keyPath(A.propString).split(separator: ".")
|
|
func keyPathSwitch(keyPath: String?) {
|
|
switch keyPath {
|
|
case (#keyPath(A.propString))?: break
|
|
case #keyPath(A.propString)?: break
|
|
default: break
|
|
}
|
|
}
|
|
|
|
// Array property (make sure we look at the array element).
|
|
let _: String = #keyPath(A.propArray)
|
|
let _: String = #keyPath(A.propArray.URLsInText) // expected-warning{{'URLsInText' has been renamed to 'urlsInText'}}
|
|
|
|
// Dictionary property (make sure we look at the value type).
|
|
let _: String = #keyPath(A.propDict.anyKeyName)
|
|
let _: String = #keyPath(A.propDict.anyKeyName.propA)
|
|
|
|
// Set property (make sure we look at the set element).
|
|
let _: String = #keyPath(A.propSet)
|
|
let _: String = #keyPath(A.propSet.URLsInText) // expected-warning{{'URLsInText' has been renamed to 'urlsInText'}}
|
|
|
|
// AnyObject property
|
|
let _: String = #keyPath(A.propAnyObject.URLsInText) // expected-warning{{'URLsInText' has been renamed to 'urlsInText'}}
|
|
let _: String = #keyPath(A.propAnyObject.propA)
|
|
let _: String = #keyPath(A.propAnyObject.propB)
|
|
let _: String = #keyPath(A.propAnyObject.description)
|
|
|
|
// NSString property
|
|
let _: String = #keyPath(A.propNSString.URLsInText) // expected-warning{{'URLsInText' has been renamed to 'urlsInText'}}
|
|
|
|
// NSArray property (AnyObject array element).
|
|
let _: String = #keyPath(A.propNSArray)
|
|
let _: String = #keyPath(A.propNSArray.URLsInText) // expected-warning{{'URLsInText' has been renamed to 'urlsInText'}}
|
|
|
|
// NSDictionary property (AnyObject value type).
|
|
let _: String = #keyPath(A.propNSDict.anyKeyName)
|
|
let _: String = #keyPath(A.propNSDict.anyKeyName.propA)
|
|
|
|
// NSSet property (AnyObject set element).
|
|
let _: String = #keyPath(A.propNSSet)
|
|
let _: String = #keyPath(A.propNSSet.URLsInText) // expected-warning{{'URLsInText' has been renamed to 'urlsInText'}}
|
|
|
|
// Property with keyword name.
|
|
let _: String = #keyPath(A.repeat)
|
|
|
|
// Nested type of a bridged type (rdar://problem/28061409).
|
|
typealias IntArray = [Int]
|
|
let _: String = #keyPath(IntArray.Foo.propString)
|
|
|
|
let dict: [String: Int] = [:]
|
|
let _: Int? = dict[#keyPath(A.propB)]
|
|
let _ = [#keyPath(A.propB)]
|
|
}
|
|
|
|
func testAsStaticString() {
|
|
let _: StaticString = #keyPath(A.propB)
|
|
}
|
|
|
|
func testSemanticErrors() {
|
|
let _: String = #keyPath(A.blarg) // expected-error{{type 'A' has no member 'blarg'}}
|
|
let _: String = #keyPath(blarg) // expected-error{{cannot find 'blarg' in scope}}
|
|
let _: String = #keyPath(AnyObject.ambiguous) // expected-error{{ambiguous reference to member 'ambiguous'}}
|
|
let _: String = #keyPath(C.nonObjC) // expected-error{{argument of '#keyPath' refers to non-'@objc' property 'nonObjC'}}
|
|
let _: String = #keyPath(A.propArray.UTF8View) // expected-error{{type 'String' has no member 'UTF8View'}}
|
|
let _: String = #keyPath(A.someMethod) // expected-error{{key path cannot refer to instance method 'someMethod()'}}
|
|
let _: String = #keyPath(A) // expected-error{{empty key path does not refer to a property}}
|
|
let _: String = #keyPath(A.propDict.anyKeyName.unknown) // expected-error{{type 'B' has no member 'unknown'}}
|
|
let _: String = #keyPath(A.propNSDict.anyKeyName.unknown) // expected-error{{type 'AnyObject' has no member 'unknown'}}
|
|
}
|
|
|
|
func testParseErrors() {
|
|
let _: String = #keyPath; // expected-error{{expected '(' following '#keyPath'}}
|
|
let _: String = #keyPath(123; // expected-error{{expected property or type name within '#keyPath(...)'}}
|
|
let _: String = #keyPath(a.123; // expected-error{{expected property or type name within '#keyPath(...)'}}
|
|
let _: String = #keyPath(A(b:c:d:).propSet); // expected-error{{an Objective-C key path cannot reference a declaration with a compound name}} expected-error{{cannot find 'propSet' in scope}}
|
|
let _: String = #keyPath(A.propString; // expected-error{{expected ')' to complete '#keyPath' expression}}
|
|
// expected-note@-1{{to match this opening '('}}
|
|
}
|
|
|
|
func testTypoCorrection() {
|
|
let _: String = #keyPath(A.proString) // expected-error {{type 'A' has no member 'proString'}}
|
|
}
|
|
|
|
// https://github.com/apple/swift/issues/52548
|
|
|
|
class C2 {
|
|
@objc let b = 1
|
|
}
|
|
|
|
class C1_52548: C2 {
|
|
let a = \AnyObject.b // expected-error {{the root type of a Swift key path cannot be 'AnyObject'}}
|
|
}
|
|
|
|
class C2_52548 {
|
|
@objc let abc: Int = 1
|
|
|
|
func doNotCrash() {
|
|
let _: KeyPath<AnyObject, Int> = \.abc // expected-error {{the root type of a Swift key path cannot be 'AnyObject'}}
|
|
}
|
|
|
|
func doNotCrash_1(_ obj: AnyObject, _ kp: KeyPath<AnyObject, Int>) {
|
|
let _ = obj[keyPath: \.abc] // expected-error {{the root type of a Swift key path cannot be 'AnyObject'}}
|
|
let _ = obj[keyPath: kp] // expected-error {{the root type of a Swift key path cannot be 'AnyObject'}}
|
|
}
|
|
}
|