243 lines
7.2 KiB
C++
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);
|
|
}
|
|
|
|
}
|