Skip to content

Commit 7163a40

Browse files
authored
[Migrator] Support framework API function renames. rdar://31766131 (#9013)
1 parent bae6015 commit 7163a40

File tree

11 files changed

+195
-13
lines changed

11 files changed

+195
-13
lines changed

include/swift/IDE/Utils.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,11 @@ class DeclNameViewer {
300300
SmallVector<StringRef, 4> Labels;
301301
public:
302302
DeclNameViewer(StringRef Text);
303+
DeclNameViewer() : DeclNameViewer(StringRef()) {}
304+
operator bool() const { return !BaseName.empty(); }
303305
StringRef base() const { return BaseName; }
304306
llvm::ArrayRef<StringRef> args() const { return llvm::makeArrayRef(Labels); }
307+
unsigned argSize() const { return Labels.size(); }
305308
unsigned partsCount() const { return 1 + Labels.size(); }
306309
unsigned commonPartsCount(DeclNameViewer &Other) const;
307310
};
@@ -398,8 +401,15 @@ class SourceEditOutputConsumer : public SourceEditConsumer {
398401
void accept(SourceManager &SM, RegionType RegionType, ArrayRef<Replacement> Replacements) override;
399402
};
400403

404+
enum class LabelRangeEndAt: int8_t {
405+
BeforeElemStart,
406+
LabelNameOnly,
407+
};
408+
401409
// Get the ranges of argument labels from an Arg, either tuple or paren.
402-
std::vector<CharSourceRange> getCallArgLabelRanges(SourceManager &SM, Expr *Arg);
410+
std::vector<CharSourceRange>
411+
getCallArgLabelRanges(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind);
412+
403413
} // namespace ide
404414
} // namespace swift
405415

