diff --git a/CMakeLists.txt b/CMakeLists.txt index 70d0a5af..3eef6981 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/include/Compiler/Selection.h b/include/Compiler/Selection.h index 7c4edaf1..ae2ebeb5 100644 --- a/include/Compiler/Selection.h +++ b/include/Compiler/Selection.h @@ -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 diff --git a/src/Compiler/Selection.cpp b/src/Compiler/Selection.cpp index 0584b165..2130c324 100644 --- a/src/Compiler/Selection.cpp +++ b/src/Compiler/Selection.cpp @@ -6,57 +6,47 @@ namespace { class SelectionBuilder { public: + SelectionBuilder(clang::SourceRange input, clang::ASTContext& context) : input(input), context(context) {} + void push() {} void pop() {} - template - bool hook(const clang::Stmt* stmt, const Callback& callback) { - auto range = stmt->getSourceRange(); + template + bool isSkippable(const Node* node) { + if constexpr(std::is_same_v) { + if(llvm::dyn_cast(node)) { + return false; + } + } + + clang::SourceRange range; + if constexpr(std::is_base_of_v) { + 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 + bool hook(const Node* node, const Callback& callback) { + if(isSkippable(node)) { + return true; + } + return callback(); } - template - bool hook(const clang::TypeLoc& loc, const Callback& callback) { - auto range = loc.getSourceRange(); - return callback(); - } - - template - bool hook(const clang::Attr* attr, const Callback& callback) { - auto range = attr->getRange(); - return callback(); - } - - template - bool hook(const clang::Decl* decl, const Callback& callback) { - auto range = decl->getSourceRange(); - return callback(); - } - - template - bool hook(const clang::NestedNameSpecifierLoc& NNS, const Callback& callback) { - auto range = NNS.getSourceRange(); - return callback(); - } - - template - bool hook(const clang::TemplateArgumentLoc& argument, const Callback& callback) { - auto range = argument.getSourceRange(); - return callback(); - } - - template - bool hook(const clang::CXXBaseSpecifier& base, const Callback& callback) { - auto range = base.getSourceRange(); - return callback(); - } - - template - 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 { @@ -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 diff --git a/tests/AST/Resolver.cpp b/tests/AST/Resolver.cpp index 22f9f1b8..03ef15ab 100644 --- a/tests/AST/Resolver.cpp +++ b/tests/AST/Resolver.cpp @@ -58,23 +58,11 @@ void match(clang::QualType type, std::string name, std::initializer_listpath(); - 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 diff --git a/tests/AST/Selection.cpp b/tests/AST/Selection.cpp new file mode 100644 index 00000000..53278154 --- /dev/null +++ b/tests/AST/Selection.cpp @@ -0,0 +1,28 @@ +#include "../Test.h" +#include + +namespace { + +std::vector 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 + diff --git a/tests/Source/SelectionTree/test.cpp b/tests/Source/SelectionTree/test.cpp new file mode 100644 index 00000000..676a651f --- /dev/null +++ b/tests/Source/SelectionTree/test.cpp @@ -0,0 +1 @@ +int foo = 122; \ No newline at end of file diff --git a/tests/Test.h b/tests/Test.h index cbed29d4..076e840f 100644 --- a/tests/Test.h +++ b/tests/Test.h @@ -1,5 +1,33 @@ +#pragma once + #include #include +#include +namespace clice { std::string test_dir(); + +template +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 + diff --git a/tests/main.cpp b/tests/main.cpp index ee85a7a0..7500346f 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,6 +1,8 @@ #include #include +namespace clice { + llvm::cl::opt 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");