mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
PrintAsClang is supposed to emit declarations in the same order regardless of the compiler’s internal state, but we have repeatedly found that our current criteria are inadequate, resulting in non-functionality-affecting changes to generated header content. Add a diagnostic that’s emitted when this happens soliciting a bug report. Since there *should* be no cases where the compiler fails to order declarations, this diagnostic is never actually emitted. Instead, we test this change by enabling `-verify` on nearly all PrintAsClang tests to make sure they are unaffected. This did demonstrate a missing criterion that only mattered in C++ mode: extensions that varied only in their generic signature were not sorted stably. Add a sort criterion for this.
241 lines
8.3 KiB
Swift
241 lines
8.3 KiB
Swift
// Please keep this file in alphabetical order!
|
|
|
|
// RUN: %empty-directory(%t)
|
|
|
|
// FIXME: BEGIN -enable-source-import hackaround
|
|
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift -disable-objc-attr-requires-foundation-module
|
|
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift
|
|
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/Foundation.swift
|
|
// FIXME: END -enable-source-import hackaround
|
|
|
|
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource) -I %t -emit-module -o %t %s -disable-objc-attr-requires-foundation-module
|
|
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource) -I %t -parse-as-library %t/protocols.swiftmodule -typecheck -verify -emit-objc-header-path %t/protocols.h -import-objc-header %S/../Inputs/empty.h -disable-objc-attr-requires-foundation-module
|
|
// RUN: %FileCheck %s < %t/protocols.h
|
|
// RUN: %FileCheck --check-prefix=NEGATIVE %s < %t/protocols.h
|
|
// RUN: %check-in-clang %t/protocols.h
|
|
|
|
// REQUIRES: objc_interop
|
|
|
|
import Foundation
|
|
import objc_generics
|
|
|
|
// CHECK-LABEL: @protocol A{{$}}
|
|
// CHECK-NEXT: @end
|
|
@objc protocol A {}
|
|
|
|
// CHECK-LABEL: @protocol B <A>
|
|
// CHECK-NEXT: @end
|
|
@objc protocol B : A, Sendable {}
|
|
|
|
// CHECK-LABEL: @protocol CompletionAndAsync
|
|
// CHECK-NEXT: - (void)helloWithCompletion:(void (^ _Nonnull)(BOOL))completion;
|
|
// CHECK-NEXT: @end
|
|
@objc protocol CompletionAndAsync {
|
|
// We don't want this one printed because it has more limited availability.
|
|
@available(SwiftStdlib 5.7, *)
|
|
@objc(helloWithCompletion:)
|
|
func hello() async -> Bool
|
|
|
|
@available(*, renamed: "hello()")
|
|
@objc(helloWithCompletion:)
|
|
func hello(completion: @escaping (Bool) -> Void)
|
|
}
|
|
|
|
// CHECK: @protocol CustomName2;
|
|
// CHECK-LABEL: SWIFT_PROTOCOL_NAMED("CustomName")
|
|
// CHECK-NEXT: @protocol CustomName{{$}}
|
|
// CHECK-NEXT: - (void)forwardCustomName:(id <CustomName2> _Nonnull)_;
|
|
// CHECK-NEXT: @end
|
|
@objc(CustomName)
|
|
protocol CustomName {
|
|
func forwardCustomName(_: CustomNameType2)
|
|
}
|
|
|
|
// CHECK-LABEL: SWIFT_PROTOCOL_NAMED("CustomNameType2")
|
|
// CHECK-NEXT: @protocol CustomName2{{$}}
|
|
// CHECK-NEXT: @end
|
|
@objc(CustomName2)
|
|
protocol CustomNameType2 {}
|
|
|
|
// CHECK-LABEL: @protocol Initializers{{$}}
|
|
// CHECK-NEXT: - (nonnull instancetype)init;
|
|
// CHECK-NEXT: - (nonnull instancetype)initWithObject:(id _Nonnull)any;
|
|
// CHECK-NEXT: @end
|
|
@objc protocol Initializers {
|
|
init()
|
|
init(object any: AnyObject)
|
|
}
|
|
|
|
// CHECK-LABEL: @interface MyObject : NSObject <NSCoding, Fungible>
|
|
// CHECK-NEXT: initWithCoder
|
|
// CHECK-NEXT: init SWIFT_UNAVAILABLE
|
|
// CHECK-NEXT: new SWIFT_DEPRECATED
|
|
// CHECK-NEXT: @end
|
|
// NEGATIVE-NOT: @protocol NSCoding
|
|
class MyObject : NSObject, NSCoding, Fungible {
|
|
required init(coder aCoder: NSCoder) {
|
|
super.init()
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: @protocol Methods{{$}}
|
|
// CHECK-NEXT: - (void)test;
|
|
// CHECK-NEXT: + (void)test2;
|
|
// CHECK-NEXT: - (void)testRawAnyTypes:(id _Nonnull)any other:(Class _Nonnull)other;
|
|
// CHECK-NEXT: - (void)testSingleProtocolTypes:(id <A> _Nonnull)a aAgain:(id <A> _Nonnull)a2 b:(id <B> _Nonnull)b bAgain:(id <B> _Nonnull)b2 both:(id <B> _Nonnull)both;
|
|
// CHECK-NEXT: - (void)testSingleProtocolClassTypes:(Class <A> _Nonnull)a aAgain:(Class <A> _Nonnull)a2 b:(Class <B> _Nonnull)b bAgain:(Class <B> _Nonnull)b2 both:(Class <B> _Nonnull)both;
|
|
// CHECK-NEXT: - (void)testComposition:(id <A, ZZZ> _Nonnull)x meta:(Class <A, ZZZ> _Nonnull)xClass;
|
|
// CHECK-NEXT: - (void)testSubclassComposition:(MyObject <ZZZ> * _Nonnull)x meta:(SWIFT_METATYPE(MyObject) <ZZZ> _Nonnull)xClass;
|
|
// CHECK-NEXT: - (void)testGenericSubclassComposition:(FungibleContainer<MyObject *> <ZZZ> * _Nonnull)x meta:(SWIFT_METATYPE(FungibleContainer) <ZZZ> _Nonnull)xClass;
|
|
// CHECK-NEXT: - (void)testOptional:(id <A> _Nullable)opt meta:(Class <A> _Nullable)m;
|
|
// CHECK-NEXT: @end
|
|
@objc protocol Methods {
|
|
func test()
|
|
static func test2()
|
|
|
|
func testRawAnyTypes(_ any: AnyObject, other: AnyObject.Type)
|
|
|
|
func testSingleProtocolTypes(_ a : A, aAgain a2: A, b: B, bAgain b2: B, both: A & B)
|
|
func testSingleProtocolClassTypes(_ a : A.Type, aAgain a2: A.Type, b: B.Type, bAgain b2: B.Type, both: (A & B).Type)
|
|
func testComposition(_ x: A & ZZZ, meta xClass: (A & ZZZ).Type)
|
|
func testSubclassComposition(_ x: MyObject & ZZZ, meta xClass: (MyObject & ZZZ).Type)
|
|
func testGenericSubclassComposition(_ x: FungibleContainer<MyObject> & ZZZ, meta xClass: (FungibleContainer<MyObject> & ZZZ).Type)
|
|
|
|
func testOptional(_ opt: A?, meta m: A.Type?)
|
|
}
|
|
|
|
// NEGATIVE-NOT: NotObjC
|
|
protocol NotObjC : class {}
|
|
|
|
// NEGATIVE-NOT: @interface NSString (SWIFT_EXTENSION(protocols)){{$}}
|
|
extension NSString : NotObjC {}
|
|
|
|
// CHECK-LABEL: @protocol ZZZ{{$}}
|
|
// CHECK-LABEL: @interface NSString (SWIFT_EXTENSION(protocols)) <A, ZZZ>
|
|
extension NSString : A, ZZZ {}
|
|
|
|
// CHECK-LABEL: @protocol Optional
|
|
// CHECK-NEXT: - (void)a;
|
|
// CHECK-NEXT: - (void)b;
|
|
// CHECK-NEXT: @optional
|
|
// CHECK-NEXT: - (void)c;
|
|
// CHECK-NEXT: - (void)d;
|
|
// CHECK-NEXT: @required
|
|
// CHECK-NEXT: - (void)e;
|
|
// CHECK-NEXT: @optional
|
|
// CHECK-NEXT: - (void)f;
|
|
// CHECK-NEXT: @end
|
|
@objc protocol Optional {
|
|
func a()
|
|
func b()
|
|
|
|
@objc optional func c()
|
|
@objc optional func d()
|
|
|
|
func e()
|
|
|
|
@objc optional func f()
|
|
}
|
|
|
|
// NESTED-LABEL: @interface ParentClass
|
|
// NESTED-NEXT: @end
|
|
@objc class ParentClass {
|
|
|
|
// NESTED-LABEL: @protocol Nested
|
|
// NESTED-NEXT: @end
|
|
@objc protocol Nested {}
|
|
|
|
// NESTED-LABEL: SWIFT_PROTOCOL_NAMED("Nested2")
|
|
// NESTED-NEXT: @protocol NestedInParent
|
|
// NESTED-NEXT: @end
|
|
@objc(NestedInParent) protocol Nested2 {}
|
|
}
|
|
|
|
extension ParentClass {
|
|
// NESTED-LABEL: @protocol NestedInExtensionOfParent
|
|
// NESTED-NEXT: @end
|
|
@objc protocol NestedInExtensionOfParent {}
|
|
}
|
|
|
|
// NEGATIVE-NOT: @protocol PrivateProto
|
|
@objc private protocol PrivateProto {}
|
|
|
|
// CHECK-LABEL: @interface PrivateProtoAdopter{{$}}
|
|
// CHECK-NEXT: init
|
|
// CHECK-NEXT: @end
|
|
@objc @objcMembers class PrivateProtoAdopter : PrivateProto {}
|
|
|
|
// CHECK-LABEL: @interface PrivateProtoAdopter2 <A>
|
|
// CHECK-NEXT: init
|
|
// CHECK-NEXT: @end
|
|
@objc @objcMembers class PrivateProtoAdopter2 : PrivateProto, A {}
|
|
|
|
// CHECK-LABEL: @protocol Properties
|
|
// CHECK-NEXT: @property (nonatomic, readonly) NSInteger a;
|
|
// CHECK-NEXT: @property (nonatomic, strong) id <Properties> _Nullable b;
|
|
// CHECK-NEXT: @optional
|
|
// CHECK-NEXT: @property (nonatomic, readonly, copy) NSString * _Nonnull c;
|
|
// CHECK-NEXT: @end
|
|
@objc protocol Properties {
|
|
var a: Int { get }
|
|
var b: Properties? { get set }
|
|
@objc optional var c: String { get }
|
|
}
|
|
|
|
|
|
// Forward declaration of class referenced from subclass existential.
|
|
|
|
// CHECK-LABEL: @class ReferencesSomeClass2;
|
|
|
|
// CHECK-LABEL: @protocol ReferencesSomeClass1
|
|
// CHECK-NEXT: - (void)referencesWithSomeClassAndZZZ:(ReferencesSomeClass2 <ZZZ> * _Nonnull)someClassAndZZZ;
|
|
// CHECK-NEXT: @end
|
|
|
|
// CHECK-LABEL: @interface ReferencesSomeClass2
|
|
// CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
|
// CHECK-NEXT: @end
|
|
|
|
@objc protocol ReferencesSomeClass1 {
|
|
@objc func references(someClassAndZZZ: ReferencesSomeClass2 & ZZZ)
|
|
}
|
|
|
|
@objc @objcMembers class ReferencesSomeClass2 {}
|
|
|
|
|
|
// CHECK-LABEL: @protocol ReversedOrder2{{$}}
|
|
// CHECK-NEXT: @end
|
|
// CHECK: SWIFT_PROTOCOL
|
|
// CHECK-NEXT: @protocol ReversedOrder1 <ReversedOrder2>
|
|
// CHECK-NEXT: @end
|
|
@objc protocol ReversedOrder1 : ReversedOrder2 {}
|
|
@objc protocol ReversedOrder2 {}
|
|
|
|
|
|
// CHECK-LABEL: @interface RootClass1{{$}}
|
|
// CHECK: @interface RootClass2 <A>{{$}}
|
|
// CHECK: @interface RootClass3 <B>{{$}}
|
|
@objc class RootClass1 : NotObjC {}
|
|
@objc class RootClass2 : A, NotObjC {}
|
|
@objc class RootClass3 : NotObjC, B {}
|
|
|
|
// CHECK: @interface RootClass4 <A, ZZZ>{{$}}
|
|
@objc class RootClass4 : A, ZZZ {}
|
|
|
|
// CHECK-LABEL: @interface Subclass : RootClass1 <ZZZ>{{$}}
|
|
@objc class Subclass : RootClass1, ZZZ {}
|
|
|
|
// CHECK-LABEL: @protocol UnownedProperty
|
|
// CHECK-NEXT: @property (nonatomic, unsafe_unretained) id _Nonnull unownedProp;
|
|
@objc protocol UnownedProperty {
|
|
unowned var unownedProp: AnyObject { get set }
|
|
}
|
|
|
|
// CHECK-LABEL: @protocol WeakProperty
|
|
// CHECK-NEXT: @property (nonatomic, weak) id _Nullable weakProp;
|
|
@objc protocol WeakProperty {
|
|
weak var weakProp: AnyObject? { get set }
|
|
}
|
|
|
|
// Deliberately at the end of the file.
|
|
@objc protocol ZZZ {}
|