Skip to content

Commit 00c7cb6

Browse files
authored
Merge pull request #18226 from nkcsgexi/42480588
migrator: handle AppKit protocol migrations. rdar://42480588
2 parents b275edd + a8d43cc commit 00c7cb6

File tree

3 files changed

+349
-1
lines changed

3 files changed

+349
-1
lines changed

Diff for: lib/Migrator/APIDiffMigratorPass.cpp

+97-1
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
363363

364364
std::vector<ConversionFunctionInfo> HelperFuncInfo;
365365
SourceLoc FileEndLoc;
366+
llvm::StringSet<> OverridingRemoveNames;
366367

367368
/// For a given expression, check whether the type of this expression is
368369
/// name alias type, and the name alias type is known to change to raw
@@ -385,7 +386,8 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
385386
APIDiffMigratorPass(EditorAdapter &Editor, SourceFile *SF,
386387
const MigratorOptions &Opts):
387388
ASTMigratorPass(Editor, SF, Opts), DiffStore(Diags),
388-
FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()) {}
389+
FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()),
390+
OverridingRemoveNames(funcNamesForOverrideRemoval()) {}
389391

390392
~APIDiffMigratorPass() {
391393
Editor.disableCache();
@@ -1290,6 +1292,92 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
12901292
}
12911293
}
12921294

1295+
llvm::StringSet<> funcNamesForOverrideRemoval() {
1296+
llvm::StringSet<> Results;
1297+
Results.insert("c:objc(cs)NSObject(im)application:delegateHandlesKey:");
1298+
Results.insert("c:objc(cs)NSObject(im)changeColor:");
1299+
Results.insert("c:objc(cs)NSObject(im)controlTextDidBeginEditing:");
1300+
Results.insert("c:objc(cs)NSObject(im)controlTextDidEndEditing:");
1301+
Results.insert("c:objc(cs)NSObject(im)controlTextDidChange:");
1302+
Results.insert("c:objc(cs)NSObject(im)changeFont:");
1303+
Results.insert("c:objc(cs)NSObject(im)validModesForFontPanel:");
1304+
Results.insert("c:objc(cs)NSObject(im)discardEditing");
1305+
Results.insert("c:objc(cs)NSObject(im)commitEditing");
1306+
Results.insert("c:objc(cs)NSObject(im)commitEditingWithDelegate:didCommitSelector:contextInfo:");
1307+
Results.insert("c:objc(cs)NSObject(im)commitEditingAndReturnError:");
1308+
Results.insert("c:objc(cs)NSObject(im)objectDidBeginEditing:");
1309+
Results.insert("c:objc(cs)NSObject(im)objectDidEndEditing:");
1310+
Results.insert("c:objc(cs)NSObject(im)validateMenuItem:");
1311+
Results.insert("c:objc(cs)NSObject(im)pasteboard:provideDataForType:");
1312+
Results.insert("c:objc(cs)NSObject(im)pasteboardChangedOwner:");
1313+
Results.insert("c:objc(cs)NSObject(im)validateToolbarItem:");
1314+
Results.insert("c:objc(cs)NSObject(im)layer:shouldInheritContentsScale:fromWindow:");
1315+
Results.insert("c:objc(cs)NSObject(im)view:stringForToolTip:point:userData:");
1316+
return Results;
1317+
}
1318+
1319+
SourceLoc shouldRemoveOverride(AbstractFunctionDecl *AFD) {
1320+
if (AFD->getKind() != DeclKind::Func)
1321+
return SourceLoc();
1322+
SourceLoc OverrideLoc;
1323+
1324+
// Get the location of override keyword.
1325+
if (auto *Override = AFD->getAttrs().getAttribute<OverrideAttr>()) {
1326+
if (Override->getRange().isValid()) {
1327+
OverrideLoc = Override->getLocation();
1328+
}
1329+
}
1330+
if (OverrideLoc.isInvalid())
1331+
return SourceLoc();
1332+
auto *OD = AFD->getOverriddenDecl();
1333+
llvm::SmallString<64> Buffer;
1334+
llvm::raw_svector_ostream OS(Buffer);
1335+
if (swift::ide::printDeclUSR(OD, OS))
1336+
return SourceLoc();
1337+
return OverridingRemoveNames.find(OS.str()) == OverridingRemoveNames.end() ?
1338+
SourceLoc() : OverrideLoc;
1339+
}
1340+
1341+
struct SuperRemoval: public ASTWalker {
1342+
EditorAdapter &Editor;
1343+
llvm::StringSet<> &USRs;
1344+
SuperRemoval(EditorAdapter &Editor, llvm::StringSet<> &USRs):
1345+
Editor(Editor), USRs(USRs) {}
1346+
bool isSuperExpr(Expr *E) {
1347+
if (E->isImplicit())
1348+
return false;
1349+
// Check if the expression is super.foo().
1350+
if (auto *CE = dyn_cast<CallExpr>(E)) {
1351+
if (auto *DSC = dyn_cast<DotSyntaxCallExpr>(CE->getFn())) {
1352+
if (DSC->getBase()->getKind() != ExprKind::SuperRef)
1353+
return false;
1354+
llvm::SmallString<64> Buffer;
1355+
llvm::raw_svector_ostream OS(Buffer);
1356+
auto *RD = DSC->getFn()->getReferencedDecl().getDecl();
1357+
if (swift::ide::printDeclUSR(RD, OS))
1358+
return false;
1359+
return USRs.find(OS.str()) != USRs.end();
1360+
}
1361+
}
1362+
// We should handle try super.foo() too.
1363+
if (auto *TE = dyn_cast<AnyTryExpr>(E)) {
1364+
return isSuperExpr(TE->getSubExpr());
1365+
}
1366+
return false;
1367+
}
1368+
std::pair<bool, Stmt*> walkToStmtPre(Stmt *S) override {
1369+
if (auto *BS = dyn_cast<BraceStmt>(S)) {
1370+
for(auto Ele: BS->getElements()) {
1371+
if (Ele.is<Expr*>() && isSuperExpr(Ele.get<Expr*>())) {
1372+
Editor.remove(Ele.getSourceRange());
1373+
}
1374+
}
1375+
}
1376+
// We only handle top-level expressions, so avoid visiting further.
1377+
return {false, S};
1378+
}
1379+
};
1380+
12931381
bool walkToDeclPre(Decl *D, CharSourceRange Range) override {
12941382
if (D->isImplicit())
12951383
return true;
@@ -1305,6 +1393,14 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
13051393
handleLocalParameterBridge(AFD, DiffItem);
13061394
}
13071395
}
1396+
auto OverrideLoc = shouldRemoveOverride(AFD);
1397+
if (OverrideLoc.isValid()) {
1398+
// Remove override keyword.
1399+
Editor.remove(OverrideLoc);
1400+
// Remove super-dot call.
1401+
SuperRemoval Removal(Editor, OverridingRemoveNames);
1402+
D->walk(Removal);
1403+
}
13081404
}
13091405
return true;
13101406
}

