18
18
#include " clang/AST/ASTContext.h"
19
19
#include " clang/AST/ASTTypeTraits.h"
20
20
#include " clang/AST/Decl.h"
21
+ #include " clang/AST/DeclBase.h"
21
22
#include " clang/AST/DeclCXX.h"
22
23
#include " clang/AST/DeclObjC.h"
23
24
#include " clang/AST/DeclTemplate.h"
25
+ #include " clang/AST/DeclarationName.h"
24
26
#include " clang/AST/ParentMapContext.h"
25
27
#include " clang/AST/Stmt.h"
26
28
#include " clang/Basic/CharInfo.h"
@@ -597,11 +599,12 @@ bool isMatchingSelectorName(const syntax::Token &Cur, const syntax::Token &Next,
597
599
// The search will terminate upon seeing Terminator or a ; at the top level.
598
600
std::optional<SymbolRange>
599
601
findAllSelectorPieces (llvm::ArrayRef<syntax::Token> Tokens,
600
- const SourceManager &SM, Selector Sel ,
602
+ const SourceManager &SM, const RenameSymbolName &Name ,
601
603
tok::TokenKind Terminator) {
602
604
assert (!Tokens.empty ());
603
605
604
- unsigned NumArgs = Sel.getNumArgs ();
606
+ ArrayRef<std::string> NamePieces = Name.getNamePieces ();
607
+ unsigned NumArgs = NamePieces.size ();
605
608
llvm::SmallVector<tok::TokenKind, 8 > Closes;
606
609
std::vector<Range> SelectorPieces;
607
610
for (unsigned Index = 0 , Last = Tokens.size (); Index < Last - 1 ; ++Index) {
@@ -611,12 +614,12 @@ findAllSelectorPieces(llvm::ArrayRef<syntax::Token> Tokens,
611
614
auto PieceCount = SelectorPieces.size ();
612
615
if (PieceCount < NumArgs &&
613
616
isMatchingSelectorName (Tok, Tokens[Index + 1 ], SM,
614
- Sel. getNameForSlot ( PieceCount) )) {
617
+ NamePieces[ PieceCount] )) {
615
618
// If 'foo:' instead of ':' (empty selector), we need to skip the ':'
616
619
// token after the name. We don't currently properly support empty
617
620
// selectors since we may lex them improperly due to ternary statements
618
621
// as well as don't properly support storing their ranges for edits.
619
- if (!Sel. getNameForSlot ( PieceCount) .empty ())
622
+ if (!NamePieces[ PieceCount] .empty ())
620
623
++Index;
621
624
SelectorPieces.push_back (
622
625
halfOpenToRange (SM, Tok.range (SM).toCharRange (SM)));
@@ -668,16 +671,17 @@ findAllSelectorPieces(llvm::ArrayRef<syntax::Token> Tokens,
668
671
669
672
// / Collects all ranges of the given identifier/selector in the source code.
670
673
// /
671
- // / If a selector is given, this does a full lex of the given source code in
672
- // / order to identify all selector fragments (e.g. in method exprs/decls) since
673
- // / they are non-contiguous.
674
- std::vector<SymbolRange> collectRenameIdentifierRanges (
675
- llvm::StringRef Identifier, llvm::StringRef Content,
676
- const LangOptions &LangOpts, std::optional<Selector> Selector) {
674
+ // / If `Name` is an Objective-C symbol name, this does a full lex of the given
675
+ // / source code in order to identify all selector fragments (e.g. in method
676
+ // / exprs/decls) since they are non-contiguous.
677
+ std::vector<SymbolRange>
678
+ collectRenameIdentifierRanges (const RenameSymbolName &Name,
679
+ llvm::StringRef Content,
680
+ const LangOptions &LangOpts) {
677
681
std::vector<SymbolRange> Ranges;
678
- if (!Selector ) {
682
+ if (auto SinglePiece = Name. getSinglePiece () ) {
679
683
auto IdentifierRanges =
680
- collectIdentifierRanges (Identifier , Content, LangOpts);
684
+ collectIdentifierRanges (*SinglePiece , Content, LangOpts);
681
685
for (const auto &R : IdentifierRanges)
682
686
Ranges.emplace_back (R);
683
687
return Ranges;
@@ -691,7 +695,7 @@ std::vector<SymbolRange> collectRenameIdentifierRanges(
691
695
// parsing a method declaration or definition which isn't at the top level or
692
696
// similar looking expressions (e.g. an @selector() expression).
693
697
llvm::SmallVector<tok::TokenKind, 8 > Closes;
694
- llvm::StringRef FirstSelPiece = Selector-> getNameForSlot ( 0 ) ;
698
+ llvm::StringRef FirstSelPiece = Name. getNamePieces ()[ 0 ] ;
695
699
696
700
auto Tokens = syntax::tokenize (SM.getMainFileID (), SM, LangOpts);
697
701
unsigned Last = Tokens.size () - 1 ;
@@ -723,7 +727,7 @@ std::vector<SymbolRange> collectRenameIdentifierRanges(
723
727
// Check if we can find all the relevant selector peices starting from
724
728
// this token
725
729
auto SelectorRanges =
726
- findAllSelectorPieces (ArrayRef (Tokens).slice (Index), SM, *Selector ,
730
+ findAllSelectorPieces (ArrayRef (Tokens).slice (Index), SM, Name ,
727
731
Closes.empty () ? tok::l_brace : Closes.back ());
728
732
if (SelectorRanges)
729
733
Ranges.emplace_back (std::move (*SelectorRanges));
@@ -770,7 +774,6 @@ renameObjCMethodWithinFile(ParsedAST &AST, const ObjCMethodDecl *MD,
770
774
std::vector<SourceLocation> SelectorOccurences) {
771
775
const SourceManager &SM = AST.getSourceManager ();
772
776
auto Code = SM.getBufferData (SM.getMainFileID ());
773
- auto RenameIdentifier = MD->getSelector ().getNameForSlot (0 ).str ();
774
777
llvm::SmallVector<llvm::StringRef, 8 > NewNames;
775
778
NewName.split (NewNames, " :" );
776
779
@@ -780,7 +783,7 @@ renameObjCMethodWithinFile(ParsedAST &AST, const ObjCMethodDecl *MD,
780
783
Ranges.push_back (tokenRangeForLoc (AST, Loc, SM, LangOpts));
781
784
auto FilePath = AST.tuPath ();
782
785
auto RenameRanges = collectRenameIdentifierRanges (
783
- RenameIdentifier , Code, LangOpts, MD-> getSelector () );
786
+ RenameSymbolName (MD-> getDeclName ()) , Code, LangOpts);
784
787
auto RenameEdit = buildRenameEdit (FilePath, Code, RenameRanges, NewNames);
785
788
if (!RenameEdit)
786
789
return error (" failed to rename in file {0}: {1}" , FilePath,
@@ -942,21 +945,14 @@ renameOutsideFile(const NamedDecl &RenameDecl, llvm::StringRef MainFilePath,
942
945
ExpBuffer.getError ().message ());
943
946
continue ;
944
947
}
945
- std::string RenameIdentifier = RenameDecl.getNameAsString ();
946
- std::optional<Selector> Selector = std::nullopt;
948
+ RenameSymbolName RenameName (RenameDecl.getDeclName ());
947
949
llvm::SmallVector<llvm::StringRef, 8 > NewNames;
948
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(&RenameDecl)) {
949
- RenameIdentifier = MD->getSelector ().getNameForSlot (0 ).str ();
950
- if (MD->getSelector ().getNumArgs () > 1 )
951
- Selector = MD->getSelector ();
952
- }
953
950
NewName.split (NewNames, " :" );
954
951
955
952
auto AffectedFileCode = (*ExpBuffer)->getBuffer ();
956
- auto RenameRanges =
957
- adjustRenameRanges (AffectedFileCode, RenameIdentifier,
958
- std::move (FileAndOccurrences.second ),
959
- RenameDecl.getASTContext ().getLangOpts (), Selector);
953
+ auto RenameRanges = adjustRenameRanges (
954
+ AffectedFileCode, RenameName, std::move (FileAndOccurrences.second ),
955
+ RenameDecl.getASTContext ().getLangOpts ());
960
956
if (!RenameRanges) {
961
957
// Our heuristics fails to adjust rename ranges to the current state of
962
958
// the file, it is most likely the index is stale, so we give up the
@@ -1017,6 +1013,50 @@ void findNearMiss(
1017
1013
1018
1014
} // namespace
1019
1015
1016
+ RenameSymbolName::RenameSymbolName () : NamePieces({}) {}
1017
+
1018
+ namespace {
1019
+ std::vector<std::string> extractNamePieces (const DeclarationName &DeclName) {
1020
+ if (DeclName.getNameKind () ==
1021
+ DeclarationName::NameKind::ObjCMultiArgSelector ||
1022
+ DeclName.getNameKind () == DeclarationName::NameKind::ObjCOneArgSelector) {
1023
+ const Selector &Sel = DeclName.getObjCSelector ();
1024
+ std::vector<std::string> Result;
1025
+ for (unsigned Slot = 0 ; Slot < Sel.getNumArgs (); ++Slot) {
1026
+ Result.push_back (Sel.getNameForSlot (Slot).str ());
1027
+ }
1028
+ return Result;
1029
+ }
1030
+ return {DeclName.getAsString ()};
1031
+ }
1032
+ } // namespace
1033
+
1034
+ RenameSymbolName::RenameSymbolName (const DeclarationName &DeclName)
1035
+ : RenameSymbolName(extractNamePieces(DeclName)) {}
1036
+
1037
+ RenameSymbolName::RenameSymbolName (ArrayRef<std::string> NamePieces) {
1038
+ for (const auto &Piece : NamePieces)
1039
+ this ->NamePieces .push_back (Piece);
1040
+ }
1041
+
1042
+ std::optional<std::string> RenameSymbolName::getSinglePiece () const {
1043
+ if (getNamePieces ().size () == 1 ) {
1044
+ return NamePieces.front ();
1045
+ }
1046
+ return std::nullopt;
1047
+ }
1048
+
1049
+ std::string RenameSymbolName::getAsString () const {
1050
+ std::string Result;
1051
+ llvm::raw_string_ostream OS (Result);
1052
+ this ->print (OS);
1053
+ return Result;
1054
+ }
1055
+
1056
+ void RenameSymbolName::print (raw_ostream &OS) const {
1057
+ llvm::interleave (NamePieces, OS, " :" );
1058
+ }
1059
+
1020
1060
SymbolRange::SymbolRange (Range R) : Ranges({R}) {}
1021
1061
1022
1062
SymbolRange::SymbolRange (std::vector<Range> Ranges)
@@ -1244,14 +1284,13 @@ llvm::Expected<Edit> buildRenameEdit(llvm::StringRef AbsFilePath,
1244
1284
// were inserted). If such a "near miss" is found, the rename is still
1245
1285
// possible
1246
1286
std::optional<std::vector<SymbolRange>>
1247
- adjustRenameRanges (llvm::StringRef DraftCode, llvm::StringRef Identifier,
1248
- std::vector<Range> Indexed, const LangOptions &LangOpts,
1249
- std::optional<Selector> Selector) {
1287
+ adjustRenameRanges (llvm::StringRef DraftCode, const RenameSymbolName &Name,
1288
+ std::vector<Range> Indexed, const LangOptions &LangOpts) {
1250
1289
trace::Span Tracer (" AdjustRenameRanges" );
1251
1290
assert (!Indexed.empty ());
1252
1291
assert (llvm::is_sorted (Indexed));
1253
1292
std::vector<SymbolRange> Lexed =
1254
- collectRenameIdentifierRanges (Identifier , DraftCode, LangOpts, Selector );
1293
+ collectRenameIdentifierRanges (Name , DraftCode, LangOpts);
1255
1294
llvm::sort (Lexed);
1256
1295
return getMappedRanges (Indexed, Lexed);
1257
1296
}
0 commit comments