From 14c9f9466d899508fe09fcc22518666fec5170d6 Mon Sep 17 00:00:00 2001 From: ykiko Date: Thu, 17 Oct 2024 21:51:20 +0800 Subject: [PATCH] Update Index. --- .vscode/launch.json | 11 +++ include/Index/CSIF.h | 13 +-- include/Index/Index.h | 10 --- include/Index/{SymbolID.h => Symbol.h} | 0 include/Index/SymbolSlab.h | 38 +++++++++ include/Support/JSON.h | 8 +- scripts/build-dev-test.sh | 2 +- src/Index/Index.cpp | 105 +++++-------------------- src/Index/SymbolSlab.cpp | 37 +++++++++ tests/Index/Index.cpp | 13 ++- 10 files changed, 132 insertions(+), 105 deletions(-) delete mode 100644 include/Index/Index.h rename include/Index/{SymbolID.h => Symbol.h} (100%) create mode 100644 include/Index/SymbolSlab.h create mode 100644 src/Index/SymbolSlab.cpp diff --git a/.vscode/launch.json b/.vscode/launch.json index 599c1b55..ee045047 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -37,6 +37,17 @@ "--gtest_filter=clice.TemplateResolver" ], "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Index", + "program": "${workspaceFolder}/build/bin/clice_test", + "args": [ + "--test-dir=/home/ykiko/C++/clice2/tests/Source", + "--gtest_filter=clice.Index" + ], + "cwd": "${workspaceFolder}" } ] } \ No newline at end of file diff --git a/include/Index/CSIF.h b/include/Index/CSIF.h index 1319c4cb..d20902fa 100644 --- a/include/Index/CSIF.h +++ b/include/Index/CSIF.h @@ -3,7 +3,7 @@ #include #include -#include "SymbolID.h" +#include namespace clice { @@ -33,8 +33,9 @@ struct CSIF { llvm::ArrayRef symbols; /// The occurrences in the source file. llvm::ArrayRef occurrences; - /// The semantic tokens in the source file. - llvm::ArrayRef semanticTokens; + + ///// The semantic tokens in the source file. + // llvm::ArrayRef semanticTokens; // FIXME: /// The diagnostics in the source file. @@ -53,7 +54,7 @@ enum Role { Override, Write, Read, - + ExplicitInstantiation, ImplicitInstantiation, // TODO: @@ -83,7 +84,7 @@ enum class SymbolKind { struct Symbol { /// The ID of the symbol. - SymbolID id; + SymbolID ID; /// display when hover. llvm::StringRef document; @@ -97,7 +98,7 @@ struct Occurrence { /// The ID of the symbol. SymbolID symbol; /// The range of the occurrence. - // Range range; + protocol::Range range; /// The role of the occurrence. Role role; }; diff --git a/include/Index/Index.h b/include/Index/Index.h deleted file mode 100644 index ac47f26d..00000000 --- a/include/Index/Index.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include - -namespace clice { - -CSIF index(clang::ASTContext& context); - -} diff --git a/include/Index/SymbolID.h b/include/Index/Symbol.h similarity index 100% rename from include/Index/SymbolID.h rename to include/Index/Symbol.h diff --git a/include/Index/SymbolSlab.h b/include/Index/SymbolSlab.h new file mode 100644 index 00000000..5e634270 --- /dev/null +++ b/include/Index/SymbolSlab.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +namespace clice { + +class SymbolSlab { +public: + SymbolSlab& addSymbol(const clang::Decl* decl); + + SymbolSlab& addOccurrence(const clang::Decl* decl, protocol::Range range, Role role); + + SymbolSlab& addRelation(const clang::Decl* from, const clang::Decl* to, Role role); + + std::size_t lookup(const clang::Decl* decl) { + auto iter = cache.find(decl); + if(iter != cache.end()) { + return iter->second; + } + + llvm::outs() << "SymbolSlab::lookup: decl not found\n"; + std::terminate(); + } + + CSIF index(clang::ASTContext& context); + +private: + llvm::BumpPtrAllocator allocator; + llvm::StringSaver saver{allocator}; + + std::vector symbols; + std::vector occurrences; + std::vector> relations; + llvm::DenseMap cache; +}; + +} // namespace clice + diff --git a/include/Support/JSON.h b/include/Support/JSON.h index 995d7cbc..b0da1dc6 100644 --- a/include/Support/JSON.h +++ b/include/Support/JSON.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include namespace clice::json { @@ -17,6 +17,9 @@ constexpr inline bool is_array_v> = true; template constexpr inline bool is_array_v> = true; +template +constexpr inline bool is_array_v> = true; + template constexpr inline bool is_string_v = false; @@ -31,7 +34,8 @@ constexpr inline bool is_string_v = true; template constexpr inline bool is_integral_v = - std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v; + std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v; template json::Value serialize(const Value& value) { diff --git a/scripts/build-dev-test.sh b/scripts/build-dev-test.sh index 2c219785..7cc4afcc 100755 --- a/scripts/build-dev-test.sh +++ b/scripts/build-dev-test.sh @@ -1 +1 @@ -cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug -DCLICE_ENABLE_TEST=ON -DCMAKE_CXX_FLAGS="-fno-rtti -g -O0" \ No newline at end of file +cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug -DCLICE_ENABLE_TEST=ON -DCMAKE_CXX_FLAGS="-fno-rtti -g -O0 -fsanitize=address" \ No newline at end of file diff --git a/src/Index/Index.cpp b/src/Index/Index.cpp index 51949eff..9a203472 100644 --- a/src/Index/Index.cpp +++ b/src/Index/Index.cpp @@ -1,71 +1,15 @@ -#include +#include #include namespace clice { namespace { -class SymbolBuilder { -public: - CSIF dump() { - CSIF csif; - csif.version = "0.0.1"; - csif.language = "C++"; - csif.symbols = symbols; - csif.occurrences = occurrences; - return csif; - } - - std::size_t addSymbolID(const clang::Decl* decl) { - auto iter = cache.find(decl); - if(iter != cache.end()) { - return iter->second; - } - - // Generate and save USR. - llvm::SmallString<128> USR; - clang::index::generateUSRForDecl(decl, USR); - saver.save(USR.str()); - - auto index = symbols.size(); - cache[decl] = index; - return index; - } - - SymbolBuilder& addSymbol(const clang::Decl* decl) { - return *this; - } - - SymbolBuilder& addRelation(const clang::Decl* from, const clang::Decl* to, Role role) { - // FIXME: - return *this; - } - - // TODO: - SymbolBuilder& addOccurrence() { - return *this; - } - - template - bool hook(Node* node, const Callback& callback) { - return true; - } - -private: - std::vector symbols; - std::vector occurrences; - std::vector> relations; - llvm::DenseMap cache; - - llvm::BumpPtrAllocator allocator; - llvm::StringSaver saver{allocator}; -}; - class SymbolCollector : public clang::RecursiveASTVisitor { using Base = clang::RecursiveASTVisitor; public: - SymbolCollector(SymbolBuilder& builder) : builder(builder) {} + SymbolCollector(SymbolSlab& builder) : builder(builder) {} bool TraverseDecl(clang::Decl* decl) { /// `TranslationUnitDecl` has invalid location information. @@ -74,27 +18,22 @@ public: return Base::TraverseDecl(decl); } + builder.addSymbol(decl); // TODO: generate SymbolID for every decl. // Distinguish linkage, for no or internal linkage. // For them, relation lookup is only occurred in current TU. - return builder.hook(decl, [&] { - return Base::TraverseDecl(decl); - }); + return Base::TraverseDecl(decl); } // FIXME: check DeclRefExpr, MemberExpr, etc. bool TraverseStmt(clang::Stmt* stmt) { - return builder.hook(stmt, [&] { - return Base::TraverseStmt(stmt); - }); + return Base::TraverseStmt(stmt); } bool TraverseAttr(clang::Attr* attr) { - return builder.hook(attr, [&] { - return Base::TraverseAttr(attr); - }); + return Base::TraverseAttr(attr); } /// we don't care about the node without location information, so skip them. @@ -117,27 +56,19 @@ public: return TraverseTypeLoc(QTL.getUnqualifiedLoc()); } - return builder.hook(&loc, [&] { - return Base::TraverseTypeLoc(loc); - }); + return Base::TraverseTypeLoc(loc); } bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& argument) { - return builder.hook(&argument, [&] { - return Base::TraverseTemplateArgumentLoc(argument); - }); + return Base::TraverseTemplateArgumentLoc(argument); } bool TraverseCXXBaseSpecifier(const clang::CXXBaseSpecifier& base) { - return builder.hook(&base, [&] { - return Base::TraverseCXXBaseSpecifier(base); - }); + return Base::TraverseCXXBaseSpecifier(base); } bool TraverseConstructorInitializer(clang::CXXCtorInitializer* init) { - return builder.hook(init, [&] { - return Base::TraverseConstructorInitializer(init); - }); + return Base::TraverseConstructorInitializer(init); } bool VisiDeclRefExpr(const clang::DeclRefExpr* expr) { @@ -191,6 +122,7 @@ public: VISIT_TYOELOC(ElaboratedTypeLoc) { auto loc1 = loc.getElaboratedKeywordLoc(); + return true; // render keyword. } @@ -208,16 +140,21 @@ public: // MemberPointerTypeLoc private: - SymbolBuilder& builder; + SymbolSlab& builder; }; } // namespace -CSIF index(clang::ASTContext& context) { - SymbolBuilder builder; - SymbolCollector collector(builder); +CSIF SymbolSlab::index(clang::ASTContext& context) { + CSIF csif; + SymbolCollector collector(*this); collector.TraverseAST(context); - return builder.dump(); + + csif.version = "0.1"; + csif.language = "C++"; + csif.symbols = symbols; + csif.occurrences = occurrences; + return csif; }; } // namespace clice diff --git a/src/Index/SymbolSlab.cpp b/src/Index/SymbolSlab.cpp new file mode 100644 index 00000000..dfb16acd --- /dev/null +++ b/src/Index/SymbolSlab.cpp @@ -0,0 +1,37 @@ +#include +#include + +namespace clice { + +SymbolSlab& SymbolSlab::addSymbol(const clang::Decl* decl) { + // Generate and save USR. + llvm::SmallString<128> USR; + clang::index::generateUSRForDecl(decl, USR); + saver.save(USR.str()); + + if(cache.contains(decl)) { + llvm::outs() << "SymbolSlab::addSymbol: decl already exists\n"; + std::terminate(); + } + + auto index = symbols.size(); + symbols.emplace_back(SymbolID::fromUSR(USR.str())); + cache.try_emplace(decl, index); + return *this; +} + +SymbolSlab& SymbolSlab::addOccurrence(const clang::Decl* decl, protocol::Range range, Role role) { + auto ID = symbols[lookup(decl)].ID; + occurrences.emplace_back(Occurrence{ID, range, role}); + return *this; +} + +SymbolSlab& SymbolSlab::addRelation(const clang::Decl* from, const clang::Decl* to, Role role) { + std::size_t index = lookup(from); + SymbolID fromID = symbols[index].ID; + SymbolID toID = symbols[lookup(to)].ID; + relations[index].emplace_back(Relation{toID, role}); + return *this; +} + +} // namespace clice diff --git a/tests/Index/Index.cpp b/tests/Index/Index.cpp index e0773fef..916721d7 100644 --- a/tests/Index/Index.cpp +++ b/tests/Index/Index.cpp @@ -1,9 +1,11 @@ #include -#include +#include +#include +#include using namespace clice; -TEST(clice_test, index) { +TEST(clice, Index) { std::vector compileArgs = { "clang++", "-std=c++20", @@ -21,4 +23,11 @@ void f() { X x; } )"; + + Compiler compiler("main.cpp", code, compileArgs); + compiler.buildAST(); + SymbolSlab slab; + auto csif = slab.index(compiler.context()); + auto value = json::serialize(csif); + llvm::outs() << value << "\n"; }