Files
tsl-devkit/lsp-server/src/language/symbol/table.cpp
T

243 lines
7.2 KiB
C++

#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,
bool is_class_method)
{
// 创建符号定义
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;
def.is_class_method = is_class_method;
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);
}
}