Skip to content

[WIP]migrator: handle function hoist API changes. rdar://31234806 #9544

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 6 commits into from
May 13, 2017
Merged
Show file tree
Hide file tree
Changes from 3 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
26 changes: 25 additions & 1 deletion include/swift/IDE/APIDigesterData.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "swift/Basic/LLVM.h"
#include "swift/Basic/JSONSerialization.h"
#include "swift/IDE/Utils.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
Expand Down Expand Up @@ -198,28 +199,51 @@ struct CommonDiffItem: public APIDiffItem {
// myColor.components
//
//
enum class TypeMemberDiffItemSubKind {
SimpleReplacement,
HoistSelfOnly,
HoistSelfAndRemoveParam,
HoistSelfAndUseProperty,
};

struct TypeMemberDiffItem: public APIDiffItem {
StringRef usr;
StringRef newTypeName;
StringRef newPrintedName;
Optional<uint8_t> selfIndex;
Optional<uint8_t> removedIndex;
StringRef oldPrintedName;

private:
DeclNameViewer OldNameViwer;
DeclNameViewer NewNameViwer;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: Viwer


public:
TypeMemberDiffItemSubKind Subkind;

public:
TypeMemberDiffItem(StringRef usr, StringRef newTypeName,
StringRef newPrintedName, Optional<uint8_t> selfIndex,
Optional<uint8_t> removedIndex,
StringRef oldPrintedName) : usr(usr),
newTypeName(newTypeName), newPrintedName(newPrintedName),
selfIndex(selfIndex), oldPrintedName(oldPrintedName) {}
selfIndex(selfIndex), removedIndex(removedIndex),
oldPrintedName(oldPrintedName), OldNameViwer(oldPrintedName),
NewNameViwer(newPrintedName), Subkind(getSubKind()) {}
static StringRef head();
static void describe(llvm::raw_ostream &os);
static void undef(llvm::raw_ostream &os);
void streamDef(llvm::raw_ostream &os) const override;
bool operator<(TypeMemberDiffItem Other) const;
static bool classof(const APIDiffItem *D);
StringRef getKey() const override { return usr; }
const DeclNameViewer &getOldName() const { return OldNameViwer; }
const DeclNameViewer &getNewName() const { return NewNameViwer; }
APIDiffItemKind getKind() const override {
return APIDiffItemKind::ADK_TypeMemberDiffItem;
}
private:
TypeMemberDiffItemSubKind getSubKind() const;
};

struct NoEscapeFuncParam: public APIDiffItem {
Expand Down
1 change: 1 addition & 0 deletions include/swift/IDE/DigesterEnums.def
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ DIFF_ITEM_KEY_KIND_STRING(NewPrintedName)
DIFF_ITEM_KEY_KIND_STRING(OldPrintedName)

DIFF_ITEM_KEY_KIND_INT(SelfIndex)
DIFF_ITEM_KEY_KIND_INT(RemovedIndex)
DIFF_ITEM_KEY_KIND_INT(Index)

#undef DIFF_ITEM_KEY_KIND_INT
Expand Down
11 changes: 11 additions & 0 deletions include/swift/IDE/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ class RangeResolver : public SourceEntityWalker {
class DeclNameViewer {
StringRef BaseName;
SmallVector<StringRef, 4> Labels;
bool HasParen;
public:
DeclNameViewer(StringRef Text);
DeclNameViewer() : DeclNameViewer(StringRef()) {}
Expand All @@ -316,6 +317,7 @@ class DeclNameViewer {
unsigned argSize() const { return Labels.size(); }
unsigned partsCount() const { return 1 + Labels.size(); }
unsigned commonPartsCount(DeclNameViewer &Other) const;
bool isFunction() const { return HasParen; }
};

/// This provide a utility for writing to an underlying string buffer multiple
Expand Down Expand Up @@ -415,6 +417,15 @@ enum class LabelRangeEndAt: int8_t {
LabelNameOnly,
};

struct CallArgInfo {
Expr *ArgExp;
CharSourceRange LabelRange;
CharSourceRange getEntireCharRange(const SourceManager &SM) const;
};

std::vector<CallArgInfo>
getCallArgInfo(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind);

// Get the ranges of argument labels from an Arg, either tuple or paren.
std::vector<CharSourceRange>
getCallArgLabelRanges(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind);
Expand Down
44 changes: 42 additions & 2 deletions lib/IDE/APIDigesterData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/StringSet.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/MemoryBuffer.h"
Expand Down Expand Up @@ -105,6 +106,39 @@ StringRef swift::ide::api::TypeMemberDiffItem::head() {
return "SDK_CHANGE_TYPE_MEMBER";
}

TypeMemberDiffItemSubKind
swift::ide::api::TypeMemberDiffItem::getSubKind() const {
DeclNameViewer OldName = getOldName();
DeclNameViewer NewName = getNewName();
if(!OldName.isFunction()) {
assert(!NewName.isFunction());
return TypeMemberDiffItemSubKind::SimpleReplacement;
}
assert(OldName.isFunction());
bool ToProperty = !NewName.isFunction();
if (selfIndex) {
if (removedIndex) {
if (ToProperty)
llvm_unreachable("unknown situation");
else {
assert(NewName.argSize() + 2 == OldName.argSize());
return TypeMemberDiffItemSubKind::HoistSelfAndRemoveParam;
}
} else if (ToProperty) {
assert(OldName.argSize() == 1);
return TypeMemberDiffItemSubKind::HoistSelfAndUseProperty;
} else {
assert(NewName.argSize() + 1 == OldName.argSize());
return TypeMemberDiffItemSubKind::HoistSelfOnly;
}
} else if (ToProperty) {
llvm_unreachable("unknown situation");
} else {
assert(NewName.argSize() == OldName.argSize());
return TypeMemberDiffItemSubKind::SimpleReplacement;
}
}

void swift::ide::api::TypeMemberDiffItem::describe(llvm::raw_ostream &os) {
os << "#ifndef " << head() << "\n";
os << "#define " << head() << "(USR, NEW_TYPE_NAME, NEW_PRINTED_NAME, "
Expand Down Expand Up @@ -274,11 +308,14 @@ serializeDiffItem(llvm::BumpPtrAllocator &Alloc,
}
case APIDiffItemKind::ADK_TypeMemberDiffItem: {
Optional<uint8_t> SelfIndexShort;
Optional<uint8_t> RemovedIndexShort;
if (SelfIndex)
SelfIndexShort = SelfIndex.getValue();
if (RemovedIndex)
RemovedIndexShort = RemovedIndex.getValue();
return new (Alloc.Allocate<TypeMemberDiffItem>())
TypeMemberDiffItem(Usr, NewTypeName, NewPrintedName, SelfIndexShort,
OldPrintedName);
RemovedIndexShort, OldPrintedName);
}
case APIDiffItemKind::ADK_NoEscapeFuncParam: {
return new (Alloc.Allocate<NoEscapeFuncParam>())
Expand Down Expand Up @@ -395,6 +432,7 @@ struct swift::ide::api::APIDiffItemStore::Implementation {
llvm::StringMap<std::vector<APIDiffItem*>> Data;
bool PrintUsr;
std::vector<APIDiffItem*> AllItems;
llvm::StringSet<> PrintedUsrs;
void addStorePath(StringRef FileName) {
llvm::MemoryBuffer *pMemBuffer = nullptr;
{
Expand Down Expand Up @@ -428,8 +466,10 @@ struct swift::ide::api::APIDiffItemStore::Implementation {

ArrayRef<APIDiffItem*> swift::ide::api::APIDiffItemStore::
getDiffItems(StringRef Key) const {
if (Impl.PrintUsr)
if (Impl.PrintUsr && !Impl.PrintedUsrs.count(Key)) {
llvm::outs() << Key << "\n";
Impl.PrintedUsrs.insert(Key);
}
return Impl.Data[Key];
}

Expand Down
25 changes: 19 additions & 6 deletions lib/IDE/SwiftSourceDocInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -962,9 +962,14 @@ void swift::ide::getLocationInfo(const ValueDecl *VD,
}
}

std::vector<CharSourceRange> swift::ide::
getCallArgLabelRanges(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind) {
std::vector<CharSourceRange> Ranges;
CharSourceRange CallArgInfo::getEntireCharRange(const SourceManager &SM) const {
return CharSourceRange(SM, LabelRange.getStart(),
Lexer::getLocForEndOfToken(SM, ArgExp->getEndLoc()));
}

std::vector<CallArgInfo> swift::ide::
getCallArgInfo(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind) {
std::vector<CallArgInfo> InfoVec;
if (auto *TE = dyn_cast<TupleExpr>(Arg)) {
size_t ElemIndex = 0;
for (Expr *Elem : TE->getElements()) {
Expand All @@ -978,13 +983,21 @@ getCallArgLabelRanges(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind) {
LabelEnd = LabelStart.getAdvancedLoc(NameIdentifier.getLength());
}

Ranges.push_back(CharSourceRange(SM, LabelStart, LabelEnd));
InfoVec.push_back({Elem, CharSourceRange(SM, LabelStart, LabelEnd)});
++ElemIndex;
}
} else if (auto *PE = dyn_cast<ParenExpr>(Arg)) {
if (PE->getSubExpr())
Ranges.push_back(CharSourceRange(PE->getSubExpr()->getStartLoc(), 0));
if (auto Sub = PE->getSubExpr())
InfoVec.push_back({Sub, CharSourceRange(Sub->getStartLoc(), 0)});
}
return InfoVec;
}

std::vector<CharSourceRange> swift::ide::
getCallArgLabelRanges(SourceManager &SM, Expr *Arg, LabelRangeEndAt EndKind) {
std::vector<CharSourceRange> Ranges;
auto InfoVec = getCallArgInfo(SM, Arg, EndKind);
std::transform(InfoVec.begin(), InfoVec.end(), std::back_inserter(Ranges),
[](CallArgInfo &Info) { return Info.LabelRange; });
return Ranges;
}
4 changes: 3 additions & 1 deletion lib/IDE/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,12 +781,14 @@ void ide::collectModuleNames(StringRef SDKPath,
}
}

DeclNameViewer::DeclNameViewer(StringRef Text) {

DeclNameViewer::DeclNameViewer(StringRef Text): HasParen(false) {
auto ArgStart = Text.find_first_of('(');
if (ArgStart == StringRef::npos) {
BaseName = Text;
return;
}
HasParen = true;
BaseName = Text.substr(0, ArgStart);
auto ArgEnd = Text.find_last_of(')');
assert(ArgEnd != StringRef::npos);
Expand Down
118 changes: 102 additions & 16 deletions lib/Migrator/APIDiffMigratorPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,14 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
return DeclNameViewer();
}


bool isSimpleReplacement(APIDiffItem *Item, std::string &Text) {
if (auto *MD = dyn_cast<TypeMemberDiffItem>(Item)) {
// We need to pull the self if self index is set.
if (MD->selfIndex.hasValue())
return false;
Text = (llvm::Twine(MD->newTypeName) + "." + MD->newPrintedName).str();
return true;
if (MD->Subkind == TypeMemberDiffItemSubKind::SimpleReplacement) {
Text = (llvm::Twine(MD->newTypeName) + "." + MD->getNewName().base()).
str();
return true;
}
}

// Simple rename.
Expand Down Expand Up @@ -319,6 +320,30 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
}
};

void emitRenameLabelChanges(Expr *Arg, DeclNameViewer NewName,
llvm::ArrayRef<unsigned> IgnoreArgIndex) {
unsigned Idx = 0;
auto Ranges = getCallArgLabelRanges(SM, Arg,
LabelRangeEndAt::LabelNameOnly);
for (unsigned I = 0; I < Ranges.size(); I ++) {
if (std::any_of(IgnoreArgIndex.begin(), IgnoreArgIndex.end(),
[I](unsigned Ig) { return Ig == I; }))
continue;
auto LR = Ranges[I];
if (Idx < NewName.argSize()) {
auto Label = NewName.args()[Idx++];

// FIXME: We update only when args are consistently valid.
if (Label != "_") {
if (LR.getByteLength())
Editor.replace(LR, Label);
else
Editor.insert(LR.getStart(), (llvm::Twine(Label) + ":").str());
}
}
}
}

void handleFuncRename(ValueDecl *FD, Expr* FuncRefContainer, Expr *Arg) {
bool IgnoreBase = false;
if (auto View = getFuncRename(FD, IgnoreBase)) {
Expand All @@ -327,17 +352,76 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
Walker.walk(FuncRefContainer);
Editor.replace(Walker.Result, View.base());
}
unsigned Idx = 0;
for (auto LR :getCallArgLabelRanges(SM, Arg,
LabelRangeEndAt::LabelNameOnly)) {
if (Idx < View.argSize()) {
auto Label = View.args()[Idx++];

// FIXME: We update only when args are consistently valid.
if (Label != "_" && LR.getByteLength())
Editor.replace(LR, Label);
}
emitRenameLabelChanges(Arg, View, {});
}
}

bool handleTypeHoist(ValueDecl *FD, CallExpr* Call, Expr *Arg) {
TypeMemberDiffItem *Item = nullptr;
for (auto *I: getRelatedDiffItems(FD)) {
Item = dyn_cast<TypeMemberDiffItem>(I);
if (Item)
break;
}
if (!Item)
return false;
if (Item->Subkind == TypeMemberDiffItemSubKind::SimpleReplacement)
return false;
if (*Item->selfIndex)
return false;
std::vector<CallArgInfo> AllArgs =
getCallArgInfo(SM, Arg, LabelRangeEndAt::LabelNameOnly);
if (!AllArgs.size())
return false;
DeclNameViewer NewName = Item->getNewName();
llvm::SmallVector<unsigned, 2> IgnoredArgIndices;
IgnoredArgIndices.push_back(*Item->selfIndex);
if (auto RI = Item->removedIndex)
IgnoredArgIndices.push_back(*RI);
emitRenameLabelChanges(Arg, NewName, IgnoredArgIndices);
auto *SelfExpr = AllArgs[0].ArgExp;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this assume SelfIndex is 0? Would an assert be worthwhile?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, line 370 will return if SelfIndex is not 0. Current transformation mechanism may have limitation to handle non-zero selfindex. Fortunately, we don't see any of them in real frameworks.


// Remove the global function name: "Foo(a, b..." to "a, b..."
Editor.remove(CharSourceRange(SM, Call->getStartLoc(),
SelfExpr->getStartLoc()));

std::string MemberFuncBase;
if (Item->Subkind == TypeMemberDiffItemSubKind::HoistSelfAndUseProperty)
MemberFuncBase = (llvm::Twine(".") + Item->getNewName().base()).str();
else
MemberFuncBase = (llvm::Twine(".") + Item->getNewName().base() + "(").str();

if (AllArgs.size() > 1) {
Editor.replace(CharSourceRange(SM, Lexer::getLocForEndOfToken(SM,
SelfExpr->getEndLoc()), AllArgs[1].LabelRange.getStart()),
MemberFuncBase);
} else {
Editor.insert(Lexer::getLocForEndOfToken(SM, SelfExpr->getEndLoc()),
MemberFuncBase);
}

switch (Item->Subkind) {
case TypeMemberDiffItemSubKind::SimpleReplacement:
llvm_unreachable("should be handled elsewhere");
case TypeMemberDiffItemSubKind::HoistSelfOnly:
// we are done here.
return true;
case TypeMemberDiffItemSubKind::HoistSelfAndRemoveParam: {
unsigned RI = *Item->removedIndex;
CallArgInfo &ToRemove = AllArgs[RI];
if (AllArgs.size() == RI + 1) {
Editor.remove(ToRemove.getEntireCharRange(SM));
} else {
CallArgInfo &AfterToRemove = AllArgs[RI + 1];
Editor.remove(CharSourceRange(SM, ToRemove.LabelRange.getStart(),
AfterToRemove.LabelRange.getStart()));
}
return true;
}
case TypeMemberDiffItemSubKind::HoistSelfAndUseProperty:
// Remove ).
Editor.remove(Arg->getEndLoc());
return true;
}
}

Expand Down Expand Up @@ -380,8 +464,10 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
auto Args = CE->getArg();
switch (Fn->getKind()) {
case ExprKind::DeclRef: {
if (auto FD = Fn->getReferencedDecl().getDecl())
if (auto FD = Fn->getReferencedDecl().getDecl()) {
handleFuncRename(FD, Fn, Args);
handleTypeHoist(FD, CE, Args);
}
break;
}
case ExprKind::DotSyntaxCall: {
Expand Down
Loading