Update SelectionTree.
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
28
tests/AST/Selection.cpp
Normal 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
|
||||
|
||||
1
tests/Source/SelectionTree/test.cpp
Normal file
1
tests/Source/SelectionTree/test.cpp
Normal file
@@ -0,0 +1 @@
|
||||
int foo = 122;
|
||||
28
tests/Test.h
28
tests/Test.h
@@ -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
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user