Skip to content

Commit 2d88bb6

Browse files
authored
Merge pull request #18081 from pitiphong-p/objc-rename-attribute
Use the custom @objc name in the available attribute when generates ObjC headers https://bugs.swift.org/browse/SR-8231
2 parents 7f38046 + 0a29962 commit 2d88bb6

File tree

3 files changed

+615
-35
lines changed

3 files changed

+615
-35
lines changed

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -794,13 +794,12 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
794794
if (AvAttr->PlatformAgnostic == PlatformAgnosticAvailabilityKind::Unavailable) {
795795
// Availability for *
796796
if (!AvAttr->Rename.empty() && isa<ValueDecl>(D)) {
797-
// NB: Don't bother getting obj-c names, we can't get one for the
798797
// rename
799798
maybePrintLeadingSpace();
800799
os << "SWIFT_UNAVAILABLE_MSG(\"'"
801800
<< cast<ValueDecl>(D)->getBaseName()
802801
<< "' has been renamed to '";
803-
printEncodedString(AvAttr->Rename, false);
802+
printRenameForDecl(AvAttr, cast<ValueDecl>(D), false);
804803
os << '\'';
805804
if (!AvAttr->Message.empty()) {
806805
os << ": ";
@@ -825,7 +824,7 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
825824
printEncodedString(AvAttr->Message);
826825
if (!AvAttr->Rename.empty()) {
827826
os << ", ";
828-
printEncodedString(AvAttr->Rename);
827+
printRenameForDecl(AvAttr, cast<ValueDecl>(D), true);
829828
}
830829
os << ")";
831830
} else {
@@ -899,10 +898,9 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
899898
}
900899
}
901900
if (!AvAttr->Rename.empty() && isa<ValueDecl>(D)) {
902-
// NB: Don't bother getting obj-c names, we can't get one for the rename
903901
os << ",message=\"'" << cast<ValueDecl>(D)->getBaseName()
904902
<< "' has been renamed to '";
905-
printEncodedString(AvAttr->Rename, false);
903+
printRenameForDecl(AvAttr, cast<ValueDecl>(D), false);
906904
os << '\'';
907905
if (!AvAttr->Message.empty()) {
908906
os << ": ";
@@ -917,6 +915,61 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
917915
}
918916
return hasPrintedAnything;
919917
}
918+
919+
void printRenameForDecl(const AvailableAttr *AvAttr, const ValueDecl *D,
920+
bool includeQuotes) {
921+
assert(!AvAttr->Rename.empty());
922+
923+
auto renamedParsedDeclName = parseDeclName(AvAttr->Rename);
924+
auto renamedDeclName = renamedParsedDeclName.formDeclName(D->getASTContext());
925+
926+
auto declContext = D->getDeclContext();
927+
const ValueDecl *renamedDecl = nullptr;
928+
929+
if (isa<ClassDecl>(D) || isa<ProtocolDecl>(D)) {
930+
UnqualifiedLookup lookup(renamedDeclName.getBaseIdentifier(),
931+
declContext->getModuleScopeContext(),
932+
nullptr,
933+
SourceLoc(),
934+
UnqualifiedLookup::Flags::TypeLookup);
935+
renamedDecl = lookup.getSingleTypeResult();
936+
} else {
937+
SmallVector<ValueDecl *, 4> lookupResults;
938+
declContext->lookupQualified(declContext->getSelfTypeInContext(),
939+
renamedDeclName, NL_QualifiedDefault, NULL,
940+
lookupResults);
941+
for (auto candidate : lookupResults) {
942+
if (!shouldInclude(candidate))
943+
continue;
944+
945+
if (candidate->getKind() != D->getKind() ||
946+
(candidate->isInstanceMember() !=
947+
cast<ValueDecl>(D)->isInstanceMember()))
948+
continue;
949+
950+
if (isa<FuncDecl>(candidate) &&
951+
(cast<FuncDecl>(candidate)->getParameters()->size() !=
952+
cast<FuncDecl>(D)->getParameters()->size()))
953+
continue;
954+
955+
if (renamedDecl) {
956+
// If we found a duplicated candidate then we would silently fail.
957+
renamedDecl = nullptr;
958+
break;
959+
}
960+
renamedDecl = candidate;
961+
}
962+
}
963+
964+
if (renamedDecl) {
965+
SmallString<128> scratch;
966+
auto renamedObjCRuntimeName = renamedDecl->getObjCRuntimeName()
967+
->getString(scratch);
968+
printEncodedString(renamedObjCRuntimeName, includeQuotes);
969+
} else {
970+
printEncodedString(AvAttr->Rename, includeQuotes);
971+
}
972+
}
920973

921974
void printSwift3ObjCDeprecatedInference(ValueDecl *VD) {
922975
const LangOptions &langOpts = M.getASTContext().LangOpts;
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t %s
3+
// RUN: %target-swift-frontend -parse-as-library %t/availability-real-sdk.swiftmodule -typecheck -emit-objc-header-path %t/availability-real-sdk.h -import-objc-header %S/../Inputs/empty.h
4+
// RUN: %FileCheck %s < %t/availability-real-sdk.h
5+
// RUN: %check-in-clang %t/availability-real-sdk.h
6+
7+
// REQUIRES: objc_interop
8+
9+
10+
// CHECK-LABEL: @interface NSArray<ObjectType> (SWIFT_EXTENSION(main))
11+
// CHECK-NEXT: - (id _Nonnull)deprecatedMethodInFavorOfReverseObjectEnumerator SWIFT_WARN_UNUSED_RESULT
12+
// CHECK-SAME: SWIFT_DEPRECATED_MSG("This method is deprecated in favor to the old reverseObjectEnumerator method", "reverseObjectEnumerator");
13+
// CHECK-NEXT: - (id _Nonnull)deprecatedMethodOnMacOSInFavorOfReverseObjectEnumerator SWIFT_WARN_UNUSED_RESULT
14+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,deprecated=0.0.1,message="'deprecatedMethodOnMacOSInFavorOfReverseObjectEnumerator' has been renamed to 'reverseObjectEnumerator': This method is deprecated in favor to the old reverseObjectEnumerator method");
15+
// CHECK-NEXT: - (id _Nonnull)unavailableMethodInFavorOfReverseObjectEnumerator SWIFT_WARN_UNUSED_RESULT
16+
// CHECK-SAME: SWIFT_UNAVAILABLE_MSG("'unavailableMethodInFavorOfReverseObjectEnumerator' has been renamed to 'reverseObjectEnumerator': This method is unavailable in favor to the old reverseObjectEnumerator method");
17+
// CHECK-NEXT: - (id _Nonnull)unavailableMethodOnMacOSInFavorOfReverseObjectEnumerator SWIFT_WARN_UNUSED_RESULT
18+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,unavailable,message="'unavailableMethodOnMacOSInFavorOfReverseObjectEnumerator' has been renamed to 'reverseObjectEnumerator': This method is unavailable in favor to the old reverseObjectEnumerator method");
19+
// CHECK-NEXT: - (NSArray * _Nonnull)deprecatedMethodInFavorOfAddingObjectWithObject:(id _Nonnull)object SWIFT_WARN_UNUSED_RESULT
20+
// CHECK-SAME: SWIFT_DEPRECATED_MSG("This method is deprecated in favor to the old adding method", "arrayByAddingObject:");
21+
// CHECK-NEXT: - (NSArray * _Nonnull)deprecatedMethodOnMacOSInFavorOfAddingObjectWithObject:(id _Nonnull)object SWIFT_WARN_UNUSED_RESULT
22+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,deprecated=0.0.1,message="'deprecatedMethodOnMacOSInFavorOfAddingObject' has been renamed to 'arrayByAddingObject:': This method is deprecated in favor to the old adding method");
23+
// CHECK-NEXT: - (NSArray * _Nonnull)unavailableMethodInFavorOfAddingObjectWithObject:(id _Nonnull)object SWIFT_WARN_UNUSED_RESULT
24+
// CHECK-SAME: SWIFT_UNAVAILABLE_MSG("'unavailableMethodInFavorOfAddingObject' has been renamed to 'arrayByAddingObject:': This method is unavailable in favor to the old adding method");
25+
// CHECK-NEXT: - (NSArray * _Nonnull)unavailableMethodOnMacOSInFavorOfAddingObjectWithObject:(id _Nonnull)object SWIFT_WARN_UNUSED_RESULT
26+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,unavailable,message="'unavailableMethodOnMacOSInFavorOfAddingObject' has been renamed to 'arrayByAddingObject:': This method is unavailable in favor to the old adding method");
27+
// CHECK-NEXT: @end
28+
29+
// CHECK-LABEL: @interface SubClassOfSet : NSSet
30+
// CHECK-NEXT: - (id _Nonnull)deprecatedMethodInFavorOfAnyObject SWIFT_WARN_UNUSED_RESULT
31+
// CHECK-SAME: SWIFT_DEPRECATED_MSG("This method is deprecated in favor to the old anyObject method", "anyObject");
32+
// CHECK-NEXT: - (id _Nonnull)deprecatedMethodOnMacOSInFavorOfAnyObject SWIFT_WARN_UNUSED_RESULT
33+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,deprecated=0.0.1,message="'deprecatedMethodOnMacOSInFavorOfAnyObject' has been renamed to 'anyObject': This method is deprecated in favor to the old anyObject method");
34+
// CHECK-NEXT: - (id _Nonnull)unavailableMethodInFavorOfAnyObject SWIFT_WARN_UNUSED_RESULT
35+
// CHECK-SAME: SWIFT_UNAVAILABLE_MSG("'unavailableMethodInFavorOfAnyObject' has been renamed to 'anyObject': This method is unavailable in favor to the old anyObject method");
36+
// CHECK-NEXT: - (id _Nonnull)unavailableMethodOnMacOSInFavorOfAnyObject SWIFT_WARN_UNUSED_RESULT
37+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,unavailable,message="'unavailableMethodOnMacOSInFavorOfAnyObject' has been renamed to 'anyObject': This method is unavailable in favor to the old anyObject method");
38+
// CHECK-NEXT: @property (nonatomic, readonly) NSInteger deprecatedPropertyInFavorOfCount
39+
// CHECK-SAME: SWIFT_DEPRECATED_MSG("This property is deprecated in favor to the old count property", "count");
40+
// CHECK-NEXT: @property (nonatomic, readonly) NSInteger deprecatedOnMacOSPropertyInFavorOfCount
41+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,deprecated=0.0.1,message="'deprecatedOnMacOSPropertyInFavorOfCount' has been renamed to 'count': This property is deprecated in favor to the old count property");
42+
// CHECK-NEXT: @property (nonatomic, readonly) NSInteger unavailablePropertyInFavorOfCount
43+
// CHECK-SAME: SWIFT_UNAVAILABLE_MSG("'unavailablePropertyInFavorOfCount' has been renamed to 'count': This property is unavailable in favor to the old count property");
44+
// CHECK-NEXT: @property (nonatomic, readonly) NSInteger unavailableOnMacOSPropertyInFavorOfCount
45+
// CHECK-SAME: SWIFT_AVAILABILITY(macos,unavailable,message="'unavailableOnMacOSPropertyInFavorOfCount' has been renamed to 'count': This property is unavailable in favor to the old count property");
46+
47+
// CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
48+
// CHECK-NEXT: - (nonnull instancetype)initWithObjects:(id _Nonnull const * _Nullable)objects count:(NSUInteger)cnt OBJC_DESIGNATED_INITIALIZER;
49+
// CHECK-NEXT: - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
50+
// CHECK-NEXT: @end
51+
52+
53+
import Foundation
54+
55+
56+
public class SubClassOfSet: NSSet {
57+
@available(*, deprecated,
58+
message: "This method is deprecated in favor to the old anyObject method",
59+
renamed: "anyObject()")
60+
@objc func deprecatedMethodInFavorOfAnyObject() -> Any { return 0 }
61+
@available(macOS, deprecated,
62+
message: "This method is deprecated in favor to the old anyObject method",
63+
renamed: "anyObject()")
64+
@objc func deprecatedMethodOnMacOSInFavorOfAnyObject() -> Any { return 0 }
65+
66+
@available(*, unavailable,
67+
message: "This method is unavailable in favor to the old anyObject method",
68+
renamed: "anyObject()")
69+
@objc func unavailableMethodInFavorOfAnyObject() -> Any { return 0 }
70+
@available(macOS, unavailable,
71+
message: "This method is unavailable in favor to the old anyObject method",
72+
renamed: "anyObject()")
73+
@objc func unavailableMethodOnMacOSInFavorOfAnyObject() -> Any { return 0 }
74+
75+
@available(*, deprecated,
76+
message: "This property is deprecated in favor to the old count property",
77+
renamed: "count")
78+
@objc var deprecatedPropertyInFavorOfCount: Int {
79+
get {
80+
return 0
81+
}
82+
}
83+
@available(macOS, deprecated,
84+
message: "This property is deprecated in favor to the old count property",
85+
renamed: "count")
86+
@objc var deprecatedOnMacOSPropertyInFavorOfCount: Int {
87+
get {
88+
return 0
89+
}
90+
}
91+
@available(*, unavailable,
92+
message: "This property is unavailable in favor to the old count property",
93+
renamed: "count")
94+
@objc var unavailablePropertyInFavorOfCount: Int {
95+
get {
96+
return 0
97+
}
98+
}
99+
@available(macOS, unavailable,
100+
message: "This property is unavailable in favor to the old count property",
101+
renamed: "count")
102+
@objc var unavailableOnMacOSPropertyInFavorOfCount: Int {
103+
get {
104+
return 0
105+
}
106+
}
107+
}
108+
109+
110+
extension NSArray {
111+
@available(*, deprecated,
112+
message: "This method is deprecated in favor to the old reverseObjectEnumerator method",
113+
renamed: "reverseObjectEnumerator()")
114+
@objc func deprecatedMethodInFavorOfReverseObjectEnumerator() -> Any { return 0 }
115+
@available(macOS, deprecated,
116+
message: "This method is deprecated in favor to the old reverseObjectEnumerator method",
117+
renamed: "reverseObjectEnumerator()")
118+
@objc func deprecatedMethodOnMacOSInFavorOfReverseObjectEnumerator() -> Any { return 0 }
119+
120+
@available(*, unavailable,
121+
message: "This method is unavailable in favor to the old reverseObjectEnumerator method",
122+
renamed: "reverseObjectEnumerator()")
123+
@objc func unavailableMethodInFavorOfReverseObjectEnumerator() -> Any { return 0 }
124+
@available(macOS, unavailable,
125+
message: "This method is unavailable in favor to the old reverseObjectEnumerator method",
126+
renamed: "reverseObjectEnumerator()")
127+
@objc func unavailableMethodOnMacOSInFavorOfReverseObjectEnumerator() -> Any { return 0 }
128+
129+
130+
@available(*, deprecated,
131+
message: "This method is deprecated in favor to the old adding method",
132+
renamed: "adding(_:)")
133+
@objc func deprecatedMethodInFavorOfAddingObject(object: Any) -> NSArray {
134+
return self.adding(object) as NSArray
135+
}
136+
@available(macOS, deprecated,
137+
message: "This method is deprecated in favor to the old adding method",
138+
renamed: "adding(_:)")
139+
@objc func deprecatedMethodOnMacOSInFavorOfAddingObject(object: Any) -> NSArray {
140+
return self.adding(object) as NSArray
141+
}
142+
@available(*, unavailable,
143+
message: "This method is unavailable in favor to the old adding method",
144+
renamed: "adding(_:)")
145+
@objc func unavailableMethodInFavorOfAddingObject(object: Any) -> NSArray {
146+
return self.adding(object) as NSArray
147+
}
148+
@available(macOS, unavailable,
149+
message: "This method is unavailable in favor to the old adding method",
150+
renamed: "adding(_:)")
151+
@objc func unavailableMethodOnMacOSInFavorOfAddingObject(object: Any) -> NSArray {
152+
return self.adding(object) as NSArray
153+
}
154+
}
155+

0 commit comments

Comments
 (0)