Skip to content

Commit edfc859

Browse files
authored
Add support for renaming objc methods, even those with multiple selector pieces (llvm#76466)
This adds support for renaming Objective-C methods, which are unique since their method names can be split across multiple tokens.
1 parent 834d11c commit edfc859

File tree

10 files changed

+692
-86
lines changed

10 files changed

+692
-86
lines changed

clang-tools-extra/clangd/ClangdLSPServer.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,14 +844,17 @@ void ClangdLSPServer::onWorkspaceSymbol(
844844
}
845845

846846
void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
847-
Callback<std::optional<Range>> Reply) {
847+
Callback<PrepareRenameResult> Reply) {
848848
Server->prepareRename(
849849
Params.textDocument.uri.file(), Params.position, /*NewName*/ std::nullopt,
850850
Opts.Rename,
851851
[Reply = std::move(Reply)](llvm::Expected<RenameResult> Result) mutable {
852852
if (!Result)
853853
return Reply(Result.takeError());
854-
return Reply(std::move(Result->Target));
854+
PrepareRenameResult PrepareResult;
855+
PrepareResult.range = Result->Target;
856+
PrepareResult.placeholder = Result->Placeholder;
857+
return Reply(std::move(PrepareResult));
855858
});
856859
}
857860

clang-tools-extra/clangd/ClangdLSPServer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class ClangdLSPServer : private ClangdServer::Callbacks,
134134
void onWorkspaceSymbol(const WorkspaceSymbolParams &,
135135
Callback<std::vector<SymbolInformation>>);
136136
void onPrepareRename(const TextDocumentPositionParams &,
137-
Callback<std::optional<Range>>);
137+
Callback<PrepareRenameResult>);
138138
void onRename(const RenameParams &, Callback<WorkspaceEdit>);
139139
void onHover(const TextDocumentPositionParams &,
140140
Callback<std::optional<Hover>>);

clang-tools-extra/clangd/Protocol.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,15 @@ bool fromJSON(const llvm::json::Value &Params, RenameParams &R,
11871187
O.map("position", R.position) && O.map("newName", R.newName);
11881188
}
11891189

1190+
llvm::json::Value toJSON(const PrepareRenameResult &PRR) {
1191+
if (PRR.placeholder.empty())
1192+
return toJSON(PRR.range);
1193+
return llvm::json::Object{
1194+
{"range", toJSON(PRR.range)},
1195+
{"placeholder", PRR.placeholder},
1196+
};
1197+
}
1198+
11901199
llvm::json::Value toJSON(const DocumentHighlight &DH) {
11911200
return llvm::json::Object{
11921201
{"range", toJSON(DH.range)},

clang-tools-extra/clangd/Protocol.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,14 @@ struct RenameParams {
14361436
};
14371437
bool fromJSON(const llvm::json::Value &, RenameParams &, llvm::json::Path);
14381438

1439+
struct PrepareRenameResult {
1440+
/// Range of the string to rename.
1441+
Range range;
1442+
/// Placeholder text to use in the editor if non-empty.
1443+
std::string placeholder;
1444+
};
1445+
llvm::json::Value toJSON(const PrepareRenameResult &PRR);
1446+
14391447
enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };
14401448

14411449
/// A document highlight is a range inside a text document which deserves
@@ -1969,6 +1977,28 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ASTNode &);
19691977
} // namespace clang
19701978

19711979
namespace llvm {
1980+
1981+
template <> struct DenseMapInfo<clang::clangd::Range> {
1982+
using Range = clang::clangd::Range;
1983+
static inline Range getEmptyKey() {
1984+
static clang::clangd::Position Tomb{-1, -1};
1985+
static Range R{Tomb, Tomb};
1986+
return R;
1987+
}
1988+
static inline Range getTombstoneKey() {
1989+
static clang::clangd::Position Tomb{-2, -2};
1990+
static Range R{Tomb, Tomb};
1991+
return R;
1992+
}
1993+
static unsigned getHashValue(const Range &Val) {
1994+
return llvm::hash_combine(Val.start.line, Val.start.character, Val.end.line,
1995+
Val.end.character);
1996+
}
1997+
static bool isEqual(const Range &LHS, const Range &RHS) {
1998+
return std::tie(LHS.start, LHS.end) == std::tie(RHS.start, RHS.end);
1999+
}
2000+
};
2001+
19722002
template <> struct format_provider<clang::clangd::Position> {
19732003
static void format(const clang::clangd::Position &Pos, raw_ostream &OS,
19742004
StringRef Style) {

clang-tools-extra/clangd/index/SymbolCollector.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,21 @@ bool isSpelled(SourceLocation Loc, const NamedDecl &ND) {
174174
auto Name = ND.getDeclName();
175175
const auto NameKind = Name.getNameKind();
176176
if (NameKind != DeclarationName::Identifier &&
177-
NameKind != DeclarationName::CXXConstructorName)
177+
NameKind != DeclarationName::CXXConstructorName &&
178+
NameKind != DeclarationName::ObjCZeroArgSelector &&
179+
NameKind != DeclarationName::ObjCOneArgSelector &&
180+
NameKind != DeclarationName::ObjCMultiArgSelector)
178181
return false;
179182
const auto &AST = ND.getASTContext();
180183
const auto &SM = AST.getSourceManager();
181184
const auto &LO = AST.getLangOpts();
182185
clang::Token Tok;
183186
if (clang::Lexer::getRawToken(Loc, Tok, SM, LO))
184187
return false;
185-
auto StrName = Name.getAsString();
186-
return clang::Lexer::getSpelling(Tok, SM, LO) == StrName;
188+
auto TokSpelling = clang::Lexer::getSpelling(Tok, SM, LO);
189+
if (const auto *MD = dyn_cast<ObjCMethodDecl>(&ND))
190+
return TokSpelling == MD->getSelector().getNameForSlot(0);
191+
return TokSpelling == Name.getAsString();
187192
}
188193
} // namespace
189194

0 commit comments

Comments
 (0)