Update Index.
This commit is contained in:
11
.vscode/launch.json
vendored
11
.vscode/launch.json
vendored
@@ -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}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <Support/ADT.h>
|
||||
#include <Protocol/Basic.h>
|
||||
|
||||
#include "SymbolID.h"
|
||||
#include <Index/Symbol.h>
|
||||
|
||||
namespace clice {
|
||||
|
||||
@@ -33,8 +33,9 @@ struct CSIF {
|
||||
llvm::ArrayRef<Symbol> symbols;
|
||||
/// The occurrences in the source file.
|
||||
llvm::ArrayRef<Occurrence> occurrences;
|
||||
/// The semantic tokens in the source file.
|
||||
llvm::ArrayRef<std::uint32_t> semanticTokens;
|
||||
|
||||
///// The semantic tokens in the source file.
|
||||
// llvm::ArrayRef<std::uint32_t> 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;
|
||||
};
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Index/CSIF.h>
|
||||
#include <Compiler/Compiler.h>
|
||||
|
||||
namespace clice {
|
||||
|
||||
CSIF index(clang::ASTContext& context);
|
||||
|
||||
}
|
||||
38
include/Index/SymbolSlab.h
Normal file
38
include/Index/SymbolSlab.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <Index/CSIF.h>
|
||||
|
||||
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<Symbol> symbols;
|
||||
std::vector<Occurrence> occurrences;
|
||||
std::vector<std::vector<Relation>> relations;
|
||||
llvm::DenseMap<const clang::Decl*, std::size_t> cache;
|
||||
};
|
||||
|
||||
} // namespace clice
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <llvm/Support/JSON.h>
|
||||
#include <Support/Reflection.h>
|
||||
#include <array>
|
||||
|
||||
namespace clice::json {
|
||||
|
||||
@@ -17,6 +17,9 @@ constexpr inline bool is_array_v<std::array<T, N>> = true;
|
||||
template <typename T, typename A>
|
||||
constexpr inline bool is_array_v<std::vector<T, A>> = true;
|
||||
|
||||
template <typename T>
|
||||
constexpr inline bool is_array_v<llvm::ArrayRef<T>> = true;
|
||||
|
||||
template <typename T>
|
||||
constexpr inline bool is_string_v = false;
|
||||
|
||||
@@ -31,7 +34,8 @@ constexpr inline bool is_string_v<llvm::StringRef> = true;
|
||||
|
||||
template <typename T>
|
||||
constexpr inline bool is_integral_v =
|
||||
std::is_same_v<T, int> || std::is_same_v<T, unsigned> || std::is_same_v<T, long> || std::is_same_v<T, long long>;
|
||||
std::is_same_v<T, int> || std::is_same_v<T, unsigned> || std::is_same_v<T, long> ||
|
||||
std::is_same_v<T, unsigned long> || std::is_same_v<T, long long> || std::is_same_v<T, unsigned long long>;
|
||||
|
||||
template <typename Value>
|
||||
json::Value serialize(const Value& value) {
|
||||
|
||||
@@ -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"
|
||||
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"
|
||||
@@ -1,71 +1,15 @@
|
||||
#include <Index/Index.h>
|
||||
#include <Index/SymbolSlab.h>
|
||||
#include <clang/Index/USRGeneration.h>
|
||||
|
||||
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 <typename Node, typename Callback>
|
||||
bool hook(Node* node, const Callback& callback) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Symbol> symbols;
|
||||
std::vector<Occurrence> occurrences;
|
||||
std::vector<std::vector<Relation>> relations;
|
||||
llvm::DenseMap<const clang::Decl*, std::size_t> cache;
|
||||
|
||||
llvm::BumpPtrAllocator allocator;
|
||||
llvm::StringSaver saver{allocator};
|
||||
};
|
||||
|
||||
class SymbolCollector : public clang::RecursiveASTVisitor<SymbolCollector> {
|
||||
using Base = clang::RecursiveASTVisitor<SymbolCollector>;
|
||||
|
||||
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
|
||||
|
||||
37
src/Index/SymbolSlab.cpp
Normal file
37
src/Index/SymbolSlab.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <Index/SymbolSlab.h>
|
||||
#include <clang/Index/USRGeneration.h>
|
||||
|
||||
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
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <Index/Index.h>
|
||||
#include <Index/SymbolSlab.h>
|
||||
#include <Support/JSON.h>
|
||||
#include <Compiler/Compiler.h>
|
||||
|
||||
using namespace clice;
|
||||
|
||||
TEST(clice_test, index) {
|
||||
TEST(clice, Index) {
|
||||
std::vector<const char*> compileArgs = {
|
||||
"clang++",
|
||||
"-std=c++20",
|
||||
@@ -21,4 +23,11 @@ void f() {
|
||||
X<int, int> 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";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user