Skip to content

Commit 429ed87

Browse files
authored
Merge pull request #15995 from nkcsgexi/simple-attribute-migration
2 parents d3b40ae + 6a4df3e commit 429ed87

File tree

7 files changed

+214
-25
lines changed

7 files changed

+214
-25
lines changed

include/swift/Migrator/EditorAdapter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class EditorAdapter {
5151
/// below. That doesn't handle duplicate or redundant changes.
5252
mutable llvm::SmallSet<Replacement, 32> Replacements;
5353

54+
bool CacheEnabled;
55+
5456
/// A running transactional collection of basic edit operations.
5557
/// Clang uses this transaction concept to cancel a batch of edits due to
5658
/// incompatibilities, such as those due to macro expansions, but we don't
@@ -82,7 +84,7 @@ class EditorAdapter {
8284
public:
8385
EditorAdapter(swift::SourceManager &SwiftSrcMgr,
8486
clang::SourceManager &ClangSrcMgr)
85-
: SwiftSrcMgr(SwiftSrcMgr), ClangSrcMgr(ClangSrcMgr),
87+
: SwiftSrcMgr(SwiftSrcMgr), ClangSrcMgr(ClangSrcMgr), CacheEnabled(true),
8688
Edits(clang::edit::Commit(ClangSrcMgr, clang::LangOptions())) {}
8789

8890
/// Lookup the BufferID in the SwiftToClangBufferMap. If it doesn't exist,
@@ -128,6 +130,8 @@ class EditorAdapter {
128130
const clang::edit::Commit &getEdits() const {
129131
return Edits;
130132
}
133+
void enableCache() { CacheEnabled = true; }
134+
void disableCache() { CacheEnabled = false; }
131135
};
132136

133137
} // end namespace migrator

lib/Migrator/APIDiffMigratorPass.cpp

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "clang/Rewrite/Core/RewriteBuffer.h"
2929
#include "llvm/Support/FileSystem.h"
3030
#include "swift/IDE/APIDigesterData.h"
31+
#include "swift/Basic/Defer.h"
3132

3233
using namespace swift;
3334
using namespace swift::migrator;
@@ -302,13 +303,12 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
302303
return false;
303304
}
304305

306+
std::set<std::string> InsertedFunctions;
305307
SourceLoc FileEndLoc;
306-
llvm::SmallSet<StringRef, 4> InsertedFunctions;
307-
308308
APIDiffMigratorPass(EditorAdapter &Editor, SourceFile *SF,
309-
const MigratorOptions &Opts)
310-
: ASTMigratorPass(Editor, SF, Opts),
311-
FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()) {}
309+
const MigratorOptions &Opts):
310+
ASTMigratorPass(Editor, SF, Opts),
311+
FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()) {}
312312

313313
void run() {
314314
if (Opts.APIDigesterDataStorePaths.empty())
@@ -702,52 +702,62 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
702702
}
703703

