Skip to content

Commit 0389ea5

Browse files
committed
[ClangImporter] Add @available(*, renamed:) to imported async getters
The attribute was missing from functions with getters as their async alternative. Only getters are imported like this, so no need to check for the other accessors. Resolves rdar://80612566
1 parent 94ca17e commit 0389ea5

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

lib/AST/Attr.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,23 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
884884
if (!Attr->Rename.empty()) {
885885
Printer << ", renamed: \"" << Attr->Rename << "\"";
886886
} else if (Attr->RenameDecl) {
887-
Printer << ", renamed: \"" << Attr->RenameDecl->getName() << "\"";
887+
Printer << ", renamed: \"";
888+
if (auto *Accessor = dyn_cast<AccessorDecl>(Attr->RenameDecl)) {
889+
switch (Accessor->getAccessorKind()) {
890+
case AccessorKind::Get:
891+
Printer << "getter:";
892+
break;
893+
case AccessorKind::Set:
894+
Printer << "setter:";
895+
break;
896+
default:
897+
break;
898+
}
899+
Printer << Accessor->getStorage()->getName() << "()";
900+
} else {
901+
Printer << Attr->RenameDecl->getName();
902+
}
903+
Printer << "\"";
888904
}
889905

890906
// If there's no message, but this is specifically an imported

lib/ClangImporter/ImportDecl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8161,11 +8161,18 @@ void addCompletionHandlerAttribute(Decl *asyncImport,
81618161
ArrayRef<Decl *> members,
81628162
ASTContext &SwiftContext) {
81638163
auto *asyncFunc = dyn_cast_or_null<AbstractFunctionDecl>(asyncImport);
8164+
// Completion handler functions can be imported as getters, but the decl
8165+
// given back from the import is the property. Grab the underlying getter
8166+
if (auto *property = dyn_cast_or_null<AbstractStorageDecl>(asyncImport))
8167+
asyncFunc = property->getAccessor(AccessorKind::Get);
8168+
81648169
if (!asyncFunc)
81658170
return;
81668171

81678172
for (auto *member : members) {
8168-
if (member != asyncImport) {
8173+
// Only add the attribute to functions that don't already have availability
8174+
if (member != asyncImport && isa<AbstractFunctionDecl>(member) &&
8175+
!member->getAttrs().hasAttribute<AvailableAttr>()) {
81698176
member->getAttrs().add(
81708177
AvailableAttr::createForAlternative(SwiftContext, asyncFunc));
81718178
}

test/IDE/print_clang_objc_effectful_properties.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,32 @@
77
// REQUIRES: objc_interop
88

99
// CHECK-LABEL: class EffProps : NSObject {
10-
// CHECK: func getDogWithCompletion(_ completionHandler: @escaping (NSObject) -> Void)
11-
// CHECK: var doggo: NSObject { get async }
10+
// CHECK: @available(*, renamed: "getter:doggo()")
11+
// CHECK-NEXT: func getDogWithCompletion(_ completionHandler: @escaping (NSObject) -> Void)
12+
// CHECK: var doggo: NSObject { get async }
1213

13-
// CHECK: func obtainCat(_ completionHandler: @escaping (NSObject?, Error?) -> Void)
14+
// CHECK: @available(*, renamed: "getter:catto()")
15+
// CHECK-NEXT: func obtainCat(_ completionHandler: @escaping (NSObject?, Error?) -> Void)
1416
// CHECK-NEXT: var catto: NSObject? { get async throws }
1517

16-
// CHECK: func checkAvailability(completionHandler: @escaping (Bool) -> Void)
18+
// CHECK: @available(*, renamed: "getter:available()")
19+
// CHECK-NEXT: func checkAvailability(completionHandler: @escaping (Bool) -> Void)
1720
// CHECK-NEXT: var available: Bool { get async }
1821
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "checkAvailability(completionHandler:)")
1922
// CHECK-NEXT: func checkAvailabilityWithCompletionHandler(_ completionHandler: @escaping (Bool) -> Void)
2023

21-
// CHECK: func returnNothing(completion completionHandler: @escaping () -> Void)
24+
// CHECK: @available(*, renamed: "getter:touch()")
25+
// CHECK-NEXT: func returnNothing(completion completionHandler: @escaping () -> Void)
2226
// CHECK-NEXT: var touch: Void { get async }
2327
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "returnNothing(completion:)")
2428
// CHECK-NEXT: func returnNothingWithCompletion(_ completionHandler: @escaping () -> Void)
2529

26-
// CHECK: func nullableHandler(_ completion: ((String) -> Void)? = nil)
30+
// CHECK: @available(*, renamed: "getter:fromNullableHandler()")
31+
// CHECK-NEXT: func nullableHandler(_ completion: ((String) -> Void)? = nil)
2732
// CHECK-NEXT: var fromNullableHandler: String { get async }
2833

29-
// CHECK: func getMainDog(_ completion: @escaping (String) -> Void)
34+
// CHECK: @available(*, renamed: "getter:mainDogProp()")
35+
// CHECK-NEXT: func getMainDog(_ completion: @escaping (String) -> Void)
3036
// CHECK-NEXT: var mainDogProp: String { get async }
3137

3238
// CHECK: @available(*, renamed: "regularMainDog()")

0 commit comments

Comments
 (0)