add symbol table and test file

This commit is contained in:
csh 2025-10-26 22:52:31 +08:00
parent 7d9b966bc7
commit 100e210ed1
43 changed files with 3829 additions and 3095 deletions

View File

@ -0,0 +1,662 @@
#include "./builder.hpp"
namespace lsp::language::symbol
{
Builder::Builder(SymbolTable& table) : table_(table), current_scope_id_(kInvalidScopeId)
{
}
void Builder::Build(ast::ASTNode& root)
{
current_scope_id_ = table_.CreateScope(
ScopeKind::Global,
root.span,
std::nullopt,
std::nullopt);
SymbolId global_symbol = table_.CreateSymbol(
"::",
SymbolKind::Namespace,
root.span,
current_scope_id_,
std::nullopt,
std::nullopt);
table_.GetScopeManager().AddSymbol(current_scope_id_, "::", global_symbol);
root.Accept(*this);
}
SymbolId Builder::CreateSymbol(const std::string& name, SymbolKind kind, const ast::ASTNode& node, const std::optional<std::string>& type_hint)
{
return table_.CreateSymbol(
name,
kind,
node.span,
current_scope_id_,
current_parent_symbol_id_,
type_hint);
}
ScopeId Builder::EnterScopeWithSymbol(ScopeKind kind, SymbolId symbol_id, const ast::Location& range)
{
ScopeId parent_scope = current_scope_id_;
current_scope_id_ = table_.CreateScope(kind, range, parent_scope, symbol_id);
return current_scope_id_;
}
ScopeId Builder::EnterScope(ScopeKind kind, const ast::Location& range)
{
ScopeId parent_scope = current_scope_id_;
current_scope_id_ = table_.CreateScope(kind, range, parent_scope, std::nullopt);
return current_scope_id_;
}
void Builder::ExitScope()
{
auto info = table_.GetScopeManager().GetScopeInfo(current_scope_id_);
if (info && info->parent_scope_id)
current_scope_id_ = *info->parent_scope_id;
}
void Builder::VisitStatements(const std::vector<ast::StatementPtr>& statements)
{
for (const auto& stmt : statements)
{
if (stmt)
stmt->Accept(*this);
}
}
void Builder::VisitExpression(ast::Expression& expr)
{
expr.Accept(*this);
}
std::string Builder::FormatSignature(const ast::Signature& signature)
{
std::string result = "(";
for (size_t i = 0; i < signature.parameters.size(); ++i)
{
if (i > 0)
result += ", ";
const auto& param = signature.parameters[i];
if (param.is_var)
result += "var ";
if (param.is_out)
result += "out ";
result += param.name;
if (param.type)
result += ": " + param.type->name;
}
result += ")";
if (signature.return_type)
result += ": " + signature.return_type->name;
return result;
}
void Builder::ProcessLeftHandSide(const ast::LeftHandSide& lhs, bool is_write)
{
std::visit([this, is_write](auto& variant) {
using T = std::decay_t<decltype(variant)>;
if constexpr (std::is_same_v<T, std::unique_ptr<ast::Identifier>>)
{
if (variant)
{
auto symbol_id = table_.GetScopeManager().FindInScopeChain(current_scope_id_, variant->name);
if (symbol_id)
table_.AddReference(*symbol_id, variant->span, is_write);
}
}
else if constexpr (std::is_same_v<T, std::unique_ptr<ast::AttributeExpression>>)
{
if (variant)
VisitExpression(*variant->object);
}
else if constexpr (std::is_same_v<T, std::unique_ptr<ast::SubscriptExpression>>)
{
if (variant)
VisitExpression(*variant->value);
}
},
lhs);
}
void Builder::VisitProgram(ast::Program& node)
{
VisitStatements(node.statements);
}
void Builder::VisitUnitDefinition(ast::UnitDefinition& node)
{
auto symbol_id = CreateSymbol(node.name, SymbolKind::Module, node);
EnterScopeWithSymbol(ScopeKind::Unit, symbol_id, node.span);
auto prev_parent = current_parent_symbol_id_;
current_parent_symbol_id_ = symbol_id;
VisitStatements(node.interface_statements);
VisitStatements(node.implementation_statements);
VisitStatements(node.initialization_statements);
VisitStatements(node.finalization_statements);
current_parent_symbol_id_ = prev_parent;
ExitScope();
}
void Builder::VisitClassDefinition(ast::ClassDefinition& node)
{
auto symbol_id = CreateSymbol(node.name, SymbolKind::Class, node);
// 处理继承关系
for (const auto& parent_class : node.parent_classes)
{
auto parent_symbols = table_.GetDefinitionStore().FindByName(parent_class.name);
for (const auto* parent_def : parent_symbols)
{
if (parent_def->kind == SymbolKind::Class)
table_.GetInheritanceGraph().AddInheritance(symbol_id, parent_def->id);
}
}
EnterScopeWithSymbol(ScopeKind::Class, symbol_id, node.span);
auto prev_parent = current_parent_symbol_id_;
current_parent_symbol_id_ = symbol_id;
for (const auto& member : node.members)
{
if (member)
member->Accept(*this);
}
current_parent_symbol_id_ = prev_parent;
ExitScope();
}
void Builder::VisitFunctionDefinition(ast::FunctionDefinition& node)
{
auto symbol_id = CreateSymbol(node.name, SymbolKind::Function, node);
// 使用新的 Update 接口更新符号信息
table_.GetDefinitionStore().Update(symbol_id, [&](SymbolDefinition& def) {
def.detail = FormatSignature(node.signature);
});
EnterScopeWithSymbol(ScopeKind::Function, symbol_id, node.span);
auto prev_function = current_function_id_;
current_function_id_ = symbol_id;
// 添加参数
for (const auto& param : node.signature.parameters)
{
std::optional<std::string> type_hint;
if (param.type)
type_hint = param.type->name;
CreateSymbol(param.name, SymbolKind::Variable, node, type_hint);
}
if (node.body)
node.body->Accept(*this);
current_function_id_ = prev_function;
ExitScope();
}
void Builder::VisitFunctionDeclaration(ast::FunctionDeclaration& node)
{
auto symbol_id = CreateSymbol(node.name, SymbolKind::Function, node);
table_.GetDefinitionStore().Update(symbol_id, [&](SymbolDefinition& def) {
def.detail = FormatSignature(node.signature);
});
}
void Builder::VisitMethodDeclaration(ast::MethodDeclaration& node)
{
SymbolKind kind = node.method_type == ast::MethodType::kConstructor ? SymbolKind::Constructor : SymbolKind::Method;
auto symbol_id = CreateSymbol(node.name, kind, node);
table_.GetDefinitionStore().Update(symbol_id, [&](SymbolDefinition& def) {
def.detail = FormatSignature(node.signature);
def.method_modifier = node.modifier;
});
EnterScopeWithSymbol(ScopeKind::Function, symbol_id, node.span);
auto prev_function = current_function_id_;
current_function_id_ = symbol_id;
for (const auto& param : node.signature.parameters)
{
std::optional<std::string> type_hint;
if (param.type)
type_hint = param.type->name;
CreateSymbol(param.name, SymbolKind::Variable, node, type_hint);
}
if (node.body)
node.body->Accept(*this);
current_function_id_ = prev_function;
ExitScope();
}
void Builder::VisitPropertyDeclaration(ast::PropertyDeclaration& node)
{
CreateSymbol(node.name, SymbolKind::Property, node, node.type_name);
}
void Builder::VisitExternalMethodDefinition(ast::ExternalMethodDefinition& node)
{
SymbolKind kind = node.method_type == ast::MethodType::kConstructor ? SymbolKind::Constructor : SymbolKind::Method;
auto symbol_id = CreateSymbol(node.name, kind, node);
table_.GetDefinitionStore().Update(symbol_id, [&](SymbolDefinition& def) {
def.detail = FormatSignature(node.signature);
def.method_modifier = node.modifier;
});
EnterScopeWithSymbol(ScopeKind::Function, symbol_id, node.span);
auto prev_function = current_function_id_;
current_function_id_ = symbol_id;
for (const auto& param : node.signature.parameters)
{
std::optional<std::string> type_hint;
if (param.type)
type_hint = param.type->name;
CreateSymbol(param.name, SymbolKind::Variable, node, type_hint);
}
if (node.body)
node.body->Accept(*this);
current_function_id_ = prev_function;
ExitScope();
}
void Builder::VisitClassMember(ast::ClassMember& node)
{
std::visit([this](auto& member_ptr) {
if (member_ptr)
member_ptr->Accept(*this);
}, node.member);
}
void Builder::VisitVarStatement(ast::VarStatement& node)
{
for (const auto& decl : node.declarations)
{
if (decl)
decl->Accept(*this);
}
}
void Builder::VisitStaticStatement(ast::StaticStatement& node)
{
for (const auto& decl : node.declarations)
{
if (decl)
decl->Accept(*this);
}
}
void Builder::VisitGlobalStatement(ast::GlobalStatement& node)
{
for (const auto& decl : node.declarations)
{
if (decl)
decl->Accept(*this);
}
}
void Builder::VisitConstStatement(ast::ConstStatement& node)
{
std::optional<std::string> type_hint;
if (node.type_name)
type_hint = *node.type_name;
CreateSymbol(node.name, SymbolKind::Constant, node, type_hint);
}
void Builder::VisitVarDeclaration(ast::VarDeclaration& node)
{
std::optional<std::string> type_hint;
if (node.type)
type_hint = node.type->name;
CreateSymbol(node.name, SymbolKind::Variable, node, type_hint);
}
void Builder::VisitStaticDeclaration(ast::StaticDeclaration& node)
{
std::optional<std::string> type_hint;
if (node.type)
type_hint = node.type->name;
CreateSymbol(node.name, SymbolKind::Variable, node, type_hint);
}
void Builder::VisitGlobalDeclaration(ast::GlobalDeclaration& node)
{
std::optional<std::string> type_hint;
if (node.type)
type_hint = node.type->name;
CreateSymbol(node.name, SymbolKind::Variable, node, type_hint);
}
void Builder::VisitFieldDeclaration(ast::FieldDeclaration& node)
{
std::optional<std::string> type_hint;
if (node.type)
type_hint = node.type->name;
CreateSymbol(node.name, SymbolKind::Field, node, type_hint);
}
void Builder::VisitBlockStatement(ast::BlockStatement& node)
{
// 为块创建新作用域
EnterScope(ScopeKind::Block, node.span);
VisitStatements(node.statements);
ExitScope();
}
void Builder::VisitIfStatement(ast::IfStatement& node)
{
for (auto& branch : node.branches)
{
if (branch.condition)
VisitExpression(*branch.condition);
if (branch.body)
branch.body->Accept(*this);
}
}
void Builder::VisitForInStatement(ast::ForInStatement& node)
{
// 为循环创建作用域
EnterScope(ScopeKind::Block, node.span);
CreateSymbol(node.key, SymbolKind::Variable, node);
CreateSymbol(node.value, SymbolKind::Variable, node);
if (node.collection)
VisitExpression(*node.collection);
if (node.body)
node.body->Accept(*this);
ExitScope();
}
void Builder::VisitForToStatement(ast::ForToStatement& node)
{
// 为循环创建作用域
EnterScope(ScopeKind::Block, node.span);
CreateSymbol(node.counter, SymbolKind::Variable, node);
if (node.start)
VisitExpression(*node.start);
if (node.end)
VisitExpression(*node.end);
if (node.body)
node.body->Accept(*this);
ExitScope();
}
void Builder::VisitWhileStatement(ast::WhileStatement& node)
{
if (node.condition)
VisitExpression(*node.condition);
if (node.body)
node.body->Accept(*this);
}
void Builder::VisitRepeatStatement(ast::RepeatStatement& node)
{
EnterScope(ScopeKind::Block, node.span);
VisitStatements(node.body);
if (node.condition)
VisitExpression(*node.condition);
ExitScope();
}
void Builder::VisitCaseStatement(ast::CaseStatement& node)
{
if (node.discriminant)
VisitExpression(*node.discriminant);
for (auto& branch : node.branches)
{
for (auto& value : branch.values)
{
if (value)
VisitExpression(*value);
}
if (branch.body)
branch.body->Accept(*this);
}
if (node.default_case)
node.default_case->Accept(*this);
}
void Builder::VisitTryStatement(ast::TryStatement& node)
{
if (node.try_body)
node.try_body->Accept(*this);
if (node.except_body)
node.except_body->Accept(*this);
}
void Builder::VisitIdentifier(ast::Identifier& node)
{
auto symbol_id = table_.GetScopeManager().FindInScopeChain(current_scope_id_, node.name);
if (symbol_id)
table_.AddReference(*symbol_id, node.span, false);
}
void Builder::VisitCallExpression(ast::CallExpression& node)
{
if (node.callee)
{
VisitExpression(*node.callee);
if (auto* ident = dynamic_cast<ast::Identifier*>(node.callee.get()))
{
auto callee_id = table_.GetScopeManager().FindInScopeChain(current_scope_id_, ident->name);
if (callee_id && current_function_id_)
table_.GetCallGraph().AddCall(*current_function_id_, *callee_id, node.span);
}
}
for (auto& arg : node.arguments)
{
if (arg.value)
VisitExpression(*arg.value);
}
}
void Builder::VisitAttributeExpression(ast::AttributeExpression& node)
{
if (node.object)
VisitExpression(*node.object);
}
void Builder::VisitAssignmentExpression(ast::AssignmentExpression& node)
{
ProcessLeftHandSide(node.left, true);
if (node.right)
VisitExpression(*node.right);
}
void Builder::VisitAssignmentStatement(ast::AssignmentStatement& node)
{
ProcessLeftHandSide(node.left, true);
if (node.right)
VisitExpression(*node.right);
}
void Builder::VisitBinaryExpression(ast::BinaryExpression& node)
{
if (node.left)
VisitExpression(*node.left);
if (node.right)
VisitExpression(*node.right);
}
void Builder::VisitUnaryExpression(ast::UnaryExpression& node)
{
if (node.argument)
VisitExpression(*node.argument);
}
void Builder::VisitTernaryExpression(ast::TernaryExpression& node)
{
if (node.condition)
VisitExpression(*node.condition);
if (node.consequence)
VisitExpression(*node.consequence);
if (node.alternative)
VisitExpression(*node.alternative);
}
void Builder::VisitSubscriptExpression(ast::SubscriptExpression& node)
{
if (node.value)
VisitExpression(*node.value);
for (auto& index : node.indices)
{
if (index.start)
VisitExpression(*index.start);
if (index.end)
VisitExpression(*index.end);
if (index.step)
VisitExpression(*index.step);
}
}
void Builder::VisitArrayExpression(ast::ArrayExpression& node)
{
for (auto& elem : node.elements)
{
if (elem.key)
VisitExpression(*elem.key);
if (elem.value)
VisitExpression(*elem.value);
}
}
void Builder::VisitAnonymousFunctionExpression(ast::AnonymousFunctionExpression& node)
{
// 为匿名函数创建作用域
EnterScope(ScopeKind::Function, node.span);
for (const auto& param : node.signature.parameters)
{
std::optional<std::string> type_hint;
if (param.type)
type_hint = param.type->name;
CreateSymbol(param.name, SymbolKind::Variable, node, type_hint);
}
if (node.body)
node.body->Accept(*this);
ExitScope();
}
void Builder::VisitPrefixIncrementExpression(ast::PrefixIncrementExpression& node)
{
if (node.argument)
VisitExpression(*node.argument);
}
void Builder::VisitPrefixDecrementExpression(ast::PrefixDecrementExpression& node)
{
if (node.argument)
VisitExpression(*node.argument);
}
void Builder::VisitPostfixIncrementExpression(ast::PostfixIncrementExpression& node)
{
if (node.argument)
VisitExpression(*node.argument);
}
void Builder::VisitPostfixDecrementExpression(ast::PostfixDecrementExpression& node)
{
if (node.argument)
VisitExpression(*node.argument);
}
void Builder::VisitComparisonExpression(ast::ComparisonExpression& node)
{
if (node.left)
VisitExpression(*node.left);
for (auto& comp : node.comparisons)
{
if (comp.right)
VisitExpression(*comp.right);
}
}
void Builder::VisitExpressionStatement(ast::ExpressionStatement& node)
{
if (node.expression)
VisitExpression(*node.expression);
}
void Builder::VisitReturnStatement(ast::ReturnStatement& node)
{
if (node.value)
VisitExpression(*node.value);
}
void Builder::VisitUsesStatement(ast::UsesStatement& node)
{
// 为每个导入创建一个符号
for (const auto& unit_name : node.units)
{
// 记录导入关系
table_.AddUnitImport(unit_name, node.span);
// 创建一个符号来表示这个导入
[[maybe_unused]] SymbolId import_symbol_id = CreateSymbol(
unit_name,
SymbolKind::Module,
node,
std::nullopt);
}
}
void Builder::VisitMatrixIterationStatement(ast::MatrixIterationStatement& node)
{
// 为矩阵迭代创建作用域
EnterScope(ScopeKind::Block, node.span);
if (node.target)
VisitExpression(*node.target);
if (node.body)
node.body->Accept(*this);
ExitScope();
}
}

View File