704704
StringRef insertHelperFunction(NodeAnnotation Anno, StringRef NewType,
705-
SmallString<256> &Buffer) {
705+
SmallString<256> &Buffer, bool FromString) {
706706
llvm::raw_svector_ostream OS(Buffer);
707707
OS << "\n";
708708
OS << "// Helper function inserted by Swift 4.2 migrator.\n";
709709
OS << "fileprivate func ";
710710
unsigned FuncNameStart = Buffer.size();
711-
OS << "convertTo";
711+
OS << (FromString ? "convertTo" : "convertFrom");
712712
SmallVector<std::string, 8> Segs;
713+
StringRef guard = "\tguard let input = input else { return nil }\n";
713714
switch(Anno) {
714715
case NodeAnnotation::OptionalArrayMemberUpdate:
715716
Segs = {"Optional", "Array", "[String]?"};
716717
Segs.push_back((Twine("[") + NewType +"]?").str());
717-
Segs.push_back(Twine("\tguard let input = input else { return nil }\n"
718-
"\treturn input.map { key in " + NewType +"(key) }").str());
718+
Segs.push_back((Twine(guard) + "\treturn input.map { key in " + NewType +"(key) }").str());
719+
Segs.push_back((Twine(guard) + "\treturn input.map { key in key.rawValue }").str());
719720
break;
720721
case NodeAnnotation::OptionalDictionaryKeyUpdate:
721722
Segs = {"Optional", "Dictionary", "[String: Any]?"};
722723
Segs.push_back((Twine("[") + NewType +": Any]?").str());
723-
Segs.push_back((Twine("\tguard let input = input else { return nil }\n"
724-
"\treturn Dictionary(uniqueKeysWithValues: input.map"
725-
" { key, value in (") + NewType + "(rawValue: key), value)})").str());
724+
Segs.push_back((Twine(guard) +
725+
"\treturn Dictionary(uniqueKeysWithValues: input.map"
726+
" { key, value in (" + NewType + "(rawValue: key), value)})").str());
727+
Segs.push_back((Twine(guard) +
728+
"\treturn Dictionary(uniqueKeysWithValues: input.map"
729+
" {key, value in (key.rawValue, value)})").str());
726730
break;
727731
case NodeAnnotation::ArrayMemberUpdate:
728732
Segs = {"", "Array", "[String]"};
729733
Segs.push_back((Twine("[") + NewType +"]").str());
730-
Segs.push_back(Twine("\treturn input.map { key in " + NewType +"(key) }").str());
734+
Segs.push_back((Twine("\treturn input.map { key in ") + NewType +"(key) }").str());
735+
Segs.push_back("\treturn input.map { key in key.rawValue }");
731736
break;
732737
case NodeAnnotation::DictionaryKeyUpdate:
733738
Segs = {"", "Dictionary", "[String: Any]"};
734739
Segs.push_back((Twine("[") + NewType +": Any]").str());
735740
Segs.push_back((Twine("\treturn Dictionary(uniqueKeysWithValues: input.map"
736741
" { key, value in (") + NewType + "(rawValue: key), value)})").str());
742+
Segs.push_back("\treturn Dictionary(uniqueKeysWithValues: input.map"
743+
" {key, value in (key.rawValue, value)})");
737744
break;
738745
case NodeAnnotation::SimpleStringRepresentableUpdate:
739746
Segs = {"", "", "String"};
740747
Segs.push_back(NewType);
741-
Segs.push_back("// Not implemented");
748+
Segs.push_back((Twine("\treturn ") + NewType + "(rawValue: input)").str());
749+
Segs.push_back("\treturn input.rawValue");
742750
break;
743751
case NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
744752
Segs = {"Optional", "", "String?"};
745753
Segs.push_back((Twine(NewType) +"?").str());
746-
Segs.push_back("// Not implemented");
754+
Segs.push_back((Twine(guard) + "\treturn " + NewType + "(rawValue: input)").str());
755+
Segs.push_back((Twine(guard) + "\treturn input.rawValue").str());
747756
break;
748757
default:
749758
llvm_unreachable("shouldn't handle this key.");
750759
}
760+
assert(Segs.size() == 6);
751761
OS << Segs[0];
752762
SmallVector<StringRef, 4> Parts;
753763
NewType.split(Parts, '.');
@@ -756,15 +766,22 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
756766
OS << Segs[1];
757767
auto FuncName = Buffer.str().substr(FuncNameStart);
758768
if (!InsertedFunctions.count(FuncName)) {
759-
OS << "(_ input: " << Segs[2] << ") -> " << Segs[3] << " {\n";
760-
OS << Segs[4] << "\n}\n";
769+
if (FromString) {
770+
OS << "(_ input: " << Segs[2] << ") -> " << Segs[3] << " {\n";
771+
OS << Segs[4] << "\n}\n";
772+
} else {
773+
OS << "(_ input: " << Segs[3] << ") -> " << Segs[2] << " {\n";
774+
OS << Segs[5] << "\n}\n";
775+
}
761776
Editor.insert(FileEndLoc, OS.str());
762777
InsertedFunctions.insert(FuncName);
763778
}
764779
return FuncName;
765780
}
766781

