Update SelectionTree.

This commit is contained in:
ykiko
2024-10-07 21:19:30 +08:00
parent 36cabb9529
commit 0540c67c52
8 changed files with 123 additions and 71 deletions

View File

@@ -76,8 +76,11 @@ if(CLICE_ENABLE_TEST)
# add googletest
add_subdirectory("${CMAKE_SOURCE_DIR}/deps/googletest")
target_include_directories(clice_test PRIVATE "${CMAKE_SOURCE_DIR}/deps/googletest/googletest/include")
target_link_libraries(clice_test PRIVATE gtest_main)
target_include_directories(clice_test PRIVATE
"${CMAKE_SOURCE_DIR}/deps/googletest/googletest/include"
"${CMAKE_SOURCE_DIR}/deps/spdlog/include"
)
target_link_libraries(clice_test PRIVATE gtest_main spdlog::spdlog)
target_clang(clice_test)
file(GLOB_RECURSE AST_SRC_FILES
@@ -86,6 +89,6 @@ if(CLICE_ENABLE_TEST)
"${CMAKE_SOURCE_DIR}/src/Feature/*.cpp"
"${CMAKE_SOURCE_DIR}/src/Support/*.cpp"
)
file(GLOB_RECURSE TEST_SRC_FILES "${CMAKE_SOURCE_DIR}/tests/*/*.cpp")
file(GLOB TEST_SRC_FILES "${CMAKE_SOURCE_DIR}/tests/*/*.cpp")
target_sources(clice_test PRIVATE ${AST_SRC_FILES} ${TEST_SRC_FILES} ${CMAKE_SOURCE_DIR}/tests/main.cpp)
endif()

View File

@@ -13,11 +13,10 @@ namespace clice {
class SelectionTree {
public:
SelectionTree(clang::ASTContext& context, const clang::syntax::TokenBuffer& tokens, unsigned start, unsigned end);
private:
SelectionTree(clang::ASTContext& context,
const clang::syntax::TokenBuffer& tokens,
clang::SourceLocation begin,
clang::SourceLocation end);
};
} // namespace clice

View File

