Skip to content

Commit d84f2d0

Browse files
author
Nathan Hawes
authored
Merge pull request #9084 from nathawes/migrator-api-optional-wrap
[migrator] Add pass for API type changes
2 parents 81c111f + 4ff254d commit d84f2d0

File tree

13 files changed

+737
-92
lines changed

13 files changed

+737
-92
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/Utils.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===--- Utils.h - Index utilities that are generally useful ----*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_INDEX_UTILS_H
14+
#define SWIFT_INDEX_UTILS_H
15+
16+
#include "swift/Basic/LLVM.h"
17+
#include "llvm/ADT/ArrayRef.h"
18+
#include "llvm/ADT/SmallVector.h"
19+
20+
namespace swift {
21+
class ValueDecl;
22+
23+
/// \brief Collect all the protocol requirements that a given declaration can
24+
/// provide default implementations for. VD is a declaration in extension
25+
/// declaration. Scratch is the buffer to collect those protocol
26+
/// requirements.
27+
///
28+
/// \returns the slice of Scratch
29+
ArrayRef<ValueDecl*>
30+
canDeclProvideDefaultImplementationFor(ValueDecl* VD,
31+
llvm::SmallVectorImpl<ValueDecl*> &Scratch);
32+
33+
/// \brief Get decls that the given decl overrides, protocol requirements that
34+
/// it serves as a default implementation of, and optionally protocol
35+
/// requirements it satisfies in a conforming class
36+
std::vector<ValueDecl*>
37+
getOverriddenDecls(ValueDecl *VD, bool IncludeProtocolRequirements = true,
38+
bool Transitive = false);
39+
40+
} // end namespace swift
41+
#endif // SWIFT_INDEX_UTILS_H

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);