767-
void handleStringRepresentableArg(ValueDecl *FD, Expr *Arg) {
782+
void handleStringRepresentableArg(ValueDecl *FD, Expr *Arg, Expr *Call) {
783+
Editor.disableCache();
784+
SWIFT_DEFER { Editor.enableCache(); };
768785
NodeAnnotation Kind;
769786
StringRef NewAttributeType;
770787
uint8_t ArgIdx;
@@ -781,18 +798,20 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
781798
}
782799
if (NewAttributeType.empty())
783800
return;
801+
SmallString<256> Buffer;
802+
auto FuncName = insertHelperFunction(Kind, NewAttributeType, Buffer,
803+
/*FromString*/ArgIdx);
784804
if (ArgIdx) {
785805
ArgIdx --;
786806
auto AllArgs = getCallArgInfo(SM, Arg, LabelRangeEndAt::LabelNameOnly);
787807
if (AllArgs.size() <= ArgIdx)
788808
return;
789-
SmallString<256> Buffer;
790-
auto FuncName = insertHelperFunction(Kind, NewAttributeType, Buffer);
791809
auto Exp = AllArgs[ArgIdx].ArgExp;
792810
Editor.insert(Exp->getStartLoc(), (Twine(FuncName) + "(").str());
793811
Editor.insertAfterToken(Exp->getEndLoc(), ")");
794812
} else {
795-
// FIXME: return value migration.
813+
Editor.insert(Call->getStartLoc(), (Twine(FuncName) + "(").str());
814+
Editor.insertAfterToken(Call->getEndLoc(), ")");
796815
}
797816
}
798817

@@ -810,7 +829,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
810829
handleFuncRename(FD, Fn, Args);
811830
handleTypeHoist(FD, CE, Args);
812831
handleSpecialCases(FD, CE, Args);
813-
handleStringRepresentableArg(FD, Args);
832+
handleStringRepresentableArg(FD, Args, CE);
814833
}
815834
break;
816835
}
@@ -820,7 +839,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
820839
handleFuncRename(FD, DSC->getFn(), Args);
821840
handleFunctionCallToPropertyChange(FD, DSC->getFn(), Args);
822841
handleSpecialCases(FD, CE, Args);
823-
handleStringRepresentableArg(FD, Args);
842+
handleStringRepresentableArg(FD, Args, CE);
824843
}
825844
break;
826845
}
@@ -829,7 +848,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
829848
if (auto FD = CCE->getFn()->getReferencedDecl().getDecl()) {
830849
auto *CE = CCE->getFn();
831850
handleFuncRename(FD, CE, Args);
832-
handleStringRepresentableArg(FD, Args);
851+
handleStringRepresentableArg(FD, Args, CE);
833852
}
834853
break;
835854
}