@@ -6,57 +6,47 @@ namespace {
class SelectionBuilder {
public:
SelectionBuilder(clang::SourceRange input, clang::ASTContext& context) : input(input), context(context) {}
void push() {}
void pop() {}
template <typename Callback>
bool hook(const clang::Stmt* stmt, const Callback& callback) {
auto range = stmt->getSourceRange();
template <typename Node>
bool isSkippable(const Node* node) {
if constexpr(std::is_same_v<Node, clang::Decl>) {
if(llvm::dyn_cast<clang::TranslationUnitDecl>(node)) {
return false;
}
}
clang::SourceRange range;
if constexpr(std::is_base_of_v<Node, clang::Attr>) {
range = node->getRange();
} else {
range = node->getSourceRange();
}
if(range.isInvalid()) {
return true;
}
range.dump(context.getSourceManager());
return input.getBegin() > range.getEnd() || input.getEnd() < range.getBegin();
}
template <typename Node, typename Callback>
bool hook(const Node* node, const Callback& callback) {
if(isSkippable(node)) {
return true;
}
return callback();
}
template <typename Callback>
bool hook(const clang::TypeLoc& loc, const Callback& callback) {
auto range = loc.getSourceRange();
return callback();
}
template <typename Callback>
bool hook(const clang::Attr* attr, const Callback& callback) {
auto range = attr->getRange();
return callback();
}
template <typename Callback>
bool hook(const clang::Decl* decl, const Callback& callback) {
auto range = decl->getSourceRange();
return callback();
}
template <typename Callback>
bool hook(const clang::NestedNameSpecifierLoc& NNS, const Callback& callback) {
auto range = NNS.getSourceRange();
return callback();
}
template <typename Callback>
bool hook(const clang::TemplateArgumentLoc& argument, const Callback& callback) {
auto range = argument.getSourceRange();
return callback();
}
template <typename Callback>
bool hook(const clang::CXXBaseSpecifier& base, const Callback& callback) {
auto range = base.getSourceRange();
return callback();
}
template <typename Callback>
bool hook(const clang::CXXCtorInitializer* init, const Callback& callback) {
auto range = init->getSourceRange();
return callback();
}
private:
clang::SourceRange input;
clang::ASTContext& context;
};
class SelectionCollector : public clang::RecursiveASTVisitor<SelectionCollector> {
@@ -78,7 +68,7 @@ public:
}
bool TraverseTypeLoc(clang::TypeLoc loc) {
return builder.hook(loc, [&] {
return builder.hook(&loc, [&] {
return Base::TraverseTypeLoc(loc);
});
}
@@ -102,19 +92,19 @@ public:
}
bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc NNS) {
return builder.hook(NNS, [&] {
return builder.hook(&NNS, [&] {
return Base::TraverseNestedNameSpecifierLoc(NNS);
});
}
bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& argument) {
return builder.hook(argument, [&] {
return builder.hook(&argument, [&] {
return Base::TraverseTemplateArgumentLoc(argument);
});
}
bool TraverseCXXBaseSpecifier(const clang::CXXBaseSpecifier& base) {
return builder.hook(base, [&] {
return builder.hook(&base, [&] {
return Base::TraverseCXXBaseSpecifier(base);
});
}
@@ -136,4 +126,15 @@ private:
} // namespace
SelectionTree::SelectionTree(clang::ASTContext& context,
const clang::syntax::TokenBuffer& tokens,
clang::SourceLocation begin,
clang::SourceLocation end) {
SelectionBuilder builder({begin, end}, context);
SelectionCollector collector(builder);
collector.TraverseAST(context);
// context.getTranslationUnitDecl()->dump();
}
} // namespace clice

View File

@@ -58,23 +58,11 @@ void match(clang::QualType type, std::string name, std::initializer_list<std::st
}
TEST(clice, TemplateResolver) {
// FIXME: more flexible
auto path = test_dir() + "/TemplateResolver";
std::error_code error;
fs::directory_iterator iter(path, error);
fs::directory_iterator end;
while(!error && iter != end) {
auto file = iter->path();
llvm::outs() << "test: " << file << " " << error.message() << "\n";
auto buffer = llvm::MemoryBuffer::getFile(file);
if(!buffer) {
llvm::outs() << "failed to open file: " << buffer.getError().message() << file << "\n";
}
auto content = buffer.get()->getBuffer();
foreachFile("TemplateResolver", [&](std::string file, llvm::StringRef content) {
Visitor visitor(content);
visitor.test();
iter.increment(error);
}
llvm::outs() << fmt::format(fg(fmt::color::yellow_green), "[TemplateResolver: {}]\n", file);
});
}
} // namespace

28
tests/AST/Selection.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include "../Test.h"
#include <Compiler/Selection.h>
namespace {
std::vector<const char*> compileArgs = {
"clang++",
"-std=c++20",
"main.cpp",
"-resource-dir",
"/home/ykiko/C++/clice2/build/lib/clang/20",
};
using namespace clice;
TEST(clice, SelectionTree) {
foreachFile("SelectionTree", [](std::string file, llvm::StringRef content) {
auto AST = ParsedAST::build("main.cpp", content, compileArgs);
auto id = AST->getFileID("main.cpp");
auto& sm = AST->context.getSourceManager();
auto begin = sm.translateLineCol(id, 1, 5);
auto end = sm.translateLineCol(id, 1, 8);
SelectionTree tree(AST->context, AST->tokenBuffer, begin, end);
});
}
} // namespace

View File

@@ -0,0 +1 @@
int foo = 122;

View File

@@ -1,5 +1,33 @@
#pragma once
#include <gtest/gtest.h>
#include <Support/FileSystem.h>
#include <spdlog/fmt/bundled/color.h>
namespace clice {
std::string test_dir();
template <typename Callback>
inline void foreachFile(std::string name, const Callback& callback) {
llvm::SmallString<128> path;
path += test_dir();
path::append(path, name);
std::error_code error;
fs::directory_iterator iter(path, error);
fs::directory_iterator end;
while(!error && iter != end) {
auto file = iter->path();
auto buffer = llvm::MemoryBuffer::getFile(file);
if(!buffer) {
llvm::outs() << "failed to open file: " << buffer.getError().message() << file << "\n";
// TODO:
}
auto content = buffer.get()->getBuffer();
callback(file, content);
iter.increment(error);
}
}
} // namespace clice

View File

@@ -1,6 +1,8 @@
#include <gtest/gtest.h>
#include <llvm/Support/CommandLine.h>
namespace clice {
llvm::cl::opt<std::string> test_dir_path("test-dir",
llvm::cl::desc("specify the test source directory path"),
llvm::cl::value_desc("path"),
@@ -10,6 +12,8 @@ std::string test_dir() {
return test_dir_path;
}
} // namespace clice
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
llvm::cl::ParseCommandLineOptions(argc, argv, "clice test\n");