Skip to content

Commit fc76bf8

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 a67f470 commit fc76bf8

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
@@ -878,7 +878,23 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
878878
if (!Attr->Rename.empty()) {
879879
Printer << ", renamed: \"" << Attr->Rename << "\"";
880880
} else if (Attr->RenameDecl) {
881-
Printer << ", renamed: \"" << Attr->RenameDecl->getName() << "\"";
881+
Printer << ", renamed: \"";
882+
if (auto *Accessor = dyn_cast<AccessorDecl>(Attr->RenameDecl)) {
883+
switch (Accessor->getAccessorKind()) {
884+
case AccessorKind::Get:
885+
Printer << "getter:";
886+
break;
887+
case AccessorKind::Set:
888+
Printer << "setter:";
889+
break;
890+
default:
891+
break;
892+
}
893+
Printer << Accessor->getStorage()->getName() << "()";
894+
} else {
895+
Printer << Attr->RenameDecl->getName();
896+
}
897+
Printer << "\"";
882898
}
883899

884900
// 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
@@ -8087,11 +8087,18 @@ void addCompletionHandlerAttribute(Decl *asyncImport,
80878087
ArrayRef<Decl *> members,
80888088
ASTContext &SwiftContext) {
80898089
auto *asyncFunc = dyn_cast_or_null<AbstractFunctionDecl>(asyncImport);
8090+
// Completion handler functions can be imported as getters, but the decl
8091+
// given back from the import is the property. Grab the underlying getter
8092+
if (auto *property = dyn_cast_or_null<AbstractStorageDecl>(asyncImport))
8093+
asyncFunc = property->getAccessor(AccessorKind::Get);
8094+
80908095
if (!asyncFunc)
80918096
return;
80928097

80938098
for (auto *member : members) {
8094-
if (member != asyncImport) {
8099+
// Only add the attribute to functions that don't already have availability
8100+
if (member != asyncImport && isa<AbstractFunctionDecl>(member) &&
8101+
!member->getAttrs().hasAttribute<AvailableAttr>()) {
80958102
member->getAttrs().add(
80968103
AvailableAttr::createForAlternative(SwiftContext, asyncFunc));
80978104
}

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)