Skip to content

Commit 8ad6aa4

Browse files
author
Nathan Hawes
committed
[migrator] Add pass for API type changes
This handles optionality changes and type rewrites in function param and return types and constructor param and failability types. Resolves rdar://problem/31766010
1 parent 06c3c99 commit 8ad6aa4

File tree

11 files changed

+663
-43
lines changed

11 files changed

+663
-43
lines changed

include/swift/IDE/APIDigesterData.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ struct CommonDiffItem: public APIDiffItem {
9595
return DiffKind == NodeAnnotation::Rename ||
9696
DiffKind == NodeAnnotation::ModernizeEnum;
9797
}
98+
99+
bool isTypeChange() const {
100+
switch (DiffKind) {
101+
case NodeAnnotation::WrapOptional:
102+
case NodeAnnotation::UnwrapOptional:
103+
case NodeAnnotation::ImplicitOptionalToOptional:
104+
case NodeAnnotation::OptionalToImplicitOptional:
105+
case NodeAnnotation::WrapImplicitOptional:
106+
case NodeAnnotation::TypeRewritten:
107+
return true;
108+
default:
109+
return false;
110+
}
111+
}
98112
StringRef getNewName() const { assert(isRename()); return RightComment; }
99113
APIDiffItemKind getKind() const override {
100114
return APIDiffItemKind::ADK_CommonDiffItem;

include/swift/Index/Index.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ class ModuleDecl;
2020
class SourceFile;
2121
class DeclContext;
2222

23+
// Get decls that the given decl overrides, protocol requirements that it
24+
// serves as a default implementation of, and optionally (as it is more
25+
// expensive) protocol requirements it satisfies in a conforming class
26+
std::vector<ValueDecl*>
27+
getOverriddenDecls(ValueDecl *VD, bool IncludeProtocolRequirements = true,
28+
bool Transitive = false);
29+
30+
2331
namespace index {
2432

2533
void indexDeclContext(DeclContext *DC, IndexDataConsumer &consumer);

include/swift/Migrator/EditorAdapter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class EditorAdapter {
105105
bool AfterToken = false,
106106
bool BeforePreviousInsertions = false);
107107
bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after);
108+
bool remove(SourceLoc TokenLoc);
108109
bool remove(SourceRange TokenRange);
109110
bool replace(SourceRange TokenRange, StringRef Text);
110111
bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange);

lib/Index/Index.cpp

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -663,30 +663,11 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
663663
return false;
664664
}
665665

666-
if (auto Overridden = D->getOverriddenDecl()) {
667-
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overridden))
666+
for (auto Overriden: getOverriddenDecls(D, /*IncludeProtocolReqs=*/!isSystemModule)) {
667+
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overriden))
668668
return false;
669669
}
670670