@ -0,0 +1,92 @@
#pragma once
#include "./table.hpp"
namespace lsp::language::symbol
{
// 符号表构建器
class Builder : public ast::ASTVisitor
{
public:
explicit Builder(SymbolTable& table);
void Build(ast::ASTNode& root);
// 访问语句和声明
void VisitProgram(ast::Program& node) override;
void VisitUnitDefinition(ast::UnitDefinition& node) override;
void VisitClassDefinition(ast::ClassDefinition& node) override;
void VisitFunctionDefinition(ast::FunctionDefinition& node) override;
void VisitFunctionDeclaration(ast::FunctionDeclaration& node) override;
void VisitMethodDeclaration(ast::MethodDeclaration& node) override;
void VisitPropertyDeclaration(ast::PropertyDeclaration& node) override;
void VisitExternalMethodDefinition(ast::ExternalMethodDefinition& node) override;
void VisitClassMember(ast::ClassMember& node) override;
void VisitVarStatement(ast::VarStatement& node) override;
void VisitStaticStatement(ast::StaticStatement& node) override;
void VisitGlobalStatement(ast::GlobalStatement& node) override;
void VisitConstStatement(ast::ConstStatement& node) override;
void VisitVarDeclaration(ast::VarDeclaration& node) override;
void VisitStaticDeclaration(ast::StaticDeclaration& node) override;
void VisitGlobalDeclaration(ast::GlobalDeclaration& node) override;
void VisitFieldDeclaration(ast::FieldDeclaration& node) override;
void VisitBlockStatement(ast::BlockStatement& node) override;
void VisitIfStatement(ast::IfStatement& node) override;
void VisitForInStatement(ast::ForInStatement& node) override;
void VisitForToStatement(ast::ForToStatement& node) override;
void VisitWhileStatement(ast::WhileStatement& node) override;
void VisitRepeatStatement(ast::RepeatStatement& node) override;
void VisitCaseStatement(ast::CaseStatement& node) override;
void VisitTryStatement(ast::TryStatement& node) override;
// Uses 语句处理
void VisitUsesStatement(ast::UsesStatement& node) override;
// 访问表达式(收集引用)
void VisitIdentifier(ast::Identifier& node) override;
void VisitCallExpression(ast::CallExpression& node) override;
void VisitAttributeExpression(ast::AttributeExpression& node) override;
void VisitAssignmentExpression(ast::AssignmentExpression& node) override;
void VisitAssignmentStatement(ast::AssignmentStatement& node) override;
// 其他节点访问
void VisitLiteral(ast::Literal&) override {}
void VisitBinaryExpression(ast::BinaryExpression& node) override;
void VisitUnaryExpression(ast::UnaryExpression& node) override;
void VisitTernaryExpression(ast::TernaryExpression& node) override;
void VisitSubscriptExpression(ast::SubscriptExpression& node) override;
void VisitArrayExpression(ast::ArrayExpression& node) override;
void VisitAnonymousFunctionExpression(ast::AnonymousFunctionExpression& node) override;
void VisitPrefixIncrementExpression(ast::PrefixIncrementExpression& node) override;
void VisitPrefixDecrementExpression(ast::PrefixDecrementExpression& node) override;
void VisitPostfixIncrementExpression(ast::PostfixIncrementExpression& node) override;
void VisitPostfixDecrementExpression(ast::PostfixDecrementExpression& node) override;
void VisitFunctionPointerExpression(ast::FunctionPointerExpression&) override {}
void VisitComparisonExpression(ast::ComparisonExpression& node) override;
void VisitExpressionStatement(ast::ExpressionStatement& node) override;
void VisitBreakStatement(ast::BreakStatement&) override {}
void VisitContinueStatement(ast::ContinueStatement&) override {}
void VisitReturnStatement(ast::ReturnStatement& node) override;
void VisitTSSQLExpression(ast::TSSQLExpression&) override {}
void VisitUnpackPattern(ast::UnpackPattern&) override {}
void VisitMatrixIterationStatement(ast::MatrixIterationStatement& node) override;
private:
SymbolId CreateSymbol(const std::string& name, SymbolKind kind, const ast::ASTNode& node, const std::optional<std::string>& type_hint = std::nullopt);
ScopeId EnterScopeWithSymbol(ScopeKind kind, SymbolId symbol_id, const ast::Location& range);
ScopeId EnterScope(ScopeKind kind, const ast::Location& range);
void ExitScope();
void VisitStatements(const std::vector<ast::StatementPtr>& statements);
void VisitExpression(ast::Expression& expr);
void ProcessLeftHandSide(const ast::LeftHandSide& lhs, bool is_write);
std::string FormatSignature(const ast::Signature& signature);
private:
SymbolTable& table_;
ScopeId current_scope_id_;
std::optional<SymbolId> current_parent_symbol_id_;
std::optional<SymbolId> current_function_id_;
};
}

View File

@ -1,160 +0,0 @@
#include "./builder.hpp"
#include "../collector/symbol_collector.hpp"
#include "../collector/incremental_collector.hpp"
#include "../incremental/incremental_engine.hpp"
namespace lsp::language::symbol
{
// ==================== 构造和析构 ====================
SymbolTableBuilder::SymbolTableBuilder() :
incremental_enabled_(false)
{
}
SymbolTableBuilder::~SymbolTableBuilder() = default;
// ==================== 构建接口 ====================
bool SymbolTableBuilder::Build(const std::vector<ast::ASTNode>& nodes)
{
// 清空错误
error_reporter_.Clear();
// 初始化统计信息
stats_ = BuildStatistics{};
stats_.is_incremental = false;
stats_.total_symbols = nodes.size();
// 创建收集上下文
CollectorContext context(registry_, error_reporter_);
// 创建基础收集器并执行
SymbolCollector collector(context);
bool success = collector.Collect(nodes);
// 更新统计信息
stats_.success = success && !error_reporter_.HasErrors();
stats_.new_symbols = stats_.total_symbols;
stats_.reused_symbols = 0;
stats_.reuse_rate = 0.0;
// 完整构建后,如果启用增量,则构建缓存
if (stats_.success && incremental_enabled_ && incremental_engine_)
{
incremental_engine_->BuildCache(registry_);
}
return stats_.success;
}
bool SymbolTableBuilder::BuildIncremental(
const ast::IncrementalParseResult& parse_result)
{
// 检查增量是否启用
if (!incremental_enabled_ || !incremental_engine_)
{
// 增量未启用,退回完整构建
return Build(parse_result.result.nodes);
}
// 清空错误
error_reporter_.Clear();
// 初始化统计信息
stats_ = BuildStatistics{};
stats_.is_incremental = true;
stats_.total_symbols = parse_result.result.nodes.size();
// 创建收集上下文
CollectorContext context(registry_, error_reporter_);
// 创建增量收集器并执行
IncrementalCollector collector(context, *incremental_engine_);
bool success = collector.CollectIncremental(parse_result);
// 更新统计信息
stats_.reused_symbols = collector.GetReusedCount();
stats_.new_symbols = collector.GetNewCount();
// 修复:防止除零
if (stats_.total_symbols > 0)
{
stats_.reuse_rate = static_cast<double>(stats_.reused_symbols) / stats_.total_symbols;
}
else
{
stats_.reuse_rate = 0.0;
}
stats_.success = success && !error_reporter_.HasErrors();
// 检查缓存大小,必要时进行清理
if (incremental_engine_->GetCacheSize() > 10000) // 可配置
{
// LRU 会自动处理,这里只是检查
// 如果需要强制限制,可以调用 SetMaxCacheSize
}
return stats_.success;
}
// ==================== 访问器 ====================
const std::vector<Error>& SymbolTableBuilder::GetErrors() const
{
return error_reporter_.GetErrors();
}
bool SymbolTableBuilder::HasErrors() const
{
return error_reporter_.HasErrors();
}
size_t SymbolTableBuilder::ErrorCount() const
{
return error_reporter_.ErrorCount();
}
void SymbolTableBuilder::ClearErrors()
{
error_reporter_.Clear();
}
// ==================== 增量配置 ====================
void SymbolTableBuilder::EnableIncremental(bool enable)
{
incremental_enabled_ = enable;
if (enable && !incremental_engine_)
{
incremental_engine_ = std::make_unique<IncrementalEngine>();
}
}
void SymbolTableBuilder::SetMaxCacheSize(size_t max_size)
{
if (incremental_engine_)
{
incremental_engine_->SetMaxCacheSize(max_size);
}
}
void SymbolTableBuilder::ClearCache()
{
if (incremental_engine_)
{
incremental_engine_->Clear();
}
}
size_t SymbolTableBuilder::GetCacheSize() const
{
if (incremental_engine_)
{
return incremental_engine_->GetCacheSize();
}
return 0;
}
}

View File

@ -1,105 +0,0 @@
#pragma once
#include <vector>
#include <memory>
#include "../../ast/types.hpp"
#include "../../ast/deserializer.hpp"
#include "../core/registry.hpp"
#include "../core/error.hpp"
namespace lsp::language::symbol
{
// 前向声明
class IncrementalEngine;
// ==================== 构建统计信息 ====================
struct BuildStatistics
{
size_t total_symbols = 0; // 总符号数
size_t reused_symbols = 0; // 复用的符号数
size_t new_symbols = 0; // 新创建的符号数
double reuse_rate = 0.0; // 复用率
bool is_incremental = false; // 是否为增量构建
bool success = false; // 构建是否成功
};
// ==================== 符号表构建器 ====================
/**
* -
*
*
* - /
* - RegistryErrorReporter
* -
* -
*
*
* - Collector
* - IncrementalEngine
* -
*/
class SymbolTableBuilder
{
public:
SymbolTableBuilder();
~SymbolTableBuilder();
// 禁止拷贝
SymbolTableBuilder(const SymbolTableBuilder&) = delete;
SymbolTableBuilder& operator=(const SymbolTableBuilder&) = delete;
bool Build(const std::vector<ast::ASTNode>& nodes);
bool BuildIncremental(const ast::IncrementalParseResult& parse_result);
SymbolRegistry& GetRegistry() { return registry_; }
const SymbolRegistry& GetRegistry() const { return registry_; }
const std::vector<Error>& GetErrors() const;
bool HasErrors() const;
size_t ErrorCount() const;
void ClearErrors();
BuildStatistics GetStatistics() const { return stats_; }
void EnableIncremental(bool enable);
void SetMaxCacheSize(size_t max_size);
void ClearCache();
size_t GetCacheSize() const;
bool IsIncrementalEnabled() const { return incremental_enabled_; }
private:
// 核心组件
SymbolRegistry registry_;
ErrorReporter error_reporter_;
// 增量支持(可选)
std::unique_ptr<IncrementalEngine> incremental_engine_;
bool incremental_enabled_;
// 统计信息
BuildStatistics stats_;
};
// ==================== 便捷函数 ====================
/**
* 便
*
* @param nodes AST节点列表
* @param errors
* @return
*/
inline SymbolRegistry BuildSymbolTable(const std::vector<ast::ASTNode>& nodes, std::vector<Error>* errors = nullptr)
{
SymbolTableBuilder builder;
builder.Build(nodes);
if (errors)
*errors = builder.GetErrors();
// 移动 Registry避免拷贝
return std::move(builder.GetRegistry());
}
}

View File

@ -1,100 +0,0 @@
#pragma once
#include <sstream>
#include "../core/registry.hpp"
#include "../core/error.hpp"
#include "../factory/scope_manager.hpp"
namespace lsp::language::symbol
{
/**
* -
*
*
* - RegistryErrorReporterScopeManager 访
* - Unit Class
* - 便
*/
struct CollectorContext
{
SymbolRegistry& registry;
ErrorReporter& error_reporter;
ScopeManager scope_manager;
// 当前上下文
Unit* current_unit = nullptr;
Class* current_class = nullptr;
CollectorContext(SymbolRegistry& reg, ErrorReporter& reporter) :
registry(reg), error_reporter(reporter), scope_manager(reg.GlobalScope())
{
}
// 便捷访问
Table* CurrentScope() { return scope_manager.Current(); }
Table* GlobalScope() { return registry.GlobalScope(); }
// ==================== 改进的错误报告 ====================
void ReportError(ErrorKind kind, const std::string& msg, const ast::Location& loc)
{
error_reporter.Report(kind, msg, loc);
}
void ReportDuplicateDefinition(const std::string& name, const ast::Location& loc)
{
// 查找已存在的符号位置
auto existing = CurrentScope()->LookupLocal(name);
if (existing && existing.symbol)
{
std::ostringstream msg;
msg << "Symbol '" << name << "' already defined at "
<< existing.symbol->location.start_line << ":"
<< existing.symbol->location.start_column;
error_reporter.Report(ErrorKind::kDuplicateDefinition, msg.str(), loc);
}
else
{
error_reporter.ReportDuplicateDefinition(name, loc);
}
}
void ReportSignatureConflict(const std::string& name, const ast::Location& loc)
{
// 查找冲突的函数重载
auto overloads = CurrentScope()->LookupOverloads(name);
if (!overloads.empty())
{
std::ostringstream msg;
msg << "Function signature conflict: '" << name
<< "' (conflicts with overload at "
<< overloads[0]->location.start_line << ":"
<< overloads[0]->location.start_column << ")";
error_reporter.Report(ErrorKind::kSignatureConflict, msg.str(), loc);
}
else
{
error_reporter.Report(ErrorKind::kSignatureConflict,
"Function signature conflict: " + name,
loc);
}
}
void ReportUnitConflict(const std::string& name, const ast::Location& loc)
{
auto existing_unit = registry.FindUnit(name);
if (existing_unit)
{
std::ostringstream msg;
msg << "Unit '" << name << "' already defined at "
<< existing_unit->location.start_line << ":"
<< existing_unit->location.start_column;
error_reporter.Report(ErrorKind::kDuplicateDefinition, msg.str(), loc);
}
else
{
error_reporter.ReportDuplicateDefinition(name, loc);
}
}
};
}

View File

@ -1,87 +0,0 @@
#include "./incremental_collector.hpp"
#include "../incremental/incremental_engine.hpp"
namespace lsp::language::symbol
{
IncrementalCollector::IncrementalCollector(CollectorContext& context, IncrementalEngine& engine) :
SymbolCollector(context), engine_(engine)
{
}
bool IncrementalCollector::CollectIncremental(const ast::IncrementalParseResult& parse_result)
{
// 重置统计
reused_count_ = 0;
new_count_ = 0;
// 构建变化节点索引
std::unordered_set<size_t> changed_set(
parse_result.changed_indices.begin(),
parse_result.changed_indices.end());
// 处理所有节点
for (size_t i = 0; i < parse_result.result.nodes.size(); ++i)
{
const auto& node = parse_result.result.nodes[i];
bool is_changed = changed_set.count(i) > 0;
if (!ProcessNode(node, is_changed))
return false;
}
return !ctx_.error_reporter.HasErrors();
}
bool IncrementalCollector::ProcessNode(const ast::ASTNode& node, bool is_changed)
{
if (is_changed)
{
// 节点已变化,必须重新收集
new_count_++;
bool success = Visit(node);
if (success)
{
// 收集成功后,缓存新符号
CacheCurrentSymbol(node);
}
return success;
}
else
{
// 节点未变化,尝试复用缓存
if (TryReuseFromCache(node))
{
reused_count_++;
return true;
}
else
{
// 缓存未命中,重新收集
new_count_++;
bool success = Visit(node);
if (success)
{
CacheCurrentSymbol(node);
}
return success;
}
}
}
bool IncrementalCollector::TryReuseFromCache(const ast::ASTNode& node)
{
// 委托给增量引擎,传入 Registry 用于 Unit 复用
return engine_.TryReuseSymbol(node, ctx_.CurrentScope(), &ctx_.registry);
}
void IncrementalCollector::CacheCurrentSymbol(const ast::ASTNode& node)
{
// 委托给增量引擎
engine_.CacheSymbol(node, ctx_.CurrentScope());
}
}

View File

@ -1,47 +0,0 @@
#pragma once
#include "./symbol_collector.hpp"
#include "../../ast/deserializer.hpp"
namespace lsp::language::symbol
{
// 前向声明
class IncrementalEngine;
/**
*
*
*
* -
* -
* - IncrementalEngine
* -
*/
class IncrementalCollector : public SymbolCollector
{
public:
IncrementalCollector(CollectorContext& context, IncrementalEngine& engine);
// 增量收集入口
bool CollectIncremental(const ast::IncrementalParseResult& parse_result);
// 统计信息
size_t GetReusedCount() const { return reused_count_; }
size_t GetNewCount() const { return new_count_; }
private:
// 处理单个节点(判断是复用还是重新收集)
bool ProcessNode(const ast::ASTNode& node, bool is_changed);
// 尝试从缓存复用符号
bool TryReuseFromCache(const ast::ASTNode& node);
// 缓存当前收集的符号
void CacheCurrentSymbol(const ast::ASTNode& node);
private:
IncrementalEngine& engine_;
size_t reused_count_ = 0;
size_t new_count_ = 0;
};
}

View File