include/swift/Sema/IDETypeChecking.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,6 @@ namespace swift {
4949
void collectDefaultImplementationForProtocolMembers(ProtocolDecl *PD,
5050
llvm::SmallDenseMap<ValueDecl*, ValueDecl*> &DefaultMap);
5151

52-
/// \brief Collect all the protocol requirements that a given declaration can
53-
/// provide default implementations for. VD is a declaration in extension
54-
/// declaration. Scratch is the buffer to collect those protocol
55-
/// requirements.
56-
///
57-
/// \returns the slice of Scratch
58-
ArrayRef<ValueDecl*> canDeclProvideDefaultImplementationFor(ValueDecl* VD,
59-
llvm::SmallVectorImpl<ValueDecl*> &Scratch);
60-
6152
/// \brief Given an unresolved member E and its parent P, this function tries
6253
/// to infer the type of E.
6354
/// \returns true on success, false on error.

lib/IDE/IDETypeChecking.cpp

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,46 +18,6 @@
1818

1919
using namespace swift;
2020

21-
static Type getContextFreeInterfaceType(ValueDecl *VD) {
22-
if (auto AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
23-
return AFD->getMethodInterfaceType();
24-
}
25-
return VD->getInterfaceType();
26-
}
27-
28-
ArrayRef<ValueDecl*> swift::
29-
canDeclProvideDefaultImplementationFor(ValueDecl* VD,
30-
llvm::SmallVectorImpl<ValueDecl*> &Scratch) {
31-
32-
// Skip decls that don't have valid names.
33-
if (!VD->getFullName())
34-
return {};
35-
36-
// Check if VD is from a protocol extension.
37-
auto P = VD->getDeclContext()->getAsProtocolExtensionContext();
38-
if (!P)
39-
return {};
40-
41-
// Look up all decls in the protocol's inheritance chain for the ones with
42-
// the same name with VD.
43-
ResolvedMemberResult LookupResult =
44-
resolveValueMember(*P->getInnermostDeclContext(),
45-
P->getDeclaredInterfaceType(), VD->getFullName());
46-
47-
auto VDType = getContextFreeInterfaceType(VD);
48-
for (auto Mem : LookupResult.getMemberDecls(InterestedMemberKind::All)) {
49-
if (isa<ProtocolDecl>(Mem->getDeclContext())) {
50-
if (Mem->isProtocolRequirement() &&
51-
getContextFreeInterfaceType(Mem)->isEqual(VDType)) {
52-
// We find a protocol requirement VD can provide default
53-
// implementation for.
54-
Scratch.push_back(Mem);
55-
}
56-
}
57-
}
58-
return Scratch;
59-
}
60-
6121
void swift::
6222
collectDefaultImplementationForProtocolMembers(ProtocolDecl *PD,
6323
llvm::SmallDenseMap<ValueDecl*, ValueDecl*> &DefaultMap) {

lib/Index/Index.cpp

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/Index/Index.h"
14+
#include "swift/Index/Utils.h"
1415

1516
#include "swift/AST/ASTContext.h"
1617
#include "swift/AST/Comment.h"
@@ -663,30 +664,11 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
663664
return false;
664665
}
665666

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

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-
690672
if (auto Parent = getParentDecl()) {
691673
if (auto ParentVD = dyn_cast<ValueDecl>(Parent)) {
692674
SymbolRoleSet RelationsToParent = (SymbolRoleSet)SymbolRole::RelationChildOf;
@@ -1398,6 +1380,73 @@ void IndexSwiftASTWalker::getModuleHash(SourceFileOrModule Mod,
13981380
OS << llvm::APInt(64, code).toString(36, /*Signed=*/false);
13991381
}
14001382

1383+
static Type getContextFreeInterfaceType(ValueDecl *VD) {
1384+
if (auto AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
1385+
return AFD->getMethodInterfaceType();
1386+
}
1387+
return VD->getInterfaceType();
1388+
}
1389+
1390+
ArrayRef<ValueDecl*> swift::
1391+
canDeclProvideDefaultImplementationFor(ValueDecl* VD,
1392+
llvm::SmallVectorImpl<ValueDecl*> &Scratch) {
1393+
1394+
// Skip decls that don't have valid names.
1395+
if (!VD->getFullName())
1396+
return {};
1397+
1398+
// Check if VD is from a protocol extension.
1399+
auto P = VD->getDeclContext()->getAsProtocolExtensionContext();
1400+
if (!P)
1401+
return {};
1402+
1403+
// Look up all decls in the protocol's inheritance chain for the ones with
1404+
// the same name with VD.
1405+
ResolvedMemberResult LookupResult =
1406+
resolveValueMember(*P->getInnermostDeclContext(),
1407+
P->getDeclaredInterfaceType(), VD->getFullName());
1408+
1409+
auto VDType = getContextFreeInterfaceType(VD);
1410+
for (auto Mem : LookupResult.getMemberDecls(InterestedMemberKind::All)) {
1411+
if (isa<ProtocolDecl>(Mem->getDeclContext())) {
1412+
if (Mem->isProtocolRequirement() &&
1413+
getContextFreeInterfaceType(Mem)->isEqual(VDType)) {
1414+
// We find a protocol requirement VD can provide default
1415+
// implementation for.
1416+
Scratch.push_back(Mem);
1417+
}
1418+
}
1419+
}
1420+
return Scratch;
1421+
}
1422+
1423+
std::vector<ValueDecl*> swift::
1424+
getOverriddenDecls(ValueDecl *VD, bool IncludeProtocolRequirements,
1425+
bool Transitive) {
1426+
std::vector<ValueDecl*> results;
1427+
1428+
if (auto Overridden = VD->getOverriddenDecl()) {
1429+
results.push_back(Overridden);
1430+
while (Transitive && (Overridden = Overridden->getOverriddenDecl()))
1431+
results.push_back(Overridden);
1432+
}
1433+
1434+
// Collect the protocol requirements this decl is a default impl for
1435+
llvm::SmallVector<ValueDecl*, 2> Buffer;
1436+
for (auto Req : canDeclProvideDefaultImplementationFor(VD, Buffer)) {
1437+
results.push_back(Req);
1438+
}
1439+
1440+
if (IncludeProtocolRequirements) {
1441+
for (auto Satisfied : VD->getSatisfiedProtocolRequirements()) {
1442+
results.push_back(Satisfied);
1443+
}
1444+
}
1445+
1446+
return results;
1447+
}
1448+
1449+
14011450
//===----------------------------------------------------------------------===//
14021451
// Indexing entry points
14031452
//===----------------------------------------------------------------------===//

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)