Skip to content

Commit

Permalink
Add support for renaming objc methods, even those with multiple selec…
Browse files Browse the repository at this point in the history
…tor pieces (#76466)

This adds support for  renaming Objective-C methods, which are unique since their method names can be split across multiple tokens.
  • Loading branch information
DavidGoldman committed Feb 15, 2024
1 parent 834d11c commit edfc859
Show file tree
Hide file tree
Showing 10 changed files with 692 additions and 86 deletions.
7 changes: 5 additions & 2 deletions clang-tools-extra/clangd/ClangdLSPServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,14 +844,17 @@ void ClangdLSPServer::onWorkspaceSymbol(
}

void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
Callback<std::optional<Range>> Reply) {
Callback<PrepareRenameResult> Reply) {
Server->prepareRename(
Params.textDocument.uri.file(), Params.position, /*NewName*/ std::nullopt,
Opts.Rename,
[Reply = std::move(Reply)](llvm::Expected<RenameResult> Result) mutable {
if (!Result)
return Reply(Result.takeError());
return Reply(std::move(Result->Target));
PrepareRenameResult PrepareResult;
PrepareResult.range = Result->Target;
PrepareResult.placeholder = Result->Placeholder;
return Reply(std::move(PrepareResult));
});
}

Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/ClangdLSPServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class ClangdLSPServer : private ClangdServer::Callbacks,
void onWorkspaceSymbol(const WorkspaceSymbolParams &,
Callback<std::vector<SymbolInformation>>);
void onPrepareRename(const TextDocumentPositionParams &,
Callback<std::optional<Range>>);
Callback<PrepareRenameResult>);
void onRename(const RenameParams &, Callback<WorkspaceEdit>);
void onHover(const TextDocumentPositionParams &,
Callback<std::optional<Hover>>);
Expand Down
9 changes: 9 additions & 0 deletions clang-tools-extra/clangd/Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,15 @@ bool fromJSON(const llvm::json::Value &Params, RenameParams &R,
O.map("position", R.position) && O.map("newName", R.newName);
}

llvm::json::Value toJSON(const PrepareRenameResult &PRR) {
if (PRR.placeholder.empty())
return toJSON(PRR.range);
return llvm::json::Object{
{"range", toJSON(PRR.range)},
{"placeholder", PRR.placeholder},
};
}

llvm::json::Value toJSON(const DocumentHighlight &DH) {
return llvm::json::Object{
{"range", toJSON(DH.range)},
Expand Down
30 changes: 30 additions & 0 deletions clang-tools-extra/clangd/Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,14 @@ struct RenameParams {
};
bool fromJSON(const llvm::json::Value &, RenameParams &, llvm::json::Path);

struct PrepareRenameResult {
/// Range of the string to rename.
Range range;
/// Placeholder text to use in the editor if non-empty.
std::string placeholder;
};
llvm::json::Value toJSON(const PrepareRenameResult &PRR);

enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };

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

namespace llvm {

template <> struct DenseMapInfo<clang::clangd::Range> {
using Range = clang::clangd::Range;
static inline Range getEmptyKey() {
static clang::clangd::Position Tomb{-1, -1};
static Range R{Tomb, Tomb};
return R;
}
static inline Range getTombstoneKey() {
static clang::clangd::Position Tomb{-2, -2};
static Range R{Tomb, Tomb};
return R;
}
static unsigned getHashValue(const Range &Val) {
return llvm::hash_combine(Val.start.line, Val.start.character, Val.end.line,
Val.end.character);
}
static bool isEqual(const Range &LHS, const Range &RHS) {
return std::tie(LHS.start, LHS.end) == std::tie(RHS.start, RHS.end);
}
};

template <> struct format_provider<clang::clangd::Position> {
static void format(const clang::clangd::Position &Pos, raw_ostream &OS,
StringRef Style) {
Expand Down
11 changes: 8 additions & 3 deletions clang-tools-extra/clangd/index/SymbolCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,21 @@ bool isSpelled(SourceLocation Loc, const NamedDecl &ND) {
auto Name = ND.getDeclName();
const auto NameKind = Name.getNameKind();
if (NameKind != DeclarationName::Identifier &&
NameKind != DeclarationName::CXXConstructorName)
NameKind != DeclarationName::CXXConstructorName &&
NameKind != DeclarationName::ObjCZeroArgSelector &&
NameKind != DeclarationName::ObjCOneArgSelector &&
NameKind != DeclarationName::ObjCMultiArgSelector)
return false;
const auto &AST = ND.getASTContext();
const auto &SM = AST.getSourceManager();
const auto &LO = AST.getLangOpts();
clang::Token Tok;
if (clang::Lexer::getRawToken(Loc, Tok, SM, LO))
return false;
auto StrName = Name.getAsString();
return clang::Lexer::getSpelling(Tok, SM, LO) == StrName;
auto TokSpelling = clang::Lexer::getSpelling(Tok, SM, LO);
if (const auto *MD = dyn_cast<ObjCMethodDecl>(&ND))
return TokSpelling == MD->getSelector().getNameForSlot(0);
return TokSpelling == Name.getAsString();
}
} // namespace

Expand Down

0 comments on commit edfc859

Please sign in to comment.