@ -1,518 +0,0 @@
#include "./symbol_collector.hpp"
#include "../utils/type.hpp"
#include "../factory/factory.hpp"
namespace lsp::language::symbol
{
SymbolCollector::SymbolCollector(CollectorContext& context) :
ctx_(context)
{
}
bool SymbolCollector::Collect(const std::vector<ast::ASTNode>& nodes)
{
for (const auto& node : nodes)
{
if (!Visit(node))
return false;
}
return !ctx_.error_reporter.HasErrors();
}
// ==================== AST 访问 ====================
bool SymbolCollector::Visit(const ast::ASTNode& node)
{
if (std::holds_alternative<std::monostate>(node))
return true;
if (auto* unit = std::get_if<ast::UnitDefinition>(&node))
return CollectUnit(*unit);
if (auto* global = std::get_if<ast::GlobalDeclaration>(&node))
return CollectGlobal(*global);
if (auto* static_decl = std::get_if<ast::StaticDeclaration>(&node))
return CollectStatic(*static_decl);
if (auto* var = std::get_if<ast::VarDeclaration>(&node))
return CollectVariable(*var);
if (auto* constant = std::get_if<ast::ConstDeclaration>(&node))
return CollectConstant(*constant);
if (auto* stmt = std::get_if<ast::AssignmentStatement>(&node))
return CollectAssignment(*stmt);
if (auto* func_def = std::get_if<ast::FunctionDefinition>(&node))
return CollectFunctionDef(*func_def);
if (auto* cls = std::get_if<ast::ClassDefinition>(&node))
return CollectClass(*cls);
if (auto* uses = std::get_if<ast::UsesClause>(&node))
return CollectUsesClause(*uses);
// 跳过表达式和块
if (std::holds_alternative<ast::Expression>(node) ||
std::holds_alternative<ast::Block>(node))
return true;
return true;
}
// ==================== 收集方法 ====================
bool SymbolCollector::CollectUnit(const ast::UnitDefinition& unit)
{
auto unit_symbol = factory::CreateUnit(unit.name, unit.location);
if (!TryInsertUnit(unit_symbol))
return false;
ctx_.current_unit = unit_symbol.get();
// 创建 interface 和 implementation 作用域
unit_symbol->interface_symbols =
std::make_unique<Table>(ScopeKind::kInterface, ctx_.GlobalScope());
unit_symbol->implementation_symbols =
std::make_unique<Table>(ScopeKind::kImplementation, ctx_.GlobalScope());
// 收集 uses 子句
if (unit.uses)
CollectUsesClause(*unit.uses);
// 收集各部分的声明
CollectInScope(unit_symbol->interface_symbols.get(), unit.interface_statements);
CollectInScope(unit_symbol->implementation_symbols.get(), unit.implementation_statements);
CollectInScope(unit_symbol->implementation_symbols.get(), unit.initialization_statements);
CollectInScope(unit_symbol->implementation_symbols.get(), unit.finalization_statements);
ctx_.current_unit = nullptr;
return true;
}
bool SymbolCollector::CollectGlobal(const ast::GlobalDeclaration& global)
{
TypeInfo type = global.type_name ?
TypeFactory::FromAnnotation(*global.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
global.name, Kind::kGlobalVariable, global.location, type);
if (global.value)
var_symbol->initialization_expr = global.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectStatic(const ast::StaticDeclaration& decl)
{
TypeInfo type = decl.type_name ?
TypeFactory::FromAnnotation(*decl.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
decl.name, Kind::kStaticVariable, decl.location, type);
var_symbol->attributes.is_static = true;
if (decl.value)
var_symbol->initialization_expr = decl.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectVariable(const ast::VarDeclaration& var)
{
TypeInfo type = var.type_name ?
TypeFactory::FromAnnotation(*var.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
var.name, Kind::kVariable, var.location, type);
if (var.value)
var_symbol->initialization_expr = var.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectConstant(const ast::ConstDeclaration& constant)
{
TypeInfo type = constant.type_name ?
TypeFactory::FromAnnotation(*constant.type_name) :
TypeInfo();
auto const_symbol = factory::CreateConstant(
constant.name, constant.location, type, constant.value.text);
return TryInsert(const_symbol);
}
bool SymbolCollector::CollectAssignment(const ast::AssignmentStatement& stmt)
{
TypeInfo type;
auto var_symbol = factory::CreateVariable(
stmt.name, Kind::kVariable, stmt.location, type);
var_symbol->initialization_expr = stmt.value.text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectFunctionDef(const ast::FunctionDefinition& func)
{
Signature sig = CreateSignature(func.signature);
auto func_symbol = factory::CreateFunction(
func.name, func.location, sig);
if (!TryInsertFunction(func_symbol, func.location))
return false;
// 收集函数体
if (!func.body.statements.empty())
CollectFunctionBody(func_symbol.get(), func.body);
return true;
}
bool SymbolCollector::CollectClass(const ast::ClassDefinition& class_def)
{
auto class_symbol = factory::CreateClass(
class_def.name, class_def.location);
// 存储父类名称(字符串形式,不解析引用)
class_symbol->parent_names = class_def.parents;
if (!TryInsert(class_symbol))
return false;
// 创建成员作用域
class_symbol->members = std::make_unique<Table>(
ScopeKind::kClass, ctx_.CurrentScope());
ctx_.current_class = class_symbol.get();
// 进入类作用域,收集成员
auto guard = ctx_.scope_manager.EnterScope(class_symbol->members.get());
for (const auto& member : class_def.members)
{
CollectClassMember(member, class_symbol.get());
}
ctx_.current_class = nullptr;
return true;
}
bool SymbolCollector::CollectUsesClause(const ast::UsesClause& uses)
{
if (ctx_.current_unit)
ctx_.current_unit->uses = uses.units;
return true;
}
// ==================== 类成员收集 ====================
bool SymbolCollector::CollectClassMember(const ast::ClassMember& member, Class* owner)
{
if (std::holds_alternative<std::monostate>(member.content))
return true;
Access access = member.access;
if (auto* var = std::get_if<ast::VarDeclaration>(&member.content))
return CollectMemberVariable(*var, access);
if (auto* static_decl = std::get_if<ast::StaticDeclaration>(&member.content))
return CollectMemberStatic(*static_decl, access);
if (auto* method = std::get_if<ast::Method>(&member.content))
return CollectMemberMethod(*method, access, owner);
if (auto* property = std::get_if<ast::Property>(&member.content))
return CollectMemberProperty(*property, access);
if (auto* ctor = std::get_if<ast::ConstructorDeclaration>(&member.content))
return CollectMemberConstructor(*ctor, access, owner);
if (auto* dtor = std::get_if<ast::DestructorDeclaration>(&member.content))
return CollectMemberDestructor(*dtor, access, owner);
return true;
}
bool SymbolCollector::CollectMemberVariable(const ast::VarDeclaration& var, Access access)
{
TypeInfo type = var.type_name ?
TypeFactory::FromAnnotation(*var.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
var.name, Kind::kVariable, var.location, type);
var_symbol->attributes.access = access;
if (var.value)
var_symbol->initialization_expr = var.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectMemberStatic(const ast::StaticDeclaration& decl, Access access)
{
TypeInfo type = decl.type_name ?
TypeFactory::FromAnnotation(*decl.type_name) :
TypeInfo();
auto var_symbol = factory::CreateVariable(
decl.name, Kind::kStaticVariable, decl.location, type);
var_symbol->attributes.access = access;
var_symbol->attributes.is_static = true;
if (decl.value)
var_symbol->initialization_expr = decl.value->text;
return TryInsert(var_symbol);
}
bool SymbolCollector::CollectMemberMethod(const ast::Method& method,
Access access,
Class* owner)
{
Signature sig = CreateSignature(method.signature);
auto method_symbol = factory::CreateMethod(
method.name, method.location, sig, owner);
method_symbol->attributes.access = access;
method_symbol->attributes.is_class_method = method.is_class_method;
// 设置 virtual/override 属性
switch (method.modifier)
{
case ast::Modifier::kVirtual:
method_symbol->attributes.is_virtual = true;
break;
case ast::Modifier::kOverride:
method_symbol->attributes.is_override = true;
break;
case ast::Modifier::kOverload:
method_symbol->attributes.is_overload = true;
break;
case ast::Modifier::kNone:
default:
break;
}
if (!TryInsertFunction(method_symbol, method.location))
return false;
// 收集方法体
if (method.body)
CollectFunctionBody(method_symbol.get(), *method.body);
return true;
}
bool SymbolCollector::CollectMemberProperty(const ast::Property& property, Access access)
{
TypeInfo type = property.type_name ?
TypeFactory::FromAnnotation(*property.type_name) :
TypeInfo();
auto property_symbol = factory::CreateProperty(
property.name, property.location, type);
property_symbol->attributes.access = access;
property_symbol->getter = property.getter;
property_symbol->setter = property.setter;
return TryInsert(property_symbol);
}
bool SymbolCollector::CollectMemberConstructor(const ast::ConstructorDeclaration& ctor,
Access access,
Class* owner)
{
Signature sig = CreateSignature(ctor.signature);
auto ctor_symbol = factory::CreateConstructor(
"Create", ctor.location, sig, owner);
ctor_symbol->attributes.access = access;
if (!TryInsert(ctor_symbol))
return false;
// 收集构造函数体
if (ctor.body)
CollectConstructorBody(ctor_symbol.get(), *ctor.body);
return true;
}
bool SymbolCollector::CollectMemberDestructor(const ast::DestructorDeclaration& dtor,
Access access,
Class* owner)
{
auto dtor_symbol = factory::CreateDestructor(
"Destroy", dtor.location, owner);
dtor_symbol->attributes.access = access;
if (!TryInsert(dtor_symbol))
return false;
// 收集析构函数体
if (dtor.body)
CollectDestructorBody(dtor_symbol.get(), *dtor.body);
return true;
}
// ==================== 函数体收集 ====================
void SymbolCollector::CollectFunctionBody(Function* func, const ast::Block& body)
{
// 创建函数作用域
func->body_scope = std::make_unique<Table>(
ScopeKind::kFunction, ctx_.CurrentScope());
// 进入函数作用域
auto guard = ctx_.scope_manager.EnterScope(func->body_scope.get());
// 收集参数符号
CollectFunctionParams(func);
// 收集函数体中的局部声明
CollectStatements(body.statements);
}
void SymbolCollector::CollectFunctionParams(Function* func)
{
for (const auto& param : func->signature.parameters)
{
auto param_symbol = factory::CreateVariable(
param.name, Kind::kParameter, func->location, param.type);
param_symbol->attributes.is_var_param = param.is_var;
param_symbol->attributes.is_out_param = param.is_out;
func->body_scope->Insert(param_symbol);
}
}
void SymbolCollector::CollectConstructorBody(Constructor* ctor, const ast::Block& body)
{
ctor->body_scope = std::make_unique<Table>(
ScopeKind::kFunction, ctx_.CurrentScope());
auto guard = ctx_.scope_manager.EnterScope(ctor->body_scope.get());
// 收集参数
for (const auto& param : ctor->signature.parameters)
{
auto param_symbol = factory::CreateVariable(
param.name, Kind::kParameter, ctor->location, param.type);
param_symbol->attributes.is_var_param = param.is_var;
param_symbol->attributes.is_out_param = param.is_out;
ctor->body_scope->Insert(param_symbol);
}
CollectStatements(body.statements);
}
void SymbolCollector::CollectDestructorBody(Destructor* dtor, const ast::Block& body)
{
dtor->body_scope = std::make_unique<Table>(
ScopeKind::kFunction, ctx_.CurrentScope());
auto guard = ctx_.scope_manager.EnterScope(dtor->body_scope.get());
CollectStatements(body.statements);
}
// ==================== 辅助方法 ====================
void SymbolCollector::CollectInScope(Table* scope,
const std::vector<ast::ASTNode>& statements)
{
auto guard = ctx_.scope_manager.EnterScope(scope);
CollectStatements(statements);
}
void SymbolCollector::CollectStatements(const std::vector<ast::ASTNode>& statements)
{
for (const auto& stmt : statements)
Visit(stmt);
}
// ==================== 插入方法 ====================
bool SymbolCollector::TryInsert(SymbolPtr symbol)
{
if (!ctx_.CurrentScope()->Insert(symbol))
{
ctx_.ReportDuplicateDefinition(symbol->name, symbol->location);
return false;
}
return true;
}
bool SymbolCollector::TryInsertFunction(FunctionPtr func, const ast::Location& loc)
{
if (!ctx_.CurrentScope()->InsertFunction(func))
{
ctx_.ReportSignatureConflict(func->name, loc);
return false;
}
return true;
}
bool SymbolCollector::TryInsertUnit(UnitPtr unit)
{
if (!ctx_.registry.AddUnit(unit))
{
ctx_.ReportUnitConflict(unit->name, unit->location);
return false;
}
return true;
}
// ==================== 创建签名 ====================
Signature SymbolCollector::CreateSignature(const ast::Signature& ast_sig)
{
Signature sig;
for (const auto& ast_param : ast_sig.parameters)
{
sig.parameters.push_back(CreateParameter(ast_param));
}
if (ast_sig.return_type)
sig.return_type = TypeFactory::FromAnnotation(*ast_sig.return_type);
return sig;
}
Signature::Param SymbolCollector::CreateParameter(const ast::Parameter& ast_param)
{
Signature::Param param;
param.name = ast_param.name;
param.type = ast_param.type_name ?
TypeFactory::FromAnnotation(*ast_param.type_name) :
TypeInfo();
param.is_var = ast_param.is_var;
param.is_out = ast_param.is_out;
param.default_value = ast_param.default_value;
return param;
}
}

View File

@ -1,86 +0,0 @@
#pragma once
#include <vector>
#include "../../ast/types.hpp"
#include "./context.hpp"
namespace lsp::language::symbol
{
/**
* - AST
*
*
* - AST
* -
* -
* -
*
*
* -
* -
* -
* -
*/
class SymbolCollector
{
public:
explicit SymbolCollector(CollectorContext& context);
virtual ~SymbolCollector() = default;
// 主入口 - 收集所有节点
bool Collect(const std::vector<ast::ASTNode>& nodes);
protected:
// ==================== AST 访问 ====================
virtual bool Visit(const ast::ASTNode& node);
// ==================== 顶层声明 ====================
bool CollectUnit(const ast::UnitDefinition& unit);
bool CollectGlobal(const ast::GlobalDeclaration& global);
bool CollectStatic(const ast::StaticDeclaration& decl);
bool CollectVariable(const ast::VarDeclaration& var);
bool CollectConstant(const ast::ConstDeclaration& constant);
bool CollectAssignment(const ast::AssignmentStatement& stmt);
bool CollectFunctionDef(const ast::FunctionDefinition& func);
bool CollectClass(const ast::ClassDefinition& class_def);
bool CollectUsesClause(const ast::UsesClause& uses);
// ==================== 类成员收集 ====================
bool CollectClassMember(const ast::ClassMember& member, Class* owner);
bool CollectMemberVariable(const ast::VarDeclaration& var, Access access);
bool CollectMemberStatic(const ast::StaticDeclaration& decl, Access access);
bool CollectMemberMethod(const ast::Method& method, Access access, Class* owner);
bool CollectMemberProperty(const ast::Property& property, Access access);
bool CollectMemberConstructor(const ast::ConstructorDeclaration& ctor, Access access, Class* owner);
bool CollectMemberDestructor(const ast::DestructorDeclaration& dtor, Access access, Class* owner);
// ==================== 函数体收集 ====================
void CollectFunctionBody(Function* func, const ast::Block& body);
void CollectFunctionParams(Function* func);
void CollectConstructorBody(Constructor* ctor, const ast::Block& body);
void CollectDestructorBody(Destructor* dtor, const ast::Block& body);
// ==================== 辅助方法 ====================
void CollectInScope(Table* scope, const std::vector<ast::ASTNode>& statements);
void CollectStatements(const std::vector<ast::ASTNode>& statements);
// ==================== 插入方法 ====================
bool TryInsert(SymbolPtr symbol);
bool TryInsertFunction(FunctionPtr func, const ast::Location& loc);
bool TryInsertUnit(UnitPtr unit);
// ==================== 创建签名 ====================
Signature CreateSignature(const ast::Signature& ast_sig);
Signature::Param CreateParameter(const ast::Parameter& ast_param);
protected:
CollectorContext& ctx_;
};
}

View File

@ -1,108 +0,0 @@
#include <sstream>
#include <unordered_map>
#include "./error.hpp"
namespace lsp::language::symbol
{
// ==================== 错误类型名称映射 ====================
namespace
{
const char* GetErrorKindName(ErrorKind kind)
{
static const std::unordered_map<ErrorKind, const char*> names = {
{ ErrorKind::kDuplicateDefinition, "Duplicate definition" },
{ ErrorKind::kSignatureConflict, "Signature conflict" },
{ ErrorKind::kUndefinedType, "Undefined type" },
{ ErrorKind::kInvalidAccess, "Invalid access" },
{ ErrorKind::kCircularDependency, "Circular dependency" },
{ ErrorKind::kInvalidOverride, "Invalid override" },
{ ErrorKind::kInvalidTypeReference, "Invalid type reference" },
{ ErrorKind::kMemberNotFound, "Member not found" },
{ ErrorKind::kInvalidModifier, "Invalid modifier" },
{ ErrorKind::kInvalidParent, "Invalid parent" },
};
auto it = names.find(kind);
return it != names.end() ? it->second : "Unknown error";
}
}
// ==================== Error 实现 ====================
Error::Error(ErrorKind k, const std::string& msg, const ast::Location& loc) :
kind(k), message(msg), location(loc)
{
}
std::string Error::ToString() const
{
std::ostringstream oss;
oss << "[" << location.start_line << ":" << location.start_column << "] ";
oss << GetErrorKindName(kind);
oss << ": " << message;
return oss.str();
}
Error Error::DuplicateDefinition(const std::string& name, const ast::Location& loc)
{
return Error(ErrorKind::kDuplicateDefinition, "Duplicate definition: " + name, loc);
}
Error Error::UndefinedType(const std::string& type, const ast::Location& loc)
{
return Error(ErrorKind::kUndefinedType, "Undefined type: " + type, loc);
}
Error Error::CircularDependency(const std::string& msg, const ast::Location& loc)
{
return Error(ErrorKind::kCircularDependency, msg, loc);
}
// ==================== ErrorReporter 实现 ====================
void ErrorReporter::Report(ErrorKind kind, const std::string& msg, const ast::Location& loc)
{
errors_.emplace_back(kind, msg, loc);
}
void ErrorReporter::Report(const Error& error)
{
errors_.push_back(error);
}
const std::vector<Error>& ErrorReporter::GetErrors() const
{
return errors_;
}
bool ErrorReporter::HasErrors() const
{
return !errors_.empty();
}
size_t ErrorReporter::ErrorCount() const
{
return errors_.size();
}
void ErrorReporter::Clear()
{
errors_.clear();
}
void ErrorReporter::ReportDuplicateDefinition(const std::string& name, const ast::Location& loc)
{
Report(Error::DuplicateDefinition(name, loc));
}
void ErrorReporter::ReportUndefinedType(const std::string& type, const ast::Location& loc)
{
Report(Error::UndefinedType(type, loc));
}
void ErrorReporter::ReportCircularDependency(const std::string& msg, const ast::Location& loc)
{
Report(Error::CircularDependency(msg, loc));
}
}

View File

@ -1,56 +0,0 @@
#pragma once
#include <string>
#include "../../ast/types.hpp"
namespace lsp::language::symbol
{
enum class ErrorKind
{
kDuplicateDefinition,
kSignatureConflict,
kUndefinedType,
kInvalidAccess,
kCircularDependency,
kInvalidOverride,
kInvalidTypeReference,
kMemberNotFound,
kInvalidModifier,
kInvalidParent,
};
struct Error
{
ErrorKind kind;
std::string message;
ast::Location location;
Error(ErrorKind k, const std::string& msg, const ast::Location& loc);
std::string ToString() const;
static Error DuplicateDefinition(const std::string& name, const ast::Location& loc);
static Error UndefinedType(const std::string& type, const ast::Location& loc);
static Error CircularDependency(const std::string& msg, const ast::Location& loc);
};
class ErrorReporter
{
public:
ErrorReporter() = default;
void Report(ErrorKind kind, const std::string& msg, const ast::Location& loc);
void Report(const Error& error);
const std::vector<Error>& GetErrors() const;
bool HasErrors() const;
size_t ErrorCount() const;
void Clear();
void ReportDuplicateDefinition(const std::string& name, const ast::Location& loc);
void ReportUndefinedType(const std::string& type, const ast::Location& loc);
void ReportCircularDependency(const std::string& msg, const ast::Location& loc);
private:
std::vector<Error> errors_;
};
}

View File

@ -1,100 +0,0 @@
#include "./registry.hpp"
namespace lsp::language::symbol
{
SymbolRegistry::SymbolRegistry() :
global_scope_(ScopeKind::kGlobal, nullptr)
{
}
// 移动构造函数
SymbolRegistry::SymbolRegistry(SymbolRegistry&& other) noexcept :
global_scope_(std::move(other.global_scope_)),
units_(std::move(other.units_))
{
// 修复 global_scope_ 中所有符号的 scope 指针
for (auto& [name, symbol] : global_scope_.Symbols())
{
if (symbol && symbol->scope == &other.global_scope_)
{
symbol->scope = &global_scope_;
}
}
// 修复 units_ 中所有符号的 scope 指针
for (auto& [name, unit] : units_)
{
if (unit && unit->scope == &other.global_scope_)
{
unit->scope = &global_scope_;
}
}
}
// 移动赋值运算符
SymbolRegistry& SymbolRegistry::operator=(SymbolRegistry&& other) noexcept
{
if (this != &other)
{
global_scope_ = std::move(other.global_scope_);
units_ = std::move(other.units_);
// 修复 global_scope_ 中所有符号的 scope 指针
for (auto& [name, symbol] : global_scope_.Symbols())
{
if (symbol && symbol->scope == &other.global_scope_)
{
symbol->scope = &global_scope_;
}
}
// 修复 units_ 中所有符号的 scope 指针
for (auto& [name, unit] : units_)
{
if (unit && unit->scope == &other.global_scope_)
{
unit->scope = &global_scope_;
}
}
}
return *this;
}
Table* SymbolRegistry::GlobalScope()
{
return &global_scope_;
}
const Table* SymbolRegistry::GlobalScope() const
{
return &global_scope_;
}
bool SymbolRegistry::AddUnit(UnitPtr unit)
{
if (!unit)
return false;
if (units_.count(unit->name) > 0)
return false;
if (!global_scope_.Insert(unit))
return false;
units_[unit->name] = unit;
return true;
}
UnitPtr SymbolRegistry::FindUnit(const std::string& name) const
{
auto it = units_.find(name);
if (it != units_.end())
return it->second;
return nullptr;
}
const std::unordered_map<std::string, UnitPtr>& SymbolRegistry::Units() const
{
return units_;
}
}

View File

@ -1,37 +0,0 @@
#pragma once
#include <unordered_map>
#include "./symbol.hpp"
#include "./table.hpp"
namespace lsp::language::symbol
{
class SymbolRegistry
{
public:
SymbolRegistry();
~SymbolRegistry() = default;
SymbolRegistry(const SymbolRegistry&) = delete;
SymbolRegistry& operator=(const SymbolRegistry&) = delete;
// 自定义移动构造和移动赋值
SymbolRegistry(SymbolRegistry&& other) noexcept;
SymbolRegistry& operator=(SymbolRegistry&& other) noexcept;
// ==================== 访问全局作用域 ====================
Table* GlobalScope();
const Table* GlobalScope() const;
// ==================== Unit 管理 ====================
bool AddUnit(UnitPtr unit);
UnitPtr FindUnit(const std::string& name) const;
const std::unordered_map<std::string, UnitPtr>& Units() const;
private:
Table global_scope_;
std::unordered_map<std::string, UnitPtr> units_;
};
}

View File

@ -1,78 +0,0 @@
#include "./symbol.hpp"
#include "./table.hpp"
namespace lsp::language::symbol
{
// ==================== Function 实现 ====================
Function::Function(const std::string& name, const ast::Location& loc, const Signature& sig) :
Symbol(name, Kind::kFunction, loc), signature(sig), is_overload(false), body_scope(nullptr)
{
}
Function::~Function() = default;
Function::Function(Function&&) noexcept = default;
Function& Function::operator=(Function&&) noexcept = default;
// ==================== Method 实现 ====================
Method::Method(const std::string& name, const ast::Location& loc, const Signature& sig) :
Function(name, loc, sig), owner_class(nullptr)
{
kind = Kind::kMethod;
}
// ==================== Constructor 实现 ====================
Constructor::Constructor(const std::string& name, const ast::Location& loc, const Signature& sig) :
Symbol(name, Kind::kConstructor, loc), signature(sig), owner_class(nullptr), body_scope(nullptr)
{
}
Constructor::~Constructor() = default;
Constructor::Constructor(Constructor&&) noexcept = default;
Constructor& Constructor::operator=(Constructor&&) noexcept = default;
// ==================== Destructor 实现 ====================
Destructor::Destructor(const std::string& name, const ast::Location& loc) :
Symbol(name, Kind::kDestructor, loc), owner_class(nullptr), body_scope(nullptr)
{
}
Destructor::~Destructor() = default;
Destructor::Destructor(Destructor&&) noexcept = default;
Destructor& Destructor::operator=(Destructor&&) noexcept = default;
// ==================== Class 实现 ====================
Class::Class(const std::string& name, const ast::Location& loc) :
Symbol(name, Kind::kClass, loc), members(nullptr)
{
}
Class::~Class() = default;
Class::Class(Class&&) noexcept = default;
Class& Class::operator=(Class&&) noexcept = default;
// ==================== Unit 实现 ====================
Unit::Unit(const std::string& name, const ast::Location& loc) :
Symbol(name, Kind::kUnit, loc), interface_symbols(nullptr), implementation_symbols(nullptr)
{
}
Unit::~Unit() = default;
Unit::Unit(Unit&&) noexcept = default;
Unit& Unit::operator=(Unit&&) noexcept = default;
}

View File

@ -1,270 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <optional>
#include <memory>
#include "../../ast/types.hpp"
namespace lsp::language::symbol
{
// 前向声明
class Table;
// ==================== 基本枚举 ====================
enum class Kind
{
kVariable,
kStaticVariable,
kGlobalVariable,
kConstant,
kParameter,
kFunction,
kClass,
kMethod,
kConstructor,
kDestructor,
kProperty,
kUnit,
};
enum class ScopeKind
{
kGlobal,
kUnit,
kInterface,
kImplementation,
kFunction,
kClass,
kBlock,
};
using Access = ast::Access;
// ==================== 符号属性 ====================
struct Attributes
{
bool is_const = false;
bool is_static = false;
bool is_var_param = false;
bool is_out_param = false;
Access access = Access::kPublic;
bool is_virtual = false;
bool is_override = false;
bool is_overload = false;
bool is_class_method = false;
};
// ==================== 类型信息(纯数据) ====================
class TypeInfo
{
public:
TypeInfo() = default;
explicit TypeInfo(const std::string& annotation) :
annotation_(annotation) {}
bool HasAnnotation() const { return !annotation_.empty(); }
const std::string& Annotation() const { return annotation_; }
// bool IsArray() const;
// bool IsPrimitive() const;
private:
std::string annotation_; // 类型注解(原始字符串)
};
// ==================== 函数签名(纯数据) ====================
class Signature
{
public:
size_t ParamCount() const { return parameters.size(); }
bool HasReturnType() const { return return_type.has_value(); }
public:
struct Param
{
std::string name;
TypeInfo type;
bool is_var = false;
bool is_out = false;
std::optional<std::string> default_value;
};
std::vector<Param> parameters;
std::optional<TypeInfo> return_type;
};
// ==================== 符号基类 ====================
class Symbol
{
public:
Symbol(const std::string& name, Kind kind, const ast::Location& loc) :
name(name), kind(kind), location(loc), scope(nullptr)
{
}
virtual ~Symbol() = default;
Symbol(const Symbol&) = delete;
Symbol& operator=(const Symbol&) = delete;
Symbol(Symbol&&) noexcept = default;
Symbol& operator=(Symbol&&) noexcept = default;
public:
std::string name;
Kind kind;
ast::Location location;
Table* scope;
Attributes attributes;
};
// ==================== 具体符号类 ====================
class Variable : public Symbol
{
public:
Variable(const std::string& name, Kind kind, const ast::Location& loc, const TypeInfo& type) :
Symbol(name, kind, loc), type(type)
{
}
public:
TypeInfo type;
std::optional<std::string> initialization_expr;
};
class Constant : public Symbol
{
public:
Constant(const std::string& name, const ast::Location& loc, const TypeInfo& type, const std::string& value) :
Symbol(name, Kind::kConstant, loc), type(type), value(value)
{
attributes.is_const = true;
}
public:
TypeInfo type;
std::string value;
};
class Function : public Symbol
{
public:
Function(const std::string& name, const ast::Location& loc, const Signature& sig);
~Function() override;
Function(const Function&) = delete;
Function& operator=(const Function&) = delete;
Function(Function&&) noexcept;
Function& operator=(Function&&) noexcept;
public:
Signature signature;
bool is_overload;
std::unique_ptr<Table> body_scope;
};
class Method : public Function
{
public:
Method(const std::string& name, const ast::Location& loc, const Signature& sig);
public:
class Class* owner_class;
std::optional<ast::Location> implementation_location;
};
class Constructor : public Symbol
{
public:
Signature signature;
class Class* owner_class;
std::unique_ptr<Table> body_scope;
Constructor(const std::string& name, const ast::Location& loc, const Signature& sig);
~Constructor() override;
Constructor(const Constructor&) = delete;
Constructor& operator=(const Constructor&) = delete;
Constructor(Constructor&&) noexcept;
Constructor& operator=(Constructor&&) noexcept;
};
class Destructor : public Symbol
{
public:
class Class* owner_class;
std::unique_ptr<Table> body_scope;
Destructor(const std::string& name, const ast::Location& loc);
~Destructor() override;
Destructor(const Destructor&) = delete;
Destructor& operator=(const Destructor&) = delete;
Destructor(Destructor&&) noexcept;
Destructor& operator=(Destructor&&) noexcept;
};
class Property : public Symbol
{
public:
TypeInfo type;
std::optional<std::string> getter;
std::optional<std::string> setter;
Property(const std::string& name, const ast::Location& loc, const TypeInfo& type) :
Symbol(name, Kind::kProperty, loc), type(type)
{
}
};
class Class : public Symbol
{
public:
std::vector<std::string> parent_names;
std::vector<Class*> parents;
std::unique_ptr<Table> members;
Class(const std::string& name, const ast::Location& loc);
~Class() override;
Class(const Class&) = delete;
Class& operator=(const Class&) = delete;
Class(Class&&) noexcept;
Class& operator=(Class&&) noexcept;
};
class Unit : public Symbol
{
public:
std::vector<std::string> uses;
std::unique_ptr<Table> interface_symbols;
std::unique_ptr<Table> implementation_symbols;
Unit(const std::string& name, const ast::Location& loc);
~Unit() override;
Unit(const Unit&) = delete;
Unit& operator=(const Unit&) = delete;
Unit(Unit&&) noexcept;
Unit& operator=(Unit&&) noexcept;
};
// ==================== 智能指针类型别名 ====================
using SymbolPtr = std::shared_ptr<Symbol>;
using VariablePtr = std::shared_ptr<Variable>;
using ConstantPtr = std::shared_ptr<Constant>;
using FunctionPtr = std::shared_ptr<Function>;
using MethodPtr = std::shared_ptr<Method>;
using ConstructorPtr = std::shared_ptr<Constructor>;
using DestructorPtr = std::shared_ptr<Destructor>;
using PropertyPtr = std::shared_ptr<Property>;
using ClassPtr = std::shared_ptr<Class>;
using UnitPtr = std::shared_ptr<Unit>;
}

View File

@ -1,146 +0,0 @@
#include "./table.hpp"
namespace lsp::language::symbol
{
// ==================== LookupResult 实现 ====================
LookupResult LookupResult::Found(Symbol* sym, Table* scp)
{
LookupResult result;
result.symbol = sym;
result.scope = scp;
result.success = true;
return result;
}
LookupResult LookupResult::NotFound()
{
return LookupResult{};
}
LookupResult::operator bool() const
{
return success;
}
// ==================== Table 实现 ====================
Table::Table(ScopeKind kind, Table* parent) :
kind_(kind), parent_(parent)
{
}
ScopeKind Table::Kind() const
{
return kind_;
}
Table* Table::Parent() const
{
return parent_;
}
const std::unordered_map<std::string, SymbolPtr>& Table::Symbols() const
{
return symbols_;
}
const std::unordered_map<std::string, std::vector<FunctionPtr>>& Table::OverloadedFunctions() const
{
return overloaded_functions_;
}
Table* Table::CreateChild(ScopeKind kind)
{
auto child = std::make_unique<Table>(kind, this);
Table* ptr = child.get();
children_.push_back(std::move(child));
return ptr;
}
bool Table::Insert(SymbolPtr symbol)
{
if (!symbol)
return false;
if (symbols_.count(symbol->name) > 0)
return false;
symbol->scope = this;
symbols_[symbol->name] = symbol;
return true;
}
bool Table::InsertFunction(FunctionPtr func)
{
if (!func)
return false;
func->scope = this;
auto& overloads = overloaded_functions_[func->name];
if (func->is_overload)
overloads.push_back(func);
if (overloads.size() == 1)
symbols_[func->name] = func;
return true;
}
LookupResult Table::LookupLocal(const std::string& name) const
{
auto it = symbols_.find(name);
if (it != symbols_.end())
return LookupResult::Found(it->second.get(), const_cast<Table*>(this));
return LookupResult::NotFound();
}
LookupResult Table::Lookup(const std::string& name) const
{
auto result = LookupLocal(name);
if (result)
return result;
if (parent_)
return parent_->Lookup(name);
return LookupResult::NotFound();
}
std::vector<FunctionPtr> Table::LookupOverloads(const std::string& name) const
{
auto it = overloaded_functions_.find(name);
if (it != overloaded_functions_.end())
return it->second;
if (parent_)
return parent_->LookupOverloads(name);
return {};
}
MethodPtr Table::FindMethodInClass(const std::string& class_name, const std::string& method_name) const
{
// 1. 查找类符号
auto class_result = Lookup(class_name);
if (!class_result || class_result.symbol->kind != Kind::kClass)
return nullptr;
auto class_sym = static_cast<Class*>(class_result.symbol);
if (!class_sym->members)
return nullptr;
auto method_result = class_sym->members->LookupLocal(method_name);
if (!method_result || method_result.symbol->kind != Kind::kMethod)
return nullptr;
auto it = class_sym->members->Symbols().find(method_name);
if (it != class_sym->members->Symbols().end())
return std::static_pointer_cast<Method>(it->second);
return nullptr;
}
}

View File

@ -1,69 +0,0 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <memory>
#include "./symbol.hpp"
namespace lsp::language::symbol
{
// ==================== 查找结果 ====================
struct LookupResult
{
Symbol* symbol = nullptr;
Table* scope = nullptr;
bool success = false;
static LookupResult Found(Symbol* sym, Table* scp);
static LookupResult NotFound();
explicit operator bool() const;
};
// ==================== 符号表 / 作用域 ====================
class Table
{
public:
explicit Table(ScopeKind kind, Table* parent = nullptr);
~Table() = default;
Table(const Table&) = delete;
Table& operator=(const Table&) = delete;
Table(Table&&) noexcept = default;
Table& operator=(Table&&) noexcept = default;
// ==================== 访问器 ====================
ScopeKind Kind() const;
Table* Parent() const;
const std::unordered_map<std::string, SymbolPtr>& Symbols() const;
const std::unordered_map<std::string, std::vector<FunctionPtr>>& OverloadedFunctions() const;
// ==================== 作用域管理 ====================
Table* CreateChild(ScopeKind kind);
// ==================== 符号插入(核心方法) ====================
bool Insert(SymbolPtr symbol);
bool InsertFunction(FunctionPtr func);
// ==================== 符号查找 ====================
LookupResult LookupLocal(const std::string& name) const;
LookupResult Lookup(const std::string& name) const;
// 优化:返回 vector 引用或空 vector
std::vector<FunctionPtr> LookupOverloads(const std::string& name) const;
MethodPtr FindMethodInClass(const std::string& class_name, const std::string& method_name) const;
private:
ScopeKind kind_;
Table* parent_;
std::vector<std::unique_ptr<Table>> children_;
std::unordered_map<std::string, SymbolPtr> symbols_;
std::unordered_map<std::string, std::vector<FunctionPtr>> overloaded_functions_;
};
}

View File

@ -1,114 +0,0 @@
#include "../utils/type.hpp"
#include "./factory.hpp"
namespace lsp::language::symbol
{
// ==================== 创建符号对象 ====================
VariablePtr factory::CreateVariable(
const std::string& name,
Kind kind,
const ast::Location& loc,
const TypeInfo& type)
{
return std::make_shared<Variable>(name, kind, loc, type);
}
ConstantPtr factory::CreateConstant(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type,
const std::string& value)
{
return std::make_shared<Constant>(name, loc, type, value);
}
FunctionPtr factory::CreateFunction(
const std::string& name,
const ast::Location& loc,
const Signature& sig)
{
return std::make_shared<Function>(name, loc, sig);
}
MethodPtr factory::CreateMethod(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner)
{
auto method = std::make_shared<Method>(name, loc, sig);
method->owner_class = owner;
return method;
}
ConstructorPtr factory::CreateConstructor(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner)
{
auto ctor = std::make_shared<Constructor>(name, loc, sig);
ctor->owner_class = owner;
return ctor;
}
DestructorPtr factory::CreateDestructor(
const std::string& name,
const ast::Location& loc,
Class* owner)
{
auto dtor = std::make_shared<Destructor>(name, loc);
dtor->owner_class = owner;
return dtor;
}
PropertyPtr factory::CreateProperty(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type)
{
return std::make_shared<Property>(name, loc, type);
}
ClassPtr factory::CreateClass(
const std::string& name,
const ast::Location& loc)
{
return std::make_shared<Class>(name, loc);
}
UnitPtr factory::CreateUnit(
const std::string& name,
const ast::Location& loc)
{
return std::make_shared<Unit>(name, loc);
}
// ==================== 便捷方法 ====================
VariablePtr factory::CreateAndInsert(
Table* table,
const std::string& name,
Kind kind,
const ast::Location& loc,
const TypeInfo& type)
{
auto var = CreateVariable(name, kind, loc, type);
if (table && table->Insert(var))
return var;
return nullptr;
}
VariablePtr factory::CreateVariableFromAST(
const std::string& name,
Kind kind,
const ast::Location& loc,
const std::optional<std::string>& type_str)
{
TypeInfo type = type_str ?
TypeFactory::FromAnnotation(*type_str) :
TypeInfo();
return CreateVariable(name, kind, loc, type);
}
}

View File

@ -1,110 +0,0 @@
#pragma once
#include <optional>
#include "../../ast/types.hpp"
#include "../core/symbol.hpp"
#include "../core/table.hpp"
namespace lsp::language::symbol
{
/**
* -
*
*
* -
* - std::make_shared
*
*
* - AST Symbol Collector
*/
namespace factory
{
// ==================== 创建符号对象 ====================
/**
*
*/
VariablePtr CreateVariable(
const std::string& name,
Kind kind,
const ast::Location& loc,
const TypeInfo& type);
/**
*
*/
ConstantPtr CreateConstant(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type,
const std::string& value);
/**
*
*/
FunctionPtr CreateFunction(
const std::string& name,
const ast::Location& loc,
const Signature& sig);
/**
*
*/
MethodPtr CreateMethod(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner);
/**
*
*/
ConstructorPtr CreateConstructor(
const std::string& name,
const ast::Location& loc,
const Signature& sig,
Class* owner);
/**
*
*/
DestructorPtr CreateDestructor(
const std::string& name,
const ast::Location& loc,
Class* owner);
/**
*
*/
PropertyPtr CreateProperty(
const std::string& name,
const ast::Location& loc,
const TypeInfo& type);
/**
*
*/
ClassPtr CreateClass(
const std::string& name,
const ast::Location& loc);
/**
* Unit
*/
UnitPtr CreateUnit(const std::string& name, const ast::Location& loc);
// ==================== 便捷方法 ====================
/**
*
* @return nullptr
*/
VariablePtr CreateAndInsert(Table* table, const std::string& name, Kind kind, const ast::Location& loc, const TypeInfo& type);
/**
* AST
*/
VariablePtr CreateVariableFromAST(const std::string& name, Kind kind, const ast::Location& loc,
const std::optional<std::string>& type_str);
}
}

View File

@ -1,74 +0,0 @@
#include "./scope_manager.hpp"
namespace lsp::language::symbol
{
// ==================== ScopeGuard 实现 ====================
ScopeGuard::ScopeGuard(Table*& current, Table* new_scope) :
current_(current), previous_(current), active_(true)
{
current_ = new_scope;
}
ScopeGuard::~ScopeGuard()
{
if (active_)
{
current_ = previous_;
}
}
ScopeGuard::ScopeGuard(ScopeGuard&& other) noexcept :
current_(other.current_),
previous_(other.previous_),
active_(other.active_)
{
other.active_ = false;
}
ScopeGuard& ScopeGuard::operator=(ScopeGuard&& other) noexcept
{
if (this != &other)
{
if (active_)
{
current_ = previous_;
}
current_ = other.current_;
previous_ = other.previous_;
active_ = other.active_;
other.active_ = false;
}
return *this;
}
// ==================== ScopeManager 实现 ====================
ScopeManager::ScopeManager(Table* root) :
root_(root), current_(root)
{
}
Table* ScopeManager::Current() const
{
return current_;
}
ScopeGuard ScopeManager::EnterScope(Table* scope)
{
return ScopeGuard(current_, scope);
}
ScopeGuard ScopeManager::CreateAndEnterChild(ScopeKind kind)
{
Table* child = current_->CreateChild(kind);
return ScopeGuard(current_, child);
}
void ScopeManager::SetCurrent(Table* scope)
{
current_ = scope;
}
}

View File

@ -1,53 +0,0 @@
#pragma once
#include "../core/table.hpp"
namespace lsp::language::symbol
{
// ==================== 作用域守卫 ====================
// RAII风格的作用域管理
class ScopeGuard
{
public:
ScopeGuard(Table*& current, Table* new_scope);
~ScopeGuard();
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
ScopeGuard(ScopeGuard&& other) noexcept;
ScopeGuard& operator=(ScopeGuard&& other) noexcept;
private:
Table*& current_;
Table* previous_;
bool active_;
};
// ==================== 作用域管理器 ====================
// 负责管理当前作用域的切换和导航
class ScopeManager
{
public:
explicit ScopeManager(Table* root);
// 获取当前作用域
Table* Current() const;
// 进入指定作用域(返回守卫,自动恢复)
[[nodiscard]] ScopeGuard EnterScope(Table* scope);
// 创建子作用域并进入
[[nodiscard]] ScopeGuard CreateAndEnterChild(ScopeKind kind);
// 直接设置当前作用域不推荐破坏RAII
void SetCurrent(Table* scope);
// 获取根作用域
Table* Root() const { return root_; }
private:
Table* root_;
Table* current_;
};
}

View File

@ -1,145 +0,0 @@
#include <sstream>
#include "./incremental.hpp"
namespace lsp::language::symbol
{
// ==================== SymbolCacheKey 实现 ====================
std::string SymbolCacheKey::ComputeSignatureHash(const Signature& sig)
{
std::ostringstream oss;
oss << sig.parameters.size() << "|";
for (const auto& param : sig.parameters)
{
oss << param.name << ":"
<< param.type.Annotation() << ":"
<< (param.is_var ? "v" : "")
<< (param.is_out ? "o" : "") << "|";
}
if (sig.return_type)
{
oss << "ret:" << sig.return_type->Annotation();
}
return oss.str();
}
// ==================== SymbolCache 实现 ====================
SymbolCache::SymbolCache(size_t max_size) :
max_size_(max_size)
{
}
const SymbolPtr* SymbolCache::Find(const SymbolCacheKey& key)
{
auto it = cache_.find(key);
if (it != cache_.end())
{
// 更新 LRU移到最前面
TouchKey(key);
return &it->second.symbol;
}
return nullptr;
}
void SymbolCache::Insert(const SymbolCacheKey& key, const SymbolPtr& symbol)
{
// 检查是否已存在
auto it = cache_.find(key);
if (it != cache_.end())
{
// 更新现有条目
it->second.symbol = symbol;
TouchKey(key);
return;
}
// 检查是否需要淘汰
if (cache_.size() >= max_size_)
{
EvictLRU();
}
// 插入新条目
lru_list_.push_front(key);
cache_[key] = CacheEntry{ symbol, lru_list_.begin() };
}
void SymbolCache::Clear()
{
cache_.clear();
lru_list_.clear();
}
void SymbolCache::EvictLRU()
{
if (lru_list_.empty())
return;
// 删除最久未使用的项(列表末尾)
auto lru_key = lru_list_.back();
lru_list_.pop_back();
cache_.erase(lru_key);
}
void SymbolCache::TouchKey(const SymbolCacheKey& key)
{
auto it = cache_.find(key);
if (it == cache_.end())
return;
// 从当前位置删除
lru_list_.erase(it->second.lru_iter);
// 移到最前面
lru_list_.push_front(key);
it->second.lru_iter = lru_list_.begin();
}
SymbolCacheKey SymbolCache::MakeKey(const Symbol* symbol)
{
if (!symbol)
return SymbolCacheKey{};
SymbolCacheKey key;
key.symbol_name = symbol->name;
key.symbol_kind = symbol->kind;
key.declaration_line = symbol->location.start_line;
key.declaration_column = symbol->location.start_column;
// 对于函数,添加签名哈希
if (auto* func = dynamic_cast<const Function*>(symbol))
{
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(func->signature);
}
else if (auto* ctor = dynamic_cast<const Constructor*>(symbol))
{
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(ctor->signature);
}
return key;
}
SymbolCacheKey SymbolCache::MakeKeyFromAST(
const std::string& name,
Kind kind,
const ast::Location& name_location,
const std::optional<Signature>& signature)
{
SymbolCacheKey key;
key.symbol_name = name;
key.symbol_kind = kind;
key.declaration_line = name_location.start_line;
key.declaration_column = name_location.start_column;
if (signature)
{
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(*signature);
}
return key;
}
}

View File

@ -1,97 +0,0 @@
#pragma once
#include <unordered_map>
#include <optional>
#include <list>
#include "../core/symbol.hpp"
namespace lsp::language::symbol
{
// ==================== 改进的缓存键设计 ====================
// 基于 AST 位置和内容,避免指针地址依赖
struct SymbolCacheKey
{
std::string symbol_name;
Kind symbol_kind;
uint32_t declaration_line; // 使用声明位置行号
uint32_t declaration_column; // 使用声明位置列号
std::optional<std::string> signature_hash; // 函数签名哈希
bool operator==(const SymbolCacheKey& other) const
{
return symbol_name == other.symbol_name &&
symbol_kind == other.symbol_kind &&
declaration_line == other.declaration_line &&
declaration_column == other.declaration_column &&
signature_hash == other.signature_hash;
}
// 生成签名哈希(用于函数/方法)
static std::string ComputeSignatureHash(const Signature& sig);
};
struct SymbolCacheKeyHash
{
size_t operator()(const SymbolCacheKey& key) const
{
size_t h1 = std::hash<std::string>()(key.symbol_name);
size_t h2 = std::hash<int>()(static_cast<int>(key.symbol_kind));
size_t h3 = std::hash<uint32_t>()(key.declaration_line);
size_t h4 = std::hash<uint32_t>()(key.declaration_column);
size_t h5 = key.signature_hash ?
std::hash<std::string>()(*key.signature_hash) :
0;
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3) ^ (h5 << 4);
}
};
// ==================== 符号缓存管理器带LRU ====================
class SymbolCache
{
public:
explicit SymbolCache(size_t max_size = 10000);
// 查找缓存
const SymbolPtr* Find(const SymbolCacheKey& key);
// 插入缓存
void Insert(const SymbolCacheKey& key, const SymbolPtr& symbol);
// 清空缓存
void Clear();
// 获取缓存大小
size_t Size() const { return cache_.size(); }
// 设置最大缓存大小
void SetMaxSize(size_t max_size) { max_size_ = max_size; }
// 从 Symbol 生成 Key
static SymbolCacheKey MakeKey(const Symbol* symbol);
// 从 AST 信息生成 Key
static SymbolCacheKey MakeKeyFromAST(
const std::string& name,
Kind kind,
const ast::Location& name_location,
const std::optional<Signature>& signature = std::nullopt);
private:
// LRU 淘汰策略
void EvictLRU();
void TouchKey(const SymbolCacheKey& key);
private:
struct CacheEntry
{
SymbolPtr symbol;
std::list<SymbolCacheKey>::iterator lru_iter;
};
std::unordered_map<SymbolCacheKey, CacheEntry, SymbolCacheKeyHash> cache_;
std::list<SymbolCacheKey> lru_list_; // 最近使用列表
size_t max_size_;
};
}

View File

@ -1,344 +0,0 @@
#include "../core/symbol.hpp"
#include "./incremental_engine.hpp"
namespace lsp::language::symbol
{
IncrementalEngine::IncrementalEngine() :
cache_(10000),
max_cache_size_(10000)
{
}
// ==================== 符号复用与缓存 ====================
bool IncrementalEngine::TryReuseSymbol(const ast::ASTNode& node, Table* scope, SymbolRegistry* registry)
{
return std::visit([this, scope, registry](auto&& arg) -> bool {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::monostate>)
{
return true;
}
else if constexpr (std::is_same_v<T, ast::VarDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kVariable, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::GlobalDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kGlobalVariable, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::StaticDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kStaticVariable, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::ConstDeclaration>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kConstant, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::FunctionDefinition>)
{
// 创建签名用于缓存键
Signature sig;
for (const auto& param : arg.signature.parameters)
{
Signature::Param p;
p.name = param.name;
if (param.type_name)
{
p.type = TypeInfo(*param.type_name);
}
p.is_var = param.is_var;
p.is_out = param.is_out;
sig.parameters.push_back(p);
}
if (arg.signature.return_type)
{
sig.return_type = TypeInfo(*arg.signature.return_type);
}
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kFunction, arg.name_location, sig);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
auto func = std::dynamic_pointer_cast<Function>(*cached);
if (func)
{
return scope->InsertFunction(func);
}
}
return false;
}
else if constexpr (std::is_same_v<T, ast::ClassDefinition>)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kClass, arg.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
return scope->Insert(*cached);
}
return false;
}
else if constexpr (std::is_same_v<T, ast::UnitDefinition>)
{
// Unit 支持复用
if (registry)
{
return TryReuseUnit(arg, registry);
}
return false;
}
else
{
// 其他类型Expression, Block 等)直接跳过
return true;
}
},
node);
}
bool IncrementalEngine::TryReuseUnit(
const ast::UnitDefinition& unit_ast,
SymbolRegistry* registry)
{
if (!registry)
return false;
auto key = SymbolCache::MakeKeyFromAST(
unit_ast.name, Kind::kUnit, unit_ast.name_location);
const SymbolPtr* cached = cache_.Find(key);
if (cached && *cached)
{
auto unit = std::dynamic_pointer_cast<Unit>(*cached);
if (unit)
{
// 尝试将缓存的 Unit 添加到 Registry
return registry->AddUnit(unit);
}
}
return false;
}
void IncrementalEngine::CacheSymbol(const ast::ASTNode& node, Table* scope)
{
std::visit([this, scope](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, ast::VarDeclaration> ||
std::is_same_v<T, ast::GlobalDeclaration> ||
std::is_same_v<T, ast::StaticDeclaration>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, result.symbol->kind, arg.name_location);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::ConstDeclaration>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kConstant, arg.name_location);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::FunctionDefinition>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
// 创建签名用于缓存键
Signature sig;
for (const auto& param : arg.signature.parameters)
{
Signature::Param p;
p.name = param.name;
if (param.type_name)
{
p.type = TypeInfo(*param.type_name);
}
p.is_var = param.is_var;
p.is_out = param.is_out;
sig.parameters.push_back(p);
}
if (arg.signature.return_type)
{
sig.return_type = TypeInfo(*arg.signature.return_type);
}
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kFunction, arg.name_location, sig);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::ClassDefinition>)
{
auto result = scope->LookupLocal(arg.name);
if (result && result.symbol)
{
auto key = SymbolCache::MakeKeyFromAST(
arg.name, Kind::kClass, arg.name_location);
const auto& symbols = scope->Symbols();
auto it = symbols.find(arg.name);
if (it != symbols.end())
{
cache_.Insert(key, it->second);
}
}
}
else if constexpr (std::is_same_v<T, ast::UnitDefinition>)
{
// Unit 缓存需要从 Registry 获取
// 这里暂时不处理,在 BuildCache 中统一处理
}
// 其他类型不需要缓存
},
node);
}
void IncrementalEngine::BuildCache(const SymbolRegistry& registry)
{
// 缓存所有 Unit
for (const auto& [name, unit] : registry.Units())
{
auto key = SymbolCache::MakeKey(unit.get());
cache_.Insert(key, unit);
// 递归缓存 Unit 内部的符号
if (unit->interface_symbols)
CacheScopeRecursive(unit->interface_symbols.get());
if (unit->implementation_symbols)
CacheScopeRecursive(unit->implementation_symbols.get());
}
// 缓存全局作用域
CacheScopeRecursive(const_cast<Table*>(registry.GlobalScope()));
}
void IncrementalEngine::CacheScopeRecursive(Table* scope)
{
if (!scope)
return;
// 缓存当前作用域的所有符号
for (const auto& [name, symbol] : scope->Symbols())
{
auto key = SymbolCache::MakeKey(symbol.get());
cache_.Insert(key, symbol);
// 递归缓存类成员
if (auto* cls = dynamic_cast<Class*>(symbol.get()))
{
if (cls->members)
{
CacheScopeRecursive(cls->members.get());
}
}
// 递归缓存函数体作用域
if (auto* func = dynamic_cast<Function*>(symbol.get()))
{
if (func->body_scope)
{
CacheScopeRecursive(func->body_scope.get());
}
}
// 递归缓存构造函数体作用域
if (auto* ctor = dynamic_cast<Constructor*>(symbol.get()))
{
if (ctor->body_scope)
{
CacheScopeRecursive(ctor->body_scope.get());
}
}
// 递归缓存析构函数体作用域
if (auto* dtor = dynamic_cast<Destructor*>(symbol.get()))
{
if (dtor->body_scope)
{
CacheScopeRecursive(dtor->body_scope.get());
}
}
}
}
// ==================== 管理接口 ====================
void IncrementalEngine::Clear()
{
cache_.Clear();
}
void IncrementalEngine::SetMaxCacheSize(size_t max_size)
{
max_cache_size_ = max_size;
cache_.SetMaxSize(max_size);
}
size_t IncrementalEngine::GetCacheSize() const
{
return cache_.Size();
}
}

