@@ -616,29 +616,54 @@ static const ValueDecl *getRelatedSystemDecl(const ValueDecl *VD) {
616
616
return nullptr ;
617
617
}
618
618
619
- static Optional<RefactoringKind>
620
- getAvailableRenameForDecl (const ValueDecl *VD,
621
- Optional<RenameRefInfo> RefInfo) {
622
- SmallVector<RenameAvailabilityInfo, 2 > Infos;
623
- collectRenameAvailabilityInfo (VD, RefInfo, Infos);
624
- for (auto &Info : Infos) {
625
- if (Info.AvailableKind == RenameAvailableKind::Available)
626
- return Info.Kind ;
619
+ struct RenameInfo {
620
+ ValueDecl *VD;
621
+ RenameAvailabilityInfo Availability;
622
+ };
623
+
624
+ // / Given a cursor, return the decl and its rename availability. \c None if
625
+ // / the cursor did not resolve to a decl or it resolved to a decl that we do
626
+ // / not allow renaming on.
627
+ static Optional<RenameInfo> getRenameInfo (ResolvedCursorInfoPtr cursorInfo) {
628
+ auto valueCursor = dyn_cast<ResolvedValueRefCursorInfo>(cursorInfo);
629
+ if (!valueCursor)
630
+ return None;
631
+
632
+ ValueDecl *VD = valueCursor->typeOrValue ();
633
+ if (!VD)
634
+ return None;
635
+
636
+ Optional<RenameRefInfo> refInfo;
637
+ if (!valueCursor->getShorthandShadowedDecls ().empty ()) {
638
+ // Find the outermost decl for a shorthand if let/closure capture
639
+ VD = valueCursor->getShorthandShadowedDecls ().back ();
640
+ } else if (valueCursor->isRef ()) {
641
+ refInfo = {valueCursor->getSourceFile (), valueCursor->getLoc (),
642
+ valueCursor->isKeywordArgument ()};
627
643
}
628
- return None;
644
+
645
+ Optional<RenameAvailabilityInfo> info = renameAvailabilityInfo (VD, refInfo);
646
+ if (!info)
647
+ return None;
648
+
649
+ return RenameInfo{VD, *info};
629
650
}
630
651
631
652
class RenameRangeCollector : public IndexDataConsumer {
632
653
public:
633
654
RenameRangeCollector (StringRef USR, StringRef newName)
634
- : USR(USR.str()) , newName(newName.str() ) {}
655
+ : USR(USR) , newName(newName) {}
635
656
636
657
RenameRangeCollector (const ValueDecl *D, StringRef newName)
637
- : newName(newName.str()) {
638
- llvm::raw_string_ostream OS (USR);
658
+ : newName(newName) {
659
+ SmallString<64 > SS;
660
+ llvm::raw_svector_ostream OS (SS);
639
661
printValueDeclUSR (D, OS);
662
+ USR = stringStorage.copyString (SS.str ());
640
663
}
641
664
665
+ RenameRangeCollector (RenameRangeCollector &&collector) = default ;
666
+
642
667
ArrayRef<RenameLoc> results () const { return locations; }
643
668
644
669
private:
@@ -680,8 +705,8 @@ class RenameRangeCollector : public IndexDataConsumer {
680
705
StringRef NewName);
681
706
682
707
private:
683
- std::string USR;
684
- std::string newName;
708
+ StringRef USR;
709
+ StringRef newName;
685
710
StringScratchSpace stringStorage;
686
711
std::vector<RenameLoc> locations;
687
712
};
@@ -836,29 +861,14 @@ class RefactoringAction##KIND: public RangeBasedRefactoringAction { \
836
861
837
862
bool RefactoringActionLocalRename::isApplicable (
838
863
ResolvedCursorInfoPtr CursorInfo, DiagnosticEngine &Diag) {
839
- auto ValueRefInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
840
- if (!ValueRefInfo)
841
- return false ;
842
-
843
- Optional<RenameRefInfo> RefInfo;
844
- if (ValueRefInfo->isRef ())
845
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
846
- ValueRefInfo->isKeywordArgument ()};
847
-
848
- auto RenameOp = getAvailableRenameForDecl (ValueRefInfo->getValueD (), RefInfo);
849
- return RenameOp.has_value () &&
850
- RenameOp.value () == RefactoringKind::LocalRename;
864
+ Optional<RenameInfo> Info = getRenameInfo (CursorInfo);
865
+ return Info &&
866
+ Info->Availability .AvailableKind == RenameAvailableKind::Available &&
867
+ Info->Availability .Kind == RefactoringKind::LocalRename;
851
868
}
852
869
853
- static void analyzeRenameScope (ValueDecl *VD, Optional<RenameRefInfo> RefInfo,
854
- DiagnosticEngine &Diags,
870
+ static void analyzeRenameScope (ValueDecl *VD,
855
871
SmallVectorImpl<DeclContext *> &Scopes) {
856
- Scopes.clear ();
857
- if (!getAvailableRenameForDecl (VD, RefInfo).has_value ()) {
858
- Diags.diagnose (SourceLoc (), diag::value_decl_no_loc, VD->getName ());
859
- return ;
860
- }
861
-
862
872
auto *Scope = VD->getDeclContext ();
863
873
// There may be sibling decls that the renamed symbol is visible from.
864
874
switch (Scope->getContextKind ()) {
@@ -883,6 +893,53 @@ static void analyzeRenameScope(ValueDecl *VD, Optional<RenameRefInfo> RefInfo,
883
893
Scopes.push_back (Scope);
884
894
}
885
895
896
+ static Optional<RenameRangeCollector> localRenames (SourceFile *SF,
897
+ SourceLoc startLoc,
898
+ StringRef preferredName,
899
+ DiagnosticEngine &diags) {
900
+ auto cursorInfo =
901
+ evaluateOrDefault (SF->getASTContext ().evaluator ,
902
+ CursorInfoRequest{CursorInfoOwner (SF, startLoc)},
903
+ new ResolvedCursorInfo ());
904
+
905
+ Optional<RenameInfo> info = getRenameInfo (cursorInfo);
906
+ if (!info) {
907
+ diags.diagnose (startLoc, diag::unresolved_location);
908
+ return None;
909
+ }
910
+
911
+ switch (info->Availability .AvailableKind ) {
912
+ case RenameAvailableKind::Available:
913
+ break ;
914
+ case RenameAvailableKind::Unavailable_system_symbol:
915
+ diags.diagnose (startLoc, diag::decl_is_system_symbol, info->VD ->getName ());
916
+ return None;
917
+ case RenameAvailableKind::Unavailable_has_no_location:
918
+ diags.diagnose (startLoc, diag::value_decl_no_loc, info->VD ->getName ());
919
+ return None;
920
+ case RenameAvailableKind::Unavailable_has_no_name:
921
+ diags.diagnose (startLoc, diag::decl_has_no_name);
922
+ return None;
923
+ case RenameAvailableKind::Unavailable_has_no_accessibility:
924
+ diags.diagnose (startLoc, diag::decl_no_accessibility);
925
+ return None;
926
+ case RenameAvailableKind::Unavailable_decl_from_clang:
927
+ diags.diagnose (startLoc, diag::decl_from_clang);
928
+ return None;
929
+ }
930
+
931
+ SmallVector<DeclContext *, 8 > scopes;
932
+ analyzeRenameScope (info->VD , scopes);
933
+ if (scopes.empty ())
934
+ return None;
935
+
936
+ RenameRangeCollector rangeCollector (info->VD , preferredName);
937
+ for (DeclContext *DC : scopes)
938
+ indexDeclContext (DC, rangeCollector);
939
+
940
+ return rangeCollector;
941
+ }
942
+
886
943
bool RefactoringActionLocalRename::performChange () {
887
944
if (StartLoc.isInvalid ()) {
888
945
DiagEngine.diagnose (SourceLoc (), diag::invalid_location);
@@ -897,40 +954,16 @@ bool RefactoringActionLocalRename::performChange() {
897
954
MD->getNameStr ());
898
955
return true ;
899
956
}
900
- CursorInfo =
901
- evaluateOrDefault (TheFile->getASTContext ().evaluator ,
902
- CursorInfoRequest{CursorInfoOwner (TheFile, StartLoc)},
903
- new ResolvedCursorInfo ());
904
- auto ValueRefCursorInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
905
- if (ValueRefCursorInfo && ValueRefCursorInfo->getValueD ()) {
906
- ValueDecl *VD = ValueRefCursorInfo->typeOrValue ();
907
- // The index always uses the outermost shadow for references
908
- if (!ValueRefCursorInfo->getShorthandShadowedDecls ().empty ()) {
909
- VD = ValueRefCursorInfo->getShorthandShadowedDecls ().back ();
910
- }
911
-
912
- SmallVector<DeclContext *, 8 > Scopes;
913
-
914
- Optional<RenameRefInfo> RefInfo;
915
- if (ValueRefCursorInfo->isRef ())
916
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
917
- ValueRefCursorInfo->isKeywordArgument ()};
918
957
919
- analyzeRenameScope (VD, RefInfo, DiagEngine, Scopes);
920
- if (Scopes.empty ())
921
- return true ;
922
- RenameRangeCollector rangeCollector (VD, PreferredName);
923
- for (DeclContext *DC : Scopes)
924
- indexDeclContext (DC, rangeCollector);
925
-
926
- auto consumers = DiagEngine.takeConsumers ();
927
- assert (consumers.size () == 1 );
928
- return syntacticRename (TheFile, rangeCollector.results (), EditConsumer,
929
- *consumers[0 ]);
930
- } else {
931
- DiagEngine.diagnose (StartLoc, diag::unresolved_location);
958
+ Optional<RenameRangeCollector> rangeCollector =
959
+ localRenames (TheFile, StartLoc, PreferredName, DiagEngine);
960
+ if (!rangeCollector)
932
961
return true ;
933
- }
962
+
963
+ auto consumers = DiagEngine.takeConsumers ();
964
+ assert (consumers.size () == 1 );
965
+ return syntacticRename (TheFile, rangeCollector->results (), EditConsumer,
966
+ *consumers[0 ]);
934
967
}
935
968
936
969
StringRef getDefaultPreferredName (RefactoringKind Kind) {
@@ -8783,9 +8816,9 @@ accept(SourceManager &SM, RegionType RegionType,
8783
8816
}
8784
8817
}
8785
8818
8786
- void swift::ide::collectRenameAvailabilityInfo (
8787
- const ValueDecl *VD, Optional<RenameRefInfo> RefInfo ,
8788
- SmallVectorImpl<RenameAvailabilityInfo> &Infos ) {
8819
+ Optional<RenameAvailabilityInfo>
8820
+ swift::ide::renameAvailabilityInfo ( const ValueDecl *VD,
8821
+ Optional<RenameRefInfo> RefInfo ) {
8789
8822
RenameAvailableKind AvailKind = RenameAvailableKind::Available;
8790
8823
if (getRelatedSystemDecl (VD)){
8791
8824
AvailKind = RenameAvailableKind::Unavailable_system_symbol;
@@ -8800,22 +8833,22 @@ void swift::ide::collectRenameAvailabilityInfo(
8800
8833
if (isa<AbstractFunctionDecl>(VD)) {
8801
8834
// Disallow renaming accessors.
8802
8835
if (isa<AccessorDecl>(VD))
8803
- return ;
8836
+ return None ;
8804
8837
8805
8838
// Disallow renaming deinit.
8806
8839
if (isa<DestructorDecl>(VD))
8807
- return ;
8840
+ return None ;
8808
8841
8809
8842
// Disallow renaming init with no arguments.
8810
8843
if (auto CD = dyn_cast<ConstructorDecl>(VD)) {
8811
8844
if (!CD->getParameters ()->size ())
8812
- return ;
8845
+ return None ;
8813
8846
8814
8847
if (RefInfo && !RefInfo->IsArgLabel ) {
8815
8848
NameMatcher Matcher (*(RefInfo->SF ));
8816
8849
auto Resolved = Matcher.resolve ({RefInfo->Loc , /* ResolveArgs*/ true });
8817
8850
if (Resolved.LabelRanges .empty ())
8818
- return ;
8851
+ return None ;
8819
8852
}
8820
8853
}
8821
8854
@@ -8825,30 +8858,27 @@ void swift::ide::collectRenameAvailabilityInfo(
8825
8858
// whether it's an instance method, so we do the same here for now.
8826
8859
if (FD->getBaseIdentifier () == FD->getASTContext ().Id_callAsFunction ) {
8827
8860
if (!FD->getParameters ()->size ())
8828
- return ;
8861
+ return None ;
8829
8862
8830
8863
if (RefInfo && !RefInfo->IsArgLabel ) {
8831
8864
NameMatcher Matcher (*(RefInfo->SF ));
8832
8865
auto Resolved = Matcher.resolve ({RefInfo->Loc , /* ResolveArgs*/ true });
8833
8866
if (Resolved.LabelRanges .empty ())
8834
- return ;
8867
+ return None ;
8835
8868
}
8836
8869
}
8837
8870
}
8838
8871
}
8839
8872
8840
8873
// Always return local rename for parameters.
8841
8874
// FIXME: if the cursor is on the argument, we should return global rename.
8842
- if (isa<ParamDecl>(VD)) {
8843
- Infos.emplace_back (RefactoringKind::LocalRename, AvailKind);
8844
- return ;
8845
- }
8875
+ if (isa<ParamDecl>(VD))
8876
+ return RenameAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
8846
8877
8847
8878
// If the indexer considers VD a global symbol, then we apply global rename.
8848
8879
if (index::isLocalSymbol (VD))
8849
- Infos.emplace_back (RefactoringKind::LocalRename, AvailKind);
8850
- else
8851
- Infos.emplace_back (RefactoringKind::GlobalRename, AvailKind);
8880
+ return RenameAvailabilityInfo{RefactoringKind::LocalRename, AvailKind};
8881
+ return RenameAvailabilityInfo{RefactoringKind::GlobalRename, AvailKind};
8852
8882
}
8853
8883
8854
8884
void swift::ide::collectAvailableRefactorings (
@@ -8858,27 +8888,10 @@ void swift::ide::collectAvailableRefactorings(
8858
8888
CursorInfo->getSourceFile ()->getASTContext ().SourceMgr );
8859
8889
8860
8890
if (!ExcludeRename) {
8861
- if (RefactoringActionLocalRename::isApplicable (CursorInfo, DiagEngine))
8862
- Kinds.push_back (RefactoringKind::LocalRename);
8863
-
8864
- switch (CursorInfo->getKind ()) {
8865
- case CursorInfoKind::ModuleRef:
8866
- case CursorInfoKind::Invalid:
8867
- case CursorInfoKind::StmtStart:
8868
- case CursorInfoKind::ExprStart:
8869
- break ;
8870
- case CursorInfoKind::ValueRef: {
8871
- auto ValueRefInfo = cast<ResolvedValueRefCursorInfo>(CursorInfo);
8872
- Optional<RenameRefInfo> RefInfo;
8873
- if (ValueRefInfo->isRef ())
8874
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
8875
- ValueRefInfo->isKeywordArgument ()};
8876
- auto RenameOp =
8877
- getAvailableRenameForDecl (ValueRefInfo->getValueD (), RefInfo);
8878
- if (RenameOp.has_value () &&
8879
- RenameOp.value () == RefactoringKind::GlobalRename)
8880
- Kinds.push_back (RenameOp.value ());
8881
- }
8891
+ if (auto Info = getRenameInfo (CursorInfo)) {
8892
+ if (Info->Availability .AvailableKind == RenameAvailableKind::Available) {
8893
+ Kinds.push_back (Info->Availability .Kind );
8894
+ }
8882
8895
}
8883
8896
}
8884
8897
@@ -9084,29 +9097,11 @@ int swift::ide::findLocalRenameRanges(
9084
9097
Diags.addConsumer (DiagConsumer);
9085
9098
9086
9099
auto StartLoc = Lexer::getLocForStartOfToken (SM, Range.getStart (SM));
9087
- ResolvedCursorInfoPtr CursorInfo =
9088
- evaluateOrDefault (SF->getASTContext ().evaluator ,
9089
- CursorInfoRequest{CursorInfoOwner (SF, StartLoc)},
9090
- new ResolvedCursorInfo ());
9091
- auto ValueRefCursorInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
9092
- if (!ValueRefCursorInfo || !ValueRefCursorInfo->getValueD ()) {
9093
- Diags.diagnose (StartLoc, diag::unresolved_location);
9094
- return true ;
9095
- }
9096
- ValueDecl *VD = ValueRefCursorInfo->typeOrValue ();
9097
- Optional<RenameRefInfo> RefInfo;
9098
- if (ValueRefCursorInfo->isRef ())
9099
- RefInfo = {CursorInfo->getSourceFile (), CursorInfo->getLoc (),
9100
- ValueRefCursorInfo->isKeywordArgument ()};
9101
-
9102
- llvm::SmallVector<DeclContext *, 8 > Scopes;
9103
- analyzeRenameScope (VD, RefInfo, Diags, Scopes);
9104
- if (Scopes.empty ())
9100
+ Optional<RenameRangeCollector> RangeCollector =
9101
+ localRenames (SF, StartLoc, StringRef (), Diags);
9102
+ if (!RangeCollector)
9105
9103
return true ;
9106
- RenameRangeCollector RangeCollector (VD, StringRef ());
9107
- for (DeclContext *DC : Scopes)
9108
- indexDeclContext (DC, RangeCollector);
9109
9104
9110
- return findSyntacticRenameRanges (SF, RangeCollector. results (), RenameConsumer ,
9111
- DiagConsumer);
9105
+ return findSyntacticRenameRanges (SF, RangeCollector-> results (),
9106
+ RenameConsumer, DiagConsumer);
9112
9107
}
0 commit comments