671-
{
672-
// Collect the protocol requirements this decl can provide default
673-
// implementations to, and record them as overriding.
674-
llvm::SmallVector<ValueDecl*, 2> Buffer;
675-
for (auto Req : canDeclProvideDefaultImplementationFor(D, Buffer)) {
676-
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Req))
677-
return false;
678-
}
679-
}
680-
681-
// FIXME: This is quite expensive and not worth the cost for indexing purposes
682-
// of system modules. Revisit if this becomes more efficient.
683-
if (!isSystemModule) {
684-
for (auto Conf : D->getSatisfiedProtocolRequirements()) {
685-
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Conf))
686-
return false;
687-
}
688-
}
689-
690671
if (auto Parent = getParentDecl()) {
691672
if (auto ParentVD = dyn_cast<ValueDecl>(Parent)) {
692673
SymbolRoleSet RelationsToParent = (SymbolRoleSet)SymbolRole::RelationChildOf;
@@ -1398,6 +1379,33 @@ void IndexSwiftASTWalker::getModuleHash(SourceFileOrModule Mod,
13981379
OS << llvm::APInt(64, code).toString(36, /*Signed=*/false);
13991380
}
14001381

1382+
std::vector<ValueDecl*> swift::
1383+
getOverriddenDecls(ValueDecl *VD, bool IncludeProtocolRequirements,
1384+
bool Transitive) {
1385+
std::vector<ValueDecl*> results;
1386+
1387+
if (auto Overridden = VD->getOverriddenDecl()) {
1388+
results.push_back(Overridden);
1389+
while (Transitive && (Overridden = Overridden->getOverriddenDecl()))
1390+
results.push_back(Overridden);
1391+
}
1392+
1393+
// Collect the protocol requirements this decl is a default impl for
1394+
llvm::SmallVector<ValueDecl*, 2> Buffer;
1395+
for (auto Req : canDeclProvideDefaultImplementationFor(VD, Buffer)) {
1396+
results.push_back(Req);
1397+
}
1398+
1399+
if (IncludeProtocolRequirements) {
1400+
for (auto Satisfied : VD->getSatisfiedProtocolRequirements()) {
1401+
results.push_back(Satisfied);
1402+
}
1403+
}
1404+
1405+
return results;
1406+
}
1407+
1408+
14011409
//===----------------------------------------------------------------------===//
14021410
// Indexing entry points
14031411
//===----------------------------------------------------------------------===//

lib/Migrator/EditorAdapter.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "swift/Basic/SourceLoc.h"
1414
#include "swift/Basic/SourceManager.h"
1515
#include "swift/Migrator/EditorAdapter.h"
16+
#include "swift/Parse/Lexer.h"
1617
#include "clang/Basic/SourceManager.h"
1718

1819
using namespace swift;
@@ -60,12 +61,27 @@ translateCharSourceRange(CharSourceRange SwiftSourceSourceRange) const {
6061
return clang::CharSourceRange::getCharRange(ClangStartLoc, ClangEndLoc);
6162
}
6263

64+
bool EditorAdapter::insert(SourceLoc Loc, StringRef Text, bool AfterToken,
65+
bool BeforePreviousInsertions) {
66+
// We don't have tokens on the clang side, so handle AfterToken in Swift
67+
if (AfterToken)
68+
Loc = Lexer::getLocForEndOfToken(SwiftSrcMgr, Loc);
69+
70+
auto ClangLoc = translateSourceLoc(Loc);
71+
return Edits.insert(ClangLoc, Text, /*AfterToken=*/false, BeforePreviousInsertions);
72+
}
73+
6374
bool EditorAdapter::insertFromRange(SourceLoc Loc, CharSourceRange Range,
6475
bool AfterToken,
6576
bool BeforePreviousInsertions) {
77+
// We don't have tokens on the clang side, so handle AfterToken in Swift
78+
if (AfterToken)
79+
Loc = Lexer::getLocForEndOfToken(SwiftSrcMgr, Loc);
80+
6681
auto ClangLoc = translateSourceLoc(Loc);
6782
auto ClangCharRange = translateCharSourceRange(Range);
68-
return Edits.insertFromRange(ClangLoc, ClangCharRange, AfterToken,
83+
84+
return Edits.insertFromRange(ClangLoc, ClangCharRange, /*AfterToken=*/false,
6985
BeforePreviousInsertions);
7086
}
7187

@@ -100,32 +116,35 @@ bool EditorAdapter::replaceText(SourceLoc Loc, StringRef Text,
100116
bool EditorAdapter::insertFromRange(SourceLoc Loc, SourceRange TokenRange,
101117
bool AfterToken,
102118
bool BeforePreviousInsertions) {
103-
CharSourceRange CharRange { SwiftSrcMgr, TokenRange.Start, TokenRange.End };
119+
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
104120
return insertFromRange(Loc, CharRange,
105121
AfterToken, BeforePreviousInsertions);
106122
}
107123

108124
bool EditorAdapter::insertWrap(StringRef Before, SourceRange TokenRange,
109125
StringRef After) {
110-
CharSourceRange CharRange { SwiftSrcMgr, TokenRange.Start, TokenRange.End };
126+
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
111127
return insertWrap(Before, CharRange, After);
112128
}
113129

130+
bool EditorAdapter::remove(SourceLoc TokenLoc) {
131+
return remove(Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr,
132+
TokenLoc));
133+
}
134+
114135
bool EditorAdapter::remove(SourceRange TokenRange) {
115-
CharSourceRange CharRange { SwiftSrcMgr, TokenRange.Start, TokenRange.End };
136+
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
116137
return remove(CharRange);
117138
}
118139

119140
bool EditorAdapter::replace(SourceRange TokenRange, StringRef Text) {
120-
CharSourceRange CharRange { SwiftSrcMgr, TokenRange.Start, TokenRange.End };
141+
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr,TokenRange);
121142
return replace(CharRange, Text);
122143
}
123144

124145
bool EditorAdapter::replaceWithInner(SourceRange TokenRange,
125146
SourceRange TokenInnerRange) {
126-
CharSourceRange CharRange { SwiftSrcMgr, TokenRange.Start, TokenRange.End };
127-
CharSourceRange CharInnerRange {
128-
SwiftSrcMgr, TokenInnerRange.Start, TokenInnerRange.End
129-
};
147+
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
148+
auto CharInnerRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenInnerRange);
130149
return replaceWithInner(CharRange, CharInnerRange);
131150
}

lib/Migrator/Migrator.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,15 @@ Migrator::performAFixItMigration() {
125125
}
126126

127127
FixitApplyDiagnosticConsumer FixitApplyConsumer {
128-
InputState->getInputText(),
128+
InputState->getOutputText(),
129129
getInputFilename(),
130130
};
131131
Instance.addDiagnosticConsumer(&FixitApplyConsumer);
132132

133133
Instance.performSema();
134134

135-
StringRef ResultText = InputState->getInputText();
136-
unsigned ResultBufferID = InputState->getInputBufferID();
135+
StringRef ResultText = InputState->getOutputText();
136+
unsigned ResultBufferID = InputState->getOutputBufferID();
137137

138138
if (FixitApplyConsumer.getNumFixitsApplied() > 0) {
139139
SmallString<4096> Scratch;
@@ -145,7 +145,7 @@ Migrator::performAFixItMigration() {
145145
}
146146

147147
return MigrationState::make(MigrationKind::CompilerFixits,
148-
SrcMgr, InputState->getInputBufferID(),
148+
SrcMgr, InputState->getOutputBufferID(),
149149
ResultBufferID);
150150
}
151151

0 commit comments

Comments
 (0)