View File

@ -1,75 +0,0 @@
#pragma once
#include "../../ast/types.hpp"
#include "../core/registry.hpp"
#include "../core/table.hpp"
#include "./incremental.hpp"
namespace lsp::language::symbol
{
/**
* -
*
*
* - (SymbolCache)
* -
* -
* -
*
*
* -
* -
*/
class IncrementalEngine
{
public:
IncrementalEngine();
// ==================== 符号复用与缓存 ====================
/**
*
* @param node AST
* @param scope
* @param registry Unit
* @return
*/
bool TryReuseSymbol(const ast::ASTNode& node, Table* scope, SymbolRegistry* registry = nullptr);
/**
*
* @param node AST
* @param scope
*/
void CacheSymbol(const ast::ASTNode& node, Table* scope);
/**
*
* @param registry
*/
void BuildCache(const SymbolRegistry& registry);
// ==================== 管理接口 ====================
void Clear();
void SetMaxCacheSize(size_t max_size);
size_t GetCacheSize() const;
// 访问器
SymbolCache& GetCache() { return cache_; }
const SymbolCache& GetCache() const { return cache_; }
private:
// ==================== 内部辅助方法 ====================
// 递归缓存作用域中的所有符号
void CacheScopeRecursive(Table* scope);
// 尝试复用 Unit
bool TryReuseUnit(const ast::UnitDefinition& unit_ast, SymbolRegistry* registry);
private:
SymbolCache cache_;
size_t max_cache_size_;
};
}