Diff for: test/Migrator/remove_override.swift

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// REQUIRES: objc_interop
2+
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -emit-migrated-file-path %t/remove_override.swift.result -o %t/rename-func-decl.swift.remap
3+
// RUN: diff -u %S/remove_override.swift.expected %t/remove_override.swift.result
4+
5+
import AppKit
6+
7+
class AppDelegate: NSObject {
8+
override class func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
9+
super.application(sender, delegateHandlesKey: key)
10+
return false
11+
}
12+
override func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
13+
return super.application(sender, delegateHandlesKey: key)
14+
}
15+
override class func changeColor(_ sender: Any?) {
16+
super.changeColor(sender)
17+
}
18+
override func changeColor(_ sender: Any?) {
19+
20+
}
21+
override class func controlTextDidBeginEditing(_ obj: Notification) {
22+
23+
}
24+
override func controlTextDidBeginEditing(_ obj: Notification) {
25+
26+
}
27+
override class func controlTextDidEndEditing(_ obj: Notification) {
28+
29+
}
30+
override func controlTextDidEndEditing(_ obj: Notification) {
31+
32+
}
33+
override class func controlTextDidChange(_ obj: Notification) {
34+
35+
}
36+
override func controlTextDidChange(_ obj: Notification) {
37+
38+
}
39+
override class func changeFont(_ sender: Any?) {
40+
41+
}
42+
override func changeFont(_ sender: Any?) {
43+
44+
}
45+
override class func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
46+
return []
47+
}
48+
override func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
49+
return []
50+
}
51+
override class func discardEditing() {
52+
53+
}
54+
override func discardEditing() {
55+
56+
}
57+
override class func commitEditing() -> Bool {
58+
return false
59+
}
60+
override func commitEditing() -> Bool {
61+
return false
62+
}
63+
override class func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
64+
65+
}
66+
override func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
67+
68+
}
69+
override class func commitEditingAndReturnError() throws {
70+
71+
}
72+
override func commitEditingAndReturnError() throws {
73+
74+
}
75+
override class func objectDidBeginEditing(_ editor: Any) {
76+
77+
}
78+
override func objectDidBeginEditing(_ editor: Any) {
79+
80+
}
81+
override class func objectDidEndEditing(_ editor: Any) {
82+
83+
}
84+
override func objectDidEndEditing(_ editor: Any) {
85+
86+
}
87+
override class func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
88+
return false
89+
}
90+
override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
91+
return false
92+
}
93+
override class func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
94+
95+
}
96+
override func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
97+
98+
}
99+
override class func pasteboardChangedOwner(_ sender: NSPasteboard) {
100+
101+
}
102+
override func pasteboardChangedOwner(_ sender: NSPasteboard) {
103+
104+
}
105+
override class func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
106+
return false
107+
}
108+
override func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
109+
return false
110+
}
111+
override class func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
112+
return ""
113+
}
114+
override func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
115+
return ""
116+
}
117+
}
118+
119+
// We shouldn't migrate further sub-class.
120+
class MyAppDelegate: AppDelegate {
121+
override func commitEditing() -> Bool {
122+
super.commitEditing()
123+
return false
124+
}
125+
}
126+

