[clang-tools-extra] 0f0cbcc - [clangd] Extend the rename API.
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 2 07:04:10 PDT 2020
Author: Haojian Wu
Date: 2020-10-02T16:03:44+02:00
New Revision: 0f0cbcc4b166f32603371fb1d62ef3816cf8425f
URL: https://github.com/llvm/llvm-project/commit/0f0cbcc4b166f32603371fb1d62ef3816cf8425f
DIFF: https://github.com/llvm/llvm-project/commit/0f0cbcc4b166f32603371fb1d62ef3816cf8425f.diff
LOG: [clangd] Extend the rename API.
several changes:
- return a structure result in rename API;
- prepareRename now returns more information (main-file occurrences);
- remove the duplicated detecting-touch-identifier code in prepareRename (which is implemented in rename API);
Differential Revision: https://reviews.llvm.org/D88634
Added:
Modified:
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/ClangdServer.h
clang-tools-extra/clangd/SourceCode.h
clang-tools-extra/clangd/refactor/Rename.cpp
clang-tools-extra/clangd/refactor/Rename.h
clang-tools-extra/clangd/test/rename.test
clang-tools-extra/clangd/unittests/RenameTests.cpp
clang-tools-extra/clangd/unittests/SyncAPI.cpp
clang-tools-extra/clangd/unittests/SyncAPI.h
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index c2915aeada4f..34d5a305494c 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -793,8 +793,13 @@ void ClangdLSPServer::onWorkspaceSymbol(
void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
Callback<llvm::Optional<Range>> Reply) {
- Server->prepareRename(Params.textDocument.uri.file(), Params.position,
- Opts.Rename, std::move(Reply));
+ Server->prepareRename(
+ Params.textDocument.uri.file(), Params.position, Opts.Rename,
+ [Reply = std::move(Reply)](llvm::Expected<RenameResult> Result) mutable {
+ if (!Result)
+ return Reply(Result.takeError());
+ return Reply(std::move(Result->Target));
+ });
}
void ClangdLSPServer::onRename(const RenameParams &Params,
@@ -806,14 +811,14 @@ void ClangdLSPServer::onRename(const RenameParams &Params,
Server->rename(
File, Params.position, Params.newName, Opts.Rename,
[File, Params, Reply = std::move(Reply),
- this](llvm::Expected<FileEdits> Edits) mutable {
- if (!Edits)
- return Reply(Edits.takeError());
- if (auto Err = validateEdits(DraftMgr, *Edits))
+ this](llvm::Expected<RenameResult> R) mutable {
+ if (!R)
+ return Reply(R.takeError());
+ if (auto Err = validateEdits(DraftMgr, R->GlobalChanges))
return Reply(std::move(Err));
WorkspaceEdit Result;
Result.changes.emplace();
- for (const auto &Rep : *Edits) {
+ for (const auto &Rep : R->GlobalChanges) {
(*Result.changes)[URI::createFile(Rep.first()).toString()] =
Rep.second.asTextEdits();
}
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index 8c73b6a7d063..0840155fc8f9 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -400,46 +400,35 @@ void ClangdServer::formatOnType(PathRef File, llvm::StringRef Code,
void ClangdServer::prepareRename(PathRef File, Position Pos,
const RenameOptions &RenameOpts,
- Callback<llvm::Optional<Range>> CB) {
+ Callback<RenameResult> CB) {
auto Action = [Pos, File = File.str(), CB = std::move(CB), RenameOpts,
this](llvm::Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
return CB(InpAST.takeError());
- auto &AST = InpAST->AST;
- const auto &SM = AST.getSourceManager();
- auto Loc = sourceLocationInMainFile(SM, Pos);
- if (!Loc)
- return CB(Loc.takeError());
- const auto *TouchingIdentifier =
- spelledIdentifierTouching(*Loc, AST.getTokens());
- if (!TouchingIdentifier)
- return CB(llvm::None); // no rename on non-identifiers.
-
- auto Range = halfOpenToRange(
- SM, CharSourceRange::getCharRange(TouchingIdentifier->location(),
- TouchingIdentifier->endLocation()));
-
- if (RenameOpts.AllowCrossFile)
- // FIXME: we now assume cross-file rename always succeeds, revisit this.
- return CB(Range);
-
- // Performing the local rename isn't substantially more expensive than
- // doing an AST-based check, so we just rename and throw away the results.
- auto Changes = clangd::rename({Pos, "dummy", AST, File, Index, RenameOpts,
- /*GetDirtyBuffer=*/nullptr});
- if (!Changes) {
+ // prepareRename is latency-sensitive:
+ // - for single-file rename, performing rename isn't substantially more
+ // expensive than doing an AST-based check (the index is used to see if
+ // the rename is complete);
+ // - for cross-file rename, we deliberately pass a nullptr index to save
+ // the cost, thus the result may be incomplete as it only contains
+ // main-file occurrences;
+ auto Results = clangd::rename({Pos, /*NewName*/ "", InpAST->AST, File,
+ RenameOpts.AllowCrossFile ? nullptr : Index,
+ RenameOpts});
+ if (!Results) {
// LSP says to return null on failure, but that will result in a generic
// failure message. If we send an LSP error response, clients can surface
// the message to users (VSCode does).
- return CB(Changes.takeError());
+ return CB(Results.takeError());
}
- return CB(Range);
+ return CB(*Results);
};
WorkScheduler.runWithAST("PrepareRename", File, std::move(Action));
}
void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
- const RenameOptions &Opts, Callback<FileEdits> CB) {
+ const RenameOptions &Opts,
+ Callback<RenameResult> CB) {
// A snapshot of all file dirty buffers.
llvm::StringMap<std::string> Snapshot = WorkScheduler.getAllFileContents();
auto Action = [File = File.str(), NewName = NewName.str(), Pos, Opts,
@@ -457,24 +446,24 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
return llvm::None;
return It->second;
};
- auto Edits = clangd::rename(
+ auto R = clangd::rename(
{Pos, NewName, InpAST->AST, File, Index, Opts, GetDirtyBuffer});
- if (!Edits)
- return CB(Edits.takeError());
+ if (!R)
+ return CB(R.takeError());
if (Opts.WantFormat) {
auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
*InpAST->Inputs.TFS);
llvm::Error Err = llvm::Error::success();
- for (auto &E : *Edits)
+ for (auto &E : R->GlobalChanges)
Err =
llvm::joinErrors(reformatEdit(E.getValue(), Style), std::move(Err));
if (Err)
return CB(std::move(Err));
}
- RenameFiles.record(Edits->size());
- return CB(std::move(*Edits));
+ RenameFiles.record(R->GlobalChanges.size());
+ return CB(*R);
};
WorkScheduler.runWithAST("Rename", File, std::move(Action));
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h
index d801d3cd4353..a9d46fa5278f 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -273,9 +273,12 @@ class ClangdServer {
StringRef TriggerText, Callback<std::vector<TextEdit>> CB);
/// Test the validity of a rename operation.
+ ///
+ /// The returned result describes edits in the main-file only (all
+ /// occurrences of the renamed symbol are simply deleted.
void prepareRename(PathRef File, Position Pos,
const RenameOptions &RenameOpts,
- Callback<llvm::Optional<Range>> CB);
+ Callback<RenameResult> CB);
/// Rename all occurrences of the symbol at the \p Pos in \p File to
/// \p NewName.
@@ -283,7 +286,7 @@ class ClangdServer {
/// embedders could use this method to get all occurrences of the symbol (e.g.
/// highlighting them in prepare stage).
void rename(PathRef File, Position Pos, llvm::StringRef NewName,
- const RenameOptions &Opts, Callback<FileEdits> CB);
+ const RenameOptions &Opts, Callback<RenameResult> CB);
struct TweakRef {
std::string ID; /// ID to pass for applyTweak.
diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h
index eb63a191ab90..128f985a5266 100644
--- a/clang-tools-extra/clangd/SourceCode.h
+++ b/clang-tools-extra/clangd/SourceCode.h
@@ -181,6 +181,8 @@ struct Edit {
tooling::Replacements Replacements;
std::string InitialCode;
+ Edit() = default;
+
Edit(llvm::StringRef Code, tooling::Replacements Reps)
: Replacements(std::move(Reps)), InitialCode(Code) {}
diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp
index 2744caa58648..c48bc2856cb7 100644
--- a/clang-tools-extra/clangd/refactor/Rename.cpp
+++ b/clang-tools-extra/clangd/refactor/Rename.cpp
@@ -182,8 +182,6 @@ llvm::Optional<ReasonToReject> renameable(const NamedDecl &RenameDecl,
}
assert(CrossFile);
- if (!Index)
- return ReasonToReject::NoIndexProvided;
// FIXME: Renaming virtual methods requires to rename all overridens in
// subclasses, our index doesn't have this information.
@@ -427,7 +425,7 @@ void findNearMiss(
} // namespace
-llvm::Expected<FileEdits> rename(const RenameInputs &RInputs) {
+llvm::Expected<RenameResult> rename(const RenameInputs &RInputs) {
trace::Span Tracer("Rename flow");
const auto &Opts = RInputs.Opts;
ParsedAST &AST = RInputs.AST;
@@ -456,9 +454,13 @@ llvm::Expected<FileEdits> rename(const RenameInputs &RInputs) {
return Loc.takeError();
const syntax::Token *IdentifierToken =
spelledIdentifierTouching(*Loc, AST.getTokens());
+
// Renames should only triggered on identifiers.
if (!IdentifierToken)
return makeError(ReasonToReject::NoSymbolFound);
+ Range CurrentIdentifier = halfOpenToRange(
+ SM, CharSourceRange::getCharRange(IdentifierToken->location(),
+ IdentifierToken->endLocation()));
// FIXME: Renaming macros is not supported yet, the macro-handling code should
// be moved to rename tooling library.
if (locateMacroAt(*IdentifierToken, AST.getPreprocessor()))
@@ -489,32 +491,40 @@ llvm::Expected<FileEdits> rename(const RenameInputs &RInputs) {
auto MainFileRenameEdit = renameWithinFile(AST, RenameDecl, RInputs.NewName);
if (!MainFileRenameEdit)
return MainFileRenameEdit.takeError();
+ RenameResult Result;
+ Result.Target = CurrentIdentifier;
+ Edit MainFileEdits = Edit(MainFileCode, std::move(*MainFileRenameEdit));
+ llvm::for_each(MainFileEdits.asTextEdits(), [&Result](const TextEdit &TE) {
+ Result.LocalChanges.push_back(TE.range);
+ });
// return the main file edit if this is a within-file rename or the symbol
// being renamed is function local.
if (!Opts.AllowCrossFile || RenameDecl.getParentFunctionOrMethod()) {
- return FileEdits(
- {std::make_pair(RInputs.MainFilePath,
- Edit{MainFileCode, std::move(*MainFileRenameEdit)})});
+ Result.GlobalChanges = FileEdits(
+ {std::make_pair(RInputs.MainFilePath, std::move(MainFileEdits))});
+ return Result;
}
- FileEdits Results;
- // Renameable safely guards us that at this point we are renaming a local
- // symbol if we don't have index.
- if (RInputs.Index) {
- auto OtherFilesEdits = renameOutsideFile(
- RenameDecl, RInputs.MainFilePath, RInputs.NewName, *RInputs.Index,
- Opts.LimitFiles == 0 ? std::numeric_limits<size_t>::max()
- : Opts.LimitFiles,
- GetFileContent);
- if (!OtherFilesEdits)
- return OtherFilesEdits.takeError();
- Results = std::move(*OtherFilesEdits);
+ // If the index is nullptr, we don't know the completeness of the result, so
+ // we don't populate the field GlobalChanges.
+ if (!RInputs.Index) {
+ assert(Result.GlobalChanges.empty() && Opts.AllowCrossFile);
+ return Result;
}
+
+ auto OtherFilesEdits = renameOutsideFile(
+ RenameDecl, RInputs.MainFilePath, RInputs.NewName, *RInputs.Index,
+ Opts.LimitFiles == 0 ? std::numeric_limits<size_t>::max()
+ : Opts.LimitFiles,
+ GetFileContent);
+ if (!OtherFilesEdits)
+ return OtherFilesEdits.takeError();
+ Result.GlobalChanges = *OtherFilesEdits;
// Attach the rename edits for the main file.
- Results.try_emplace(RInputs.MainFilePath, MainFileCode,
- std::move(*MainFileRenameEdit));
- return Results;
+ Result.GlobalChanges.try_emplace(RInputs.MainFilePath,
+ std::move(MainFileEdits));
+ return Result;
}
llvm::Expected<Edit> buildRenameEdit(llvm::StringRef AbsFilePath,
diff --git a/clang-tools-extra/clangd/refactor/Rename.h b/clang-tools-extra/clangd/refactor/Rename.h
index e27951605ebc..ff23a67cfc46 100644
--- a/clang-tools-extra/clangd/refactor/Rename.h
+++ b/clang-tools-extra/clangd/refactor/Rename.h
@@ -55,10 +55,20 @@ struct RenameInputs {
DirtyBufferGetter GetDirtyBuffer = nullptr;
};
+struct RenameResult {
+ // The range of the symbol that the user can attempt to rename.
+ Range Target;
+ // Rename occurrences for the current main file.
+ std::vector<Range> LocalChanges;
+ // Complete edits for the rename, including LocalChanges.
+ // If the full set of changes is unknown, this field is empty.
+ FileEdits GlobalChanges;
+};
+
/// Renames all occurrences of the symbol. The result edits are unformatted.
/// If AllowCrossFile is false, returns an error if rename a symbol that's used
/// in another file (per the index).
-llvm::Expected<FileEdits> rename(const RenameInputs &RInputs);
+llvm::Expected<RenameResult> rename(const RenameInputs &RInputs);
/// Generates rename edits that replaces all given occurrences with the
/// NewName.
diff --git a/clang-tools-extra/clangd/test/rename.test b/clang-tools-extra/clangd/test/rename.test
index 214efb2b5e39..527b4263443a 100644
--- a/clang-tools-extra/clangd/test/rename.test
+++ b/clang-tools-extra/clangd/test/rename.test
@@ -21,9 +21,12 @@
# CHECK-NEXT: }
---
{"jsonrpc":"2.0","id":2,"method":"textDocument/prepareRename","params":{"textDocument":{"uri":"test:///foo.cpp"},"position":{"line":0,"character":2}}}
-# CHECK: "id": 2,
-# CHECK-NEXT: "jsonrpc": "2.0",
-# CHECK-NEXT: "result": null
+# CHECK: "error": {
+# CHECK-NEXT: "code": -32001,
+# CHECK-NEXT: "message": "Cannot rename symbol: there is no symbol at the given location"
+# CHECK-NEXT: },
+# CHECK-NEXT: "id": 2,
+# CHECK-NEXT: "jsonrpc": "2.0"
---
{"jsonrpc":"2.0","id":4,"method":"textDocument/rename","params":{"textDocument":{"uri":"test:///foo.cpp"},"position":{"line":0,"character":2},"newName":"bar"}}
# CHECK: "error": {
diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp
index 08af7aad0099..cc2454e9d04e 100644
--- a/clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -502,9 +502,10 @@ TEST(RenameTest, WithinFileRename) {
auto RenameResult =
rename({RenamePos, NewName, AST, testPath(TU.Filename)});
ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
- ASSERT_EQ(1u, RenameResult->size());
- EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
- expectedResult(Code, NewName));
+ ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+ EXPECT_EQ(
+ applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
+ expectedResult(Code, NewName));
}
}
}
@@ -653,8 +654,8 @@ TEST(RenameTest, Renameable) {
} else {
EXPECT_TRUE(bool(Results)) << "rename returned an error: "
<< llvm::toString(Results.takeError());
- ASSERT_EQ(1u, Results->size());
- EXPECT_EQ(applyEdits(std::move(*Results)).front().second,
+ ASSERT_EQ(1u, Results->GlobalChanges.size());
+ EXPECT_EQ(applyEdits(std::move(Results->GlobalChanges)).front().second,
expectedResult(T, NewName));
}
}
@@ -683,8 +684,8 @@ TEST(RenameTest, MainFileReferencesOnly) {
auto RenameResult =
rename({Code.point(), NewName, AST, testPath(TU.Filename)});
ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
- ASSERT_EQ(1u, RenameResult->size());
- EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+ ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+ EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
expectedResult(Code, NewName));
}
@@ -703,6 +704,44 @@ TEST(RenameTest, ProtobufSymbolIsExcluded) {
testing::HasSubstr("not a supported kind"));
}
+TEST(RenameTest, PrepareRename) {
+ Annotations FooH("void func();");
+ Annotations FooCC(R"cpp(
+ #include "foo.h"
+ void [[fu^nc]]() {}
+ )cpp");
+ std::string FooHPath = testPath("foo.h");
+ std::string FooCCPath = testPath("foo.cc");
+ MockFS FS;
+ FS.Files[FooHPath] = std::string(FooH.code());
+ FS.Files[FooCCPath] = std::string(FooCC.code());
+
+ auto ServerOpts = ClangdServer::optsForTest();
+ ServerOpts.BuildDynamicSymbolIndex = true;
+
+ MockCompilationDatabase CDB;
+ ClangdServer Server(CDB, FS, ServerOpts);
+ runAddDocument(Server, FooHPath, FooH.code());
+ runAddDocument(Server, FooCCPath, FooCC.code());
+
+ auto Results =
+ runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/true});
+ // verify that for multi-file rename, we only return main-file occurrences.
+ ASSERT_TRUE(bool(Results)) << Results.takeError();
+ // We don't know the result is complete in prepareRename (passing a nullptr
+ // index internally), so GlobalChanges should be empty.
+ EXPECT_TRUE(Results->GlobalChanges.empty());
+ EXPECT_THAT(FooCC.ranges(),
+ testing::UnorderedElementsAreArray(Results->LocalChanges));
+
+ // single-file rename on global symbols, we should report an error.
+ Results =
+ runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/false});
+ EXPECT_FALSE(Results);
+ EXPECT_THAT(llvm::toString(Results.takeError()),
+ testing::HasSubstr("is used outside"));
+}
+
TEST(CrossFileRenameTests, DirtyBuffer) {
Annotations FooCode("class [[Foo]] {};");
std::string FooPath = testPath("foo.cc");
@@ -741,7 +780,7 @@ TEST(CrossFileRenameTests, DirtyBuffer) {
GetDirtyBuffer});
ASSERT_TRUE(bool(Results)) << Results.takeError();
EXPECT_THAT(
- applyEdits(std::move(*Results)),
+ applyEdits(std::move(Results->GlobalChanges)),
UnorderedElementsAre(
Pair(Eq(FooPath), Eq(expectedResult(FooDirtyBuffer, NewName))),
Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
@@ -762,7 +801,7 @@ TEST(CrossFileRenameTests, DirtyBuffer) {
GetDirtyBuffer});
ASSERT_TRUE(bool(Results)) << Results.takeError();
EXPECT_THAT(
- applyEdits(std::move(*Results)),
+ applyEdits(std::move(Results->GlobalChanges)),
UnorderedElementsAre(
Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
@@ -847,7 +886,7 @@ TEST(CrossFileRenameTests, DeduplicateRefsFromIndex) {
{/*CrossFile=*/true}});
ASSERT_TRUE(bool(Results)) << Results.takeError();
EXPECT_THAT(
- applyEdits(std::move(*Results)),
+ applyEdits(std::move(Results->GlobalChanges)),
UnorderedElementsAre(
Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
@@ -1047,7 +1086,7 @@ TEST(CrossFileRenameTests, WithUpToDateIndex) {
Server, FooHPath, RenamePos, NewName, {/*CrossFile=*/true}));
EXPECT_THAT(Tracer.takeMetric("rename_files"), ElementsAre(2));
EXPECT_THAT(
- applyEdits(std::move(FileEditsList)),
+ applyEdits(std::move(FileEditsList.GlobalChanges)),
UnorderedElementsAre(
Pair(Eq(FooHPath), Eq(expectedResult(T.FooH, NewName))),
Pair(Eq(FooCCPath), Eq(expectedResult(T.FooCC, NewName)))));
@@ -1066,7 +1105,7 @@ TEST(CrossFileRenameTests, CrossFileOnLocalSymbol) {
auto Results = rename({Code.point(), NewName, AST, Path});
ASSERT_TRUE(bool(Results)) << Results.takeError();
EXPECT_THAT(
- applyEdits(std::move(*Results)),
+ applyEdits(std::move(Results->GlobalChanges)),
UnorderedElementsAre(Pair(Eq(Path), Eq(expectedResult(Code, NewName)))));
}
diff --git a/clang-tools-extra/clangd/unittests/SyncAPI.cpp b/clang-tools-extra/clangd/unittests/SyncAPI.cpp
index fb810f40c79f..6d6879ab62db 100644
--- a/clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ b/clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -97,14 +97,22 @@ runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
return std::move(*Result);
}
-llvm::Expected<FileEdits> runRename(ClangdServer &Server, PathRef File,
- Position Pos, llvm::StringRef NewName,
- const RenameOptions &RenameOpts) {
- llvm::Optional<llvm::Expected<FileEdits>> Result;
+llvm::Expected<RenameResult> runRename(ClangdServer &Server, PathRef File,
+ Position Pos, llvm::StringRef NewName,
+ const RenameOptions &RenameOpts) {
+ llvm::Optional<llvm::Expected<RenameResult>> Result;
Server.rename(File, Pos, NewName, RenameOpts, capture(Result));
return std::move(*Result);
}
+llvm::Expected<RenameResult> runPrepareRename(ClangdServer &Server,
+ PathRef File, Position Pos,
+ const RenameOptions &RenameOpts) {
+ llvm::Optional<llvm::Expected<RenameResult>> Result;
+ Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+ return std::move(*Result);
+}
+
llvm::Expected<tooling::Replacements>
runFormatFile(ClangdServer &Server, PathRef File, StringRef Code) {
llvm::Optional<llvm::Expected<tooling::Replacements>> Result;
diff --git a/clang-tools-extra/clangd/unittests/SyncAPI.h b/clang-tools-extra/clangd/unittests/SyncAPI.h
index 944717db4151..aa641fee91af 100644
--- a/clang-tools-extra/clangd/unittests/SyncAPI.h
+++ b/clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -40,9 +40,13 @@ runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos);
llvm::Expected<std::vector<DocumentHighlight>>
runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos);
-llvm::Expected<FileEdits> runRename(ClangdServer &Server, PathRef File,
- Position Pos, StringRef NewName,
- const clangd::RenameOptions &RenameOpts);
+llvm::Expected<RenameResult> runRename(ClangdServer &Server, PathRef File,
+ Position Pos, StringRef NewName,
+ const clangd::RenameOptions &RenameOpts);
+
+llvm::Expected<RenameResult>
+runPrepareRename(ClangdServer &Server, PathRef File, Position Pos,
+ const clangd::RenameOptions &RenameOpts);
llvm::Expected<tooling::Replacements>
runFormatFile(ClangdServer &Server, PathRef File, StringRef Code);
More information about the cfe-commits
mailing list