View File

@ -0,0 +1,105 @@
#include <algorithm>
#include "./location_index.hpp"
namespace lsp::language::symbol
{
void LocationIndex::AddSymbol(SymbolId id, const ast::Location& location)
{
symbol_entries_.push_back({ location.start_byte,
location.end_byte,
id });
symbols_sorted_ = false;
}
void LocationIndex::AddScope(ScopeId id, const ast::Location& range)
{
scope_entries_.push_back({ range.start_byte,
range.end_byte,
id });
scopes_sorted_ = false;
}
void LocationIndex::AddReference(SymbolId symbol_id, const ast::Location& location)
{
reference_entries_.push_back({ location.start_byte,
location.end_byte,
symbol_id });
references_sorted_ = false;
}
std::optional<SymbolId> LocationIndex::FindSymbolAt(const ast::Location& location) const
{
// 确保索引已排序
if (!symbols_sorted_)
return std::nullopt;
return FindInSortedEntries<LocationEntry, SymbolId>(symbol_entries_, location, true);
}
std::optional<ScopeId> LocationIndex::FindScopeAt(const ast::Location& location) const
{
// 确保索引已排序
if (!scopes_sorted_)
return std::nullopt;
return FindInSortedEntries<ScopeEntry, ScopeId>(scope_entries_, location, true);
}
std::optional<SymbolId> LocationIndex::FindReferenceAt(const ast::Location& location) const
{
// 确保索引已排序
if (!references_sorted_)
return std::nullopt;
auto it = std::lower_bound(
reference_entries_.begin(),
reference_entries_.end(),
location.start_byte,
[](const ReferenceEntry& entry, uint32_t pos) {
return entry.start_byte < pos;
});
if (it != reference_entries_.begin())
--it;
for (; it != reference_entries_.end() && it->start_byte <= location.start_byte; ++it)
{
if (IsLocationInRange(location, it->start_byte, it->end_byte))
return it->symbol_id;
}
return std::nullopt;
}
void LocationIndex::RebuildIndex()
{
if (!symbols_sorted_)
{
std::sort(symbol_entries_.begin(), symbol_entries_.end());
symbols_sorted_ = true;
}
if (!scopes_sorted_)
{
std::sort(scope_entries_.begin(), scope_entries_.end());
scopes_sorted_ = true;
}
if (!references_sorted_)
{
std::sort(reference_entries_.begin(), reference_entries_.end());
references_sorted_ = true;
}
}
void LocationIndex::Clear()
{
symbol_entries_.clear();
scope_entries_.clear();
reference_entries_.clear();
symbols_sorted_ = true;
scopes_sorted_ = true;
references_sorted_ = true;
}
}

