diff --git a/lsp-server/src/language/symbol/builder.cpp b/lsp-server/src/language/symbol/builder.cpp new file mode 100644 index 0000000..3bf20d5 --- /dev/null +++ b/lsp-server/src/language/symbol/builder.cpp @@ -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& 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& 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; + + if constexpr (std::is_same_v>) + { + 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>) + { + if (variant) + VisitExpression(*variant->object); + } + else if constexpr (std::is_same_v>) + { + 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 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 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 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 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 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 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 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 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(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 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(); + } + +} diff --git a/lsp-server/src/language/symbol/builder.hpp b/lsp-server/src/language/symbol/builder.hpp new file mode 100644 index 0000000..845006b --- /dev/null +++ b/lsp-server/src/language/symbol/builder.hpp @@ -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& 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& 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 current_parent_symbol_id_; + std::optional current_function_id_; + }; + +} diff --git a/lsp-server/src/language/symbol/builder/builder.cpp b/lsp-server/src/language/symbol/builder/builder.cpp deleted file mode 100644 index 5ca4a48..0000000 --- a/lsp-server/src/language/symbol/builder/builder.cpp +++ /dev/null @@ -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& 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(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& 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(); - } - } - - 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; - } -} diff --git a/lsp-server/src/language/symbol/builder/builder.hpp b/lsp-server/src/language/symbol/builder/builder.hpp deleted file mode 100644 index 3495d0a..0000000 --- a/lsp-server/src/language/symbol/builder/builder.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include -#include -#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; // 构建是否成功 - }; - - // ==================== 符号表构建器 ==================== - - /** - * 符号表构建器 - 简化为调度器 - * - * 职责: - * - 提供构建入口(完整/增量) - * - 管理核心组件(Registry、ErrorReporter) - * - 管理增量引擎(可选) - * - 收集和提供统计信息 - * - * 不负责: - * - 具体的符号收集逻辑(委托给 Collector) - * - 增量细节(委托给 IncrementalEngine) - * - 语义分析(属于后续阶段) - */ - class SymbolTableBuilder - { - public: - SymbolTableBuilder(); - ~SymbolTableBuilder(); - - // 禁止拷贝 - SymbolTableBuilder(const SymbolTableBuilder&) = delete; - SymbolTableBuilder& operator=(const SymbolTableBuilder&) = delete; - - bool Build(const std::vector& nodes); - bool BuildIncremental(const ast::IncrementalParseResult& parse_result); - - SymbolRegistry& GetRegistry() { return registry_; } - const SymbolRegistry& GetRegistry() const { return registry_; } - - const std::vector& 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 incremental_engine_; - bool incremental_enabled_; - - // 统计信息 - BuildStatistics stats_; - }; - - // ==================== 便捷函数 ==================== - - /** - * 便捷函数:一次性构建符号表 - * - * @param nodes AST节点列表 - * @param errors 可选的错误输出参数 - * @return 构建好的符号注册表(移动语义) - */ - inline SymbolRegistry BuildSymbolTable(const std::vector& nodes, std::vector* errors = nullptr) - { - SymbolTableBuilder builder; - builder.Build(nodes); - - if (errors) - *errors = builder.GetErrors(); - - // 移动 Registry(避免拷贝) - return std::move(builder.GetRegistry()); - } -} diff --git a/lsp-server/src/language/symbol/collector/context.hpp b/lsp-server/src/language/symbol/collector/context.hpp deleted file mode 100644 index b500164..0000000 --- a/lsp-server/src/language/symbol/collector/context.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include "../core/registry.hpp" -#include "../core/error.hpp" -#include "../factory/scope_manager.hpp" - -namespace lsp::language::symbol -{ - /** - * 收集上下文 - 封装收集过程中的共享状态 - * - * 职责: - * - 提供对 Registry、ErrorReporter、ScopeManager 的统一访问 - * - 维护当前上下文(当前 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); - } - } - }; -} diff --git a/lsp-server/src/language/symbol/collector/incremental_collector.cpp b/lsp-server/src/language/symbol/collector/incremental_collector.cpp deleted file mode 100644 index b5cfff2..0000000 --- a/lsp-server/src/language/symbol/collector/incremental_collector.cpp +++ /dev/null @@ -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 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()); - } -} diff --git a/lsp-server/src/language/symbol/collector/incremental_collector.hpp b/lsp-server/src/language/symbol/collector/incremental_collector.hpp deleted file mode 100644 index 467a7f9..0000000 --- a/lsp-server/src/language/symbol/collector/incremental_collector.hpp +++ /dev/null @@ -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; - }; -} diff --git a/lsp-server/src/language/symbol/collector/symbol_collector.cpp b/lsp-server/src/language/symbol/collector/symbol_collector.cpp deleted file mode 100644 index e08af69..0000000 --- a/lsp-server/src/language/symbol/collector/symbol_collector.cpp +++ /dev/null @@ -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& 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(node)) - return true; - - if (auto* unit = std::get_if(&node)) - return CollectUnit(*unit); - - if (auto* global = std::get_if(&node)) - return CollectGlobal(*global); - - if (auto* static_decl = std::get_if(&node)) - return CollectStatic(*static_decl); - - if (auto* var = std::get_if(&node)) - return CollectVariable(*var); - - if (auto* constant = std::get_if(&node)) - return CollectConstant(*constant); - - if (auto* stmt = std::get_if(&node)) - return CollectAssignment(*stmt); - - if (auto* func_def = std::get_if(&node)) - return CollectFunctionDef(*func_def); - - if (auto* cls = std::get_if(&node)) - return CollectClass(*cls); - - if (auto* uses = std::get_if(&node)) - return CollectUsesClause(*uses); - - // 跳过表达式和块 - if (std::holds_alternative(node) || - std::holds_alternative(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(ScopeKind::kInterface, ctx_.GlobalScope()); - unit_symbol->implementation_symbols = - std::make_unique
(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
( - 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(member.content)) - return true; - - Access access = member.access; - - if (auto* var = std::get_if(&member.content)) - return CollectMemberVariable(*var, access); - - if (auto* static_decl = std::get_if(&member.content)) - return CollectMemberStatic(*static_decl, access); - - if (auto* method = std::get_if(&member.content)) - return CollectMemberMethod(*method, access, owner); - - if (auto* property = std::get_if(&member.content)) - return CollectMemberProperty(*property, access); - - if (auto* ctor = std::get_if(&member.content)) - return CollectMemberConstructor(*ctor, access, owner); - - if (auto* dtor = std::get_if(&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
( - 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
( - 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
( - 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& statements) - { - auto guard = ctx_.scope_manager.EnterScope(scope); - CollectStatements(statements); - } - - void SymbolCollector::CollectStatements(const std::vector& 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; - } -} diff --git a/lsp-server/src/language/symbol/collector/symbol_collector.hpp b/lsp-server/src/language/symbol/collector/symbol_collector.hpp deleted file mode 100644 index 0947e16..0000000 --- a/lsp-server/src/language/symbol/collector/symbol_collector.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include -#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& 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& statements); - void CollectStatements(const std::vector& 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_; - }; -} diff --git a/lsp-server/src/language/symbol/core/error.cpp b/lsp-server/src/language/symbol/core/error.cpp deleted file mode 100644 index f5fe2f9..0000000 --- a/lsp-server/src/language/symbol/core/error.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include "./error.hpp" - -namespace lsp::language::symbol -{ - // ==================== 错误类型名称映射 ==================== - - namespace - { - const char* GetErrorKindName(ErrorKind kind) - { - static const std::unordered_map 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& 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)); - } -} diff --git a/lsp-server/src/language/symbol/core/error.hpp b/lsp-server/src/language/symbol/core/error.hpp deleted file mode 100644 index 9525a81..0000000 --- a/lsp-server/src/language/symbol/core/error.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include -#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& 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 errors_; - }; -} diff --git a/lsp-server/src/language/symbol/core/registry.cpp b/lsp-server/src/language/symbol/core/registry.cpp deleted file mode 100644 index defa35b..0000000 --- a/lsp-server/src/language/symbol/core/registry.cpp +++ /dev/null @@ -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& SymbolRegistry::Units() const - { - return units_; - } -} diff --git a/lsp-server/src/language/symbol/core/registry.hpp b/lsp-server/src/language/symbol/core/registry.hpp deleted file mode 100644 index fb40940..0000000 --- a/lsp-server/src/language/symbol/core/registry.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#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& Units() const; - - private: - Table global_scope_; - std::unordered_map units_; - }; -} diff --git a/lsp-server/src/language/symbol/core/symbol.cpp b/lsp-server/src/language/symbol/core/symbol.cpp deleted file mode 100644 index 971c425..0000000 --- a/lsp-server/src/language/symbol/core/symbol.cpp +++ /dev/null @@ -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; -} diff --git a/lsp-server/src/language/symbol/core/symbol.hpp b/lsp-server/src/language/symbol/core/symbol.hpp deleted file mode 100644 index 52f428f..0000000 --- a/lsp-server/src/language/symbol/core/symbol.hpp +++ /dev/null @@ -1,270 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#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 default_value; - }; - - std::vector parameters; - std::optional 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 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
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 implementation_location; - }; - - class Constructor : public Symbol - { - public: - Signature signature; - class Class* owner_class; - std::unique_ptr
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
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 getter; - std::optional 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 parent_names; - std::vector parents; - std::unique_ptr
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 uses; - std::unique_ptr
interface_symbols; - std::unique_ptr
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; - using VariablePtr = std::shared_ptr; - using ConstantPtr = std::shared_ptr; - using FunctionPtr = std::shared_ptr; - using MethodPtr = std::shared_ptr; - using ConstructorPtr = std::shared_ptr; - using DestructorPtr = std::shared_ptr; - using PropertyPtr = std::shared_ptr; - using ClassPtr = std::shared_ptr; - using UnitPtr = std::shared_ptr; -} diff --git a/lsp-server/src/language/symbol/core/table.cpp b/lsp-server/src/language/symbol/core/table.cpp deleted file mode 100644 index 2cfee34..0000000 --- a/lsp-server/src/language/symbol/core/table.cpp +++ /dev/null @@ -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& Table::Symbols() const - { - return symbols_; - } - - const std::unordered_map>& Table::OverloadedFunctions() const - { - return overloaded_functions_; - } - - Table* Table::CreateChild(ScopeKind kind) - { - auto child = std::make_unique
(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(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 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_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(it->second); - - return nullptr; - } - -} diff --git a/lsp-server/src/language/symbol/core/table.hpp b/lsp-server/src/language/symbol/core/table.hpp deleted file mode 100644 index af54227..0000000 --- a/lsp-server/src/language/symbol/core/table.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include -#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& Symbols() const; - const std::unordered_map>& 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 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> children_; - std::unordered_map symbols_; - std::unordered_map> overloaded_functions_; - }; -} diff --git a/lsp-server/src/language/symbol/factory/factory.cpp b/lsp-server/src/language/symbol/factory/factory.cpp deleted file mode 100644 index 4ca43cc..0000000 --- a/lsp-server/src/language/symbol/factory/factory.cpp +++ /dev/null @@ -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(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(name, loc, type, value); - } - - FunctionPtr factory::CreateFunction( - const std::string& name, - const ast::Location& loc, - const Signature& sig) - { - return std::make_shared(name, loc, sig); - } - - MethodPtr factory::CreateMethod( - const std::string& name, - const ast::Location& loc, - const Signature& sig, - Class* owner) - { - auto method = std::make_shared(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(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(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(name, loc, type); - } - - ClassPtr factory::CreateClass( - const std::string& name, - const ast::Location& loc) - { - return std::make_shared(name, loc); - } - - UnitPtr factory::CreateUnit( - const std::string& name, - const ast::Location& loc) - { - return std::make_shared(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& type_str) - { - TypeInfo type = type_str ? - TypeFactory::FromAnnotation(*type_str) : - TypeInfo(); - return CreateVariable(name, kind, loc, type); - } -} diff --git a/lsp-server/src/language/symbol/factory/factory.hpp b/lsp-server/src/language/symbol/factory/factory.hpp deleted file mode 100644 index c82ede8..0000000 --- a/lsp-server/src/language/symbol/factory/factory.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include -#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& type_str); - } -} diff --git a/lsp-server/src/language/symbol/factory/scope_manager.cpp b/lsp-server/src/language/symbol/factory/scope_manager.cpp deleted file mode 100644 index 81c8d9f..0000000 --- a/lsp-server/src/language/symbol/factory/scope_manager.cpp +++ /dev/null @@ -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; - } -} diff --git a/lsp-server/src/language/symbol/factory/scope_manager.hpp b/lsp-server/src/language/symbol/factory/scope_manager.hpp deleted file mode 100644 index 9c4a677..0000000 --- a/lsp-server/src/language/symbol/factory/scope_manager.hpp +++ /dev/null @@ -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_; - }; -} diff --git a/lsp-server/src/language/symbol/incremental/incremental.cpp b/lsp-server/src/language/symbol/incremental/incremental.cpp deleted file mode 100644 index c6a0e66..0000000 --- a/lsp-server/src/language/symbol/incremental/incremental.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include -#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(symbol)) - { - key.signature_hash = SymbolCacheKey::ComputeSignatureHash(func->signature); - } - else if (auto* ctor = dynamic_cast(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) - { - 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; - } -} diff --git a/lsp-server/src/language/symbol/incremental/incremental.hpp b/lsp-server/src/language/symbol/incremental/incremental.hpp deleted file mode 100644 index 6301796..0000000 --- a/lsp-server/src/language/symbol/incremental/incremental.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once -#include -#include -#include -#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 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()(key.symbol_name); - size_t h2 = std::hash()(static_cast(key.symbol_kind)); - size_t h3 = std::hash()(key.declaration_line); - size_t h4 = std::hash()(key.declaration_column); - size_t h5 = key.signature_hash ? - std::hash()(*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 = std::nullopt); - - private: - // LRU 淘汰策略 - void EvictLRU(); - void TouchKey(const SymbolCacheKey& key); - - private: - struct CacheEntry - { - SymbolPtr symbol; - std::list::iterator lru_iter; - }; - - std::unordered_map cache_; - std::list lru_list_; // 最近使用列表 - size_t max_size_; - }; -} diff --git a/lsp-server/src/language/symbol/incremental/incremental_engine.cpp b/lsp-server/src/language/symbol/incremental/incremental_engine.cpp deleted file mode 100644 index 8659c6a..0000000 --- a/lsp-server/src/language/symbol/incremental/incremental_engine.cpp +++ /dev/null @@ -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; - - if constexpr (std::is_same_v) - { - return true; - } - else if constexpr (std::is_same_v) - { - 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) - { - 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) - { - 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) - { - 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) - { - // 创建签名用于缓存键 - 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(*cached); - if (func) - { - return scope->InsertFunction(func); - } - } - return false; - } - else if constexpr (std::is_same_v) - { - 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) - { - // 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(*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; - - if constexpr (std::is_same_v || - std::is_same_v || - std::is_same_v) - { - 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) - { - 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) - { - 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) - { - 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) - { - // 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(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(symbol.get())) - { - if (cls->members) - { - CacheScopeRecursive(cls->members.get()); - } - } - - // 递归缓存函数体作用域 - if (auto* func = dynamic_cast(symbol.get())) - { - if (func->body_scope) - { - CacheScopeRecursive(func->body_scope.get()); - } - } - - // 递归缓存构造函数体作用域 - if (auto* ctor = dynamic_cast(symbol.get())) - { - if (ctor->body_scope) - { - CacheScopeRecursive(ctor->body_scope.get()); - } - } - - // 递归缓存析构函数体作用域 - if (auto* dtor = dynamic_cast(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(); - } -} diff --git a/lsp-server/src/language/symbol/incremental/incremental_engine.hpp b/lsp-server/src/language/symbol/incremental/incremental_engine.hpp deleted file mode 100644 index 48d1196..0000000 --- a/lsp-server/src/language/symbol/incremental/incremental_engine.hpp +++ /dev/null @@ -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_; - }; -} diff --git a/lsp-server/src/language/symbol/location_index.cpp b/lsp-server/src/language/symbol/location_index.cpp new file mode 100644 index 0000000..e91e823 --- /dev/null +++ b/lsp-server/src/language/symbol/location_index.cpp @@ -0,0 +1,105 @@ +#include +#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 LocationIndex::FindSymbolAt(const ast::Location& location) const + { + // 确保索引已排序 + if (!symbols_sorted_) + return std::nullopt; + + return FindInSortedEntries(symbol_entries_, location, true); + } + + std::optional LocationIndex::FindScopeAt(const ast::Location& location) const + { + // 确保索引已排序 + if (!scopes_sorted_) + return std::nullopt; + + return FindInSortedEntries(scope_entries_, location, true); + } + + std::optional 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; + } + +} diff --git a/lsp-server/src/language/symbol/location_index.hpp b/lsp-server/src/language/symbol/location_index.hpp new file mode 100644 index 0000000..e9fadae --- /dev/null +++ b/lsp-server/src/language/symbol/location_index.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include +#include +#include +#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 FindSymbolAt(const ast::Location& location) const; + std::optional FindScopeAt(const ast::Location& location) const; + std::optional FindReferenceAt(const ast::Location& location) const; + + private: + // 符号定义位置索引(按起始位置排序) + std::vector symbol_entries_; + bool symbols_sorted_ = true; + + // 作用域位置索引(按起始位置排序) + std::vector scope_entries_; + bool scopes_sorted_ = true; + + // 引用位置索引(位置 -> 符号ID) + std::vector reference_entries_; + bool references_sorted_ = true; + + // 辅助方法:在排序数组中查找位置(模板实现放在头文件) + template + std::optional FindInSortedEntries(const std::vector& 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 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 || std::is_same_v) + candidates.push_back(it->symbol_id); + else if constexpr (std::is_same_v) + 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; + } + }; + +} diff --git a/lsp-server/src/language/symbol/relations.cpp b/lsp-server/src/language/symbol/relations.cpp new file mode 100644 index 0000000..60b2140 --- /dev/null +++ b/lsp-server/src/language/symbol/relations.cpp @@ -0,0 +1,116 @@ +#include +#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* ReferenceGraph::GetReferences(SymbolId symbol_id) const + { + auto it = references_.find(symbol_id); + return it != references_.end() ? &it->second : nullptr; + } + + std::optional 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* InheritanceGraph::GetBaseClasses(SymbolId class_id) const + { + auto it = base_classes_.find(class_id); + return it != base_classes_.end() ? &it->second : nullptr; + } + + const std::vector* 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 visited; + std::vector 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* CallGraph::GetCallers(SymbolId function_id) const + { + auto it = callers_.find(function_id); + return it != callers_.end() ? &it->second : nullptr; + } + + const std::vector* 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(); + } + +} diff --git a/lsp-server/src/language/symbol/relations.hpp b/lsp-server/src/language/symbol/relations.hpp new file mode 100644 index 0000000..51ebb66 --- /dev/null +++ b/lsp-server/src/language/symbol/relations.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#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* GetReferences(SymbolId symbol_id) const; + std::optional GetDefinition(SymbolId symbol_id) const; + + private: + std::unordered_map> references_; + }; + + // 继承图 + class InheritanceGraph + { + public: + void AddInheritance(SymbolId derived_class, SymbolId base_class); + void Clear(); + + // 返回引用避免拷贝 + const std::vector* GetBaseClasses(SymbolId class_id) const; + const std::vector* GetDerivedClasses(SymbolId class_id) const; + bool IsSubclassOf(SymbolId derived, SymbolId base) const; + + private: + std::unordered_map> base_classes_; + std::unordered_map> derived_classes_; + }; + + // 调用图 + class CallGraph + { + public: + void AddCall(SymbolId caller, SymbolId callee, const ast::Location& location); + void Clear(); + + // 返回引用避免拷贝 + const std::vector* GetCallers(SymbolId function_id) const; + const std::vector* GetCallees(SymbolId function_id) const; + + private: + std::unordered_map> callers_; + std::unordered_map> callees_; + }; + +} diff --git a/lsp-server/src/language/symbol/scope.cpp b/lsp-server/src/language/symbol/scope.cpp new file mode 100644 index 0000000..b887030 --- /dev/null +++ b/lsp-server/src/language/symbol/scope.cpp @@ -0,0 +1,88 @@ +#include "./scope.hpp" + +namespace lsp::language::symbol +{ + ScopeId ScopeManager::CreateScope(ScopeKind kind, const ast::Location& range, std::optional parent_scope_id, std::optional 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 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 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 ScopeManager::GetSymbolsInScope(ScopeId scope_id) const + { + std::vector 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; + } + +} diff --git a/lsp-server/src/language/symbol/scope.hpp b/lsp-server/src/language/symbol/scope.hpp new file mode 100644 index 0000000..704cea8 --- /dev/null +++ b/lsp-server/src/language/symbol/scope.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include "./types.hpp" + +namespace lsp::language::symbol +{ + class ScopeManager + { + public: + ScopeId CreateScope(ScopeKind kind, const ast::Location& range, std::optional parent_scope_id = std::nullopt, std::optional associated_symbol_id = std::nullopt); + + void AddSymbol(ScopeId scope_id, const std::string& name, SymbolId symbol_id); + std::optional FindInScope(ScopeId scope_id, const std::string& name) const; + std::optional FindInScopeChain(ScopeId scope_id, const std::string& name) const; + const ScopeInfo* GetScopeInfo(ScopeId scope_id) const; + std::vector GetSymbolsInScope(ScopeId scope_id) const; + ScopeId GetGlobalScope() const { return global_scope_id_; } + const std::unordered_map& GetAllScopes() const { return scopes_; } + void Clear(); + + private: + ScopeId next_scope_id_ = 1; + ScopeId global_scope_id_ = kInvalidScopeId; + std::unordered_map scopes_; + }; + +} diff --git a/lsp-server/src/language/symbol/store.cpp b/lsp-server/src/language/symbol/store.cpp new file mode 100644 index 0000000..f2d2e5b --- /dev/null +++ b/lsp-server/src/language/symbol/store.cpp @@ -0,0 +1,101 @@ +#include +#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 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 SymbolDefinitionStore::GetAll() const + { + std::vector result; + result.reserve(definitions_.size()); + for (const auto& [id, def] : definitions_) + result.push_back(&def); + return result; + } + + std::vector SymbolDefinitionStore::FindByName(const std::string& name) const + { + std::vector 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 SymbolDefinitionStore::GetChildren(SymbolId parent_id) const + { + auto it = children_index_.find(parent_id); + return it != children_index_.end() ? it->second : std::vector{}; + } + + 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()); + } + } + +} diff --git a/lsp-server/src/language/symbol/store.hpp b/lsp-server/src/language/symbol/store.hpp new file mode 100644 index 0000000..42d4c24 --- /dev/null +++ b/lsp-server/src/language/symbol/store.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#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 updater); + bool Remove(SymbolId id); + void Clear(); + + std::vector GetAll() const; + std::vector FindByName(const std::string& name) const; + std::vector GetChildren(SymbolId parent_id) const; + + private: + SymbolId next_id_ = 1; + std::unordered_map definitions_; + std::unordered_map, utils::IHasher, utils::IEqualTo> name_index_; + std::unordered_map> children_index_; + + void UpdateIndices(const SymbolDefinition& def); + void RemoveFromIndices(const SymbolDefinition& def); + }; + +} diff --git a/lsp-server/src/language/symbol/table.cpp b/lsp-server/src/language/symbol/table.cpp new file mode 100644 index 0000000..0536d29 --- /dev/null +++ b/lsp-server/src/language/symbol/table.cpp @@ -0,0 +1,240 @@ +#include +#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 SymbolTable::GetAllDefinitions() const + { + return definition_store_.GetAll(); + } + + std::vector SymbolTable::FindDefinitionsByName(const std::string& name) const + { + return definition_store_.FindByName(name); + } + + std::optional SymbolTable::FindSymbolAt(const ast::Location& location) const + { + return location_index_.FindSymbolAt(location); + } + + std::optional SymbolTable::FindSymbol(const std::string& name, ScopeId scope_id) const + { + return scope_manager_.FindInScopeChain(scope_id, name); + } + + std::vector SymbolTable::FindSymbolsByName(const std::string& name) const + { + std::vector result; + auto defs = definition_store_.FindByName(name); + for (const auto* def : defs) + result.push_back(def->id); + return result; + } + + std::optional SymbolTable::FindScopeAt(const ast::Location& location) const + { + return location_index_.FindScopeAt(location); + } + + std::optional SymbolTable::FindReferenceAt(const ast::Location& location) const + { + return location_index_.FindReferenceAt(location); + } + + std::vector SymbolTable::GetChildren(SymbolId symbol_id) const + { + return definition_store_.GetChildren(symbol_id); + } + + ScopeId SymbolTable::GetGlobalScope() const + { + return scope_manager_.GetGlobalScope(); + } + + const std::vector* SymbolTable::GetReferences(SymbolId symbol_id) const + { + return reference_graph_.GetReferences(symbol_id); + } + + std::optional SymbolTable::GetDefinitionLocation(SymbolId symbol_id) const + { + return reference_graph_.GetDefinition(symbol_id); + } + + const std::vector* SymbolTable::GetBaseClasses(SymbolId class_id) const + { + return inheritance_graph_.GetBaseClasses(class_id); + } + + const std::vector* SymbolTable::GetDerivedClasses(SymbolId class_id) const + { + return inheritance_graph_.GetDerivedClasses(class_id); + } + + const std::vector* SymbolTable::GetCallers(SymbolId function_id) const + { + return call_graph_.GetCallers(function_id); + } + + const std::vector* 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& SymbolTable::GetUnitImports() const + { + return unit_imports_; + } + + std::optional 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 SymbolTable::GetDocumentSymbols() const + { + std::vector result; + + for (const auto* def : definition_store_.GetAll()) + { + // 只返回顶层符号(没有父符号的符号) + if (!def->parent_id) + result.push_back(def); + } + + return result; + } + + std::vector SymbolTable::GetWorkspaceSymbols(const std::string& query) const + { + if (query.empty()) + return definition_store_.GetAll(); + + // 使用小写查询字符串进行大小写无关的匹配 + std::string lower_query = utils::ToLower(query); + + std::vector 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 parent_id, + const std::optional& 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 parent_scope_id, std::optional 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); + } + +} diff --git a/lsp-server/src/language/symbol/table.hpp b/lsp-server/src/language/symbol/table.hpp new file mode 100644 index 0000000..a74d238 --- /dev/null +++ b/lsp-server/src/language/symbol/table.hpp @@ -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 GetAllDefinitions() const; + std::vector FindDefinitionsByName(const std::string& name) const; + + // ===== 第二层: 作用域和位置查询 ===== + // 名称查找 + std::optional FindSymbol(const std::string& name, ScopeId scope_id) const; + std::vector FindSymbolsByName(const std::string& name) const; + + // 位置查找 + std::optional FindSymbolAt(const ast::Location& location) const; + std::optional FindScopeAt(const ast::Location& location) const; + std::optional FindReferenceAt(const ast::Location& location) const; + + // 作用域查询 + std::vector GetChildren(SymbolId symbol_id) const; + ScopeId GetGlobalScope() const; + + // ===== 第三层: 关系访问 ===== + // 返回引用避免拷贝,使用指针表示可能为空 + const std::vector* GetReferences(SymbolId symbol_id) const; + std::optional GetDefinitionLocation(SymbolId symbol_id) const; + const std::vector* GetBaseClasses(SymbolId class_id) const; + const std::vector* GetDerivedClasses(SymbolId class_id) const; + const std::vector* GetCallers(SymbolId function_id) const; + const std::vector* GetCallees(SymbolId function_id) const; + + // ===== Unit 导入管理 ===== + // 添加单元导入 + void AddUnitImport(const std::string& unit_name, const ast::Location& location); + + // 获取所有导入的单元 + const std::vector& GetUnitImports() const; + + // 查找特定单元的导入位置(用于跳转到定义) + std::optional FindImportLocation(const std::string& unit_name) const; + + // 检查是否导入了某个单元 + bool HasImport(const std::string& unit_name) const; + + // ===== LSP 便捷接口 ===== + // 获取文档符号(用于 textDocument/documentSymbol) + std::vector GetDocumentSymbols() const; + + // 获取工作区符号(用于 workspace/symbol) + std::vector GetWorkspaceSymbols(const std::string& query = "") const; + + // ===== Builder 专用内部接口 ===== + // 统一的符号创建接口,自动处理所有索引更新 + SymbolId CreateSymbol( + const std::string& name, + SymbolKind kind, + const ast::Location& location, + ScopeId scope_id, + std::optional parent_id = std::nullopt, + const std::optional& type_hint = std::nullopt); + + // 创建作用域(可以选择关联符号) + ScopeId CreateScope( + ScopeKind kind, + const ast::Location& range, + std::optional parent_scope_id = std::nullopt, + std::optional 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 unit_imports_; + // 快速查找: unit_name -> index in unit_imports_ + std::unordered_map import_index_; + }; + +} diff --git a/lsp-server/src/language/symbol/types.hpp b/lsp-server/src/language/symbol/types.hpp new file mode 100644 index 0000000..3328f62 --- /dev/null +++ b/lsp-server/src/language/symbol/types.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#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 type_hint; + + std::string detail; + + std::optional access_modifier; + std::optional method_modifier; + std::optional reference_modifier; + + std::optional parent_id; + }; + + struct ScopeInfo + { + ScopeId scope_id; + ScopeKind kind; + ast::Location range; + std::optional parent_scope_id; + std::optional associated_symbol_id; + std::unordered_map 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 diff --git a/lsp-server/src/language/symbol/utils/type.cpp b/lsp-server/src/language/symbol/utils/type.cpp deleted file mode 100644 index 80aba8a..0000000 --- a/lsp-server/src/language/symbol/utils/type.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "./type.hpp" -#include -#include - -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(str[start]))) - ++start; - - if (start == str.length()) - return ""; - - size_t end = str.length(); - while (end > start && std::isspace(static_cast(str[end - 1]))) - --end; - - return str.substr(start, end - start); - } - - // ==================== TypeFormatter 实现 ==================== - - std::string TypeFormatter::ToString(const TypeInfo& type) - { - if (!type.HasAnnotation()) - return ""; - - 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(); - } -} diff --git a/lsp-server/src/language/symbol/utils/type.hpp b/lsp-server/src/language/symbol/utils/type.hpp deleted file mode 100644 index d23dc07..0000000 --- a/lsp-server/src/language/symbol/utils/type.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include -#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); - }; -} diff --git a/lsp-server/test/test_symbol/CMakeLists.txt b/lsp-server/test/test_symbol/CMakeLists.txt new file mode 100644 index 0000000..f1d4ee7 --- /dev/null +++ b/lsp-server/test/test_symbol/CMakeLists.txt @@ -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} # 使用变量,避免条件判断 + $<$:Threads::Threads> # 使用生成器表达式 +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(${PROJECT_NAME} PRIVATE + -Wall -Wextra -Wpedantic + $<$:-g -O0> + $<$:-O3> + ) +endif() + diff --git a/lsp-server/test/test_symbol/debug_printer.cpp b/lsp-server/test/test_symbol/debug_printer.cpp new file mode 100644 index 0000000..3b763e9 --- /dev/null +++ b/lsp-server/test/test_symbol/debug_printer.cpp @@ -0,0 +1,1111 @@ +#include +#include +#include "./debug_printer.hpp" + +namespace lsp::language::symbol::debug +{ + // ==================== PrintOptions ==================== + + PrintOptions PrintOptions::Default() + { + return PrintOptions{}; + } + + PrintOptions PrintOptions::Compact() + { + PrintOptions opts; + opts.compact_mode = true; + opts.show_details = false; + opts.show_children = false; + opts.indent_size = 1; + return opts; + } + + PrintOptions PrintOptions::Verbose() + { + PrintOptions opts; + opts.show_details = true; + opts.show_children = true; + opts.show_references = true; + return opts; + } + + PrintOptions PrintOptions::NoColor() + { + PrintOptions opts; + opts.use_color = false; + return opts; + } + + // ==================== Statistics ==================== + + void Statistics::Compute(const SymbolTable& table) + { + auto all_defs = table.GetAllDefinitions(); + total_symbols = all_defs.size(); + + symbol_counts.clear(); + + for (const auto* def : all_defs) + { + symbol_counts[def->kind]++; + + auto refs = table.GetReferences(def->id); + if (refs && !refs->empty()) + { + symbols_with_refs++; + total_references += refs->size(); + + if (refs->size() > max_references) + { + max_references = refs->size(); + most_referenced = def->id; + } + } + } + + // 统计作用域 + const auto& all_scopes = table.GetScopeManager().GetAllScopes(); + total_scopes = all_scopes.size(); + + for (const auto& [id, info] : all_scopes) + { + scope_counts[info.kind]++; + } + } + + void Statistics::Print(std::ostream& os, bool use_color) const + { + auto color = [use_color](const char* code) { + return use_color ? code : ""; + }; + + os << "\n"; + os << color(Color::Bold) << "╔════════════════════════════════════════════════════════════╗\n"; + os << "║ STATISTICS ║\n"; + os << "╚════════════════════════════════════════════════════════════╝" + << color(Color::Reset) << "\n\n"; + + // 总体统计 + os << color(Color::Bold) << "Overview:" << color(Color::Reset) << "\n"; + os << " Total Symbols: " << color(Color::Cyan) << total_symbols << color(Color::Reset) << "\n"; + os << " Total Scopes: " << color(Color::Cyan) << total_scopes << color(Color::Reset) << "\n"; + os << " Total References: " << color(Color::Cyan) << total_references << color(Color::Reset) << "\n"; + os << " Symbols w/ Refs: " << color(Color::Green) << symbols_with_refs << color(Color::Reset) << "\n"; + + if (most_referenced != kInvalidSymbolId) + { + os << " Most Referenced: " << color(Color::Yellow) << "ID=" << most_referenced + << " (" << max_references << " refs)" << color(Color::Reset) << "\n"; + } + + os << "\n"; + + // 符号类型分布 + os << color(Color::Bold) << "Symbol Distribution:" << color(Color::Reset) << "\n"; + + struct KindInfo + { + SymbolKind kind; + const char* name; + const char* icon; + }; + + KindInfo kinds[] = { + { SymbolKind::Module, "Modules", "📦" }, + { SymbolKind::Namespace, "Namespace", "🗃️" }, + { SymbolKind::Class, "Classes", "🏛️" }, + { SymbolKind::Interface, "Interfaces", "🔌" }, + { SymbolKind::Struct, "Structs", "📐" }, + { SymbolKind::Enum, "Enums", "🔢" }, + { SymbolKind::Function, "Functions", "🎄" }, + { SymbolKind::Method, "Methods", "🪀" }, + { SymbolKind::Constructor, "Constructors", "🔨" }, + { SymbolKind::Property, "Properties", "📋" }, + { SymbolKind::Field, "Fields", "📌" }, + { SymbolKind::Variable, "Variables", "📊" }, + { SymbolKind::Constant, "Constants", "🔒" } + }; + + for (const auto& kind_info : kinds) + { + auto it = symbol_counts.find(kind_info.kind); + if (it != symbol_counts.end() && it->second > 0) + { + os << " " << kind_info.icon << " " + << std::setw(15) << std::left << kind_info.name + << ": " << color(Color::BrightBlue) << std::setw(5) << std::right + << it->second << color(Color::Reset) << "\n"; + } + } + + os << "\n"; + + // 作用域分布 + if (!scope_counts.empty()) + { + os << color(Color::Bold) << "Scope Distribution:" << color(Color::Reset) << "\n"; + + struct ScopeKindInfo + { + ScopeKind kind; + const char* name; + }; + + ScopeKindInfo scope_kinds[] = { + { ScopeKind::Global, "Global" }, + { ScopeKind::Unit, "Unit" }, + { ScopeKind::Class, "Class" }, + { ScopeKind::Function, "Function" }, + { ScopeKind::Block, "Block" } + }; + + for (const auto& scope_info : scope_kinds) + { + auto it = scope_counts.find(scope_info.kind); + if (it != scope_counts.end() && it->second > 0) + { + os << " " << std::setw(15) << std::left << scope_info.name + << ": " << color(Color::BrightMagenta) << std::setw(5) << std::right + << it->second << color(Color::Reset) << "\n"; + } + } + + os << "\n"; + } + } + + // ==================== DebugPrinter ==================== + + DebugPrinter::DebugPrinter(const SymbolTable& table, const PrintOptions& options) : table_(table), options_(options) + { + stats_.Compute(table); + } + + // ===== 顶层打印 ===== + + void DebugPrinter::PrintAll(std::ostream& os) + { + PrintHeader("SYMBOL TABLE DUMP", os); + + PrintSubHeader("1. Overview", os); + PrintOverview(os); + + PrintSubHeader("2. Symbol Definitions", os); + PrintSymbolList(os); + + PrintSubHeader("3. Scope Hierarchy", os); + PrintScopeHierarchy(os); + + PrintSubHeader("4. References", os); + PrintAllReferences(os); + + PrintSubHeader("5. Inheritance", os); + PrintAllInheritance(os); + + PrintSubHeader("6. Call Graph", os); + PrintAllCalls(os); + + PrintSubHeader("7. Statistics", os); + PrintStatistics(os); + } + + void DebugPrinter::PrintOverview(std::ostream& os) + { + auto all_defs = table_.GetAllDefinitions(); + + os << "\n"; + os << Color(Color::Bold) << "Symbol Table Overview" << Color(Color::Reset) << "\n"; + os << " Total Symbols: " << Color(Color::Cyan) << all_defs.size() << Color(Color::Reset) << "\n"; + os << " Total Scopes: " << Color(Color::Cyan) << stats_.total_scopes << Color(Color::Reset) << "\n"; + os << "\n"; + + // 按类型分组显示 + std::unordered_map> by_kind; + for (const auto* def : all_defs) + { + by_kind[def->kind].push_back(def); + } + + // 定义固定的类型顺序 + std::vector kind_order = { + SymbolKind::Module, + SymbolKind::Class, + SymbolKind::Interface, + SymbolKind::Struct, + SymbolKind::Enum, + SymbolKind::Function, + SymbolKind::Method, + SymbolKind::Constructor, + SymbolKind::Property, + SymbolKind::Field, + SymbolKind::Variable, + SymbolKind::Constant + }; + + // 按固定顺序遍历类型 + for (const auto& kind : kind_order) + { + auto it = by_kind.find(kind); + if (it == by_kind.end() || it->second.empty()) + continue; + + auto& symbols = it->second; + + // 按位置排序同类型的符号 + std::sort(symbols.begin(), symbols.end(), [](const SymbolDefinition* a, const SymbolDefinition* b) { + if (a->location.start_line != b->location.start_line) + return a->location.start_line < b->location.start_line; + if (a->location.start_column != b->location.start_column) + return a->location.start_column < b->location.start_column; + return true; + }); + + os << " " << SymbolIcon(kind) << " " + << Color(Color::Bold) << FormatSymbolKind(kind) + << Color(Color::Reset) << " (" << symbols.size() << ")\n"; + + if (!options_.compact_mode) + { + for (const auto* sym : symbols) + { + os << " " << Color(Color::Dim) << "• " << Color(Color::Reset) + << ColorizeSymbolName(sym->name, kind); + + if (options_.show_location) + { + os << " " << Color(Color::Dim) + << FormatLocation(sym->location) << Color(Color::Reset); + } + + os << "\n"; + } + } + } + + os << "\n"; + } + + void DebugPrinter::PrintStatistics(std::ostream& os) + { + stats_.Print(os, options_.use_color); + } + + // ===== 符号打印 ===== + + void DebugPrinter::PrintSymbol(SymbolId id, std::ostream& os, int depth) + { + const auto* def = table_.GetDefinition(id); + if (!def) + return; + + os << Indent(depth); + os << SymbolIcon(def->kind) << " "; + os << ColorizeSymbolName(def->name, def->kind); + + if (options_.show_location) + { + os << " " << Color(Color::Dim) << FormatLocation(def->location) << Color(Color::Reset); + } + + os << "\n"; + + if (options_.show_details && !options_.compact_mode) + { + os << Indent(depth + 1) << Color(Color::Dim) << "Kind: " << Color(Color::Reset) + << FormatSymbolKind(def->kind) << "\n"; + + if (def->type_hint) + { + os << Indent(depth + 1) << Color(Color::Dim) << "Type: " << Color(Color::Reset) + << *def->type_hint << "\n"; + } + + if (!def->detail.empty()) + { + os << Indent(depth + 1) << Color(Color::Dim) << "Detail: " << Color(Color::Reset) + << def->detail << "\n"; + } + + if (def->access_modifier) + { + const char* access_str = "public"; + switch (*def->access_modifier) + { + case ast::AccessModifier::kPublic: + access_str = "public"; + break; + case ast::AccessModifier::kProtected: + access_str = "protected"; + break; + case ast::AccessModifier::kPrivate: + access_str = "private"; + break; + } + os << Indent(depth + 1) << Color(Color::Dim) << "Access: " << Color(Color::Reset) + << access_str << "\n"; + } + } + } + + void DebugPrinter::PrintSymbolTree(SymbolId id, std::ostream& os, int depth) + { + if (options_.max_depth >= 0 && depth > options_.max_depth) + return; + + PrintSymbol(id, os, depth); + + if (options_.show_children) + { + auto children = table_.GetChildren(id); + + // 按位置排序子符号 + std::vector sorted_children(children.begin(), children.end()); + std::sort(sorted_children.begin(), sorted_children.end(), [this](SymbolId a, SymbolId b) { + const auto* def_a = table_.GetDefinition(a); + const auto* def_b = table_.GetDefinition(b); + if (!def_a || !def_b) + return false; + + if (def_a->location.start_line != def_b->location.start_line) + return def_a->location.start_line < def_b->location.start_line; + if (def_a->location.start_column != def_b->location.start_column) + return def_a->location.start_column < def_b->location.start_column; + return true; + }); + + for (SymbolId child_id : sorted_children) + { + PrintSymbolTree(child_id, os, depth + 1); + } + } + } + + void DebugPrinter::PrintSymbolList(std::ostream& os) + { + auto all_defs = table_.GetAllDefinitions(); + + if (all_defs.empty()) + { + os << Color(Color::Dim) << " (no symbols)\n" + << Color(Color::Reset); + return; + } + + // 按层级排序(顶层优先) + std::vector top_level; + for (const auto* def : all_defs) + { + if (!def->parent_id) + top_level.push_back(def); + } + + // 按位置排序顶层符号 + std::sort(top_level.begin(), top_level.end(), [](const SymbolDefinition* a, const SymbolDefinition* b) { + if (a->location.start_line != b->location.start_line) + return a->location.start_line < b->location.start_line; + if (a->location.start_column != b->location.start_column) + return a->location.start_column < b->location.start_column; + return true; + }); + + for (const auto* def : top_level) + { + PrintSymbolTree(def->id, os, 0); + } + } + + void DebugPrinter::PrintSymbolsByKind(SymbolKind kind, std::ostream& os) + { + auto all_defs = table_.GetAllDefinitions(); + + os << "\n" + << Color(Color::Bold) << FormatSymbolKind(kind) << "s:" << Color(Color::Reset) << "\n\n"; + + // 收集并排序符号 + std::vector symbols; + for (const auto* def : all_defs) + { + if (def->kind == kind) + { + symbols.push_back(def); + } + } + + if (symbols.empty()) + { + os << Color(Color::Dim) << " (none)\n" + << Color(Color::Reset); + } + else + { + // 按位置排序 + std::sort(symbols.begin(), symbols.end(), [](const SymbolDefinition* a, const SymbolDefinition* b) { + if (a->location.start_line != b->location.start_line) + return a->location.start_line < b->location.start_line; + if (a->location.start_column != b->location.start_column) + return a->location.start_column < b->location.start_column; + return true; + }); + + for (const auto* def : symbols) + { + PrintSymbol(def->id, os, 0); + } + } + + os << "\n"; + } + + // ===== 作用域打印 ===== + + void DebugPrinter::PrintScope(ScopeId id, std::ostream& os, int depth) + { + const auto* info = table_.GetScopeManager().GetScopeInfo(id); + if (!info) + return; + + os << Indent(depth); + os << "🔷 " << Color(Color::Bold) << FormatScopeKind(info->kind) << Color(Color::Reset); + os << " (id=" << id << ")"; + + if (options_.show_location) + { + os << " " << Color(Color::Dim) << FormatLocation(info->range) << Color(Color::Reset); + } + + os << "\n"; + + if (!options_.compact_mode && !info->symbols.empty()) + { + os << Indent(depth + 1) << Color(Color::Dim) << "Symbols: " << info->symbols.size() << Color(Color::Reset) << "\n"; + + // 收集符号并按位置排序 + std::vector> sorted_symbols( + info->symbols.begin(), info->symbols.end()); + + std::sort(sorted_symbols.begin(), sorted_symbols.end(), [this](const auto& a, const auto& b) { + // 按符号定义的位置排序 + const auto* def_a = table_.GetDefinition(a.second); + const auto* def_b = table_.GetDefinition(b.second); + if (!def_a || !def_b) + return false; + + if (def_a->location.start_line != def_b->location.start_line) + return def_a->location.start_line < def_b->location.start_line; + if (def_a->location.start_column != def_b->location.start_column) + return def_a->location.start_column < def_b->location.start_column; + return true; + }); + + for (const auto& [name, sym_id] : sorted_symbols) + { + os << Indent(depth + 2) << "• " << name << "\n"; + } + } + } + + void DebugPrinter::PrintScopeTree(ScopeId id, std::ostream& os, int depth) + { + if (options_.max_depth >= 0 && depth > options_.max_depth) + return; + + PrintScope(id, os, depth); + + // 查找并收集子作用域 + const auto& all_scopes = table_.GetScopeManager().GetAllScopes(); + + std::vector> children; + for (const auto& [child_id, info] : all_scopes) + { + if (info.parent_scope_id && *info.parent_scope_id == id) + { + children.push_back({ child_id, &info }); + } + } + + // 按位置排序子作用域 + std::sort(children.begin(), children.end(), [](const auto& a, const auto& b) { + if (a.second->range.start_line != b.second->range.start_line) + return a.second->range.start_line < b.second->range.start_line; + if (a.second->range.start_column != b.second->range.start_column) + return a.second->range.start_column < b.second->range.start_column; + return true; + }); + + // 递归打印子作用域 + for (const auto& [child_id, info] : children) + { + PrintScopeTree(child_id, os, depth + 1); + } + } + + void DebugPrinter::PrintScopeHierarchy(std::ostream& os) + { + ScopeId global_scope = table_.GetGlobalScope(); + if (global_scope == kInvalidScopeId) + { + os << Color(Color::Dim) << " (no scopes)\n" + << Color(Color::Reset); + return; + } + + PrintScopeTree(global_scope, os, 0); + } + + // ===== 关系打印 ===== + + void DebugPrinter::PrintReferences(SymbolId id, std::ostream& os) + { + const auto* def = table_.GetDefinition(id); + if (!def) + return; + + os << "\n" + << Color(Color::Bold) << "References for: " << def->name << Color(Color::Reset) << "\n"; + + auto refs = table_.GetReferences(id); + if (!refs || refs->empty()) + { + os << Color(Color::Dim) << " (no references)\n" + << Color(Color::Reset); + return; + } + + os << " Total: " << refs->size() << "\n\n"; + + for (const auto& ref : *refs) + { + os << " "; + + if (ref.is_definition) + os << Color(Color::Green) << "[DEF]" << Color(Color::Reset) << " "; + else if (ref.is_write) + os << Color(Color::Yellow) << "[WRITE]" << Color(Color::Reset) << " "; + else + os << Color(Color::Cyan) << "[READ]" << Color(Color::Reset) << " "; + + os << FormatLocation(ref.location) << "\n"; + } + + os << "\n"; + } + + void DebugPrinter::PrintInheritance(SymbolId class_id, std::ostream& os) + { + const auto* def = table_.GetDefinition(class_id); + if (!def || def->kind != SymbolKind::Class) + return; + + os << "\n" + << Color(Color::Bold) << "Inheritance for: " << def->name << Color(Color::Reset) << "\n\n"; + + // 基类 + auto bases = table_.GetBaseClasses(class_id); + if (bases && !bases->empty()) + { + os << " " << Color(Color::Green) << "Base Classes:" << Color(Color::Reset) << "\n"; + for (SymbolId base_id : *bases) + { + const auto* base_def = table_.GetDefinition(base_id); + if (base_def) + { + os << " ↑ " << base_def->name << "\n"; + } + } + } + + // 派生类 + auto derived = table_.GetDerivedClasses(class_id); + if (derived && !derived->empty()) + { + os << " " << Color(Color::Yellow) << "Derived Classes:" << Color(Color::Reset) << "\n"; + for (SymbolId derived_id : *derived) + { + const auto* derived_def = table_.GetDefinition(derived_id); + if (derived_def) + { + os << " ↓ " << derived_def->name << "\n"; + } + } + } + + os << "\n"; + } + + void DebugPrinter::PrintCallGraph(SymbolId function_id, std::ostream& os) + { + const auto* def = table_.GetDefinition(function_id); + if (!def) + return; + + os << "\n" + << Color(Color::Bold) << "Call Graph for: " << def->name << Color(Color::Reset) << "\n\n"; + + // 调用者 + auto callers = table_.GetCallers(function_id); + if (callers && !callers->empty()) + { + os << " " << Color(Color::Green) << "Called by:" << Color(Color::Reset) << "\n"; + for (const auto& rel : *callers) + { + const auto* caller_def = table_.GetDefinition(rel.caller); + if (caller_def) + { + os << " ← " << caller_def->name + << " " << Color(Color::Dim) << FormatLocation(rel.call_location) << Color(Color::Reset) << "\n"; + } + } + } + + // 被调用的 + auto callees = table_.GetCallees(function_id); + if (callees && !callees->empty()) + { + os << " " << Color(Color::Yellow) << "Calls:" << Color(Color::Reset) << "\n"; + for (const auto& rel : *callees) + { + const auto* callee_def = table_.GetDefinition(rel.callee); + if (callee_def) + { + os << " → " << callee_def->name + << " " << Color(Color::Dim) << FormatLocation(rel.call_location) << Color(Color::Reset) << "\n"; + } + } + } + + os << "\n"; + } + + void DebugPrinter::PrintAllReferences(std::ostream& os) + { + auto all_defs = table_.GetAllDefinitions(); + + // 按位置排序 + std::vector sorted_defs(all_defs.begin(), all_defs.end()); + std::sort(sorted_defs.begin(), sorted_defs.end(), [](const SymbolDefinition* a, const SymbolDefinition* b) { + if (a->location.start_line != b->location.start_line) + return a->location.start_line < b->location.start_line; + if (a->location.start_column != b->location.start_column) + return a->location.start_column < b->location.start_column; + return true; + }); + + for (const auto* def : sorted_defs) + { + auto refs = table_.GetReferences(def->id); + if (refs && refs->size() > 1) // >1 因为定义本身算一个引用 + { + PrintReferences(def->id, os); + } + } + } + + void DebugPrinter::PrintAllInheritance(std::ostream& os) + { + auto all_defs = table_.GetAllDefinitions(); + + // 按位置排序 + std::vector sorted_defs(all_defs.begin(), all_defs.end()); + std::sort(sorted_defs.begin(), sorted_defs.end(), [](const SymbolDefinition* a, const SymbolDefinition* b) { + if (a->location.start_line != b->location.start_line) + return a->location.start_line < b->location.start_line; + if (a->location.start_column != b->location.start_column) + return a->location.start_column < b->location.start_column; + return true; + }); + + bool found = false; + for (const auto* def : sorted_defs) + { + if (def->kind == SymbolKind::Class) + { + auto bases = table_.GetBaseClasses(def->id); + auto derived = table_.GetDerivedClasses(def->id); + + if ((bases && !bases->empty()) || (derived && !derived->empty())) + { + PrintInheritance(def->id, os); + found = true; + } + } + } + + if (!found) + { + os << Color(Color::Dim) << " (no inheritance relationships)\n" + << Color(Color::Reset); + } + } + + void DebugPrinter::PrintAllCalls(std::ostream& os) + { + auto all_defs = table_.GetAllDefinitions(); + + // 按位置排序 + std::vector sorted_defs(all_defs.begin(), all_defs.end()); + std::sort(sorted_defs.begin(), sorted_defs.end(), [](const SymbolDefinition* a, const SymbolDefinition* b) { + if (a->location.start_line != b->location.start_line) + return a->location.start_line < b->location.start_line; + if (a->location.start_column != b->location.start_column) + return a->location.start_column < b->location.start_column; + return true; + }); + + bool found = false; + for (const auto* def : sorted_defs) + { + if (def->kind == SymbolKind::Function || def->kind == SymbolKind::Method) + { + auto callers = table_.GetCallers(def->id); + auto callees = table_.GetCallees(def->id); + + if ((callers && !callers->empty()) || (callees && !callees->empty())) + { + PrintCallGraph(def->id, os); + found = true; + } + } + } + + if (!found) + { + os << Color(Color::Dim) << " (no call relationships)\n" + << Color(Color::Reset); + } + } + + // ===== 搜索和查询 ===== + + void DebugPrinter::FindAndPrint(const std::string& name, std::ostream& os) + { + auto symbols = table_.FindSymbolsByName(name); + + os << "\n" + << Color(Color::Bold) << "Search results for: '" << name << "'" << Color(Color::Reset) << "\n"; + os << "Found " << symbols.size() << " symbol(s)\n\n"; + + if (symbols.empty()) + { + os << Color(Color::Dim) << " (no matches)\n" + << Color(Color::Reset); + return; + } + + // 按位置排序结果 + std::vector sorted_symbols(symbols.begin(), symbols.end()); + std::sort(sorted_symbols.begin(), sorted_symbols.end(), [this](SymbolId a, SymbolId b) { + const auto* def_a = table_.GetDefinition(a); + const auto* def_b = table_.GetDefinition(b); + if (!def_a || !def_b) + return false; + + if (def_a->location.start_line != def_b->location.start_line) + return def_a->location.start_line < def_b->location.start_line; + if (def_a->location.start_column != def_b->location.start_column) + return def_a->location.start_column < def_b->location.start_column; + return true; + }); + + for (SymbolId id : sorted_symbols) + { + const auto* def = table_.GetDefinition(id); + if (!def) + continue; + + PrintSymbol(id, os, 0); + + if (options_.show_references) + { + PrintReferences(id, os); + } + + os << "\n"; + } + } + + void DebugPrinter::FindAtLocation(const ast::Location& loc, std::ostream& os) + { + os << "\n" + << Color(Color::Bold) << "Symbols at location: " + << FormatLocation(loc) << Color(Color::Reset) << "\n\n"; + + // 查找符号 + auto symbol_id = table_.FindSymbolAt(loc); + if (symbol_id) + { + os << "Symbol: "; + PrintSymbol(*symbol_id, os, 0); + } + else + { + os << "Symbol: " << Color(Color::Dim) << "(none)\n" + << Color(Color::Reset); + } + + // 查找作用域 + auto scope_id = table_.FindScopeAt(loc); + if (scope_id) + { + os << "Scope: "; + PrintScope(*scope_id, os, 0); + } + else + { + os << "Scope: " << Color(Color::Dim) << "(none)\n" + << Color(Color::Reset); + } + + // 查找引用 + auto ref_id = table_.FindReferenceAt(loc); + if (ref_id) + { + os << "Reference to: "; + PrintSymbol(*ref_id, os, 0); + } + + os << "\n"; + } + + // ===== 辅助方法 ===== + + std::string DebugPrinter::Indent(int depth) const + { + return std::string(depth * options_.indent_size, ' '); + } + + std::string DebugPrinter::ColorizeSymbolKind(SymbolKind kind) const + { + if (!options_.use_color) + return ""; + + switch (kind) + { + case SymbolKind::Module: + return Color::BrightMagenta; + case SymbolKind::Class: + return Color::BrightYellow; + case SymbolKind::Function: + return Color::BrightBlue; + case SymbolKind::Method: + return Color::BrightCyan; + case SymbolKind::Constructor: + return Color::BrightGreen; + case SymbolKind::Interface: + return Color::BrightMagenta; + case SymbolKind::Struct: + return Color::BrightYellow; + case SymbolKind::Enum: + return Color::BrightCyan; + case SymbolKind::Property: + return Color::Magenta; + case SymbolKind::Field: + return Color::Yellow; + case SymbolKind::Variable: + return Color::White; + case SymbolKind::Constant: + return Color::BrightRed; + default: + return Color::Reset; + } + } + + std::string DebugPrinter::ColorizeSymbolName(const std::string& name, SymbolKind kind) const + { + if (!options_.use_color) + return name; + return std::string(ColorizeSymbolKind(kind)) + name + Color::Reset; + } + + std::string DebugPrinter::FormatLocation(const ast::Location& loc) const + { + std::ostringstream oss; + oss << "[" << loc.start_line << ":" << loc.start_column + << "-" << loc.end_line << ":" << loc.end_column << "]"; + return oss.str(); + } + + std::string DebugPrinter::FormatSymbolKind(SymbolKind kind) const + { + switch (kind) + { + case SymbolKind::Module: + return "Module"; + case SymbolKind::Namespace: + return "Namespace"; + case SymbolKind::Class: + return "Class"; + case SymbolKind::Interface: + return "Interface"; + case SymbolKind::Struct: + return "Struct"; + case SymbolKind::Enum: + return "Enum"; + case SymbolKind::Function: + return "Function"; + case SymbolKind::Method: + return "Method"; + case SymbolKind::Constructor: + return "Constructor"; + case SymbolKind::Property: + return "Property"; + case SymbolKind::Field: + return "Field"; + case SymbolKind::Variable: + return "Variable"; + case SymbolKind::Constant: + return "Constant"; + default: + return "Unknown"; + } + } + + std::string DebugPrinter::FormatScopeKind(ScopeKind kind) const + { + switch (kind) + { + case ScopeKind::Global: + return "Global"; + case ScopeKind::Unit: + return "Unit"; + case ScopeKind::Class: + return "Class"; + case ScopeKind::Function: + return "Function"; + case ScopeKind::Block: + return "Block"; + default: + return "Unknown"; + } + } + + std::string DebugPrinter::SymbolIcon(SymbolKind kind) const + { + if (!options_.use_color) + return ""; + + switch (kind) + { + case SymbolKind::Module: + return "📦"; + case SymbolKind::Namespace: + return "🗃️"; + case SymbolKind::Class: + return "🏛️"; + case SymbolKind::Interface: + return "🔌"; + case SymbolKind::Struct: + return "📐"; + case SymbolKind::Enum: + return "🔢"; + case SymbolKind::Function: + return "🎄"; + case SymbolKind::Method: + return "🪀"; + case SymbolKind::Constructor: + return "🔨"; + case SymbolKind::Property: + return "📋"; + case SymbolKind::Field: + return "📌"; + case SymbolKind::Variable: + return "📊"; + case SymbolKind::Constant: + return "🔒"; + default: + return "•"; + } + } + + void DebugPrinter::PrintSeparator(std::ostream& os, char ch, int width) const + { + os << std::string(width, ch) << "\n"; + } + + void DebugPrinter::PrintHeader(const std::string& title, std::ostream& os) const + { + os << "\n"; + os << Color(Color::Bold) << "╔" << std::string(78, '=') << "╗\n"; + os << "║ " << std::setw(74) << std::left << title << " ║\n"; + os << "╚" << std::string(78, '=') << "╝" << Color(Color::Reset) << "\n\n"; + } + + void DebugPrinter::PrintSubHeader(const std::string& title, std::ostream& os) const + { + os << "\n"; + os << Color(Color::Bold) << Color(Color::BrightCyan) + << "┌─ " << title << " " << std::string(73 - title.length(), '-') << "\n" + << Color(Color::Reset); + } + + std::string DebugPrinter::Color(const char* color_code) const + { + return options_.use_color ? color_code : ""; + } + + std::string DebugPrinter::Bold(const std::string& text) const + { + if (!options_.use_color) + return text; + return std::string(Color::Bold) + text + Color::Reset; + } + + std::string DebugPrinter::Dim(const std::string& text) const + { + if (!options_.use_color) + return text; + return std::string(Color::Dim) + text + Color::Reset; + } + + // ==================== 快速打印函数 ==================== + + void Print(const SymbolTable& table, std::ostream& os) + { + DebugPrinter printer(table); + printer.PrintAll(os); + } + + void PrintOverview(const SymbolTable& table, std::ostream& os) + { + DebugPrinter printer(table); + printer.PrintOverview(os); + } + + void PrintStats(const SymbolTable& table, std::ostream& os) + { + DebugPrinter printer(table); + printer.PrintStatistics(os); + } + + void PrintSymbolTree(const SymbolTable& table, std::ostream& os) + { + DebugPrinter printer(table); + printer.PrintSymbolList(os); + } + + void PrintScopeTree(const SymbolTable& table, std::ostream& os) + { + DebugPrinter printer(table); + printer.PrintScopeHierarchy(os); + } + + void Find(const SymbolTable& table, const std::string& name, std::ostream& os) + { + DebugPrinter printer(table); + printer.FindAndPrint(name, os); + } + + void PrintCompact(const SymbolTable& table, std::ostream& os) + { + DebugPrinter printer(table, PrintOptions::Compact()); + printer.PrintOverview(os); + printer.PrintStatistics(os); + } + + void PrintVerbose(const SymbolTable& table, std::ostream& os) + { + DebugPrinter printer(table, PrintOptions::Verbose()); + printer.PrintAll(os); + } + +} // namespace lsp::language::symbol::debug diff --git a/lsp-server/test/test_symbol/debug_printer.hpp b/lsp-server/test/test_symbol/debug_printer.hpp new file mode 100644 index 0000000..8ac84c1 --- /dev/null +++ b/lsp-server/test/test_symbol/debug_printer.hpp @@ -0,0 +1,165 @@ +#pragma once + +#include +#include +#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 symbol_counts; + std::unordered_map 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 diff --git a/lsp-server/test/test_symbol/test.cpp b/lsp-server/test/test_symbol/test.cpp new file mode 100644 index 0000000..5372ed2 --- /dev/null +++ b/lsp-server/test/test_symbol/test.cpp @@ -0,0 +1,557 @@ +#include +#include +#include +#include +#include + +extern "C" { +#include +} + +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 << " [options]\n\n"; + std::cout << "Options:\n"; + std::cout << " -o, --output 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 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(stmt.get())) + { + os << " - Function: " << func_def->name; + } + else if (auto* class_def = dynamic_cast(stmt.get())) + { + os << " - Class: " << class_def->name; + } + else if (auto* unit_def = dynamic_cast(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(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; + } +} diff --git a/lsp-server/test/test_symbol/test.tsf b/lsp-server/test/test_symbol/test.tsf new file mode 100644 index 0000000..4a46b0f --- /dev/null +++ b/lsp-server/test/test_symbol/test.tsf @@ -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();