add symbol table and test file
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
#include <algorithm>
|
||||
#include "./table.hpp"
|
||||
#include "./builder.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
SymbolTable::SymbolTable()
|
||||
{
|
||||
}
|
||||
|
||||
void SymbolTable::Build(ast::ASTNode& root)
|
||||
{
|
||||
Clear();
|
||||
|
||||
Builder builder(*this);
|
||||
builder.Build(root);
|
||||
|
||||
// 构建完成后优化位置索引
|
||||
location_index_.RebuildIndex();
|
||||
}
|
||||
|
||||
void SymbolTable::Clear()
|
||||
{
|
||||
definition_store_.Clear();
|
||||
scope_manager_.Clear();
|
||||
location_index_.Clear();
|
||||
reference_graph_.Clear();
|
||||
inheritance_graph_.Clear();
|
||||
call_graph_.Clear();
|
||||
unit_imports_.clear();
|
||||
import_index_.clear();
|
||||
}
|
||||
|
||||
const SymbolDefinition* SymbolTable::GetDefinition(SymbolId id) const
|
||||
{
|
||||
return definition_store_.Get(id);
|
||||
}
|
||||
|
||||
std::vector<const SymbolDefinition*> SymbolTable::GetAllDefinitions() const
|
||||
{
|
||||
return definition_store_.GetAll();
|
||||
}
|
||||
|
||||
std::vector<const SymbolDefinition*> SymbolTable::FindDefinitionsByName(const std::string& name) const
|
||||
{
|
||||
return definition_store_.FindByName(name);
|
||||
}
|
||||
|
||||
std::optional<SymbolId> SymbolTable::FindSymbolAt(const ast::Location& location) const
|
||||
{
|
||||
return location_index_.FindSymbolAt(location);
|
||||
}
|
||||
|
||||
std::optional<SymbolId> SymbolTable::FindSymbol(const std::string& name, ScopeId scope_id) const
|
||||
{
|
||||
return scope_manager_.FindInScopeChain(scope_id, name);
|
||||
}
|
||||
|
||||
std::vector<SymbolId> SymbolTable::FindSymbolsByName(const std::string& name) const
|
||||
{
|
||||
std::vector<SymbolId> result;
|
||||
auto defs = definition_store_.FindByName(name);
|
||||
for (const auto* def : defs)
|
||||
result.push_back(def->id);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<ScopeId> SymbolTable::FindScopeAt(const ast::Location& location) const
|
||||
{
|
||||
return location_index_.FindScopeAt(location);
|
||||
}
|
||||
|
||||
std::optional<SymbolId> SymbolTable::FindReferenceAt(const ast::Location& location) const
|
||||
{
|
||||
return location_index_.FindReferenceAt(location);
|
||||
}
|
||||
|
||||
std::vector<SymbolId> SymbolTable::GetChildren(SymbolId symbol_id) const
|
||||
{
|
||||
return definition_store_.GetChildren(symbol_id);
|
||||
}
|
||||
|
||||
ScopeId SymbolTable::GetGlobalScope() const
|
||||
{
|
||||
return scope_manager_.GetGlobalScope();
|
||||
}
|
||||
|
||||
const std::vector<Reference>* SymbolTable::GetReferences(SymbolId symbol_id) const
|
||||
{
|
||||
return reference_graph_.GetReferences(symbol_id);
|
||||
}
|
||||
|
||||
std::optional<ast::Location> SymbolTable::GetDefinitionLocation(SymbolId symbol_id) const
|
||||
{
|
||||
return reference_graph_.GetDefinition(symbol_id);
|
||||
}
|
||||
|
||||
const std::vector<SymbolId>* SymbolTable::GetBaseClasses(SymbolId class_id) const
|
||||
{
|
||||
return inheritance_graph_.GetBaseClasses(class_id);
|
||||
}
|
||||
|
||||
const std::vector<SymbolId>* SymbolTable::GetDerivedClasses(SymbolId class_id) const
|
||||
{
|
||||
return inheritance_graph_.GetDerivedClasses(class_id);
|
||||
}
|
||||
|
||||
const std::vector<CallRelation>* SymbolTable::GetCallers(SymbolId function_id) const
|
||||
{
|
||||
return call_graph_.GetCallers(function_id);
|
||||
}
|
||||
|
||||
const std::vector<CallRelation>* SymbolTable::GetCallees(SymbolId function_id) const
|
||||
{
|
||||
return call_graph_.GetCallees(function_id);
|
||||
}
|
||||
|
||||
// ===== Unit 导入管理实现 =====
|
||||
|
||||
void SymbolTable::AddUnitImport(const std::string& unit_name, const ast::Location& location)
|
||||
{
|
||||
// 检查是否已经导入过(避免重复)
|
||||
if (import_index_.find(unit_name) != import_index_.end())
|
||||
{
|
||||
// 已经存在,可以选择:
|
||||
// 1. 忽略重复导入
|
||||
// 2. 记录多次导入(用于诊断)
|
||||
// 这里选择忽略
|
||||
return;
|
||||
}
|
||||
|
||||
size_t index = unit_imports_.size();
|
||||
unit_imports_.push_back(UnitImport{ unit_name, location });
|
||||
import_index_[unit_name] = index;
|
||||
}
|
||||
|
||||
const std::vector<UnitImport>& SymbolTable::GetUnitImports() const
|
||||
{
|
||||
return unit_imports_;
|
||||
}
|
||||
|
||||
std::optional<ast::Location> SymbolTable::FindImportLocation(const std::string& unit_name) const
|
||||
{
|
||||
auto it = import_index_.find(unit_name);
|
||||
if (it != import_index_.end() && it->second < unit_imports_.size())
|
||||
{
|
||||
return unit_imports_[it->second].location;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool SymbolTable::HasImport(const std::string& unit_name) const
|
||||
{
|
||||
return import_index_.find(unit_name) != import_index_.end();
|
||||
}
|
||||
|
||||
// ===== LSP 接口实现 =====
|
||||
|
||||
std::vector<const SymbolDefinition*> SymbolTable::GetDocumentSymbols() const
|
||||
{
|
||||
std::vector<const SymbolDefinition*> result;
|
||||
|
||||
for (const auto* def : definition_store_.GetAll())
|
||||
{
|
||||
// 只返回顶层符号(没有父符号的符号)
|
||||
if (!def->parent_id)
|
||||
result.push_back(def);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<const SymbolDefinition*> SymbolTable::GetWorkspaceSymbols(const std::string& query) const
|
||||
{
|
||||
if (query.empty())
|
||||
return definition_store_.GetAll();
|
||||
|
||||
// 使用小写查询字符串进行大小写无关的匹配
|
||||
std::string lower_query = utils::ToLower(query);
|
||||
|
||||
std::vector<const SymbolDefinition*> result;
|
||||
for (const auto* def : definition_store_.GetAll())
|
||||
{
|
||||
std::string lower_name = utils::ToLower(def->name);
|
||||
if (lower_name.find(lower_query) != std::string::npos)
|
||||
result.push_back(def);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ===== Builder 专用内部接口实现 =====
|
||||
|
||||
SymbolId SymbolTable::CreateSymbol(
|
||||
const std::string& name,
|
||||
SymbolKind kind,
|
||||
const ast::Location& location,
|
||||
ScopeId scope_id,
|
||||
std::optional<SymbolId> parent_id,
|
||||
const std::optional<std::string>& type_hint)
|
||||
{
|
||||
// 创建符号定义
|
||||
SymbolDefinition def;
|
||||
def.name = name;
|
||||
def.kind = kind;
|
||||
def.location = location;
|
||||
def.selection_range = location;
|
||||
def.type_hint = type_hint;
|
||||
def.parent_id = parent_id;
|
||||
|
||||
SymbolId symbol_id = definition_store_.Add(std::move(def));
|
||||
|
||||
// 统一处理所有索引更新
|
||||
scope_manager_.AddSymbol(scope_id, name, symbol_id);
|
||||
location_index_.AddSymbol(symbol_id, location);
|
||||
|
||||
// 添加定义引用
|
||||
reference_graph_.AddReference(symbol_id, location, true, false);
|
||||
location_index_.AddReference(symbol_id, location);
|
||||
|
||||
return symbol_id;
|
||||
}
|
||||
|
||||
ScopeId SymbolTable::CreateScope(ScopeKind kind, const ast::Location& range, std::optional<ScopeId> parent_scope_id, std::optional<SymbolId> associated_symbol_id)
|
||||
{
|
||||
ScopeId scope_id = scope_manager_.CreateScope(kind, range, parent_scope_id, associated_symbol_id);
|
||||
|
||||
// 添加到位置索引
|
||||
location_index_.AddScope(scope_id, range);
|
||||
|
||||
return scope_id;
|
||||
}
|
||||
|
||||
void SymbolTable::AddReference(SymbolId symbol_id, const ast::Location& location, bool is_write)
|
||||
{
|
||||
reference_graph_.AddReference(symbol_id, location, false, is_write);
|
||||
location_index_.AddReference(symbol_id, location);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user