View File

@ -0,0 +1,121 @@
#pragma once
#include <vector>
#include <optional>
#include <algorithm>
#include "./types.hpp"
namespace lsp::language::symbol
{
class LocationIndex
{
public:
struct LocationEntry
{
uint32_t start_byte;
uint32_t end_byte;
SymbolId symbol_id;
bool operator<(const LocationEntry& other) const
{
if (start_byte != other.start_byte)
return start_byte < other.start_byte;
return end_byte > other.end_byte;
}
};
struct ScopeEntry
{
uint32_t start_byte;
uint32_t end_byte;
ScopeId scope_id;
bool operator<(const ScopeEntry& other) const
{
if (start_byte != other.start_byte)
return start_byte < other.start_byte;
return end_byte > other.end_byte;
}
};
struct ReferenceEntry
{
uint32_t start_byte;
uint32_t end_byte;
SymbolId symbol_id;
bool operator<(const ReferenceEntry& other) const
{
return start_byte < other.start_byte;
}
};
void AddSymbol(SymbolId id, const ast::Location& location);
void AddScope(ScopeId id, const ast::Location& range);
void AddReference(SymbolId symbol_id, const ast::Location& location);
void RebuildIndex();
void Clear();
std::optional<SymbolId> FindSymbolAt(const ast::Location& location) const;
std::optional<ScopeId> FindScopeAt(const ast::Location& location) const;
std::optional<SymbolId> FindReferenceAt(const ast::Location& location) const;
private:
// 符号定义位置索引(按起始位置排序)
std::vector<LocationEntry> symbol_entries_;
bool symbols_sorted_ = true;
// 作用域位置索引(按起始位置排序)
std::vector<ScopeEntry> scope_entries_;
bool scopes_sorted_ = true;
// 引用位置索引(位置 -> 符号ID)
std::vector<ReferenceEntry> reference_entries_;
bool references_sorted_ = true;
// 辅助方法:在排序数组中查找位置(模板实现放在头文件)
template<typename T, typename IdType>
std::optional<IdType> FindInSortedEntries(const std::vector<T>& entries, const ast::Location& location, bool find_innermost = true) const
{
if (entries.empty())
return std::nullopt;
auto it = std::lower_bound(
entries.begin(),
entries.end(),
location.start_byte,
[](const T& entry, uint32_t pos) {
return entry.start_byte < pos;
});
if (it != entries.begin())
--it;
std::vector<IdType> candidates;
for (; it != entries.end() && it->start_byte <= location.start_byte; ++it)
{
if (IsLocationInRange(location, it->start_byte, it->end_byte))
{
if constexpr (std::is_same_v<T, LocationEntry> || std::is_same_v<T, ReferenceEntry>)
candidates.push_back(it->symbol_id);
else if constexpr (std::is_same_v<T, ScopeEntry>)
candidates.push_back(it->scope_id);
}
}
if (candidates.empty())
return std::nullopt;
if (find_innermost)
return candidates.back();
else
return candidates.front();
}
static bool IsLocationInRange(const ast::Location& location, uint32_t start, uint32_t end)
{
return location.start_byte >= start && location.start_byte < end;
}
};
}

View File

@ -0,0 +1,116 @@
#include <unordered_set>
#include "./relations.hpp"
namespace lsp::language::symbol
{
// ===== ReferenceGraph 实现 =====
void ReferenceGraph::AddReference(SymbolId symbol_id, const ast::Location& location, bool is_definition, bool is_write)
{
references_[symbol_id].push_back({ location, symbol_id, is_definition, is_write });
}
const std::vector<Reference>* ReferenceGraph::GetReferences(SymbolId symbol_id) const
{
auto it = references_.find(symbol_id);
return it != references_.end() ? &it->second : nullptr;
}
std::optional<ast::Location> ReferenceGraph::GetDefinition(SymbolId symbol_id) const
{
auto it = references_.find(symbol_id);
if (it != references_.end())
{
for (const auto& ref : it->second)
{
if (ref.is_definition)
return ref.location;
}
}
return std::nullopt;
}
void ReferenceGraph::Clear()
{
references_.clear();
}
// ===== InheritanceGraph 实现 =====
void InheritanceGraph::AddInheritance(SymbolId derived_class, SymbolId base_class)
{
base_classes_[derived_class].push_back(base_class);
derived_classes_[base_class].push_back(derived_class);
}
const std::vector<SymbolId>* InheritanceGraph::GetBaseClasses(SymbolId class_id) const
{
auto it = base_classes_.find(class_id);
return it != base_classes_.end() ? &it->second : nullptr;
}
const std::vector<SymbolId>* InheritanceGraph::GetDerivedClasses(SymbolId class_id) const
{
auto it = derived_classes_.find(class_id);
return it != derived_classes_.end() ? &it->second : nullptr;
}
bool InheritanceGraph::IsSubclassOf(SymbolId derived, SymbolId base) const
{
std::unordered_set<SymbolId> visited;
std::vector<SymbolId> queue = { derived };
while (!queue.empty())
{
SymbolId current = queue.back();
queue.pop_back();
if (current == base)
return true;
if (visited.count(current))
continue;
visited.insert(current);
auto bases = GetBaseClasses(current);
if (bases)
queue.insert(queue.end(), bases->begin(), bases->end());
}
return false;
}
void InheritanceGraph::Clear()
{
base_classes_.clear();
derived_classes_.clear();
}
// ===== CallGraph 实现 =====
void CallGraph::AddCall(SymbolId caller, SymbolId callee, const ast::Location& location)
{
CallRelation rel{ caller, callee, location };
callers_[callee].push_back(rel);
callees_[caller].push_back(rel);
}
const std::vector<CallRelation>* CallGraph::GetCallers(SymbolId function_id) const
{
auto it = callers_.find(function_id);
return it != callers_.end() ? &it->second : nullptr;
}
const std::vector<CallRelation>* CallGraph::GetCallees(SymbolId function_id) const
{
auto it = callees_.find(function_id);
return it != callees_.end() ? &it->second : nullptr;
}
void CallGraph::Clear()
{
callers_.clear();
callees_.clear();
}
}

View File

@ -0,0 +1,57 @@
#pragma once
#include <unordered_map>
#include <vector>
#include "./types.hpp"
namespace lsp::language::symbol
{
// 引用图
class ReferenceGraph
{
public:
void AddReference(SymbolId symbol_id, const ast::Location& location, bool is_definition = false, bool is_write = false);
void Clear();
// 返回引用避免拷贝,如果不存在返回 nullptr
const std::vector<Reference>* GetReferences(SymbolId symbol_id) const;
std::optional<ast::Location> GetDefinition(SymbolId symbol_id) const;
private:
std::unordered_map<SymbolId, std::vector<Reference>> references_;
};
// 继承图
class InheritanceGraph
{
public:
void AddInheritance(SymbolId derived_class, SymbolId base_class);
void Clear();
// 返回引用避免拷贝
const std::vector<SymbolId>* GetBaseClasses(SymbolId class_id) const;
const std::vector<SymbolId>* GetDerivedClasses(SymbolId class_id) const;
bool IsSubclassOf(SymbolId derived, SymbolId base) const;
private:
std::unordered_map<SymbolId, std::vector<SymbolId>> base_classes_;
std::unordered_map<SymbolId, std::vector<SymbolId>> derived_classes_;
};
// 调用图
class CallGraph
{
public:
void AddCall(SymbolId caller, SymbolId callee, const ast::Location& location);
void Clear();
// 返回引用避免拷贝
const std::vector<CallRelation>* GetCallers(SymbolId function_id) const;
const std::vector<CallRelation>* GetCallees(SymbolId function_id) const;
private:
std::unordered_map<SymbolId, std::vector<CallRelation>> callers_;
std::unordered_map<SymbolId, std::vector<CallRelation>> callees_;
};
}

View File

@ -0,0 +1,88 @@
#include "./scope.hpp"
namespace lsp::language::symbol
{
ScopeId ScopeManager::CreateScope(ScopeKind kind, const ast::Location& range, std::optional<ScopeId> parent_scope_id, std::optional<SymbolId> associated_symbol_id)
{
ScopeId new_scope_id = next_scope_id_++;
ScopeInfo info;
info.scope_id = new_scope_id;
info.kind = kind;
info.range = range;
info.parent_scope_id = parent_scope_id;
info.associated_symbol_id = associated_symbol_id;
scopes_[new_scope_id] = std::move(info);
if (kind == ScopeKind::Global)
global_scope_id_ = new_scope_id;
return new_scope_id;
}
void ScopeManager::AddSymbol(ScopeId scope_id, const std::string& name, SymbolId symbol_id)
{
auto it = scopes_.find(scope_id);
if (it != scopes_.end())
it->second.symbols[name] = symbol_id;
}
std::optional<SymbolId> ScopeManager::FindInScope(ScopeId scope_id, const std::string& name) const
{
auto it = scopes_.find(scope_id);
if (it == scopes_.end())
return std::nullopt;
auto sym_it = it->second.symbols.find(name);
if (sym_it != it->second.symbols.end())
return sym_it->second;
return std::nullopt;
}
std::optional<SymbolId> ScopeManager::FindInScopeChain(ScopeId scope_id, const std::string& name) const
{
auto current_id = scope_id;
while (current_id != kInvalidScopeId)
{
if (auto result = FindInScope(current_id, name))
return result;
auto it = scopes_.find(current_id);
if (it == scopes_.end() || !it->second.parent_scope_id)
break;
current_id = *it->second.parent_scope_id;
}
return std::nullopt;
}
const ScopeInfo* ScopeManager::GetScopeInfo(ScopeId scope_id) const
{
auto it = scopes_.find(scope_id);
return it != scopes_.end() ? &it->second : nullptr;
}
std::vector<SymbolId> ScopeManager::GetSymbolsInScope(ScopeId scope_id) const
{
std::vector<SymbolId> result;
auto it = scopes_.find(scope_id);
if (it != scopes_.end())
{
for (const auto& [name, id] : it->second.symbols)
result.push_back(id);
}
return result;
}
void ScopeManager::Clear()
{
scopes_.clear();
global_scope_id_ = kInvalidScopeId;
next_scope_id_ = 1;
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <unordered_map>
#include <vector>
#include "./types.hpp"
namespace lsp::language::symbol
{
class ScopeManager
{
public:
ScopeId CreateScope(ScopeKind kind, const ast::Location& range, std::optional<ScopeId> parent_scope_id = std::nullopt, std::optional<SymbolId> associated_symbol_id = std::nullopt);
void AddSymbol(ScopeId scope_id, const std::string& name, SymbolId symbol_id);
std::optional<SymbolId> FindInScope(ScopeId scope_id, const std::string& name) const;
std::optional<SymbolId> FindInScopeChain(ScopeId scope_id, const std::string& name) const;
const ScopeInfo* GetScopeInfo(ScopeId scope_id) const;
std::vector<SymbolId> GetSymbolsInScope(ScopeId scope_id) const;
ScopeId GetGlobalScope() const { return global_scope_id_; }
const std::unordered_map<ScopeId, ScopeInfo>& GetAllScopes() const { return scopes_; }
void Clear();
private:
ScopeId next_scope_id_ = 1;
ScopeId global_scope_id_ = kInvalidScopeId;
std::unordered_map<ScopeId, ScopeInfo> scopes_;
};
}

View File

@ -0,0 +1,101 @@
#include <algorithm>
#include "./store.hpp"
namespace lsp::language::symbol
{
SymbolId SymbolDefinitionStore::Add(SymbolDefinition def)
{
def.id = next_id_++;
UpdateIndices(def);
definitions_[def.id] = std::move(def);
return def.id;
}
const SymbolDefinition* SymbolDefinitionStore::Get(SymbolId id) const
{
auto it = definitions_.find(id);
return it != definitions_.end() ? &it->second : nullptr;
}
bool SymbolDefinitionStore::Update(SymbolId id, std::function<void(SymbolDefinition&)> updater)
{
auto it = definitions_.find(id);
if (it == definitions_.end())
return false;
RemoveFromIndices(it->second);
updater(it->second);
UpdateIndices(it->second);
return true;
}
bool SymbolDefinitionStore::Remove(SymbolId id)
{
auto it = definitions_.find(id);
if (it == definitions_.end())
return false;
RemoveFromIndices(it->second);
definitions_.erase(it);
return true;
}
std::vector<const SymbolDefinition*> SymbolDefinitionStore::GetAll() const
{
std::vector<const SymbolDefinition*> result;
result.reserve(definitions_.size());
for (const auto& [id, def] : definitions_)
result.push_back(&def);
return result;
}
std::vector<const SymbolDefinition*> SymbolDefinitionStore::FindByName(const std::string& name) const
{
std::vector<const SymbolDefinition*> result;
auto it = name_index_.find(name);
if (it != name_index_.end())
{
for (SymbolId id : it->second)
{
if (auto def = Get(id))
result.push_back(def);
}
}
return result;
}
std::vector<SymbolId> SymbolDefinitionStore::GetChildren(SymbolId parent_id) const
{
auto it = children_index_.find(parent_id);
return it != children_index_.end() ? it->second : std::vector<SymbolId>{};
}
void SymbolDefinitionStore::Clear()
{
definitions_.clear();
name_index_.clear();
children_index_.clear();
next_id_ = 1;
}
void SymbolDefinitionStore::UpdateIndices(const SymbolDefinition& def)
{
name_index_[def.name].push_back(def.id);
if (def.parent_id)
children_index_[*def.parent_id].push_back(def.id);
}
void SymbolDefinitionStore::RemoveFromIndices(const SymbolDefinition& def)
{
auto& name_vec = name_index_[def.name];
name_vec.erase(std::remove(name_vec.begin(), name_vec.end(), def.id), name_vec.end());
if (def.parent_id)
{
auto& children_vec = children_index_[*def.parent_id];
children_vec.erase(std::remove(children_vec.begin(), children_vec.end(), def.id), children_vec.end());
}
}
}

View File

@ -0,0 +1,35 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <functional>
#include "./types.hpp"
namespace lsp::language::symbol
{
class SymbolDefinitionStore
{
public:
SymbolId Add(SymbolDefinition def);
const SymbolDefinition* Get(SymbolId id) const;
bool Update(SymbolId id, std::function<void(SymbolDefinition&)> updater);
bool Remove(SymbolId id);
void Clear();
std::vector<const SymbolDefinition*> GetAll() const;
std::vector<const SymbolDefinition*> FindByName(const std::string& name) const;
std::vector<SymbolId> GetChildren(SymbolId parent_id) const;
private:
SymbolId next_id_ = 1;
std::unordered_map<SymbolId, SymbolDefinition> definitions_;
std::unordered_map<std::string, std::vector<SymbolId>, utils::IHasher, utils::IEqualTo> name_index_;
std::unordered_map<SymbolId, std::vector<SymbolId>> children_index_;
void UpdateIndices(const SymbolDefinition& def);
void RemoveFromIndices(const SymbolDefinition& def);
};
}

View File

@ -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);
}
}

