forked from OSchip/llvm-project
[clangd] More unittests for cross-file rename.
Summary: The previous unittests for cross-file rename was kind of weak. With this patch, we should have more test coverage, and it is easy to add more tests in the future. Reviewers: ilya-biryukov, kbobyrev Reviewed By: ilya-biryukov Subscribers: merge_guards_bot, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D71050
This commit is contained in:
parent
54682d871d
commit
158356b82b
|
@ -7,6 +7,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Annotations.h"
|
||||
#include "ClangdServer.h"
|
||||
#include "SyncAPI.h"
|
||||
#include "TestFS.h"
|
||||
#include "TestTU.h"
|
||||
#include "index/Ref.h"
|
||||
|
@ -575,7 +577,7 @@ TEST(RenameTest, MainFileReferencesOnly) {
|
|||
expectedResult(Code, NewName));
|
||||
}
|
||||
|
||||
TEST(RenameTests, CrossFile) {
|
||||
TEST(CrossFileRenameTests, DirtyBuffer) {
|
||||
Annotations FooCode("class [[Foo]] {};");
|
||||
std::string FooPath = testPath("foo.cc");
|
||||
Annotations FooDirtyBuffer("class [[Foo]] {};\n// this is dirty buffer");
|
||||
|
@ -658,6 +660,155 @@ TEST(RenameTests, CrossFile) {
|
|||
testing::HasSubstr("too many occurrences"));
|
||||
}
|
||||
|
||||
TEST(CrossFileRenameTests, WithUpToDateIndex) {
|
||||
MockCompilationDatabase CDB;
|
||||
CDB.ExtraClangFlags = {"-xc++"};
|
||||
class IgnoreDiagnostics : public DiagnosticsConsumer {
|
||||
void onDiagnosticsReady(PathRef File,
|
||||
std::vector<Diag> Diagnostics) override {}
|
||||
} DiagConsumer;
|
||||
// rename is runnning on the "^" point in FooH, and "[[]]" ranges are the
|
||||
// expcted rename occurrences.
|
||||
struct Case {
|
||||
llvm::StringRef FooH;
|
||||
llvm::StringRef FooCC;
|
||||
} Cases [] = {
|
||||
{
|
||||
// classes.
|
||||
R"cpp(
|
||||
class [[Fo^o]] {
|
||||
[[Foo]]();
|
||||
~[[Foo]]();
|
||||
};
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
[[Foo]]::[[Foo]]() {}
|
||||
[[Foo]]::~[[Foo]]() {}
|
||||
|
||||
void func() {
|
||||
[[Foo]] foo;
|
||||
}
|
||||
)cpp",
|
||||
},
|
||||
{
|
||||
// class methods.
|
||||
R"cpp(
|
||||
class Foo {
|
||||
void [[f^oo]]();
|
||||
};
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
void Foo::[[foo]]() {}
|
||||
|
||||
void func(Foo* p) {
|
||||
p->[[foo]]();
|
||||
}
|
||||
)cpp",
|
||||
},
|
||||
{
|
||||
// functions.
|
||||
R"cpp(
|
||||
void [[f^oo]]();
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
void [[foo]]() {}
|
||||
|
||||
void func() {
|
||||
[[foo]]();
|
||||
}
|
||||
)cpp",
|
||||
},
|
||||
{
|
||||
// typedefs.
|
||||
R"cpp(
|
||||
typedef int [[IN^T]];
|
||||
[[INT]] foo();
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
[[INT]] foo() {}
|
||||
)cpp",
|
||||
},
|
||||
{
|
||||
// usings.
|
||||
R"cpp(
|
||||
using [[I^NT]] = int;
|
||||
[[INT]] foo();
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
[[INT]] foo() {}
|
||||
)cpp",
|
||||
},
|
||||
{
|
||||
// variables.
|
||||
R"cpp(
|
||||
static const int [[VA^R]] = 123;
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
int s = [[VAR]];
|
||||
)cpp",
|
||||
},
|
||||
{
|
||||
// scope enums.
|
||||
R"cpp(
|
||||
enum class [[K^ind]] { ABC };
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
[[Kind]] ff() {
|
||||
return [[Kind]]::ABC;
|
||||
}
|
||||
)cpp",
|
||||
},
|
||||
{
|
||||
// enum constants.
|
||||
R"cpp(
|
||||
enum class Kind { [[A^BC]] };
|
||||
)cpp",
|
||||
R"cpp(
|
||||
#include "foo.h"
|
||||
Kind ff() {
|
||||
return Kind::[[ABC]];
|
||||
}
|
||||
)cpp",
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& T : Cases) {
|
||||
Annotations FooH(T.FooH);
|
||||
Annotations FooCC(T.FooCC);
|
||||
std::string FooHPath = testPath("foo.h");
|
||||
std::string FooCCPath = testPath("foo.cc");
|
||||
|
||||
MockFSProvider FS;
|
||||
FS.Files[FooHPath] = FooH.code();
|
||||
FS.Files[FooCCPath] = FooCC.code();
|
||||
|
||||
auto ServerOpts = ClangdServer::optsForTest();
|
||||
ServerOpts.CrossFileRename = true;
|
||||
ServerOpts.BuildDynamicSymbolIndex = true;
|
||||
ClangdServer Server(CDB, FS, DiagConsumer, ServerOpts);
|
||||
|
||||
// Add all files to clangd server to make sure the dynamic index has been
|
||||
// built.
|
||||
runAddDocument(Server, FooHPath, FooH.code());
|
||||
runAddDocument(Server, FooCCPath, FooCC.code());
|
||||
|
||||
llvm::StringRef NewName = "NewName";
|
||||
auto FileEditsList =
|
||||
llvm::cantFail(runRename(Server, FooHPath, FooH.point(), NewName));
|
||||
EXPECT_THAT(applyEdits(std::move(FileEditsList)),
|
||||
UnorderedElementsAre(
|
||||
Pair(Eq(FooHPath), Eq(expectedResult(T.FooH, NewName))),
|
||||
Pair(Eq(FooCCPath), Eq(expectedResult(T.FooCC, NewName)))));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CrossFileRenameTests, CrossFileOnLocalSymbol) {
|
||||
// cross-file rename should work for function-local symbols, even there is no
|
||||
// index provided.
|
||||
|
|
|
@ -99,7 +99,7 @@ runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
|
|||
llvm::Expected<FileEdits> runRename(ClangdServer &Server, PathRef File,
|
||||
Position Pos, llvm::StringRef NewName) {
|
||||
llvm::Optional<llvm::Expected<FileEdits>> Result;
|
||||
Server.rename(File, Pos, NewName, /*WantFormat=*/true, capture(Result));
|
||||
Server.rename(File, Pos, NewName, /*WantFormat=*/false, capture(Result));
|
||||
return std::move(*Result);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue