Files
clice/unittests/Index/Index.cpp
2024-11-02 13:56:06 +08:00

192 lines
6.2 KiB
C++

#include <gtest/gtest.h>
#include <Support/FileSystem.h>
#include <Index/Serialize.h>
#include <Compiler/Compiler.h>
#include "../Test.h"
namespace {
using namespace clice;
struct IndexTester {
IndexTester(llvm::StringRef filepath) {
llvm::SmallString<128> path;
path::append(path, test_dir(), "Index", filepath);
this->filepath = path.str();
args = {
"clang++",
"-std=c++20",
this->filepath.c_str(),
"-resource-dir",
"/home/ykiko/C++/clice2/build/lib/clang/20",
};
compiler = std::make_unique<Compiler>(args);
compiler->buildAST();
index = index::index(*compiler);
mainFileIndex = mainFile();
}
uint32_t mainFile() {
for(uint32_t i = 0; i < index.files.size(); i++) {
if(!index.files[i].include.isValid()) {
return i;
}
}
std::terminate();
}
auto& findSymbol(index::Position source) {
auto occurrence = std::lower_bound(index.occurrences.begin(),
index.occurrences.end(),
source,
[](const auto& occurrence, index::Position pos) {
return occurrence.location.end < pos;
});
EXPECT_TRUE(occurrence != index.occurrences.end());
EXPECT_TRUE(occurrence->location.begin <= source);
auto& symbol = index.symbols[occurrence->symbol];
// auto symbol = std::lower_bound(index.symbols.begin(),
// index.symbols.end(),
// id,
// [](const auto& symbol, const auto& id) {
// return refl::less(symbol.id, id);
// });
// EXPECT_TRUE(symbol != index.symbols.end());
// EXPECT_TRUE(refl::equal(symbol->id, id));
return symbol;
}
IndexTester& GoToDefinition(index::Position source, index::Position target) {
auto& symbol = findSymbol(source);
bool hasDefinition = false;
for(auto& relation: symbol.relations) {
if(relation.kind.is(index::RelationKind::Definition)) {
auto location = relation.location;
hasDefinition = true;
EXPECT_EQ(location.begin, target);
}
}
EXPECT_TRUE(hasDefinition);
return *this;
}
IndexTester& CallRelation(index::Position source, index::Position target) {
auto& symbol = findSymbol(source);
bool hasCall = false;
for(auto& relation: symbol.relations) {
if(relation.kind.is(index::RelationKind::Callee)) {
auto location = relation.location;
hasCall = true;
// EXPECT_EQ(location.begin, target);
llvm::outs() << json::serialize(relation) << "\n";
}
if(relation.kind.is(index::RelationKind::Caller)) {
auto location = relation.location;
hasCall = true;
// EXPECT_EQ(location.begin, target);
}
}
EXPECT_TRUE(hasCall);
return *this;
}
uint32_t mainFileIndex;
std::string filepath;
std::vector<const char*> args;
std::unique_ptr<Compiler> compiler;
index::memory::Index index;
};
// TEST(Index, index) {
// foreachFile("Index", [](std::string filepath, llvm::StringRef content) {
// std::vector<const char*> compileArgs = {
// "clang++",
// "-std=c++20",
// filepath.c_str(),
// "-resource-dir",
// "/home/ykiko/C++/clice2/build/lib/clang/20",
// };
// if(filepath.ends_with("MemberExpr.cpp")) {
// Compiler compiler(compileArgs);
// compiler.buildAST();
//
// auto index = index::index(compiler);
// llvm::outs() << "files count:" << index.files.size() << "\n";
// auto json = index::toJson(index);
// // llvm::outs() << json << "\n";
//
// std::error_code error;
// llvm::raw_fd_ostream file("index.json", error);
// file << json;
// // auto file = index.files[0];
// // while(file.include.isValid()) {
// // auto includeLoc = file.include;
// // llvm::outs() << index.files[includeLoc.file].path << ":" <<
// includeLoc.begin.line
// // << ":" << includeLoc.begin.column << "\n"; file =
// index.files[file.include.file];
// // }
// // llvm::outs() << file.path << "\n";
// }
// });
// }
TEST(Index, Expr) {
IndexTester tester("Expr.cpp");
// tester.GoToDefinition(index::Position(9, 14), index::Position(4, 9));
tester.compiler->tu()->dump();
}
TEST(Index, Macro) {
IndexTester tester("Macro.cpp");
// tester.GoToDefinition(index::Position(9, 14), index::Position(4, 9));
tester.compiler->tu()->dump();
auto& srcMgr = tester.compiler->srcMgr();
for(auto tok: tester.compiler->tokBuf().expandedTokens()) {
if(tok.location().isMacroID()) {
llvm::outs() << tok.text(srcMgr) << " ";
llvm::outs() << srcMgr.getPresumedLineNumber(tok.location()) << ":"
<< srcMgr.getPresumedColumnNumber(tok.location()) << "\n";
tok.location().dump(srcMgr);
}
}
}
TEST(Index, Call) {
IndexTester tester("Call.cpp");
// tester.CallRelation(index::Position(9, 14), index::Position(4, 9));
tester.compiler->tu()->dump();
auto json = index::toJson(tester.index);
std::error_code error;
llvm::raw_fd_ostream file("index.json", error);
file << json;
for(auto& symbol: tester.index.symbols) {
llvm::outs() << symbol.name << "\n";
for(auto& relation: symbol.relations) {
llvm::outs() << " " << relation.kind << "\n"
<< json::serialize(relation.location) << "\n";
}
}
int $x = 1;
}
} // namespace