View File

@ -0,0 +1,126 @@
#pragma once
#include "./store.hpp"
#include "./scope.hpp"
#include "./location_index.hpp"
#include "./relations.hpp"
namespace lsp::language::symbol
{
class Builder;
// 统一的符号表接口
class SymbolTable
{
public:
SymbolTable();
// 构建符号表(完整构建)
void Build(ast::ASTNode& root);
// 清空所有数据
void Clear();
// ===== 第一层: 定义访问 =====
const SymbolDefinition* GetDefinition(SymbolId id) const;
std::vector<const SymbolDefinition*> GetAllDefinitions() const;
std::vector<const SymbolDefinition*> FindDefinitionsByName(const std::string& name) const;
// ===== 第二层: 作用域和位置查询 =====
// 名称查找
std::optional<SymbolId> FindSymbol(const std::string& name, ScopeId scope_id) const;
std::vector<SymbolId> FindSymbolsByName(const std::string& name) const;
// 位置查找
std::optional<SymbolId> FindSymbolAt(const ast::Location& location) const;
std::optional<ScopeId> FindScopeAt(const ast::Location& location) const;
std::optional<SymbolId> FindReferenceAt(const ast::Location& location) const;
// 作用域查询
std::vector<SymbolId> GetChildren(SymbolId symbol_id) const;
ScopeId GetGlobalScope() const;
// ===== 第三层: 关系访问 =====
// 返回引用避免拷贝,使用指针表示可能为空
const std::vector<Reference>* GetReferences(SymbolId symbol_id) const;
std::optional<ast::Location> GetDefinitionLocation(SymbolId symbol_id) const;
const std::vector<SymbolId>* GetBaseClasses(SymbolId class_id) const;
const std::vector<SymbolId>* GetDerivedClasses(SymbolId class_id) const;
const std::vector<CallRelation>* GetCallers(SymbolId function_id) const;
const std::vector<CallRelation>* GetCallees(SymbolId function_id) const;
// ===== Unit 导入管理 =====
// 添加单元导入
void AddUnitImport(const std::string& unit_name, const ast::Location& location);
// 获取所有导入的单元
const std::vector<UnitImport>& GetUnitImports() const;
// 查找特定单元的导入位置(用于跳转到定义)
std::optional<ast::Location> FindImportLocation(const std::string& unit_name) const;
// 检查是否导入了某个单元
bool HasImport(const std::string& unit_name) const;
// ===== LSP 便捷接口 =====
// 获取文档符号(用于 textDocument/documentSymbol)
std::vector<const SymbolDefinition*> GetDocumentSymbols() const;
// 获取工作区符号(用于 workspace/symbol)
std::vector<const SymbolDefinition*> GetWorkspaceSymbols(const std::string& query = "") const;
// ===== Builder 专用内部接口 =====
// 统一的符号创建接口,自动处理所有索引更新
SymbolId CreateSymbol(
const std::string& name,
SymbolKind kind,
const ast::Location& location,
ScopeId scope_id,
std::optional<SymbolId> parent_id = std::nullopt,
const std::optional<std::string>& type_hint = std::nullopt);
// 创建作用域(可以选择关联符号)
ScopeId CreateScope(
ScopeKind kind,
const ast::Location& range,
std::optional<ScopeId> parent_scope_id = std::nullopt,
std::optional<SymbolId> associated_symbol_id = std::nullopt);
// 添加引用
void AddReference(SymbolId symbol_id, const ast::Location& location, bool is_write = false);
// 获取内部组件的访问权限(供 Builder 使用)
SymbolDefinitionStore& GetDefinitionStore() { return definition_store_; }
ScopeManager& GetScopeManager() { return scope_manager_; }
LocationIndex& GetLocationIndex() { return location_index_; }
ReferenceGraph& GetReferenceGraph() { return reference_graph_; }
InheritanceGraph& GetInheritanceGraph() { return inheritance_graph_; }
CallGraph& GetCallGraph() { return call_graph_; }
const SymbolDefinitionStore& GetDefinitionStore() const { return definition_store_; }
const ScopeManager& GetScopeManager() const { return scope_manager_; }
const LocationIndex& GetLocationIndex() const { return location_index_; }
const ReferenceGraph& GetReferenceGraph() const { return reference_graph_; }
const InheritanceGraph& GetInheritanceGraph() const { return inheritance_graph_; }
const CallGraph& GetCallGraph() const { return call_graph_; }
private:
// 第一层
SymbolDefinitionStore definition_store_;
// 第二层
ScopeManager scope_manager_;
LocationIndex location_index_;
// 第三层
ReferenceGraph reference_graph_;
InheritanceGraph inheritance_graph_;
CallGraph call_graph_;
// Unit 导入
std::vector<UnitImport> unit_imports_;
// 快速查找: unit_name -> index in unit_imports_
std::unordered_map<std::string, size_t, utils::IHasher, utils::IEqualTo> import_index_;
};
}

View File

@ -0,0 +1,107 @@
#pragma once
#include <string>
#include <optional>
#include <unordered_map>
#include "../ast/types.hpp"
#include "../../utils/string.hpp"
namespace lsp::language::symbol
{
enum class SymbolKind
{
File = 1,
Module = 2,
Namespace = 3,
Package = 4,
Class = 5,
Method = 6,
Property = 7,
Field = 8,
Constructor = 9,
Enum = 10,
Interface = 11,
Function = 12,
Variable = 13,
Constant = 14,
String = 15,
Number = 16,
Boolean = 17,
Array = 18,
Object = 19,
Key = 20,
Null = 21,
EnumMember = 22,
Struct = 23,
Event = 24,
Operator = 25,
TypeParameter = 26
};
enum class ScopeKind
{
Global,
Unit,
Class,
Function,
Block
};
// 符号ID类型
using SymbolId = uint64_t;
constexpr SymbolId kInvalidSymbolId = 0;
using ScopeId = uint64_t;
constexpr ScopeId kInvalidScopeId = 0;
struct UnitImport
{
std::string unit_name;
ast::Location location;
};
struct SymbolDefinition
{
SymbolId id = kInvalidSymbolId;
std::string name;
SymbolKind kind;
ast::Location location;
ast::Location selection_range;
std::optional<std::string> type_hint;
std::string detail;
std::optional<ast::AccessModifier> access_modifier;
std::optional<ast::MethodModifier> method_modifier;
std::optional<ast::ReferenceModifier> reference_modifier;
std::optional<SymbolId> parent_id;
};
struct ScopeInfo
{
ScopeId scope_id;
ScopeKind kind;
ast::Location range;
std::optional<ScopeId> parent_scope_id;
std::optional<SymbolId> associated_symbol_id;
std::unordered_map<std::string, SymbolId, utils::IHasher, utils::IEqualTo> symbols;
};
struct Reference
{
ast::Location location;
SymbolId symbol_id;
bool is_definition;
bool is_write;
};
struct CallRelation
{
SymbolId caller;
SymbolId callee;
ast::Location call_location;
};
} // namespace lsp::language::symbol

View File

@ -1,59 +0,0 @@
#include "./type.hpp"
#include <sstream>
#include <cctype>
namespace lsp::language::symbol
{
// ==================== TypeFactory 实现 ====================
TypeInfo TypeFactory::FromAnnotation(const std::string& annotation)
{
// 直接存储原始注解字符串,不做任何解析
// 类型引用的解析将在语义分析阶段完成
return TypeInfo(Trim(annotation));
}
std::string TypeFactory::Trim(const std::string& str)
{
size_t start = 0;
while (start < str.length() && std::isspace(static_cast<unsigned char>(str[start])))
++start;
if (start == str.length())
return "";
size_t end = str.length();
while (end > start && std::isspace(static_cast<unsigned char>(str[end - 1])))
--end;
return str.substr(start, end - start);
}
// ==================== TypeFormatter 实现 ====================
std::string TypeFormatter::ToString(const TypeInfo& type)
{
if (!type.HasAnnotation())
return "<no annotation>";
return type.Annotation();
}
std::string TypeFormatter::ToDebugString(const TypeInfo& type)
{
std::ostringstream oss;
oss << "TypeInfo { ";
if (type.HasAnnotation())
{
oss << "annotation: \"" << type.Annotation() << "\"";
}
else
{
oss << "no annotation";
}
oss << " }";
return oss.str();
}
}

View File

@ -1,57 +0,0 @@
#pragma once
#include <string>
#include "../core/symbol.hpp"
namespace lsp::language::symbol
{
// ==================== 类型工厂 ====================
/**
* -
*
*
* - TypeInfo
* -
*
*
* -
* -
* -
*/
class TypeFactory
{
public:
/**
* TypeInfo
* @param annotation "Integer", "TMyClass"
* @return TypeInfo
*
*
*/
static TypeInfo FromAnnotation(const std::string& annotation);
private:
// 辅助函数:去除首尾空格
static std::string Trim(const std::string& str);
};
// ==================== 类型格式化器 ====================
/**
* -
*/
class TypeFormatter
{
public:
/**
*
*/
static std::string ToString(const TypeInfo& type);
/**
*
*/
static std::string ToDebugString(const TypeInfo& type);
};
}

View File

