@@ -625,29 +625,54 @@ static const ValueDecl *getRelatedSystemDecl(const ValueDecl *VD) {
625625 return nullptr ;
626626}
627627
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 ()};
636652 }
637- return None;
653+
654+ Optional<RenameAvailabilityInfo> info = renameAvailabilityInfo (VD, refInfo);
655+ if (!info)
656+ return None;
657+
658+ return RenameInfo{VD, *info};
638659}
639660
640661class RenameRangeCollector : public IndexDataConsumer {
641662public:
642663 RenameRangeCollector (StringRef USR, StringRef newName)
643- : USR(USR.str()) , newName(newName.str() ) {}
664+ : USR(USR) , newName(newName) {}
644665
645666 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);
648670 printValueDeclUSR (D, OS);
671+ USR = stringStorage.copyString (SS.str ());
649672 }
650673
674+ RenameRangeCollector (RenameRangeCollector &&collector) = default ;
675+
651676 ArrayRef<RenameLoc> results () const { return locations; }
652677
653678private:
@@ -689,8 +714,8 @@ class RenameRangeCollector : public IndexDataConsumer {
689714 StringRef NewName);
690715
691716private:
692- std::string USR;
693- std::string newName;
717+ StringRef USR;
718+ StringRef newName;
694719 StringScratchSpace stringStorage;
695720 std::vector<RenameLoc> locations;
696721};
@@ -845,29 +870,14 @@ class RefactoringAction##KIND: public RangeBasedRefactoringAction { \
845870
846871bool RefactoringActionLocalRename::isApplicable (
847872 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;
860877}
861878
862- static void analyzeRenameScope (ValueDecl *VD, Optional<RenameRefInfo> RefInfo,
863- DiagnosticEngine &Diags,
879+ static void analyzeRenameScope (ValueDecl *VD,
864880 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-
871881 auto *Scope = VD->getDeclContext ();
872882 // There may be sibling decls that the renamed symbol is visible from.
873883 switch (Scope->getContextKind ()) {
@@ -892,6 +902,53 @@ static void analyzeRenameScope(ValueDecl *VD, Optional<RenameRefInfo> RefInfo,
892902 Scopes.push_back (Scope);
893903}
894904
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+
895952bool RefactoringActionLocalRename::performChange () {
896953 if (StartLoc.isInvalid ()) {
897954 DiagEngine.diagnose (SourceLoc (), diag::invalid_location);
@@ -906,40 +963,16 @@ bool RefactoringActionLocalRename::performChange() {
906963 MD->getNameStr ());
907964 return true ;
908965 }
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 ()};
927966
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)
941970 return true ;
942- }
971+
972+ auto consumers = DiagEngine.takeConsumers ();
973+ assert (consumers.size () == 1 );
974+ return syntacticRename (TheFile, rangeCollector->results (), EditConsumer,
975+ *consumers[0 ]);
943976}
944977
945978StringRef getDefaultPreferredName (RefactoringKind Kind) {
@@ -8805,9 +8838,9 @@ accept(SourceManager &SM, RegionType RegionType,
88058838 }
88068839}
88078840
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 ) {
88118844 RenameAvailableKind AvailKind = RenameAvailableKind::Available;
88128845 if (getRelatedSystemDecl (VD)){
88138846 AvailKind = RenameAvailableKind::Unavailable_system_symbol;
@@ -8822,22 +8855,22 @@ void swift::ide::collectRenameAvailabilityInfo(
88228855 if (isa<AbstractFunctionDecl>(VD)) {
88238856 // Disallow renaming accessors.
88248857 if (isa<AccessorDecl>(VD))
8825- return ;
8858+ return None ;
88268859
88278860 // Disallow renaming deinit.
88288861 if (isa<DestructorDecl>(VD))
8829- return ;
8862+ return None ;
88308863
88318864 // Disallow renaming init with no arguments.
88328865 if (auto CD = dyn_cast<ConstructorDecl>(VD)) {
88338866 if (!CD->getParameters ()->size ())
8834- return ;
8867+ return None ;
88358868
88368869 if (RefInfo && !RefInfo->IsArgLabel ) {
88378870 NameMatcher Matcher (*(RefInfo->SF ));
88388871 auto Resolved = Matcher.resolve ({RefInfo->Loc , /* ResolveArgs*/ true });
88398872 if (Resolved.LabelRanges .empty ())
8840- return ;
8873+ return None ;
88418874 }
88428875 }
88438876
@@ -8847,30 +8880,27 @@ void swift::ide::collectRenameAvailabilityInfo(
88478880 // whether it's an instance method, so we do the same here for now.
88488881 if (FD->getBaseIdentifier () == FD->getASTContext ().Id_callAsFunction ) {
88498882 if (!FD->getParameters ()->size ())
8850- return ;
8883+ return None ;
88518884
88528885 if (RefInfo && !RefInfo->IsArgLabel ) {
88538886 NameMatcher Matcher (*(RefInfo->SF ));
88548887 auto Resolved = Matcher.resolve ({RefInfo->Loc , /* ResolveArgs*/ true });
88558888 if (Resolved.LabelRanges .empty ())
8856- return ;
8889+ return None ;
88578890 }
88588891 }
88598892 }
88608893 }
88618894
88628895 // Always return local rename for parameters.
88638896 // 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};
88688899
88698900 // If the indexer considers VD a global symbol, then we apply global rename.
88708901 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};
88748904}
88758905
88768906void swift::ide::collectAvailableRefactorings (
@@ -8880,27 +8910,10 @@ void swift::ide::collectAvailableRefactorings(
88808910 CursorInfo->getSourceFile ()->getASTContext ().SourceMgr );
88818911
88828912 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+ }
89048917 }
89058918 }
89068919
@@ -9106,29 +9119,11 @@ int swift::ide::findLocalRenameRanges(
91069119 Diags.addConsumer (DiagConsumer);
91079120
91089121 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)
91279125 return true ;
9128- RenameRangeCollector RangeCollector (VD, StringRef ());
9129- for (DeclContext *DC : Scopes)
9130- indexDeclContext (DC, RangeCollector);
91319126
9132- return findSyntacticRenameRanges (SF, RangeCollector. results (), RenameConsumer ,
9133- DiagConsumer);
9127+ return findSyntacticRenameRanges (SF, RangeCollector-> results (),
9128+ RenameConsumer, DiagConsumer);
91349129}
0 commit comments