module; import std; export module lsp.test.symbol.debug_printer; import lsp.protocol; import lsp.language.ast; import lsp.language.symbol; export namespace lsp::language::symbol::debug { using SymbolKind = protocol::SymbolKind; struct PrintOptions { bool use_color = true; bool show_location = true; bool show_details = true; bool show_children = true; bool compact_mode = false; int indent_size = 2; int max_depth = -1; static PrintOptions Default() { return PrintOptions(); } static PrintOptions Compact() { PrintOptions opts; opts.compact_mode = true; opts.show_children = true; opts.show_details = false; opts.indent_size = 0; return opts; } static PrintOptions Verbose() { PrintOptions opts; opts.show_children = true; opts.show_details = true; return opts; } static PrintOptions NoColor() { PrintOptions opts; opts.use_color = false; return opts; } }; struct Statistics { std::size_t total_symbols = 0; std::size_t total_scopes = 0; std::unordered_map symbol_counts; std::unordered_map scope_counts; 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 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 PrintSymbolData(const Symbol& symbol, std::ostream& os, int depth); void PrintSymbolWithChildren(SymbolId id, const std::unordered_multimap& children, std::ostream& os, int depth, int current_depth); std::string GetSymbolIcon(const Symbol& symbol) 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 { using namespace lsp::language; using namespace lsp::language::symbol; using lsp::protocol::SymbolKind; [[maybe_unused]] const char* AccessModifierToString(ast::AccessModifier access) { switch (access) { case ast::AccessModifier::kPublic: return "public"; case ast::AccessModifier::kProtected: return "protected"; case ast::AccessModifier::kPrivate: return "private"; default: return "unknown"; } } std::string ScopeKindToString(ScopeKind kind) { switch (kind) { case ScopeKind::kGlobal: return "Global"; case ScopeKind::kUnit: return "Unit"; case ScopeKind::kClass: return "Class"; case ScopeKind::kFunction: return "Function"; case ScopeKind::kAnonymousFunction: return "AnonymousFunction"; case ScopeKind::kBlock: return "Block"; default: return "Unknown"; } } std::string SymbolKindToString(SymbolKind kind) { switch (kind) { case SymbolKind::File: return "File"; case SymbolKind::Module: return "Module"; case SymbolKind::Namespace: return "Namespace"; case SymbolKind::Package: return "Package"; case SymbolKind::Class: return "Class"; case SymbolKind::Method: return "Method"; case SymbolKind::Property: return "Property"; case SymbolKind::Field: return "Field"; case SymbolKind::Constructor: return "Constructor"; case SymbolKind::Enum: return "Enum"; case SymbolKind::Interface: return "Interface"; case SymbolKind::Function: return "Function"; case SymbolKind::Variable: return "Variable"; case SymbolKind::Constant: return "Constant"; case SymbolKind::String: return "String"; case SymbolKind::Number: return "Number"; case SymbolKind::Boolean: return "Boolean"; case SymbolKind::Array: return "Array"; case SymbolKind::Object: return "Object"; case SymbolKind::Key: return "Key"; case SymbolKind::Null: return "Null"; case SymbolKind::EnumMember: return "EnumMember"; case SymbolKind::Struct: return "Struct"; case SymbolKind::Event: return "Event"; case SymbolKind::Operator: return "Operator"; case SymbolKind::TypeParameter: return "TypeParameter"; default: return "Unknown"; } } } namespace lsp::language::symbol::debug { void Statistics::Compute(const SymbolTable& table) { total_symbols = table.all_definitions().size(); total_scopes = 0; // 不再深入统计,避免依赖内部存储。 } DebugPrinter::DebugPrinter(const SymbolTable& table, const PrintOptions& options) : table_(table), options_(options) { stats_.Compute(table_); } void DebugPrinter::PrintAll(std::ostream& os) { PrintOverview(os); os << "\n"; PrintStatistics(os); os << "\nSymbols:\n"; PrintSymbolList(os); } void DebugPrinter::PrintOverview(std::ostream& os) { PrintHeader("Symbol Table Overview", os); os << "Total Symbols: " << stats_.total_symbols << "\n"; os << "Total Scopes : " << stats_.total_scopes << "\n"; } void DebugPrinter::PrintStatistics(std::ostream& os) { stats_.Print(os, options_.use_color); } void DebugPrinter::PrintSymbol(SymbolId id, std::ostream& os, int depth) { auto symbol = table_.definition(id); if (!symbol) { os << Indent(depth) << "\n"; return; } PrintSymbolData(*symbol, os, depth); } void DebugPrinter::PrintSymbolTree(SymbolId id, std::ostream& os, int depth) { auto symbol = table_.definition(id); if (!symbol) return; PrintSymbolData(*symbol, os, depth); // Example placeholder for children traversal } void DebugPrinter::PrintSymbolList(std::ostream& os) { for (const auto& sym : table_.all_definitions()) PrintSymbol(sym.get().id(), os, 0); } void DebugPrinter::PrintSymbolsByKind(SymbolKind kind, std::ostream& os) { for (const auto& sym : table_.all_definitions()) { if (sym.get().kind() == kind) PrintSymbol(sym.get().id(), os, 0); } } void DebugPrinter::PrintScope(ScopeId id, std::ostream& os, int depth) { os << Indent(depth) << "Scope " << id << "\n"; } void DebugPrinter::PrintScopeTree(ScopeId id, std::ostream& os, int depth) { PrintScope(id, os, depth); } void DebugPrinter::PrintScopeHierarchy(std::ostream& os) { PrintScopeTree(ScopeId{ 0 }, os, 0); } void DebugPrinter::FindAndPrint(const std::string& name, std::ostream& os) { auto ids = table_.FindSymbolsByName(name); for (auto id : ids) PrintSymbol(id, os, 0); } void DebugPrinter::FindAtLocation(const ast::Location& loc, std::ostream& os) { auto id = table_.FindSymbolAt(loc); if (id) PrintSymbol(*id, os, 0); else os << "No symbol at location.\n"; } std::string DebugPrinter::Indent(int depth) const { return std::string(depth * options_.indent_size, ' '); } std::string DebugPrinter::ColorizeSymbolKind(SymbolKind kind) const { return options_.use_color ? Bold(SymbolKindToString(kind)) : SymbolKindToString(kind); } std::string DebugPrinter::ColorizeSymbolName(const std::string& name, SymbolKind) const { return options_.use_color ? Bold(name) : name; } 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 { return SymbolKindToString(kind); } std::string DebugPrinter::FormatScopeKind(ScopeKind kind) const { return ScopeKindToString(kind); } 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 { PrintSeparator(os); os << title << "\n"; PrintSeparator(os); } void DebugPrinter::PrintSubHeader(const std::string& title, std::ostream& os) const { os << title << "\n"; PrintSeparator(os, '-', 40); } std::string DebugPrinter::Color(const char* color_code) const { return options_.use_color ? std::string(color_code) : std::string(); } std::string DebugPrinter::Bold(const std::string& text) const { return Color("\033[1m") + text + Color("\033[0m"); } std::string DebugPrinter::Dim(const std::string& text) const { return Color("\033[2m") + text + Color("\033[0m"); } void DebugPrinter::PrintSymbolData(const Symbol& symbol, std::ostream& os, int depth) { os << Indent(depth) << ColorizeSymbolName(symbol.name(), symbol.kind()) << " (" << FormatSymbolKind(symbol.kind()) << ")"; if (options_.show_location) os << " " << FormatLocation(symbol.selection_range()); os << "\n"; } std::string DebugPrinter::GetSymbolIcon(const Symbol& symbol) const { (void)symbol; return {}; } void Statistics::Print(std::ostream& os, bool use_color) const { auto bold = [&](const std::string& txt) { return use_color ? "\033[1m" + txt + "\033[0m" : txt; }; os << bold("Symbols: ") << total_symbols << "\n"; os << bold("Scopes : ") << total_scopes << "\n"; } 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.PrintSymbolTree(SymbolId{ 0 }, os, 0); } void PrintScopeTree(const SymbolTable& table, std::ostream& os) { DebugPrinter printer(table); printer.PrintScopeTree(ScopeId{ 0 }, os, 0); } 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.PrintSymbolList(os); } void PrintVerbose(const SymbolTable& table, std::ostream& os) { DebugPrinter printer(table, PrintOptions::Verbose()); printer.PrintAll(os); } }