@ -0,0 +1,106 @@
cmake_minimum_required(VERSION 4.0)
project(test_symbol)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
message(STATUS "CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
if (DEFINED CMAKE_TOOLCHAIN_FILE)
message(STATUS ">>> CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}")
endif()
if (DEFINED VCPKG_TARGET_TRIPLET)
message(STATUS ">>> VCPKG_TARGET_TRIPLET: ${VCPKG_TARGET_TRIPLET}")
endif()
#
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE
"Release"
CACHE STRING "Build type" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
"MinSizeRel" "RelWithDebInfo")
endif()
# MinGW/MSYS2
if(MINGW)
add_link_options(-static -static-libgcc -static-libstdc++)
elseif(UNIX AND NOT APPLE) # Linux
add_link_options(-static-libgcc -static-libstdc++)
endif()
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib" ".dll.a")
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so")
endif()
find_package(glaze CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(Taskflow REQUIRED)
if(UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
endif()
if(DEFINED CMAKE_TOOLCHAIN_FILE)
find_package(unofficial-tree-sitter CONFIG REQUIRED)
set(TREESITTER_TARGET unofficial::tree-sitter::tree-sitter)
else()
# find_package(PkgConfig REQUIRED)
# pkg_check_modules(TREESITTER tree-sitter)
find_library(TREESITTER_LIBRARY tree-sitter) # use ${TREESITTER_LIBRARY}
set(TREESITTER_TARGET ${TREESITTER_LIBRARY})
endif()
if(NOT TARGET spdlog::spdlog_header_only)
message(WARNING "spdlog header-only target not found, using shared library")
endif()
if(NOT TARGET fmt::fmt-header-only)
message(WARNING "fmt header-only target not found, using shared library")
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
set(SOURCES
./test.cpp
./debug_printer.cpp
../../src/language/ast/deserializer.cpp
../../src/language/ast/detail.cpp
../../src/language/ast/tree_sitter_utils.cpp
../../src/language/symbol/builder.cpp
../../src/language/symbol/location_index.cpp
../../src/language/symbol/relations.cpp
../../src/language/symbol/store.cpp
../../src/language/symbol/scope.cpp
../../src/language/symbol/table.cpp
../../src/language/symbol/builder.cpp
../../src/utils/string.cpp
../../src/tree-sitter/parser.c)
add_executable(${PROJECT_NAME} ${SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE src)
target_compile_definitions(${PROJECT_NAME} PRIVATE SPDLOG_HEADER_ONLY
FMT_HEADER_ONLY)
target_link_libraries(${PROJECT_NAME} PRIVATE
glaze::glaze
Taskflow::Taskflow
spdlog::spdlog_header_only
fmt::fmt-header-only
${TREESITTER_TARGET} # 使
$<$<PLATFORM_ID:Linux>:Threads::Threads> # 使
)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(${PROJECT_NAME} PRIVATE
-Wall -Wextra -Wpedantic
$<$<CONFIG:Debug>:-g -O0>
$<$<CONFIG:Release>:-O3>
)
endif()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,165 @@
#pragma once
#include <iostream>
#include <string>
#include "../../src/language/symbol/table.hpp"
namespace lsp::language::symbol::debug
{
// ==================== 颜色和样式 ====================
namespace Color
{
// ANSI 颜色码
constexpr const char* Reset = "\033[0m";
constexpr const char* Bold = "\033[1m";
constexpr const char* Dim = "\033[2m";
// 前景色
constexpr const char* Black = "\033[30m";
constexpr const char* Red = "\033[31m";
constexpr const char* Green = "\033[32m";
constexpr const char* Yellow = "\033[33m";
constexpr const char* Blue = "\033[34m";
constexpr const char* Magenta = "\033[35m";
constexpr const char* Cyan = "\033[36m";
constexpr const char* White = "\033[37m";
// 亮色
constexpr const char* BrightBlack = "\033[90m";
constexpr const char* BrightRed = "\033[91m";
constexpr const char* BrightGreen = "\033[92m";
constexpr const char* BrightYellow = "\033[93m";
constexpr const char* BrightBlue = "\033[94m";
constexpr const char* BrightMagenta = "\033[95m";
constexpr const char* BrightCyan = "\033[96m";
constexpr const char* BrightWhite = "\033[97m";
}
// ==================== 打印选项 ====================
struct PrintOptions
{
bool use_color = true; // 使用颜色
bool show_location = true; // 显示位置信息
bool show_details = true; // 显示详细信息
bool show_children = true; // 显示子符号
bool show_references = false; // 显示引用列表
bool compact_mode = false; // 紧凑模式
int indent_size = 2; // 缩进大小
int max_depth = -1; // 最大深度 (-1 = 无限制)
static PrintOptions Default();
static PrintOptions Compact();
static PrintOptions Verbose();
static PrintOptions NoColor();
};
// ==================== 统计信息 ====================
struct Statistics
{
size_t total_symbols = 0;
size_t total_scopes = 0;
size_t total_references = 0;
std::unordered_map<SymbolKind, size_t> symbol_counts;
std::unordered_map<ScopeKind, size_t> scope_counts;
size_t symbols_with_refs = 0;
size_t max_references = 0;
SymbolId most_referenced = kInvalidSymbolId;
void Compute(const SymbolTable& table);
void Print(std::ostream& os, bool use_color = true) const;
};
// ==================== 核心打印器 ====================
class DebugPrinter
{
public:
explicit DebugPrinter(const SymbolTable& table, const PrintOptions& options = PrintOptions::Default());
// ===== 顶层打印接口 =====
void PrintAll(std::ostream& os = std::cout);
void PrintOverview(std::ostream& os = std::cout);
void PrintStatistics(std::ostream& os = std::cout);
// ===== 符号打印 =====
void PrintSymbol(SymbolId id, std::ostream& os = std::cout, int depth = 0);
void PrintSymbolTree(SymbolId id, std::ostream& os = std::cout, int depth = 0);
void PrintSymbolList(std::ostream& os = std::cout);
void PrintSymbolsByKind(SymbolKind kind, std::ostream& os = std::cout);
// ===== 作用域打印 =====
void PrintScope(ScopeId id, std::ostream& os = std::cout, int depth = 0);
void PrintScopeTree(ScopeId id, std::ostream& os = std::cout, int depth = 0);
void PrintScopeHierarchy(std::ostream& os = std::cout);
// ===== 关系打印 =====
void PrintReferences(SymbolId id, std::ostream& os = std::cout);
void PrintInheritance(SymbolId class_id, std::ostream& os = std::cout);
void PrintCallGraph(SymbolId function_id, std::ostream& os = std::cout);
void PrintAllReferences(std::ostream& os = std::cout);
void PrintAllInheritance(std::ostream& os = std::cout);
void PrintAllCalls(std::ostream& os = std::cout);
// ===== 搜索和查询 =====
void FindAndPrint(const std::string& name, std::ostream& os = std::cout);
void FindAtLocation(const ast::Location& loc, std::ostream& os = std::cout);
// ===== 选项管理 =====
void SetOptions(const PrintOptions& options) { options_ = options; }
const PrintOptions& GetOptions() const { return options_; }
private:
const SymbolTable& table_;
PrintOptions options_;
Statistics stats_;
// ===== 辅助方法 =====
std::string Indent(int depth) const;
std::string ColorizeSymbolKind(SymbolKind kind) const;
std::string ColorizeSymbolName(const std::string& name, SymbolKind kind) const;
std::string FormatLocation(const ast::Location& loc) const;
std::string FormatSymbolKind(SymbolKind kind) const;
std::string FormatScopeKind(ScopeKind kind) const;
std::string SymbolIcon(SymbolKind kind) const;
void PrintSeparator(std::ostream& os, char ch = '=', int width = 80) const;
void PrintHeader(const std::string& title, std::ostream& os) const;
void PrintSubHeader(const std::string& title, std::ostream& os) const;
std::string Color(const char* color_code) const;
std::string Bold(const std::string& text) const;
std::string Dim(const std::string& text) const;
};
// ==================== 快速打印函数 ====================
// 打印所有内容(带统计)
void Print(const SymbolTable& table, std::ostream& os = std::cout);
// 打印概览
void PrintOverview(const SymbolTable& table, std::ostream& os = std::cout);
// 打印统计信息
void PrintStats(const SymbolTable& table, std::ostream& os = std::cout);
// 打印符号树
void PrintSymbolTree(const SymbolTable& table, std::ostream& os = std::cout);
// 打印作用域树
void PrintScopeTree(const SymbolTable& table, std::ostream& os = std::cout);
// 搜索并打印
void Find(const SymbolTable& table, const std::string& name, std::ostream& os = std::cout);
// 紧凑打印
void PrintCompact(const SymbolTable& table, std::ostream& os = std::cout);
// 详细打印
void PrintVerbose(const SymbolTable& table, std::ostream& os = std::cout);
} // namespace lsp::language::symbol::debug

View File

@ -0,0 +1,557 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <chrono>
extern "C" {
#include <tree_sitter/api.h>
}
extern "C" const TSLanguage* tree_sitter_tsf(void);
#include "../../src/language/ast/deserializer.hpp"
#include "../../src/language/symbol/table.hpp"
#include "./debug_printer.hpp"
using namespace lsp::language;
// ==================== 文件读取 ====================
std::string ReadFile(const std::string& filepath)
{
std::ifstream file(filepath);
if (!file.is_open())
{
throw std::runtime_error("Cannot open file: " + filepath);
}
std::ostringstream oss;
oss << file.rdbuf();
return oss.str();
}
// ==================== Tree-Sitter 解析器 ====================
class TreeSitterParser
{
public:
TreeSitterParser()
{
parser_ = ts_parser_new();
if (!parser_)
{
throw std::runtime_error("Failed to create parser");
}
if (!ts_parser_set_language(parser_, tree_sitter_tsf()))
{
ts_parser_delete(parser_);
throw std::runtime_error("Failed to set language");
}
}
~TreeSitterParser()
{
if (tree_)
{
ts_tree_delete(tree_);
}
if (parser_)
{
ts_parser_delete(parser_);
}
}
TSTree* Parse(const std::string& source)
{
if (tree_)
{
ts_tree_delete(tree_);
tree_ = nullptr;
}
tree_ = ts_parser_parse_string(
parser_,
nullptr,
source.c_str(),
source.length());
if (!tree_)
{
throw std::runtime_error("Failed to parse source");
}
return tree_;
}
TSNode GetRootNode()
{
if (!tree_)
{
throw std::runtime_error("No tree available");
}
return ts_tree_root_node(tree_);
}
private:
TSParser* parser_ = nullptr;
TSTree* tree_ = nullptr;
};
// ==================== 命令行选项 ====================
struct Options
{
std::string input_file;
std::string output_file;
bool print_all = true;
bool print_definitions = false;
bool print_scopes = false;
bool print_references = false;
bool print_inheritance = false;
bool print_calls = false;
bool compact_mode = false;
bool statistics_only = false;
std::string search_symbol;
bool verbose = false;
bool show_ast = false;
bool no_color = false;
bool print_overview = false;
};
void PrintUsage(const char* program_name)
{
std::cout << "Symbol Table Analyzer - Analyze source code symbols\n\n";
std::cout << "Usage: " << program_name << " <input_file> [options]\n\n";
std::cout << "Options:\n";
std::cout << " -o, --output <file> Write output to file instead of stdout\n";
std::cout << " -d, --definitions Print only symbol definitions\n";
std::cout << " -s, --scopes Print only scope hierarchy\n";
std::cout << " -r, --references Print only references\n";
std::cout << " -i, --inheritance Print only inheritance graph\n";
std::cout << " -c, --calls Print only call graph\n";
std::cout << " -C, --compact Use compact output format\n";
std::cout << " -S, --stats Print statistics only\n";
std::cout << " -O, --overview Print overview only\n";
std::cout << " -f, --find <name> Search for a specific symbol\n";
std::cout << " -v, --verbose Enable verbose output\n";
std::cout << " -a, --ast Show AST structure\n";
std::cout << " --no-color Disable colored output\n";
std::cout << " -h, --help Show this help message\n\n";
std::cout << "Examples:\n";
std::cout << " " << program_name << " program.tsf\n";
std::cout << " " << program_name << " program.tsf -o symbols.txt\n";
std::cout << " " << program_name << " program.tsf --definitions --scopes\n";
std::cout << " " << program_name << " program.tsf --find MyClass\n";
std::cout << " " << program_name << " program.tsf --compact --stats\n";
std::cout << " " << program_name << " program.tsf --overview\n";
}
bool ParseArguments(int argc, char* argv[], Options& options)
{
if (argc < 2)
return false;
options.input_file = argv[1];
bool any_specific_print = false;
for (int i = 2; i < argc; ++i)
{
std::string arg = argv[i];
if (arg == "-h" || arg == "--help")
{
return false;
}
else if (arg == "-o" || arg == "--output")
{
if (i + 1 < argc)
{
options.output_file = argv[++i];
}
else
{
std::cerr << "Error: " << arg << " requires an argument\n";
return false;
}
}
else if (arg == "-d" || arg == "--definitions")
{
options.print_definitions = true;
any_specific_print = true;
}
else if (arg == "-s" || arg == "--scopes")
{
options.print_scopes = true;
any_specific_print = true;
}
else if (arg == "-r" || arg == "--references")
{
options.print_references = true;
any_specific_print = true;
}
else if (arg == "-i" || arg == "--inheritance")
{
options.print_inheritance = true;
any_specific_print = true;
}
else if (arg == "-c" || arg == "--calls")
{
options.print_calls = true;
any_specific_print = true;
}
else if (arg == "-C" || arg == "--compact")
{
options.compact_mode = true;
}
else if (arg == "-S" || arg == "--stats")
{
options.statistics_only = true;
any_specific_print = true;
}
else if (arg == "-O" || arg == "--overview")
{
options.print_overview = true;
any_specific_print = true;
}
else if (arg == "-f" || arg == "--find")
{
if (i + 1 < argc)
{
options.search_symbol = argv[++i];
}
else
{
std::cerr << "Error: " << arg << " requires an argument\n";
return false;
}
}
else if (arg == "-v" || arg == "--verbose")
{
options.verbose = true;
}
else if (arg == "-a" || arg == "--ast")
{
options.show_ast = true;
}
else if (arg == "--no-color")
{
options.no_color = true;
}
else
{
std::cerr << "Error: Unknown option: " << arg << "\n";
return false;
}
}
if (any_specific_print)
options.print_all = false;
return true;
}
std::string NodeKindToString(ast::NodeKind kind)
{
switch (kind)
{
case ast::NodeKind::kProgram: return "Program";
case ast::NodeKind::kFunctionDefinition: return "FunctionDefinition";
case ast::NodeKind::kClassDefinition: return "ClassDefinition";
case ast::NodeKind::kUnitDefinition: return "UnitDefinition";
case ast::NodeKind::kVarStatement: return "VarStatement";
case ast::NodeKind::kConstStatement: return "ConstStatement";
case ast::NodeKind::kIfStatement: return "IfStatement";
case ast::NodeKind::kForInStatement: return "ForInStatement";
case ast::NodeKind::kWhileStatement: return "WhileStatement";
// ... 添加其他类型
default: return "Unknown";
}
}
void PrintASTStructure(const ast::ParseResult& parse_result, std::ostream& os)
{
os << "\n╔════════════════════════════════════════════════════════════╗\n";
os << "║ AST STRUCTURE ║\n";
os << "╚════════════════════════════════════════════════════════════╝\n\n";
os << "Statements: " << parse_result.root->statements.size() << "\n\n";
for (size_t i = 0; i < parse_result.root->statements.size(); ++i)
{
const auto& stmt = parse_result.root->statements[i];
if (!stmt)
continue;
// 修复:使用 kind 和 span
os << "[" << i << "] " << NodeKindToString(stmt->kind)
<< " at [" << stmt->span.start_line << ":" << stmt->span.start_column << "]";
// 打印特定类型的详细信息
if (auto* func_def = dynamic_cast<ast::FunctionDefinition*>(stmt.get()))
{
os << " - Function: " << func_def->name;
}
else if (auto* class_def = dynamic_cast<ast::ClassDefinition*>(stmt.get()))
{
os << " - Class: " << class_def->name;
}
else if (auto* unit_def = dynamic_cast<ast::UnitDefinition*>(stmt.get()))
{
os << " - Unit: " << unit_def->name;
}
os << "\n";
}
os << "\n";
}
// ==================== 主分析函数 ====================
void AnalyzeFile(const Options& options)
{
// 打印头部
if (!options.compact_mode)
{
std::cout << "\n╔════════════════════════════════════════════════════════════╗\n";
std::cout << "║ SYMBOL TABLE ANALYZER ║\n";
std::cout << "╚════════════════════════════════════════════════════════════╝\n\n";
std::cout << "Input file: " << options.input_file << "\n";
}
// 1. 读取源文件
if (options.verbose)
std::cout << "Reading file...\n";
std::string source = ReadFile(options.input_file);
if (options.verbose)
{
std::cout << "File size: " << source.length() << " bytes\n";
std::cout << "----------------------------------------\n";
std::cout << source << "\n";
std::cout << "----------------------------------------\n\n";
}
// 2. 使用 Tree-Sitter 解析
if (options.verbose)
std::cout << "Parsing with Tree-Sitter...\n";
TreeSitterParser ts_parser;
[[maybe_unused]] TSTree* tree = ts_parser.Parse(source);
TSNode root = ts_parser.GetRootNode();
if (options.verbose)
{
std::cout << "Root node type: " << ts_node_type(root) << "\n";
std::cout << "Root node child count: " << ts_node_child_count(root) << "\n\n";
}
// 3. 反序列化为 AST
if (options.verbose)
std::cout << "Deserializing to AST...\n";
ast::Deserializer deserializer;
ast::ParseResult parse_result = deserializer.Parse(root, source);
if (parse_result.HasErrors())
{
std::cerr << "\n⚠️ Parse Errors:\n";
for (const auto& error : parse_result.errors)
{
std::cerr << " [" << error.location.start_line << ":"
<< error.location.start_column << "] "
<< error.message << "\n";
}
std::cerr << "\n";
}
if (options.show_ast)
{
PrintASTStructure(parse_result, std::cout);
}
// 4. 构建符号表
if (options.verbose)
std::cout << "Building symbol table...\n";
symbol::SymbolTable table;
auto start = std::chrono::high_resolution_clock::now();
table.Build(*parse_result.root);
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
if (options.verbose)
std::cout << "Symbol table built in " << duration.count() << " ms\n\n";
// 5. 准备输出流
std::ostream* out = &std::cout;
std::ofstream file_out;
if (!options.output_file.empty())
{
file_out.open(options.output_file);
if (!file_out.is_open())
{
std::cerr << "Error: Cannot write to file: " << options.output_file << "\n";
return;
}
out = &file_out;
// 写入文件头
*out << "Symbol Table Analysis\n";
*out << "Source: " << options.input_file << "\n";
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
*out << "Generated: " << std::ctime(&time);
*out << std::string(80, '=') << "\n\n";
}
// 6. ✅ 使用新的 debug_print API
// 配置打印选项
symbol::debug::PrintOptions print_opts;
if (options.compact_mode)
print_opts = symbol::debug::PrintOptions::Compact();
else if (options.verbose)
print_opts = symbol::debug::PrintOptions::Verbose();
else
print_opts = symbol::debug::PrintOptions::Default();
if (options.no_color || !options.output_file.empty())
print_opts.use_color = false;
print_opts.show_references = options.print_references || options.verbose;
// 创建打印器
symbol::debug::DebugPrinter printer(table, print_opts);
// 7. 执行查询或打印
if (!options.search_symbol.empty())
{
// 搜索符号
printer.FindAndPrint(options.search_symbol, *out);
}
else if (options.statistics_only)
{
// 只打印统计
printer.PrintStatistics(*out);
}
else if (options.print_overview)
{
// 只打印概览
printer.PrintOverview(*out);
}
else if (options.compact_mode)
{
// 紧凑模式
symbol::debug::PrintCompact(table, *out);
}
else if (options.print_all)
{
// 打印所有内容
printer.PrintAll(*out);
}
else
{
// 自定义打印
bool printed_anything = false;
if (options.print_definitions)
{
printer.PrintSymbolList(*out);
printed_anything = true;
}
if (options.print_scopes)
{
printer.PrintScopeHierarchy(*out);
printed_anything = true;
}
if (options.print_references)
{
printer.PrintAllReferences(*out);
printed_anything = true;
}
if (options.print_inheritance)
{
printer.PrintAllInheritance(*out);
printed_anything = true;
}
if (options.print_calls)
{
printer.PrintAllCalls(*out);
printed_anything = true;
}
// 总是打印统计信息
if (printed_anything)
{
*out << "\n";
}
printer.PrintStatistics(*out);
}
// 8. 完成
if (file_out.is_open())
{
file_out.close();
std::cout << "✓ Symbol table exported to: " << options.output_file << "\n";
}
// 9. 打印摘要
if (!options.compact_mode)
{
std::cout << "\n========================================\n";
std::cout << "Summary:\n";
std::cout << " File: " << options.input_file << "\n";
std::cout << " Size: " << source.length() << " bytes\n";
std::cout << " Lines: " << std::count(source.begin(), source.end(), '\n') + 1 << "\n";
std::cout << " Statements: " << parse_result.root->statements.size() << "\n";
std::cout << " Symbols: " << table.GetAllDefinitions().size() << "\n";
std::cout << " Scopes: " << table.GetScopeManager().GetAllScopes().size() << "\n";
std::cout << " Parse Errors: " << parse_result.errors.size() << "\n";
std::cout << " Build Time: " << duration.count() << " ms\n";
if (parse_result.HasErrors())
{
std::cout << " Status: ⚠️ COMPLETED WITH ERRORS\n";
}
else
{
std::cout << " Status: ✓ SUCCESS\n";
}
std::cout << "========================================\n\n";
}
}
// ==================== 主程序 ====================
int main(int argc, char* argv[])
{
Options options;
if (!ParseArguments(argc, argv, options))
{
PrintUsage(argv[0]);
return 1;
}
try
{
AnalyzeFile(options);
return 0;
}
catch (const std::exception& e)
{
std::cerr << "❌ Fatal error: " << e.what() << "\n";
return 1;
}
}

View File

@ -0,0 +1,11 @@
function f1(a: string; b: boolean = true): integer;
begin
end;
function f2(a, b, c);overload;
begin
end;
// var d := 1;
// c := false;
// f := fa();