1818#include " clang/AST/ASTContext.h"
1919#include " clang/AST/ASTTypeTraits.h"
2020#include " clang/AST/Decl.h"
21+ #include " clang/AST/DeclBase.h"
2122#include " clang/AST/DeclCXX.h"
2223#include " clang/AST/DeclObjC.h"
2324#include " clang/AST/DeclTemplate.h"
25+ #include " clang/AST/DeclarationName.h"
2426#include " clang/AST/ParentMapContext.h"
2527#include " clang/AST/Stmt.h"
2628#include " clang/Basic/CharInfo.h"
@@ -591,11 +593,11 @@ bool isMatchingSelectorName(const syntax::Token &Cur, const syntax::Token &Next,
591593// The search will terminate upon seeing Terminator or a ; at the top level.
592594std::optional<SymbolRange>
593595findAllSelectorPieces (llvm::ArrayRef<syntax::Token> Tokens,
594- const SourceManager &SM, Selector Sel ,
596+ const SourceManager &SM, const RenameSymbolName &Name ,
595597 tok::TokenKind Terminator) {
596598 assert (!Tokens.empty ());
597599
598- unsigned NumArgs = Sel. getNumArgs ();
600+ unsigned NumArgs = Name. getNamePieces (). size ();
599601 llvm::SmallVector<tok::TokenKind, 8 > Closes;
600602 std::vector<Range> SelectorPieces;
601603 for (unsigned Index = 0 , Last = Tokens.size (); Index < Last - 1 ; ++Index) {
@@ -605,12 +607,12 @@ findAllSelectorPieces(llvm::ArrayRef<syntax::Token> Tokens,
605607 auto PieceCount = SelectorPieces.size ();
606608 if (PieceCount < NumArgs &&
607609 isMatchingSelectorName (Tok, Tokens[Index + 1 ], SM,
608- Sel. getNameForSlot (PieceCount) )) {
610+ Name. getNamePieces ()[PieceCount] )) {
609611 // If 'foo:' instead of ':' (empty selector), we need to skip the ':'
610612 // token after the name. We don't currently properly support empty
611613 // selectors since we may lex them improperly due to ternary statements
612614 // as well as don't properly support storing their ranges for edits.
613- if (!Sel. getNameForSlot (PieceCount) .empty ())
615+ if (!Name. getNamePieces ()[PieceCount] .empty ())
614616 ++Index;
615617 SelectorPieces.push_back (
616618 halfOpenToRange (SM, Tok.range (SM).toCharRange (SM)));
@@ -662,16 +664,17 @@ findAllSelectorPieces(llvm::ArrayRef<syntax::Token> Tokens,
662664
663665// / Collects all ranges of the given identifier/selector in the source code.
664666// /
665- // / If a selector is given, this does a full lex of the given source code in
666- // / order to identify all selector fragments (e.g. in method exprs/decls) since
667- // / they are non-contiguous.
668- std::vector<SymbolRange> collectRenameIdentifierRanges (
669- llvm::StringRef Identifier, llvm::StringRef Content,
670- const LangOptions &LangOpts, std::optional<Selector> Selector) {
667+ // / If `Name` is an Objective-C symbol name, this does a full lex of the given
668+ // / source code in order to identify all selector fragments (e.g. in method
669+ // / exprs/decls) since they are non-contiguous.
670+ std::vector<SymbolRange>
671+ collectRenameIdentifierRanges (const RenameSymbolName &Name,
672+ llvm::StringRef Content,
673+ const LangOptions &LangOpts) {
671674 std::vector<SymbolRange> Ranges;
672- if (!Selector ) {
675+ if (auto SinglePiece = Name. getSinglePiece () ) {
673676 auto IdentifierRanges =
674- collectIdentifierRanges (Identifier , Content, LangOpts);
677+ collectIdentifierRanges (*SinglePiece , Content, LangOpts);
675678 for (const auto &R : IdentifierRanges)
676679 Ranges.emplace_back (R);
677680 return Ranges;
@@ -685,7 +688,7 @@ std::vector<SymbolRange> collectRenameIdentifierRanges(
685688 // parsing a method declaration or definition which isn't at the top level or
686689 // similar looking expressions (e.g. an @selector() expression).
687690 llvm::SmallVector<tok::TokenKind, 8 > Closes;
688- llvm::StringRef FirstSelPiece = Selector-> getNameForSlot ( 0 ) ;
691+ llvm::StringRef FirstSelPiece = Name. getNamePieces ()[ 0 ] ;
689692
690693 auto Tokens = syntax::tokenize (SM.getMainFileID (), SM, LangOpts);
691694 unsigned Last = Tokens.size () - 1 ;
@@ -717,7 +720,7 @@ std::vector<SymbolRange> collectRenameIdentifierRanges(
717720 // Check if we can find all the relevant selector peices starting from
718721 // this token
719722 auto SelectorRanges =
720- findAllSelectorPieces (ArrayRef (Tokens).slice (Index), SM, *Selector ,
723+ findAllSelectorPieces (ArrayRef (Tokens).slice (Index), SM, Name ,
721724 Closes.empty () ? tok::l_brace : Closes.back ());
722725 if (SelectorRanges)
723726 Ranges.emplace_back (std::move (*SelectorRanges));
@@ -764,7 +767,6 @@ renameObjCMethodWithinFile(ParsedAST &AST, const ObjCMethodDecl *MD,
764767 std::vector<SourceLocation> SelectorOccurences) {
765768 const SourceManager &SM = AST.getSourceManager ();
766769 auto Code = SM.getBufferData (SM.getMainFileID ());
767- auto RenameIdentifier = MD->getSelector ().getNameForSlot (0 ).str ();
768770 llvm::SmallVector<llvm::StringRef, 8 > NewNames;
769771 NewName.split (NewNames, " :" );
770772
@@ -774,7 +776,7 @@ renameObjCMethodWithinFile(ParsedAST &AST, const ObjCMethodDecl *MD,
774776 Ranges.push_back (tokenRangeForLoc (AST, Loc, SM, LangOpts));
775777 auto FilePath = AST.tuPath ();
776778 auto RenameRanges = collectRenameIdentifierRanges (
777- RenameIdentifier , Code, LangOpts, MD-> getSelector () );
779+ RenameSymbolName (MD-> getDeclName ()) , Code, LangOpts);
778780 auto RenameEdit = buildRenameEdit (FilePath, Code, RenameRanges, NewNames);
779781 if (!RenameEdit)
780782 return error (" failed to rename in file {0}: {1}" , FilePath,
@@ -936,21 +938,14 @@ renameOutsideFile(const NamedDecl &RenameDecl, llvm::StringRef MainFilePath,
936938 ExpBuffer.getError ().message ());
937939 continue ;
938940 }
939- std::string RenameIdentifier = RenameDecl.getNameAsString ();
940- std::optional<Selector> Selector = std::nullopt ;
941+ RenameSymbolName RenameName (RenameDecl.getDeclName ());
941942 llvm::SmallVector<llvm::StringRef, 8 > NewNames;
942- if (const auto *MD = dyn_cast<ObjCMethodDecl>(&RenameDecl)) {
943- RenameIdentifier = MD->getSelector ().getNameForSlot (0 ).str ();
944- if (MD->getSelector ().getNumArgs () > 1 )
945- Selector = MD->getSelector ();
946- }
947943 NewName.split (NewNames, " :" );
948944
949945 auto AffectedFileCode = (*ExpBuffer)->getBuffer ();
950- auto RenameRanges =
951- adjustRenameRanges (AffectedFileCode, RenameIdentifier,
952- std::move (FileAndOccurrences.second ),
953- RenameDecl.getASTContext ().getLangOpts (), Selector);
946+ auto RenameRanges = adjustRenameRanges (
947+ AffectedFileCode, RenameName, std::move (FileAndOccurrences.second ),
948+ RenameDecl.getASTContext ().getLangOpts ());
954949 if (!RenameRanges) {
955950 // Our heuristics fails to adjust rename ranges to the current state of
956951 // the file, it is most likely the index is stale, so we give up the
@@ -1011,6 +1006,50 @@ void findNearMiss(
10111006
10121007} // namespace
10131008
1009+ RenameSymbolName::RenameSymbolName () : NamePieces({}) {}
1010+
1011+ namespace {
1012+ std::vector<std::string> extractNamePieces (const DeclarationName &DeclName) {
1013+ if (DeclName.getNameKind () ==
1014+ DeclarationName::NameKind::ObjCMultiArgSelector ||
1015+ DeclName.getNameKind () == DeclarationName::NameKind::ObjCOneArgSelector) {
1016+ const Selector &Sel = DeclName.getObjCSelector ();
1017+ std::vector<std::string> Result;
1018+ for (unsigned Slot = 0 ; Slot < Sel.getNumArgs (); ++Slot) {
1019+ Result.push_back (Sel.getNameForSlot (Slot).str ());
1020+ }
1021+ return Result;
1022+ }
1023+ return {DeclName.getAsString ()};
1024+ }
1025+ } // namespace
1026+
1027+ RenameSymbolName::RenameSymbolName (const DeclarationName &DeclName)
1028+ : RenameSymbolName(extractNamePieces(DeclName)) {}
1029+
1030+ RenameSymbolName::RenameSymbolName (ArrayRef<std::string> NamePieces) {
1031+ for (const auto &Piece : NamePieces)
1032+ this ->NamePieces .push_back (Piece);
1033+ }
1034+
1035+ std::optional<std::string> RenameSymbolName::getSinglePiece () const {
1036+ if (getNamePieces ().size () == 1 ) {
1037+ return NamePieces.front ();
1038+ }
1039+ return std::nullopt ;
1040+ }
1041+
1042+ std::string RenameSymbolName::getAsString () const {
1043+ std::string Result;
1044+ llvm::raw_string_ostream OS (Result);
1045+ this ->print (OS);
1046+ return Result;
1047+ }
1048+
1049+ void RenameSymbolName::print (raw_ostream &OS) const {
1050+ llvm::interleave (NamePieces, OS, " :" );
1051+ }
1052+
10141053SymbolRange::SymbolRange (Range R) : Ranges({R}) {}
10151054
10161055SymbolRange::SymbolRange (std::vector<Range> Ranges)
@@ -1238,14 +1277,13 @@ llvm::Expected<Edit> buildRenameEdit(llvm::StringRef AbsFilePath,
12381277// were inserted). If such a "near miss" is found, the rename is still
12391278// possible
12401279std::optional<std::vector<SymbolRange>>
1241- adjustRenameRanges (llvm::StringRef DraftCode, llvm::StringRef Identifier,
1242- std::vector<Range> Indexed, const LangOptions &LangOpts,
1243- std::optional<Selector> Selector) {
1280+ adjustRenameRanges (llvm::StringRef DraftCode, const RenameSymbolName &Name,
1281+ std::vector<Range> Indexed, const LangOptions &LangOpts) {
12441282 trace::Span Tracer (" AdjustRenameRanges" );
12451283 assert (!Indexed.empty ());
12461284 assert (llvm::is_sorted (Indexed));
12471285 std::vector<SymbolRange> Lexed =
1248- collectRenameIdentifierRanges (Identifier , DraftCode, LangOpts, Selector );
1286+ collectRenameIdentifierRanges (Name , DraftCode, LangOpts);
12491287 llvm::sort (Lexed);
12501288 return getMappedRanges (Indexed, Lexed);
12511289}
0 commit comments