Diff for: test/Migrator/remove_override.swift.expected

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// REQUIRES: objc_interop
2+
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -emit-migrated-file-path %t/remove_override.swift.result -o %t/rename-func-decl.swift.remap
3+
// RUN: diff -u %S/remove_override.swift.expected %t/remove_override.swift.result
4+
5+
import AppKit
6+
7+
class AppDelegate: NSObject {
8+
class func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
9+
10+
return false
11+
}
12+
func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
13+
return super.application(sender, delegateHandlesKey: key)
14+
}
15+
class func changeColor(_ sender: Any?) {
16+
17+
}
18+
func changeColor(_ sender: Any?) {
19+
20+
}
21+
class func controlTextDidBeginEditing(_ obj: Notification) {
22+
23+
}
24+
func controlTextDidBeginEditing(_ obj: Notification) {
25+
26+
}
27+
class func controlTextDidEndEditing(_ obj: Notification) {
28+
29+
}
30+
func controlTextDidEndEditing(_ obj: Notification) {
31+
32+
}
33+
class func controlTextDidChange(_ obj: Notification) {
34+
35+
}
36+
func controlTextDidChange(_ obj: Notification) {
37+
38+
}
39+
class func changeFont(_ sender: Any?) {
40+
41+
}
42+
func changeFont(_ sender: Any?) {
43+
44+
}
45+
class func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
46+
return []
47+
}
48+
func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
49+
return []
50+
}
51+
class func discardEditing() {
52+
53+
}
54+
func discardEditing() {
55+
56+
}
57+
class func commitEditing() -> Bool {
58+
return false
59+
}
60+
func commitEditing() -> Bool {
61+
return false
62+
}
63+
class func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
64+
65+
}
66+
func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
67+
68+
}
69+
class func commitEditingAndReturnError() throws {
70+
71+
}
72+
func commitEditingAndReturnError() throws {
73+
74+
}
75+
class func objectDidBeginEditing(_ editor: Any) {
76+
77+
}
78+
func objectDidBeginEditing(_ editor: Any) {
79+
80+
}
81+
class func objectDidEndEditing(_ editor: Any) {
82+
83+
}
84+
func objectDidEndEditing(_ editor: Any) {
85+
86+
}
87+
class func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
88+
return false
89+
}
90+
func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
91+
return false
92+
}
93+
class func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
94+
95+
}
96+
func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
97+
98+
}
99+
class func pasteboardChangedOwner(_ sender: NSPasteboard) {
100+
101+
}
102+
func pasteboardChangedOwner(_ sender: NSPasteboard) {
103+
104+
}
105+
class func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
106+
return false
107+
}
108+
func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
109+
return false
110+
}
111+
class func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
112+
return ""
113+
}
114+
func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
115+
return ""
116+
}
117+
}
118+
119+
// We shouldn't migrate further sub-class.
120+
class MyAppDelegate: AppDelegate {
121+
override func commitEditing() -> Bool {
122+
super.commitEditing()
123+
return false
124+
}
125+
}
126+

0 commit comments

Comments
 (0)