lib/IDE/APIDigesterData.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ struct swift::ide::api::APIDiffItemStore::Implementation {
403403
ArrayRef<APIDiffItem*> swift::ide::api::APIDiffItemStore::
404404
getDiffItems(StringRef Key) const {
405405
if (Impl.PrintUsr)
406-
llvm::outs() << Key;
406+
llvm::outs() << Key << "\n";
407407
return Impl.Data[Key];
408408
}
409409

lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ void swift::ide::getLocationInfo(const ValueDecl *VD,
914914
}
915915

916916
std::vector<CharSourceRange> swift::ide::
917-
getCallArgLabelRanges(SourceManager &SM, Expr *Arg) {
917+
getCallArgLabelRanges(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind) {
918918
std::vector<CharSourceRange> Ranges;
919919
if (TupleExpr *TE = dyn_cast<TupleExpr>(Arg)) {
920920
size_t ElemIndex = 0;
@@ -925,7 +925,10 @@ getCallArgLabelRanges(SourceManager &SM, Expr *Arg) {
925925
auto NameIdentifier = TE->getElementName(ElemIndex);
926926
if (!NameIdentifier.empty()) {
927927
LabelStart = TE->getElementNameLoc(ElemIndex);
928+
if (EndKind == LabelRangeEndAt::LabelNameOnly)
929+
LabelEnd = LabelStart.getAdvancedLoc(NameIdentifier.getLength());
928930
}
931+
929932
Ranges.push_back(CharSourceRange(SM, LabelStart, LabelEnd));
930933
++ElemIndex;
931934
}

lib/Migrator/SyntacticMigratorPass.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "swift/AST/USRGeneration.h"
1414
#include "swift/Frontend/Frontend.h"
15+
#include "swift/IDE/Utils.h"
1516
#include "swift/Migrator/EditorAdapter.h"
1617
#include "swift/Migrator/FixitApplyDiagnosticConsumer.h"
1718
#include "swift/Migrator/Migrator.h"
@@ -27,6 +28,7 @@
2728

2829
using namespace swift;
2930
using namespace swift::migrator;
31+
using namespace swift::ide;
3032
using namespace swift::ide::api;
3133

3234
struct SyntacticMigratorPass::Implementation : public SourceEntityWalker {
@@ -48,6 +50,26 @@ struct SyntacticMigratorPass::Implementation : public SourceEntityWalker {
4850
return DiffStore.getDiffItems(Buffer.str());
4951
}
5052

53+
DeclNameViewer getFuncRename(ValueDecl *VD, bool &IgnoreBase) {
54+
for (auto *Item : getRelatedDiffItems(VD)) {
55+
if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
56+
if (CI->isRename()) {
57+
IgnoreBase = true;
58+
switch(CI->NodeKind) {
59+
case SDKNodeKind::Function:
60+
IgnoreBase = false;
61+
LLVM_FALLTHROUGH;
62+
case SDKNodeKind::Constructor:
63+
return DeclNameViewer(CI->getNewName());
64+
default:
65+
return DeclNameViewer();
66+
}
67+
}
68+
}
69+
}
70+
return DeclNameViewer();
71+
}
72+
5173
bool isSimpleReplacement(APIDiffItem *Item, std::string &Text) {
5274
if (auto *MD = dyn_cast<TypeMemberDiffItem>(Item)) {
5375
// We need to pull the self if self index is set.
@@ -92,6 +114,72 @@ struct SyntacticMigratorPass::Implementation : public SourceEntityWalker {
92114
}
93115
return true;
94116
}
117+
118+
struct ReferenceCollector : public SourceEntityWalker {
119+
ValueDecl *Target;
120+
CharSourceRange Result;
121+
ReferenceCollector(ValueDecl* Target) : Target(Target) {}
122+
bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
123+
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
124+
Type T, ReferenceMetaData Data) override {
125+
if (D == Target) {
126+
Result = Range;
127+
return false;
128+
}
129+
return true;
130+
}
131+
};
132+
133+
void handleFuncRename(ValueDecl *FD, Expr* FuncRefContainer, Expr *Arg) {
134+
bool IgnoreBase = false;
135+
if (auto View = getFuncRename(FD, IgnoreBase)) {
136+
if(!IgnoreBase) {
137+
ReferenceCollector Walker(FD);
138+
Walker.walk(FuncRefContainer);
139+
Editor.replace(Walker.Result, View.base());
140+
}
141+
unsigned Idx = 0;
142+
for (auto LR :getCallArgLabelRanges(SM, Arg,
143+
LabelRangeEndAt::LabelNameOnly)) {
144+
if (Idx < View.argSize()) {
145+
auto Label = View.args()[Idx++];
146+
147+
// FIXME: We update only when args are consistently valid.
148+
if (Label != "_" && LR.getByteLength())
149+
Editor.replace(LR, Label);
150+
}
151+
}
152+
}
153+
}
154+
155+
bool walkToExprPre(Expr *E) override {
156+
if (auto *CE = dyn_cast<CallExpr>(E)) {
157+
auto Fn = CE->getFn();
158+
auto Args = CE->getArg();
159+
switch (Fn->getKind()) {
160+
case ExprKind::DeclRef: {
161+
if (auto FD = Fn->getReferencedDecl().getDecl())
162+
handleFuncRename(FD, Fn, Args);
163+
break;
164+
}
165+
case ExprKind::DotSyntaxCall: {
166+
auto DSC = cast<DotSyntaxCallExpr>(Fn);
167+
if (auto FD = DSC->getFn()->getReferencedDecl().getDecl())
168+
handleFuncRename(FD, DSC->getFn(), Args);
169+
break;
170+
}
171+
case ExprKind::ConstructorRefCall: {
172+
auto CCE = cast<ConstructorRefCallExpr>(Fn);
173+
if (auto FD = CCE->getFn()->getReferencedDecl().getDecl())
174+
handleFuncRename(FD, CCE->getFn(), Args);
175+
break;
176+
}
177+
default:
178+
break;
179+
}
180+
}
181+
return true;
182+
}
95183
};
96184

97185
SyntacticMigratorPass::

test/migrator/API.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,38 @@
1616
"RightUsr": "",
1717
"RightComment": "theSimpleNewName",
1818
"ModuleName": "SomeModule"
19+
},
20+
{
21+
"DiffItemKind": "CommonDiffItem",
22+
"NodeKind": "Function",
23+
"NodeAnnotation": "Rename",
24+
"ChildIndex": "0",
25+
"LeftUsr": "c:@F@barGlobalFuncOldName",
26+
"LeftComment": "",
27+
"RightUsr": "",
28+
"RightComment": "barGlobalFuncNewName(newlabel:)",
29+
"ModuleName": "bar"
30+
},
31+
{
32+
"DiffItemKind": "CommonDiffItem",
33+
"NodeKind": "Function",
34+
"NodeAnnotation": "Rename",
35+
"ChildIndex": "0",
36+
"LeftUsr": "c:objc(cs)BarForwardDeclaredClass(im)barInstanceFunc1:anotherValue:anotherValue1:anotherValue2:",
37+
"LeftComment": "",
38+
"RightUsr": "",
39+
"RightComment": "barNewInstanceFunc1(newlabel1:newlabel2:newlabel3:newlabel4:)",
40+
"ModuleName": "bar"
41+
},
42+
{
43+
"DiffItemKind": "CommonDiffItem",
44+
"NodeKind": "Constructor",
45+
"NodeAnnotation": "Rename",
46+
"ChildIndex": "0",
47+
"LeftUsr": "c:objc(cs)BarForwardDeclaredClass(im)initWithOldLabel0:",
48+
"LeftComment": "",
49+
"RightUsr": "",
50+
"RightComment": "init(newlabel1:)",
51+
"ModuleName": "bar"
1952
}
2053
]

test/migrator/dump_usr.swift

Lines changed: 0 additions & 10 deletions
This file was deleted.

test/migrator/mock-sdk/Bar.framework/Headers/Bar.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ int barGlobalFunc(int a);
66

77
int barGlobalVariable = 1;
88

9+
int barGlobalFuncOldName(int a);
10+
911
@interface BarForwardDeclaredClass
12+
- (id)initWithOldLabel0:(int)frame;
1013
- (void) barInstanceFunc0;
14+
- (void) barInstanceFunc1:(int)info anotherValue:(int)info1 anotherValue1:(int)info2 anotherValue2:(int)info3;
1115
@end
1216

1317
enum BarForwardDeclaredEnum {

test/migrator/rename-init.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// REQUIRES: objc_interop
2+
// RUN: rm -rf %t && mkdir -p %t && %swift -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename-init.swift.result -o %t/rename-init.swift.remap -disable-migrator-fixits
3+
// RUN: diff -u %S/rename-init.swift.expected %t/rename-init.swift.result
4+
5+
import Bar
6+
7+
func foo() {
8+
_ = BarForwardDeclaredClass(oldLabel0:1)
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// REQUIRES: objc_interop
2+
// RUN: rm -rf %t && mkdir -p %t && %swift -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename-init.swift.result -o %t/rename-init.swift.remap -disable-migrator-fixits
3+
// RUN: diff -u %S/rename-init.swift.expected %t/rename-init.swift.result
4+
5+
import Bar
6+
7+
func foo() {
8+
_ = BarForwardDeclaredClass(newlabel1:1)
9+
}

test/migrator/rename.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// REQUIRES: objc_interop
2+
// RUN: rm -rf %t && mkdir -p %t && %swift -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename.swift.result -o %t/rename.swift.remap
3+
// RUN: diff -u %S/rename.swift.expected %t/rename.swift.result
4+
5+
import Bar
6+
7+
func foo(_ b: BarForwardDeclaredClass) {
8+
b.barInstanceFunc1(_: 0, anotherValue: 1, anotherValue1: 2, anotherValue2: 3)
9+
barGlobalFuncOldName(2)
10+
b.barInstanceFunc1(_: 0, anotherValue: 1, anotherValue1: 2, anotherValue2: 3)
11+
barGlobalFuncOldName(2)
12+
b.barInstanceFunc1(_: 0, anotherValue: 1, anotherValue1: 2, anotherValue2: 3)
13+
barGlobalFuncOldName(2)
14+
b.barInstanceFunc1(_: 0, anotherValue: 1, anotherValue1: 2, anotherValue2: 3)
15+
barGlobalFuncOldName(2)
16+
b.barInstanceFunc1(_: 0, anotherValue: 1, anotherValue1: 2, anotherValue2: 3)
17+
barGlobalFuncOldName(2)
18+
}

test/migrator/rename.swift.expected

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// REQUIRES: objc_interop
2+
// RUN: rm -rf %t && mkdir -p %t && %swift -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename.swift.result -o %t/rename.swift.remap
3+
// RUN: diff -u %S/rename.swift.expected %t/rename.swift.result
4+
5+
import Bar
6+
7+
func foo(_ b: BarForwardDeclaredClass) {
8+
b.barNewInstanceFunc1(_: 0, newlabel2: 1, newlabel3: 2, newlabel4: 3)
9+
barGlobalFuncNewName(2)
10+
b.barNewInstanceFunc1(_: 0, newlabel2: 1, newlabel3: 2, newlabel4: 3)
11+
barGlobalFuncNewName(2)
12+
b.barNewInstanceFunc1(_: 0, newlabel2: 1, newlabel3: 2, newlabel4: 3)
13+
barGlobalFuncNewName(2)
14+
b.barNewInstanceFunc1(_: 0, newlabel2: 1, newlabel3: 2, newlabel4: 3)
15+
barGlobalFuncNewName(2)
16+
b.barNewInstanceFunc1(_: 0, newlabel2: 1, newlabel3: 2, newlabel4: 3)
17+
barGlobalFuncNewName(2)
18+
}

0 commit comments

Comments
 (0)