@@ -625,29 +625,54 @@ static const ValueDecl *getRelatedSystemDecl(const ValueDecl *VD) {
625
625
return nullptr ;
626
626
}
627
627
628
- static Optional<RefactoringKind>
629
- getAvailableRenameForDecl (const ValueDecl *VD,
630
- Optional<RenameRefInfo> RefInfo) {
631
- SmallVector<RenameAvailabilityInfo, 2 > Infos;
632
- collectRenameAvailabilityInfo (VD, RefInfo, Infos);
633
- for (auto &Info : Infos) {
634
- if (Info.AvailableKind == RenameAvailableKind::Available)
635
- return Info.Kind ;
628
+ struct RenameInfo {
629
+ ValueDecl *VD;
630
+ RenameAvailabilityInfo Availability;
631
+ };
632
+
633
+ // / Given a cursor, return the decl and its rename availability. \c None if
634
+ // / the cursor did not resolve to a decl or it resolved to a decl that we do
635
+ // / not allow renaming on.
636
+ static Optional<RenameInfo> getRenameInfo (ResolvedCursorInfoPtr cursorInfo) {
637
+ auto valueCursor = dyn_cast<ResolvedValueRefCursorInfo>(cursorInfo);
638
+ if (!valueCursor)
639
+ return None;
640
+
641
+ ValueDecl *VD = valueCursor->typeOrValue ();
642
+ if (!VD)
643
+ return None;
644
+
645
+ Optional<RenameRefInfo> refInfo;
646
+ if (!valueCursor->getShorthandShadowedDecls ().empty ()) {
647
+ // Find the outermost decl for a shorthand if let/closure capture
648
+ VD = valueCursor->getShorthandShadowedDecls ().back ();
649
+ } else if (valueCursor->isRef ()) {
650
+ refInfo = {valueCursor->getSourceFile (), valueCursor->getLoc (),
651
+ valueCursor->isKeywordArgument ()};
636
652
}
637
- return None;
653
+
654
+ Optional<RenameAvailabilityInfo> info = renameAvailabilityInfo (VD, refInfo);
655
+ if (!info)
656
+ return None;
657
+
658
+ return RenameInfo{VD, *info};
638
659
}
639
660
640
661
class RenameRangeCollector : public IndexDataConsumer {
641
662
public:
642
663
RenameRangeCollector (StringRef USR, StringRef newName)
643
- : USR(USR.str()) , newName(newName.str() ) {}
664
+ : USR(USR) , newName(newName) {}
644
665
645
666
RenameRangeCollector (const ValueDecl *D, StringRef newName)
646
- : newName(newName.str()) {
647
- llvm::raw_string_ostream OS (USR);
667
+ : newName(newName) {
668
+ SmallString<64 > SS;
669
+ llvm::raw_svector_ostream OS (SS);
648
670
printValueDeclUSR (D, OS);
671
+ USR = stringStorage.copyString (SS.str ());
649
672
}
650
673
674
+ RenameRangeCollector (RenameRangeCollector &&collector) = default ;
675
+
651
676
ArrayRef<RenameLoc> results () const { return locations; }
652
677
653
678
private:
@@ -689,8 +714,8 @@ class RenameRangeCollector : public IndexDataConsumer {
689
714
StringRef NewName);
690
715
691
716
private:
692
- std::string USR;
693
- std::string newName;
717
+ StringRef USR;
718
+ StringRef newName;
694
719
StringScratchSpace stringStorage;
695
720
std::vector<RenameLoc> locations;
696
721
};
@@ -845,29 +870,14 @@ class RefactoringAction##KIND: public RangeBasedRefactoringAction { \
845
870
846
871
bool RefactoringActionLocalRename::isApplicable (
847
872
ResolvedCursorInfoPtr CursorInfo, DiagnosticEngine &Diag) {
848
- auto ValueRefInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
849
- if (!ValueRefInfo)
850
- return false ;
851
-
852
- Optional<RenameRefInfo> RefInfo;
853
- if (ValueRefInfo->isRef ())
854
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
855
- ValueRefInfo->isKeywordArgument ()};
856
-
857
- auto RenameOp = getAvailableRenameForDecl (ValueRefInfo->getValueD (), RefInfo);
858
- return RenameOp.has_value () &&
859
- RenameOp.value () == RefactoringKind::LocalRename;
873
+ Optional<RenameInfo> Info = getRenameInfo (CursorInfo);
874
+ return Info &&
875
+ Info->Availability .AvailableKind == RenameAvailableKind::Available &&
876
+ Info->Availability .Kind == RefactoringKind::LocalRename;
860
877
}
861
878
862
- static void analyzeRenameScope (ValueDecl *VD, Optional<RenameRefInfo> RefInfo,
863
- DiagnosticEngine &Diags,
879
+ static void analyzeRenameScope (ValueDecl *VD,
864
880
SmallVectorImpl<DeclContext *> &Scopes) {
865
- Scopes.clear ();
866
- if (!getAvailableRenameForDecl (VD, RefInfo).has_value ()) {
867
- Diags.diagnose (SourceLoc (), diag::value_decl_no_loc, VD->getName ());
868
- return ;
869
- }
870
-
871
881
auto *Scope = VD->getDeclContext ();
872
882
// There may be sibling decls that the renamed symbol is visible from.
873
883
switch (Scope->getContextKind ()) {
@@ -892,6 +902,53 @@ static void analyzeRenameScope(ValueDecl *VD, Optional<RenameRefInfo> RefInfo,
892
902
Scopes.push_back (Scope);
893
903
}
894
904
905
+ static Optional<RenameRangeCollector> localRenames (SourceFile *SF,
906
+ SourceLoc startLoc,
907
+ StringRef preferredName,
908
+ DiagnosticEngine &diags) {
909
+ auto cursorInfo =
910
+ evaluateOrDefault (SF->getASTContext ().evaluator ,
911
+ CursorInfoRequest{CursorInfoOwner (SF, startLoc)},
912
+ new ResolvedCursorInfo ());
913
+
914
+ Optional<RenameInfo> info = getRenameInfo (cursorInfo);
915
+ if (!info) {
916
+ diags.diagnose (startLoc, diag::unresolved_location);
917
+ return None;
918
+ }
919
+
920
+ switch (info->Availability .AvailableKind ) {
921
+ case RenameAvailableKind::Available:
922
+ break ;
923
+ case RenameAvailableKind::Unavailable_system_symbol:
924
+ diags.diagnose (startLoc, diag::decl_is_system_symbol, info->VD ->getName ());
925
+ return None;
926
+ case RenameAvailableKind::Unavailable_has_no_location:
927
+ diags.diagnose (startLoc, diag::value_decl_no_loc, info->VD ->getName ());
928
+ return None;
929
+ case RenameAvailableKind::Unavailable_has_no_name:
930
+ diags.diagnose (startLoc, diag::decl_has_no_name);
931
+ return None;
932
+ case RenameAvailableKind::Unavailable_has_no_accessibility:
933
+ diags.diagnose (startLoc, diag::decl_no_accessibility);
934
+ return None;
935
+ case RenameAvailableKind::Unavailable_decl_from_clang:
936
+ diags.diagnose (startLoc, diag::decl_from_clang);
937
+ return None;
938
+ }
939
+
940
+ SmallVector<DeclContext *, 8 > scopes;
941
+ analyzeRenameScope (info->VD , scopes);
942
+ if (scopes.empty ())
943
+ return None;
944
+
945
+ RenameRangeCollector rangeCollector (info->VD , preferredName);
946
+ for (DeclContext *DC : scopes)
947
+ indexDeclContext (DC, rangeCollector);
948
+
949
+ return rangeCollector;
950
+ }
951
+
895
952
bool RefactoringActionLocalRename::performChange () {
896
953
if (StartLoc.isInvalid ()) {
897
954
DiagEngine.diagnose (SourceLoc (), diag::invalid_location);
@@ -906,40 +963,16 @@ bool RefactoringActionLocalRename::performChange() {
906
963
MD->getNameStr ());
907
964
return true ;
908
965
}
909
- CursorInfo =
910
- evaluateOrDefault (TheFile->getASTContext ().evaluator ,
911
- CursorInfoRequest{CursorInfoOwner (TheFile, StartLoc)},
912
- new ResolvedCursorInfo ());
913
- auto ValueRefCursorInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
914
- if (ValueRefCursorInfo && ValueRefCursorInfo->getValueD ()) {
915
- ValueDecl *VD = ValueRefCursorInfo->typeOrValue ();
916
- // The index always uses the outermost shadow for references
917
- if (!ValueRefCursorInfo->getShorthandShadowedDecls ().empty ()) {
918
- VD = ValueRefCursorInfo->getShorthandShadowedDecls ().back ();
919
- }
920
-
921
- SmallVector<DeclContext *, 8 > Scopes;
922
-
923
- Optional<RenameRefInfo> RefInfo;
924
- if (ValueRefCursorInfo->isRef ())
925
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
926
- ValueRefCursorInfo->isKeywordArgument ()};
927
966
928
- analyzeRenameScope (VD, RefInfo, DiagEngine, Scopes);
929
- if (Scopes.empty ())
930
- return true ;
931
- RenameRangeCollector rangeCollector (VD, PreferredName);
932
- for (DeclContext *DC : Scopes)
933
- indexDeclContext (DC, rangeCollector);
934
-
935
- auto consumers = DiagEngine.takeConsumers ();
936
- assert (consumers.size () == 1 );
937
- return syntacticRename (TheFile, rangeCollector.results (), EditConsumer,
938
- *consumers[0 ]);
939
- } else {
940
- DiagEngine.diagnose (StartLoc, diag::unresolved_location);
967
+ Optional<RenameRangeCollector> rangeCollector =
968
+ localRenames (TheFile, StartLoc, PreferredName, DiagEngine);
969
+ if (!rangeCollector)
941
970
return true ;
942
- }
971
+
972
+ auto consumers = DiagEngine.takeConsumers ();
973
+ assert (consumers.size () == 1 );
974
+ return syntacticRename (TheFile, rangeCollector->results (), EditConsumer,
975
+ *consumers[0 ]);
943
976
}
944
977
945
978
StringRef getDefaultPreferredName (RefactoringKind Kind) {
@@ -8805,9 +8838,9 @@ accept(SourceManager &SM, RegionType RegionType,
8805
8838
}
8806
8839
}
8807
8840
8808
- void swift::ide::collectRenameAvailabilityInfo (
8809
- const ValueDecl *VD, Optional<RenameRefInfo> RefInfo ,
8810
- SmallVectorImpl<RenameAvailabilityInfo> &Infos ) {
8841
+ Optional<RenameAvailabilityInfo>
8842
+ swift::ide::renameAvailabilityInfo ( const ValueDecl *VD,
8843
+ Optional<RenameRefInfo> RefInfo ) {
8811
8844
RenameAvailableKind AvailKind = RenameAvailableKind::Available;
8812
8845
if (getRelatedSystemDecl (VD)){
8813
8846
AvailKind = RenameAvailableKind::Unavailable_system_symbol;
@@ -8822,22 +8855,22 @@ void swift::ide::collectRenameAvailabilityInfo(
8822
8855
if (isa<AbstractFunctionDecl>(VD)) {
8823
8856
// Disallow renaming accessors.
8824
8857
if (isa<AccessorDecl>(VD))
8825
- return ;
8858
+ return None ;
8826
8859
8827
8860
// Disallow renaming deinit.
8828
8861
if (isa<DestructorDecl>(VD))
8829
- return ;
8862
+ return None ;
8830
8863
8831
8864
// Disallow renaming init with no arguments.
8832
8865
if (auto CD = dyn_cast<ConstructorDecl>(VD)) {
8833
8866
if (!CD->getParameters ()->size ())
8834
- return ;
8867
+ return None ;
8835
8868
8836
8869
if (RefInfo && !RefInfo->IsArgLabel ) {
8837
8870
NameMatcher Matcher (*(RefInfo->SF ));
8838
8871
auto Resolved = Matcher.resolve ({RefInfo->Loc , /* ResolveArgs*/ true });
8839
8872
if (Resolved.LabelRanges .empty ())
8840
- return ;
8873
+ return None ;
8841
8874
}
8842
8875
}
8843
8876
@@ -8847,30 +8880,27 @@ void swift::ide::collectRenameAvailabilityInfo(
8847
8880
// whether it's an instance method, so we do the same here for now.
8848
8881
if (FD->getBaseIdentifier () == FD->getASTContext ().Id_callAsFunction ) {
8849
8882
if (!FD->getParameters ()->size ())
8850
- return ;
8883
+ return None ;
8851
8884
8852
8885
if (RefInfo && !RefInfo->IsArgLabel ) {
8853
8886
NameMatcher Matcher (*(RefInfo->SF ));
8854
8887
auto Resolved = Matcher.resolve ({RefInfo->Loc , /* ResolveArgs*/ true });
8855
8888
if (Resolved.LabelRanges .empty ())
8856
- return ;
8889
+ return None ;
8857
8890
}
8858
8891
}
8859
8892
}
8860
8893
}
8861
8894
8862
8895
// Always return local rename for parameters.
8863
8896
// FIXME: if the cursor is on the argument, we should return global rename.
8864
- if (isa<ParamDecl>(VD)) {
8865
- Infos.emplace_back (RefactoringKind::LocalRename, AvailKind);
8866
- return ;
8867
- }
8897
+ if (isa<ParamDecl>(VD))
8898
+ return RenameAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
8868
8899
8869
8900
// If the indexer considers VD a global symbol, then we apply global rename.
8870
8901
if (index::isLocalSymbol (VD))
8871
- Infos.emplace_back (RefactoringKind::LocalRename, AvailKind);
8872
- else
8873
- Infos.emplace_back (RefactoringKind::GlobalRename, AvailKind);
8902
+ return RenameAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
8903
+ return RenameAvailabilityInfo{RefactoringKind::GlobalRename, AvailKind};
8874
8904
}
8875
8905
8876
8906
void swift::ide::collectAvailableRefactorings (
@@ -8880,27 +8910,10 @@ void swift::ide::collectAvailableRefactorings(
8880
8910
CursorInfo->getSourceFile ()->getASTContext ().SourceMgr );
8881
8911
8882
8912
if (!ExcludeRename) {
8883
- if (RefactoringActionLocalRename::isApplicable (CursorInfo, DiagEngine))
8884
- Kinds.push_back (RefactoringKind::LocalRename);
8885
-
8886
- switch (CursorInfo->getKind ()) {
8887
- case CursorInfoKind::ModuleRef:
8888
- case CursorInfoKind::Invalid:
8889
- case CursorInfoKind::StmtStart:
8890
- case CursorInfoKind::ExprStart:
8891
- break ;
8892
- case CursorInfoKind::ValueRef: {
8893
- auto ValueRefInfo = cast<ResolvedValueRefCursorInfo>(CursorInfo);
8894
- Optional<RenameRefInfo> RefInfo;
8895
- if (ValueRefInfo->isRef ())
8896
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
8897
- ValueRefInfo->isKeywordArgument ()};
8898
- auto RenameOp =
8899
- getAvailableRenameForDecl (ValueRefInfo->getValueD (), RefInfo);
8900
- if (RenameOp.has_value () &&
8901
- RenameOp.value () == RefactoringKind::GlobalRename)
8902
- Kinds.push_back (RenameOp.value ());
8903
- }
8913
+ if (auto Info = getRenameInfo (CursorInfo)) {
8914
+ if (Info->Availability .AvailableKind == RenameAvailableKind::Available) {
8915
+ Kinds.push_back (Info->Availability .Kind );
8916
+ }
8904
8917
}
8905
8918
}
8906
8919
@@ -9106,29 +9119,11 @@ int swift::ide::findLocalRenameRanges(
9106
9119
Diags.addConsumer (DiagConsumer);
9107
9120
9108
9121
auto StartLoc = Lexer::getLocForStartOfToken (SM, Range.getStart (SM));
9109
- ResolvedCursorInfoPtr CursorInfo =
9110
- evaluateOrDefault (SF->getASTContext ().evaluator ,
9111
- CursorInfoRequest{CursorInfoOwner (SF, StartLoc)},
9112
- new ResolvedCursorInfo ());
9113
- auto ValueRefCursorInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
9114
- if (!ValueRefCursorInfo || !ValueRefCursorInfo->getValueD ()) {
9115
- Diags.diagnose (StartLoc, diag::unresolved_location);
9116
- return true ;
9117
- }
9118
- ValueDecl *VD = ValueRefCursorInfo->typeOrValue ();
9119
- Optional<RenameRefInfo> RefInfo;
9120
- if (ValueRefCursorInfo->isRef ())
9121
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
9122
- ValueRefCursorInfo->isKeywordArgument ()};
9123
-
9124
- llvm::SmallVector<DeclContext *, 8 > Scopes;
9125
- analyzeRenameScope (VD, RefInfo, Diags, Scopes);
9126
- if (Scopes.empty ())
9122
+ Optional<RenameRangeCollector> RangeCollector =
9123
+ localRenames (SF, StartLoc, StringRef (), Diags);
9124
+ if (!RangeCollector)
9127
9125
return true ;
9128
- RenameRangeCollector RangeCollector (VD, StringRef ());
9129
- for (DeclContext *DC : Scopes)
9130
- indexDeclContext (DC, RangeCollector);
9131
9126
9132
- return findSyntacticRenameRanges (SF, RangeCollector. results (), RenameConsumer ,
9133
- DiagConsumer);
9127
+ return findSyntacticRenameRanges (SF, RangeCollector-> results (),
9128
+ RenameConsumer, DiagConsumer);
9134
9129
}
0 commit comments