Skip to content

migrator: handle the reversion of raw representable changes. rdar://39498127 #17267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions lib/Migrator/APIDiffMigratorPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {

std::vector<APIDiffItem*> getRelatedDiffItems(ValueDecl *VD) {
std::vector<APIDiffItem*> results;
if (!VD)
return results;
auto addDiffItems = [&](ValueDecl *VD) {
llvm::SmallString<64> Buffer;
llvm::raw_svector_ostream OS(Buffer);
Expand Down Expand Up @@ -921,9 +923,66 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
insertHelperFunction(Kind, RawType, NewAttributeType, FromString, WrapTarget);
}

bool hasRevertRawRepresentableChange(ValueDecl *VD) {
for (auto Item: getRelatedDiffItems(VD)) {
if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
if (CI->DiffKind ==
NodeAnnotation::RevertTypeAliasDeclToRawRepresentable)
return true;
}
}
return false;
}

bool handleRevertRawRepresentable(Expr *E) {
// Change attribute.rawValue to attribute
if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
auto Found = false;
if (auto *Base = MRE->getBase()) {
if (hasRevertRawRepresentableChange(Base->getType()->getAnyNominal())) {
Found = true;
}
}
if (!Found)
return false;
auto NL = MRE->getNameLoc().getStartLoc();
auto DL = MRE->getDotLoc();
if (NL.isInvalid() || DL.isInvalid())
return false;
CharSourceRange Range = Lexer::getCharSourceRangeFromSourceRange(SM, {DL, NL});
if (Range.str() == ".rawValue") {
Editor.remove(Range);
return true;
}
}

// Change attribute(rawValue: "value") to "value"
if (auto *CE = dyn_cast<CallExpr>(E)) {
auto Found = false;
if (auto *CRC = dyn_cast<ConstructorRefCallExpr>(CE->getFn())) {
if (auto *TE = dyn_cast<TypeExpr>(CRC->getBase())) {
if (hasRevertRawRepresentableChange(TE->getInstanceType()->getAnyNominal()))
Found = true;
}
}
if (!Found)
return false;
std::vector<CallArgInfo> AllArgs =
getCallArgInfo(SM, CE->getArg(), LabelRangeEndAt::LabelNameOnly);
if (AllArgs.size() == 1 && AllArgs.front().LabelRange.str() == "rawValue") {
Editor.replace(CE->getSourceRange(), Lexer::getCharSourceRangeFromSourceRange(SM,
AllArgs.front().ArgExp->getSourceRange()).str());
return true;
}
}
return false;
}

bool walkToExprPre(Expr *E) override {
if (E->getSourceRange().isInvalid())
return false;
if (handleRevertRawRepresentable(E))
return false;
if (handleQualifiedReplacement(E))
return false;
if (handleAssignDestMigration(E))
Expand Down
14 changes: 14 additions & 0 deletions test/Migrator/Inputs/Cities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,17 @@ public enum FontWeight: Int {
case Regular
case Bold
}

public struct AwesomeCityAttribute: RawRepresentable {
public init?(rawValue: String) { self.rawValue = rawValue }
public var rawValue: String
public typealias RawValue = String
}

public class Wrapper {
public struct Attribute: RawRepresentable {
public init?(rawValue: String) { self.rawValue = rawValue }
public var rawValue: String
public typealias RawValue = String
}
}
22 changes: 22 additions & 0 deletions test/Migrator/Inputs/string-representable.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,26 @@
"RightComment": "AwesomeIntWrapper",
"ModuleName": "bar"
},
{
"DiffItemKind": "CommonDiffItem",
"NodeKind": "TypeDecl",
"NodeAnnotation": "RevertTypeAliasDeclToRawRepresentable",
"ChildIndex": "0",
"LeftUsr": "s:6Cities20AwesomeCityAttributeV",
"LeftComment": "String",
"RightUsr": "",
"RightComment": "String",
"ModuleName": "Cities"
},
{
"DiffItemKind": "CommonDiffItem",
"NodeKind": "TypeDecl",
"NodeAnnotation": "RevertTypeAliasDeclToRawRepresentable",
"ChildIndex": "0",
"LeftUsr": "s:6Cities7WrapperC9AttributeV",
"LeftComment": "String",
"RightUsr": "",
"RightComment": "String",
"ModuleName": "Cities"
},
]
9 changes: 9 additions & 0 deletions test/Migrator/string-representable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,12 @@ func foo(_ c: Container) -> String {
}

class C: BarForwardDeclaredClass {}

func revert(_ a: AwesomeCityAttribute, b: Wrapper.Attribute) {
_ = AwesomeCityAttribute(rawValue: "somevalue")
_ = AwesomeCityAttribute.init(rawValue: "somevalue")
_ = a.rawValue
_ = Wrapper.Attribute(rawValue: "somevalue")
_ = Wrapper.Attribute.init(rawValue: "somevalue")
_ = b.rawValue
}
9 changes: 9 additions & 0 deletions test/Migrator/string-representable.swift.expected
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ func foo(_ c: Container) -> String {

class C: BarForwardDeclaredClass {}

func revert(_ a: AwesomeCityAttribute, b: Wrapper.Attribute) {
_ = "somevalue"
_ = "somevalue"
_ = a
_ = "somevalue"
_ = "somevalue"
_ = b
}

// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertToNewAttribute(_ input: String) -> NewAttribute {
return NewAttribute(rawValue: input)
Expand Down