lib/Migrator/EditorAdapter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ EditorAdapter::getLocInfo(swift::SourceLoc Loc) const {
2929

3030
bool
3131
EditorAdapter::cacheReplacement(CharSourceRange Range, StringRef Text) const {
32+
if (!CacheEnabled)
33+
return false;
3234
unsigned SwiftBufferID, Offset;
3335
std::tie(SwiftBufferID, Offset) = getLocInfo(Range.getStart());
3436
Replacement R { Offset, Range.getByteLength(), Text };

test/Migrator/Inputs/Cities.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,12 @@ public class Container {
4242
public init(optionalAttributes: [String: Any]?) {}
4343
public func adding(attrArray: [String]) {}
4444
public init(optionalAttrArray: [String]?) {}
45+
public func add(single: String) {}
46+
public func add(singleOptional: String?) {}
47+
public func getAttrArray() -> [String] { return [] }
48+
public func getOptionalAttrArray() -> [String]? { return [] }
49+
public func getAttrDictionary() -> [String: Any] { return [:] }
50+
public func getOptionalAttrDictionary() -> [String: Any]? { return nil }
51+
public func getSingleAttr() -> String { return "" }
52+
public func getOptionalSingleAttr() -> String? { return nil }
4553
}

test/Migrator/Inputs/string-representable.json

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,92 @@
7676
"RightComment": "SimpleAttribute",
7777
"ModuleName": "Cities"
7878
},
79+
{
80+
"DiffItemKind": "CommonDiffItem",
81+
"NodeKind": "Function",
82+
"NodeAnnotation": "SimpleStringRepresentableUpdate",
83+
"ChildIndex": "1",
84+
"LeftUsr": "s:6Cities9ContainerC3add6singleySS_tF",
85+
"LeftComment": "",
86+
"RightUsr": "",
87+
"RightComment": "SimpleAttribute",
88+
"ModuleName": "Cities"
89+
},
90+
{
91+
"DiffItemKind": "CommonDiffItem",
92+
"NodeKind": "Function",
93+
"NodeAnnotation": "SimpleOptionalStringRepresentableUpdate",
94+
"ChildIndex": "1",
95+
"LeftUsr": "s:6Cities9ContainerC3add14singleOptionalySSSg_tF",
96+
"LeftComment": "",
97+
"RightUsr": "",
98+
"RightComment": "SimpleAttribute",
99+
"ModuleName": "Cities"
100+
},
101+
{
102+
"DiffItemKind": "CommonDiffItem",
103+
"NodeKind": "Function",
104+
"NodeAnnotation": "SimpleStringRepresentableUpdate",
105+
"ChildIndex": "0",
106+
"LeftUsr": "s:6Cities9ContainerC13getSingleAttrSSyF",
107+
"LeftComment": "",
108+
"RightUsr": "",
109+
"RightComment": "SimpleAttribute",
110+
"ModuleName": "Cities"
111+
},
112+
{
113+
"DiffItemKind": "CommonDiffItem",
114+
"NodeKind": "Function",
115+
"NodeAnnotation": "SimpleOptionalStringRepresentableUpdate",
116+
"ChildIndex": "0",
117+
"LeftUsr": "s:6Cities9ContainerC21getOptionalSingleAttrSSSgyF",
118+
"LeftComment": "",
119+
"RightUsr": "",
120+
"RightComment": "SimpleAttribute",
121+
"ModuleName": "Cities"
122+
},
123+
{
124+
"DiffItemKind": "CommonDiffItem",
125+
"NodeKind": "Function",
126+
"NodeAnnotation": "ArrayMemberUpdate",
127+
"ChildIndex": "0",
128+
"LeftUsr": "s:6Cities9ContainerC12getAttrArraySaySSGyF",
129+
"LeftComment": "",
130+
"RightUsr": "",
131+
"RightComment": "SimpleAttribute",
132+
"ModuleName": "Cities"
133+
},
134+
{
135+
"DiffItemKind": "CommonDiffItem",
136+
"NodeKind": "Function",
137+
"NodeAnnotation": "OptionalArrayMemberUpdate",
138+
"ChildIndex": "0",
139+
"LeftUsr": "s:6Cities9ContainerC20getOptionalAttrArraySaySSGSgyF",
140+
"LeftComment": "",
141+
"RightUsr": "",
142+
"RightComment": "SimpleAttribute",
143+
"ModuleName": "Cities"
144+
},
145+
{
146+
"DiffItemKind": "CommonDiffItem",
147+
"NodeKind": "Function",
148+
"NodeAnnotation": "OptionalDictionaryKeyUpdate",
149+
"ChildIndex": "0",
150+
"LeftUsr": "s:6Cities9ContainerC25getOptionalAttrDictionarys0F0VySSypGSgyF",
151+
"LeftComment": "",
152+
"RightUsr": "",
153+
"RightComment": "SimpleAttribute",
154+
"ModuleName": "Cities"
155+
},
156+
{
157+
"DiffItemKind": "CommonDiffItem",
158+
"NodeKind": "Function",
159+
"NodeAnnotation": "DictionaryKeyUpdate",
160+
"ChildIndex": "0",
161+
"LeftUsr": "s:6Cities9ContainerC17getAttrDictionarys0E0VySSypGyF",
162+
"LeftComment": "",
163+
"RightUsr": "",
164+
"RightComment": "SimpleAttribute",
165+
"ModuleName": "Cities"
166+
},
79167
]

test/Migrator/string-representable.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,17 @@ func foo(_ c: Container) -> String {
1515
_ = Container(optionalAttributes: nil)
1616
_ = Container(optionalAttrArray: nil)
1717
c.adding(attrArray: ["key1", "key2"])
18+
c.add(single: "")
19+
c.add(singleOptional: nil)
20+
_ = c.getAttrDictionary()
21+
_ = c.getOptionalAttrDictionary()
22+
_ = c.getSingleAttr()
23+
_ = c.getOptionalSingleAttr()
24+
_ = c.getAttrArray()
25+
_ = c.getOptionalAttrArray()
26+
27+
c.addingAttributes(c.getAttrDictionary())
28+
c.adding(optionalAttributes: c.getAttrDictionary())
29+
1830
return c.Value
1931
}

0 commit comments

Comments
 (0)