Skip to content

Commit 8f6b7b8

Browse files
committed
[SourceKit] Refactor collection of available refactorings
Update to have a single refactoring collection method for cursor refactorings and another for ranges. The various functions were only needed because of the extra availability information on renames, so just give that to all refactorings.
1 parent df35da4 commit 8f6b7b8

File tree

4 files changed

+140
-181
lines changed

4 files changed

+140
-181
lines changed

include/swift/Refactoring/Refactoring.h

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ struct RenameRangeDetail {
7272
Optional<unsigned> Index;
7373
};
7474

75-
enum class RenameAvailableKind {
75+
enum class RefactorAvailableKind {
7676
Available,
7777
Unavailable_system_symbol,
7878
Unavailable_has_no_location,
@@ -81,14 +81,14 @@ enum class RenameAvailableKind {
8181
Unavailable_decl_from_clang,
8282
};
8383

84-
struct RenameAvailabilityInfo {
84+
struct RefactorAvailabilityInfo {
8585
RefactoringKind Kind;
86-
RenameAvailableKind AvailableKind;
87-
RenameAvailabilityInfo(RefactoringKind Kind,
88-
RenameAvailableKind AvailableKind)
86+
RefactorAvailableKind AvailableKind;
87+
RefactorAvailabilityInfo(RefactoringKind Kind,
88+
RefactorAvailableKind AvailableKind)
8989
: Kind(Kind), AvailableKind(AvailableKind) {}
90-
RenameAvailabilityInfo(RefactoringKind Kind)
91-
: RenameAvailabilityInfo(Kind, RenameAvailableKind::Available) {}
90+
RefactorAvailabilityInfo(RefactoringKind Kind)
91+
: RefactorAvailabilityInfo(Kind, RefactorAvailableKind::Available) {}
9292
};
9393

9494
class FindRenameRangesConsumer {
@@ -112,7 +112,7 @@ class FindRenameRangesAnnotatingConsumer : public FindRenameRangesConsumer {
112112

113113
StringRef getDescriptiveRefactoringKindName(RefactoringKind Kind);
114114

115-
StringRef getDescriptiveRenameUnavailableReason(RenameAvailableKind Kind);
115+
StringRef getDescriptiveRenameUnavailableReason(RefactorAvailableKind Kind);
116116

117117
bool refactorSwiftModule(ModuleDecl *M, RefactoringOptions Opts,
118118
SourceEditConsumer &EditConsumer,
@@ -131,25 +131,12 @@ int findLocalRenameRanges(SourceFile *SF, RangeConfig Range,
131131
FindRenameRangesConsumer &RenameConsumer,
132132
DiagnosticConsumer &DiagConsumer);
133133

134-
void collectAvailableRefactorings(
134+
SmallVector<RefactorAvailabilityInfo> collectRefactorings(
135135
SourceFile *SF, RangeConfig Range, bool &RangeStartMayNeedRename,
136-
llvm::SmallVectorImpl<RefactoringKind> &Kinds,
137136
llvm::ArrayRef<DiagnosticConsumer *> DiagConsumers);
138137

139-
void collectAvailableRefactorings(ResolvedCursorInfoPtr CursorInfo,
140-
llvm::SmallVectorImpl<RefactoringKind> &Kinds,
141-
bool ExcludeRename);
142-
143-
/// Stores information about the reference that rename availability is being
144-
/// queried on.
145-
struct RenameRefInfo {
146-
SourceFile *SF; ///< The source file containing the reference.
147-
SourceLoc Loc; ///< The reference's source location.
148-
bool IsArgLabel; ///< Whether Loc is on an arg label, rather than base name.
149-
};
150-
151-
Optional<RenameAvailabilityInfo>
152-
renameAvailabilityInfo(const ValueDecl *VD, Optional<RenameRefInfo> RefInfo);
138+
SmallVector<RefactorAvailabilityInfo> collectRefactorings(ResolvedCursorInfoPtr CursorInfo,
139+
bool ExcludeRename);
153140

154141
} // namespace ide
155142
} // namespace swift

lib/Refactoring/Refactoring.cpp

Lines changed: 107 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -625,11 +625,83 @@ static const ValueDecl *getRelatedSystemDecl(const ValueDecl *VD) {
625625
return nullptr;
626626
}
627627

628+
/// Stores information about the reference that rename availability is being
629+
/// queried on.
630+
struct RenameRefInfo {
631+
SourceFile *SF; ///< The source file containing the reference.
632+
SourceLoc Loc; ///< The reference's source location.
633+
bool IsArgLabel; ///< Whether Loc is on an arg label, rather than base name.
634+
};
635+
628636
struct RenameInfo {
629637
ValueDecl *VD;
630-
RenameAvailabilityInfo Availability;
638+
RefactorAvailabilityInfo Availability;
631639
};
632640

641+
static Optional<RefactorAvailabilityInfo>
642+
renameAvailabilityInfo(const ValueDecl *VD, Optional<RenameRefInfo> RefInfo) {
643+
RefactorAvailableKind AvailKind = RefactorAvailableKind::Available;
644+
if (getRelatedSystemDecl(VD)){
645+
AvailKind = RefactorAvailableKind::Unavailable_system_symbol;
646+
} else if (VD->getClangDecl()) {
647+
AvailKind = RefactorAvailableKind::Unavailable_decl_from_clang;
648+
} else if (VD->getLoc().isInvalid()) {
649+
AvailKind = RefactorAvailableKind::Unavailable_has_no_location;
650+
} else if (!VD->hasName()) {
651+
AvailKind = RefactorAvailableKind::Unavailable_has_no_name;
652+
}
653+
654+
if (isa<AbstractFunctionDecl>(VD)) {
655+
// Disallow renaming accessors.
656+
if (isa<AccessorDecl>(VD))
657+
return None;
658+
659+
// Disallow renaming deinit.
660+
if (isa<DestructorDecl>(VD))
661+
return None;
662+
663+
// Disallow renaming init with no arguments.
664+
if (auto CD = dyn_cast<ConstructorDecl>(VD)) {
665+
if (!CD->getParameters()->size())
666+
return None;
667+
668+
if (RefInfo && !RefInfo->IsArgLabel) {
669+
NameMatcher Matcher(*(RefInfo->SF));
670+
auto Resolved = Matcher.resolve({RefInfo->Loc, /*ResolveArgs*/true});
671+
if (Resolved.LabelRanges.empty())
672+
return None;
673+
}
674+
}
675+
676+
// Disallow renaming 'callAsFunction' method with no arguments.
677+
if (auto FD = dyn_cast<FuncDecl>(VD)) {
678+
// FIXME: syntactic rename can only decide by checking the spelling, not
679+
// whether it's an instance method, so we do the same here for now.
680+
if (FD->getBaseIdentifier() == FD->getASTContext().Id_callAsFunction) {
681+
if (!FD->getParameters()->size())
682+
return None;
683+
684+
if (RefInfo && !RefInfo->IsArgLabel) {
685+
NameMatcher Matcher(*(RefInfo->SF));
686+
auto Resolved = Matcher.resolve({RefInfo->Loc, /*ResolveArgs*/true});
687+
if (Resolved.LabelRanges.empty())
688+
return None;
689+
}
690+
}
691+
}
692+
}
693+
694+
// Always return local rename for parameters.
695+
// FIXME: if the cursor is on the argument, we should return global rename.
696+
if (isa<ParamDecl>(VD))
697+
return RefactorAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
698+
699+
// If the indexer considers VD a global symbol, then we apply global rename.
700+
if (index::isLocalSymbol(VD))
701+
return RefactorAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
702+
return RefactorAvailabilityInfo{RefactoringKind::GlobalRename, AvailKind};
703+
}
704+
633705
/// Given a cursor, return the decl and its rename availability. \c None if
634706
/// the cursor did not resolve to a decl or it resolved to a decl that we do
635707
/// not allow renaming on.
@@ -651,7 +723,7 @@ static Optional<RenameInfo> getRenameInfo(ResolvedCursorInfoPtr cursorInfo) {
651723
valueCursor->isKeywordArgument()};
652724
}
653725

654-
Optional<RenameAvailabilityInfo> info = renameAvailabilityInfo(VD, refInfo);
726+
Optional<RefactorAvailabilityInfo> info = renameAvailabilityInfo(VD, refInfo);
655727
if (!info)
656728
return None;
657729

@@ -872,7 +944,7 @@ bool RefactoringActionLocalRename::isApplicable(
872944
ResolvedCursorInfoPtr CursorInfo, DiagnosticEngine &Diag) {
873945
Optional<RenameInfo> Info = getRenameInfo(CursorInfo);
874946
return Info &&
875-
Info->Availability.AvailableKind == RenameAvailableKind::Available &&
947+
Info->Availability.AvailableKind == RefactorAvailableKind::Available &&
876948
Info->Availability.Kind == RefactoringKind::LocalRename;
877949
}
878950

@@ -918,21 +990,21 @@ static Optional<RenameRangeCollector> localRenames(SourceFile *SF,
918990
}
919991

920992
switch (info->Availability.AvailableKind) {
921-
case RenameAvailableKind::Available:
993+
case RefactorAvailableKind::Available:
922994
break;
923-
case RenameAvailableKind::Unavailable_system_symbol:
995+
case RefactorAvailableKind::Unavailable_system_symbol:
924996
diags.diagnose(startLoc, diag::decl_is_system_symbol, info->VD->getName());
925997
return None;
926-
case RenameAvailableKind::Unavailable_has_no_location:
998+
case RefactorAvailableKind::Unavailable_has_no_location:
927999
diags.diagnose(startLoc, diag::value_decl_no_loc, info->VD->getName());
9281000
return None;
929-
case RenameAvailableKind::Unavailable_has_no_name:
1001+
case RefactorAvailableKind::Unavailable_has_no_name:
9301002
diags.diagnose(startLoc, diag::decl_has_no_name);
9311003
return None;
932-
case RenameAvailableKind::Unavailable_has_no_accessibility:
1004+
case RefactorAvailableKind::Unavailable_has_no_accessibility:
9331005
diags.diagnose(startLoc, diag::decl_no_accessibility);
9341006
return None;
935-
case RenameAvailableKind::Unavailable_decl_from_clang:
1007+
case RefactorAvailableKind::Unavailable_decl_from_clang:
9361008
diags.diagnose(startLoc, diag::decl_from_clang);
9371009
return None;
9381010
}
@@ -3028,9 +3100,8 @@ bool RefactoringActionFillProtocolStub::performChange() {
30283100
return false;
30293101
}
30303102

3031-
static void collectAvailableRefactoringsAtCursor(
3103+
static SmallVector<RefactorAvailabilityInfo> collectRefactoringsAtCursor(
30323104
SourceFile *SF, unsigned Line, unsigned Column,
3033-
SmallVectorImpl<RefactoringKind> &Kinds,
30343105
ArrayRef<DiagnosticConsumer *> DiagConsumers) {
30353106
// Prepare the tool box.
30363107
ASTContext &Ctx = SF->getASTContext();
@@ -3040,14 +3111,14 @@ static void collectAvailableRefactoringsAtCursor(
30403111
[&](DiagnosticConsumer *Con) { DiagEngine.addConsumer(*Con); });
30413112
SourceLoc Loc = SM.getLocForLineCol(SF->getBufferID().value(), Line, Column);
30423113
if (Loc.isInvalid())
3043-
return;
3114+
return {};
30443115

30453116
ResolvedCursorInfoPtr Tok =
30463117
evaluateOrDefault(SF->getASTContext().evaluator,
30473118
CursorInfoRequest{CursorInfoOwner(
30483119
SF, Lexer::getLocForStartOfToken(SM, Loc))},
30493120
new ResolvedCursorInfo());
3050-
collectAvailableRefactorings(Tok, Kinds, /*Exclude rename*/ false);
3121+
return collectRefactorings(Tok, /*ExcludeRename=*/false);
30513122
}
30523123

30533124
static EnumDecl* getEnumDeclFromSwitchStmt(SwitchStmt *SwitchS) {
@@ -8753,19 +8824,19 @@ getDescriptiveRefactoringKindName(RefactoringKind Kind) {
87538824
}
87548825

87558826
StringRef swift::ide::
8756-
getDescriptiveRenameUnavailableReason(RenameAvailableKind Kind) {
8827+
getDescriptiveRenameUnavailableReason(RefactorAvailableKind Kind) {
87578828
switch(Kind) {
8758-
case RenameAvailableKind::Available:
8829+
case RefactorAvailableKind::Available:
87598830
return "";
8760-
case RenameAvailableKind::Unavailable_system_symbol:
8831+
case RefactorAvailableKind::Unavailable_system_symbol:
87618832
return "symbol from system module cannot be renamed";
8762-
case RenameAvailableKind::Unavailable_has_no_location:
8833+
case RefactorAvailableKind::Unavailable_has_no_location:
87638834
return "symbol without a declaration location cannot be renamed";
8764-
case RenameAvailableKind::Unavailable_has_no_name:
8835+
case RefactorAvailableKind::Unavailable_has_no_name:
87658836
return "cannot find the name of the symbol";
8766-
case RenameAvailableKind::Unavailable_has_no_accessibility:
8837+
case RefactorAvailableKind::Unavailable_has_no_accessibility:
87678838
return "cannot decide the accessibility of the symbol";
8768-
case RenameAvailableKind::Unavailable_decl_from_clang:
8839+
case RefactorAvailableKind::Unavailable_decl_from_clang:
87698840
return "cannot rename a Clang symbol from its Swift reference";
87708841
}
87718842
llvm_unreachable("unhandled kind");
@@ -8838,100 +8909,34 @@ accept(SourceManager &SM, RegionType RegionType,
88388909
}
88398910
}
88408911

8841-
Optional<RenameAvailabilityInfo>
8842-
swift::ide::renameAvailabilityInfo(const ValueDecl *VD,
8843-
Optional<RenameRefInfo> RefInfo) {
8844-
RenameAvailableKind AvailKind = RenameAvailableKind::Available;
8845-
if (getRelatedSystemDecl(VD)){
8846-
AvailKind = RenameAvailableKind::Unavailable_system_symbol;
8847-
} else if (VD->getClangDecl()) {
8848-
AvailKind = RenameAvailableKind::Unavailable_decl_from_clang;
8849-
} else if (VD->getLoc().isInvalid()) {
8850-
AvailKind = RenameAvailableKind::Unavailable_has_no_location;
8851-
} else if (!VD->hasName()) {
8852-
AvailKind = RenameAvailableKind::Unavailable_has_no_name;
8853-
}
8854-
8855-
if (isa<AbstractFunctionDecl>(VD)) {
8856-
// Disallow renaming accessors.
8857-
if (isa<AccessorDecl>(VD))
8858-
return None;
8859-
8860-
// Disallow renaming deinit.
8861-
if (isa<DestructorDecl>(VD))
8862-
return None;
8863-
8864-
// Disallow renaming init with no arguments.
8865-
if (auto CD = dyn_cast<ConstructorDecl>(VD)) {
8866-
if (!CD->getParameters()->size())
8867-
return None;
8868-
8869-
if (RefInfo && !RefInfo->IsArgLabel) {
8870-
NameMatcher Matcher(*(RefInfo->SF));
8871-
auto Resolved = Matcher.resolve({RefInfo->Loc, /*ResolveArgs*/true});
8872-
if (Resolved.LabelRanges.empty())
8873-
return None;
8874-
}
8875-
}
8876-
8877-
// Disallow renaming 'callAsFunction' method with no arguments.
8878-
if (auto FD = dyn_cast<FuncDecl>(VD)) {
8879-
// FIXME: syntactic rename can only decide by checking the spelling, not
8880-
// whether it's an instance method, so we do the same here for now.
8881-
if (FD->getBaseIdentifier() == FD->getASTContext().Id_callAsFunction) {
8882-
if (!FD->getParameters()->size())
8883-
return None;
8884-
8885-
if (RefInfo && !RefInfo->IsArgLabel) {
8886-
NameMatcher Matcher(*(RefInfo->SF));
8887-
auto Resolved = Matcher.resolve({RefInfo->Loc, /*ResolveArgs*/true});
8888-
if (Resolved.LabelRanges.empty())
8889-
return None;
8890-
}
8891-
}
8892-
}
8893-
}
8912+
SmallVector<RefactorAvailabilityInfo> swift::ide::collectRefactorings(
8913+
ResolvedCursorInfoPtr CursorInfo, bool ExcludeRename) {
8914+
SmallVector<RefactorAvailabilityInfo, 8> Infos;
88948915

8895-
// Always return local rename for parameters.
8896-
// FIXME: if the cursor is on the argument, we should return global rename.
8897-
if (isa<ParamDecl>(VD))
8898-
return RenameAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
8899-
8900-
// If the indexer considers VD a global symbol, then we apply global rename.
8901-
if (index::isLocalSymbol(VD))
8902-
return RenameAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
8903-
return RenameAvailabilityInfo{RefactoringKind::GlobalRename, AvailKind};
8904-
}
8905-
8906-
void swift::ide::collectAvailableRefactorings(
8907-
ResolvedCursorInfoPtr CursorInfo, SmallVectorImpl<RefactoringKind> &Kinds,
8908-
bool ExcludeRename) {
89098916
DiagnosticEngine DiagEngine(
89108917
CursorInfo->getSourceFile()->getASTContext().SourceMgr);
89118918

89128919
if (!ExcludeRename) {
89138920
if (auto Info = getRenameInfo(CursorInfo)) {
8914-
if (Info->Availability.AvailableKind == RenameAvailableKind::Available) {
8915-
Kinds.push_back(Info->Availability.Kind);
8916-
}
8921+
Infos.push_back(std::move(Info->Availability));
89178922
}
89188923
}
89198924

89208925
#define CURSOR_REFACTORING(KIND, NAME, ID) \
89218926
if (RefactoringKind::KIND != RefactoringKind::LocalRename && \
89228927
RefactoringAction##KIND::isApplicable(CursorInfo, DiagEngine)) \
8923-
Kinds.push_back(RefactoringKind::KIND);
8928+
Infos.emplace_back(RefactoringKind::KIND, RefactorAvailableKind::Available);
89248929
#include "swift/Refactoring/RefactoringKinds.def"
8930+
8931+
return Infos;
89258932
}
89268933

8927-
void swift::ide::collectAvailableRefactorings(
8934+
SmallVector<RefactorAvailabilityInfo> swift::ide::collectRefactorings(
89288935
SourceFile *SF, RangeConfig Range, bool &CollectRangeStartRefactorings,
8929-
SmallVectorImpl<RefactoringKind> &Kinds,
89308936
ArrayRef<DiagnosticConsumer *> DiagConsumers) {
8931-
if (Range.Length == 0) {
8932-
return collectAvailableRefactoringsAtCursor(SF, Range.Line, Range.Column,
8933-
Kinds, DiagConsumers);
8934-
}
8937+
if (Range.Length == 0)
8938+
return collectRefactoringsAtCursor(SF, Range.Line, Range.Column, DiagConsumers);
8939+
89358940
// Prepare the tool box.
89368941
ASTContext &Ctx = SF->getASTContext();
89378942
SourceManager &SM = Ctx.SourceMgr;
@@ -8946,15 +8951,19 @@ void swift::ide::collectAvailableRefactorings(
89468951

89478952
bool enableInternalRefactoring = getenv("SWIFT_ENABLE_INTERNAL_REFACTORING_ACTIONS");
89488953

8954+
SmallVector<RefactorAvailabilityInfo, 8> Infos;
8955+
89498956
#define RANGE_REFACTORING(KIND, NAME, ID) \
89508957
if (RefactoringAction##KIND::isApplicable(Result, DiagEngine)) \
8951-
Kinds.push_back(RefactoringKind::KIND);
8958+
Infos.emplace_back(RefactoringKind::KIND, RefactorAvailableKind::Available);
89528959
#define INTERNAL_RANGE_REFACTORING(KIND, NAME, ID) \
89538960
if (enableInternalRefactoring) \
89548961
RANGE_REFACTORING(KIND, NAME, ID)
89558962
#include "swift/Refactoring/RefactoringKinds.def"
89568963

89578964
CollectRangeStartRefactorings = collectRangeStartRefactorings(Result);
8965+
8966+
return Infos;
89588967
}
89598968

89608969
bool swift::ide::

0 commit comments

Comments
 (0)