15 #include "llvm/ADT/None.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
23 TEST(HeaderSourceSwitchTest, FileHeuristic) {
32 Optional<Path> PathResult =
34 EXPECT_TRUE(PathResult.hasValue());
35 ASSERT_EQ(PathResult.getValue(), FooH);
38 EXPECT_TRUE(PathResult.hasValue());
39 ASSERT_EQ(PathResult.getValue(), FooCpp);
49 EXPECT_TRUE(PathResult.hasValue());
50 ASSERT_EQ(PathResult.getValue(), FooHH);
58 EXPECT_TRUE(PathResult.hasValue());
59 ASSERT_EQ(PathResult.getValue(), Foo2HH);
68 EXPECT_TRUE(PathResult.hasValue());
69 ASSERT_EQ(PathResult.getValue(), Foo3HXX);
74 EXPECT_FALSE(PathResult.hasValue());
78 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(arg))
79 if (ND->getQualifiedNameAsString() ==
Name)
84 TEST(HeaderSourceSwitchTest, GetLocalDecls) {
86 TU.HeaderCode = R
"cpp(
99 // Non-indexable symbols
106 auto AST = TU.
build();
108 testing::UnorderedElementsAre(
109 DeclNamed(
"MainF1"), DeclNamed(
"Foo"), DeclNamed(
"ns::Foo"),
110 DeclNamed(
"ns::Foo::method"), DeclNamed(
"ns::Foo::field")));
113 TEST(HeaderSourceSwitchTest, FromHeaderToSource) {
119 Testing.HeaderFilename =
"TestTU.h";
120 Testing.HeaderCode =
"void A_Sym1();";
121 Testing.Filename =
"a.cpp";
122 Testing.Code =
"void A_Sym1() {};";
123 for (
auto &Sym : Testing.headerSymbols())
124 AllSymbols.insert(Sym);
126 Testing.HeaderCode = R
"cpp(
131 Testing.Filename = "b.cpp";
132 Testing.Code = R
"cpp(
136 for (
auto &Sym : Testing.headerSymbols())
137 AllSymbols.insert(Sym);
142 llvm::StringRef HeaderCode;
143 llvm::Optional<std::string> ExpectedSource;
147 // no definition found in the index.
148 void NonDefinition();
163 // a.cpp and b.cpp have same scope, but a.cpp because "a.cpp" < "b.cpp".
170 // We don't have definition in the index, so stay in the header.
175 for (
const auto &Case : TestCases) {
177 TU.Filename =
"TestTU.h";
178 TU.ExtraArgs.push_back(
"-xc++-header");
179 auto HeaderAST = TU.build();
180 EXPECT_EQ(Case.ExpectedSource,
186 TEST(HeaderSourceSwitchTest, FromSourceToHeader) {
199 TUForIndex.AdditionalFiles["a.h"] = R
"cpp(
202 TUForIndex.AdditionalFiles["b.h"] = R
"cpp(
206 TUForIndex.Filename = "TestTU.cpp";
207 auto Index = TUForIndex.index();
211 llvm::StringRef SourceCode;
212 llvm::Optional<std::string> ExpectedResult;
216 // symbol not in index, no header found
236 // a.h and b.h have same scope, but a.h wins because "a.h" < "b.h".
242 for (
const auto &Case : TestCases) {
244 TU.Filename =
"Test.cpp";
245 auto AST = TU.
build();
246 EXPECT_EQ(Case.ExpectedResult,
252 TEST(HeaderSourceSwitchTest, ClangdServerIntegration) {
253 MockCompilationDatabase CDB;
254 CDB.ExtraClangFlags = {
"-I" +
258 std::string CppPath =
testPath(
"src/lib/test.cpp");
259 std::string HeaderPath =
testPath(
"src/include/test.h");
260 FS.
Files[HeaderPath] =
"void foo();";
261 const std::string FileContent = R
"cpp(
265 FS.Files[CppPath] = FileContent;
267 Options.BuildDynamicSymbolIndex =
true;
268 ClangdServer Server(CDB,
FS, Options);
270 EXPECT_EQ(HeaderPath,