♻️ 使用module重构所有代码

This commit is contained in:
csh
2025-12-07 23:07:03 +08:00
parent 549f1d1b0a
commit f7d5a74615
369 changed files with 2272844 additions and 2202476 deletions
+71 -16
View File
@@ -15,23 +15,77 @@ if(UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
endif()
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
set(SOURCES
test.cpp
debug_printer.cpp
test.cppm
../../src/utils/string.cppm
../../src/utils/string.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/store.cpp
../../src/language/symbol/table.cpp
../../src/language/symbol/index/coordinator.cpp
../../src/language/symbol/index/location.cpp
../../src/language/symbol/index/scope.cpp
../../src/language/symbol/internal/builder.cppm
../../src/language/symbol/internal/store.cppm
../../src/language/symbol/internal/table.cppm
../../src/language/symbol/index/coordinator.cppm
../../src/language/symbol/index/location.cppm
../../src/language/symbol/index/scope.cppm
../../src/tree-sitter/scanner.c
../../src/tree-sitter/parser.c)
add_executable(${PROJECT_NAME} ${SOURCES})
if(TARGET std_module)
add_dependencies(${PROJECT_NAME} std_module)
endif()
target_sources(
${PROJECT_NAME}
PRIVATE
FILE_SET cxx_modules TYPE CXX_MODULES
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../src
${CMAKE_CURRENT_SOURCE_DIR}
FILES ../../src/bridge/tree_sitter.cppm
../../src/bridge/spdlog.cppm
../../src/bridge/glaze.cppm
../../src/language/ast/ast.cppm
../../src/language/ast/types.cppm
../../src/language/ast/deserializer.cppm
../../src/language/ast/deserializer_impl.cppm
../../src/language/ast/ts_utils.cppm
../../src/language/ast/detail.cppm
../../src/utils/string.cppm
../../src/protocol/common/basic_types.cppm
../../src/protocol/common/message.cppm
../../src/protocol/common/registration.cppm
../../src/protocol/window/progress.cppm
../../src/protocol/initialize/configuration.cppm
../../src/protocol/initialize/capabilities.cppm
../../src/protocol/workspace/workspace.cppm
../../src/protocol/workspace/file_operations.cppm
../../src/protocol/workspace/notebook.cppm
../../src/protocol/text_document/document_sync.cppm
../../src/protocol/text_document/completion.cppm
../../src/protocol/text_document/code_actions.cppm
../../src/protocol/text_document/diagnostics.cppm
../../src/protocol/text_document/document_features.cppm
../../src/protocol/text_document/formatting.cppm
../../src/protocol/text_document/inline_features.cppm
../../src/protocol/text_document/navigation.cppm
../../src/protocol/text_document/rename.cppm
../../src/protocol/text_document/semantic_tokens.cppm
../../src/protocol/text_document/signature_help.cppm
../../src/protocol/text_document/symbols.cppm
../../src/codec/common.cppm
../../src/codec/transformer.cppm
../../src/codec/facade.cppm
../../src/protocol/types.cppm
../../src/protocol/protocol.cppm
../../src/language/symbol/types.cppm
../../src/language/symbol/internal/builder.cppm
../../src/language/symbol/internal/store.cppm
../../src/language/symbol/internal/table.cppm
../../src/language/symbol/index/coordinator.cppm
../../src/language/symbol/index/location.cppm
../../src/language/symbol/index/scope.cppm
../../src/language/symbol/symbol.cppm
${CMAKE_CURRENT_SOURCE_DIR}/debug_printer.cppm
${CMAKE_CURRENT_SOURCE_DIR}/test.cppm)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(${PROJECT_NAME} PRIVATE SPDLOG_HEADER_ONLY
@@ -43,8 +97,9 @@ target_link_libraries(
fmt::fmt-header-only tree-sitter::tree-sitter
$<$<PLATFORM_ID:Linux>:Threads::Threads>)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(
${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic $<$<CONFIG:Debug>:-g -O0>
$<$<CONFIG:Release>:-O3>)
endif()
target_compile_options(
${PROJECT_NAME}
PRIVATE
-Wall -Wextra -Wpedantic $<$<CONFIG:Debug>:-g -O0>
-Wno-import-implementation-partition-unit-in-interface-unit
$<$<CONFIG:Release>:-O3>)
@@ -1,795 +0,0 @@
#include <algorithm>
#include <functional>
#include <iomanip>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "./debug_printer.hpp"
namespace
{
using namespace lsp::language;
using namespace lsp::language::symbol;
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";
}
return "public";
}
const char* VariableScopeToString(VariableScope scope)
{
switch (scope)
{
case VariableScope::kAutomatic:
return "auto";
case VariableScope::kStatic:
return "static";
case VariableScope::kGlobal:
return "global";
case VariableScope::kParameter:
return "param";
case VariableScope::kField:
return "field";
}
return "auto";
}
} // namespace
namespace lsp::language::symbol::debug
{
namespace Color
{
constexpr const char* Reset = "\033[0m";
constexpr const char* Bold = "\033[1m";
constexpr const char* Dim = "\033[2m";
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* BrightBlue = "\033[94m";
constexpr const char* BrightMagenta = "\033[95m";
constexpr const char* BrightGreen = "\033[92m";
constexpr const char* Gray = "\033[90m";
}
// ==================== 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;
return opts;
}
PrintOptions PrintOptions::NoColor()
{
PrintOptions opts;
opts.use_color = false;
return opts;
}
// ==================== Statistics ====================
void Statistics::Compute(const SymbolTable& table)
{
auto all_defs = table.all_definitions();
total_symbols = all_defs.size();
symbol_counts.clear();
scope_counts.clear();
for (const auto& ref : all_defs)
{
const auto& sym = ref.get();
symbol_counts[sym.kind()]++;
}
const auto& scopes = table.scopes().all_scopes();
total_scopes = scopes.size();
for (const auto& [_, info] : 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 << "\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, "Module", "🗃️" },
{ SymbolKind::Class, "Classes", "🏛️" },
{ SymbolKind::Function, "Functions", "🎄" },
{ SymbolKind::Method, "Methods", "🪀" },
{ 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";
}
}
if (!scope_counts.empty())
{
os << "\n"
<< color(Color::Bold) << "Scope Distribution:" << color(Color::Reset) << "\n";
for (const auto& [kind, count] : scope_counts)
{
os << " " << std::setw(12) << std::left << static_cast<int>(kind)
<< ": " << color(Color::BrightMagenta) << count << color(Color::Reset) << "\n";
}
}
}
// ==================== DebugPrinter ====================
DebugPrinter::DebugPrinter(const SymbolTable& table, const PrintOptions& options) : table_(table), options_(options)
{
stats_.Compute(table_);
}
void DebugPrinter::PrintSeparator(std::ostream& os, char ch, int width) const
{
for (int i = 0; i < width; ++i)
os << ch;
os << "\n";
}
std::string DebugPrinter::Color(const char* color_code) const
{
return options_.use_color ? color_code : "";
}
std::string DebugPrinter::Bold(const std::string& text) const
{
return options_.use_color ? std::string(Color::Bold) + text + Color::Reset : text;
}
std::string DebugPrinter::Dim(const std::string& text) const
{
return options_.use_color ? std::string(Color::Dim) + text + Color::Reset : text;
}
std::string DebugPrinter::Indent(int depth) const
{
return std::string(static_cast<size_t>(depth * options_.indent_size), ' ');
}
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::Class:
return "Class";
case SymbolKind::Method:
return "Method";
case SymbolKind::Property:
return "Property";
case SymbolKind::Field:
return "Field";
case SymbolKind::Function:
return "Function";
case SymbolKind::Variable:
return "Variable";
case SymbolKind::Constant:
return "Constant";
default:
return "Unknown";
}
}
std::string DebugPrinter::FormatScopeKind(ScopeKind kind) const
{
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 DebugPrinter::SymbolIcon(SymbolKind kind) const
{
switch (kind)
{
case SymbolKind::Module:
return "🗃️";
case SymbolKind::Class:
return "🏛️";
case SymbolKind::Method:
return "🔧"; // Default, will be overridden in GetSymbolIcon
case SymbolKind::Property:
return "📋";
case SymbolKind::Field:
return "📌";
case SymbolKind::Function:
return "🌲"; // Default, will be overridden in GetSymbolIcon
case SymbolKind::Variable:
return "📊";
case SymbolKind::Constant:
return "🔒";
default:
return "";
}
}
std::string DebugPrinter::GetSymbolIcon(const Symbol& symbol) const
{
// Check if it's a Method with declaration/implementation distinction
if (const auto* method = symbol.As<Method>())
{
bool has_decl = method->declaration_range.start_line != 0;
bool has_impl = method->implementation_range.has_value();
if (has_decl && has_impl)
{
// Has both declaration and implementation
if (symbol.selection_range().start_line == method->declaration_range.start_line)
{
return "🔷"; // Declaration: blue diamond (interface/contract)
}
else if (has_impl && symbol.selection_range().start_line == method->implementation_range->start_line)
{
return "🔶"; // Implementation: orange diamond (concrete/실행)
}
}
return "🔧"; // Default method icon (wrench/tool)
}
// Check if it's a Function with declaration/implementation distinction
if (const auto* func = symbol.As<Function>())
{
bool has_decl = func->declaration_range.start_line != 0;
bool has_impl = func->implementation_range.has_value();
if (has_decl && has_impl)
{
// Has both declaration and implementation
if (symbol.selection_range().start_line == func->declaration_range.start_line)
{
return "🌳"; // Declaration: deciduous tree (interface/skeleton)
}
else if (has_impl && symbol.selection_range().start_line == func->implementation_range->start_line)
{
return "🎄"; // Implementation: christmas tree (decorated/complete)
}
}
return "🌲"; // Default function icon (evergreen tree)
}
// For other types, use the default icon
return SymbolIcon(symbol.kind());
}
std::string DebugPrinter::ColorizeSymbolKind(SymbolKind kind) const
{
return Color(Color::Blue) + FormatSymbolKind(kind) + Color(Color::Reset);
}
std::string DebugPrinter::ColorizeSymbolName(const std::string& name, SymbolKind /*kind*/) const
{
return Color(Color::Yellow) + name + Color(Color::Reset);
}
void DebugPrinter::PrintHeader(const std::string& title, std::ostream& os) const
{
os << "\n"
<< Bold(title) << "\n";
PrintSeparator(os, '=', 60);
}
void DebugPrinter::PrintSubHeader(const std::string& title, std::ostream& os) const
{
os << "\n"
<< Bold(title) << "\n";
PrintSeparator(os, '-', 40);
}
void DebugPrinter::PrintSymbolData(const Symbol& symbol, std::ostream& os, int depth)
{
std::visit(
[&](const auto& data) {
// Tree connector prefix based on depth
std::string prefix;
if (depth > 0)
{
prefix = Indent(depth - 1) + Color(Color::Gray) + "├─ " + Color(Color::Reset);
}
else
{
prefix = "";
}
os << prefix << GetSymbolIcon(symbol) << " "
<< ColorizeSymbolName(symbol.name(), symbol.kind())
<< " " << Color(Color::Dim) << "(" << FormatSymbolKind(symbol.kind()) << ")" << Color(Color::Reset);
if (options_.show_location)
{
os << " " << Color(Color::Gray) << "@ " << FormatLocation(symbol.selection_range()) << Color(Color::Reset);
}
// Type-specific details
if constexpr (std::is_same_v<std::decay_t<decltype(data)>, Function>)
{
if (options_.show_details)
{
os << " " << Color(Color::BrightGreen) << "" << (data.return_type ? *data.return_type : "void") << Color(Color::Reset);
if (!data.parameters.empty())
{
os << " " << Color(Color::Dim) << "(";
for (size_t i = 0; i < data.parameters.size(); ++i)
{
const auto& p = data.parameters[i];
os << p.name;
if (p.type)
os << ":" << *p.type;
if (i + 1 < data.parameters.size())
os << ", ";
}
os << ")" << Color(Color::Reset);
}
}
}
else if constexpr (std::is_same_v<std::decay_t<decltype(data)>, Method>)
{
if (options_.show_details)
{
os << " " << Color(Color::Cyan) << "[" << AccessModifierToString(data.access) << "]" << Color(Color::Reset);
if (data.is_static)
os << " " << Color(Color::Yellow) << "static" << Color(Color::Reset);
if (data.return_type)
os << " " << Color(Color::BrightGreen) << "" << *data.return_type << Color(Color::Reset);
if (!data.parameters.empty())
{
os << " " << Color(Color::Dim) << "(";
for (size_t i = 0; i < data.parameters.size(); ++i)
{
const auto& p = data.parameters[i];
os << p.name;
if (p.type)
os << ":" << *p.type;
if (i + 1 < data.parameters.size())
os << ", ";
}
os << ")" << Color(Color::Reset);
}
}
}
else if constexpr (std::is_same_v<std::decay_t<decltype(data)>, Property>)
{
if (options_.show_details)
{
os << " " << Color(Color::Cyan) << "[" << AccessModifierToString(data.access) << "]" << Color(Color::Reset);
if (data.type)
os << " " << Color(Color::BrightGreen) << ":" << *data.type << Color(Color::Reset);
}
}
else if constexpr (std::is_same_v<std::decay_t<decltype(data)>, Field>)
{
if (options_.show_details)
{
os << " " << Color(Color::Cyan) << "[" << AccessModifierToString(data.access) << "]" << Color(Color::Reset);
if (data.type)
os << " " << Color(Color::BrightGreen) << ":" << *data.type << Color(Color::Reset);
if (data.is_static)
os << " " << Color(Color::Yellow) << "static" << Color(Color::Reset);
}
}
else if constexpr (std::is_same_v<std::decay_t<decltype(data)>, Variable>)
{
if (options_.show_details)
{
os << " " << Color(Color::Dim) << "(" << VariableScopeToString(data.storage) << ")" << Color(Color::Reset);
if (data.type)
os << " " << Color(Color::BrightGreen) << ":" << *data.type << Color(Color::Reset);
if (data.has_initializer)
os << " " << Color(Color::Gray) << "= ..." << Color(Color::Reset);
}
}
else if constexpr (std::is_same_v<std::decay_t<decltype(data)>, Constant>)
{
if (options_.show_details)
{
if (data.type)
os << " " << Color(Color::BrightGreen) << ":" << *data.type << Color(Color::Reset);
os << " " << Color(Color::Gray) << "= " << data.value << Color(Color::Reset);
}
}
os << "\n";
},
symbol.data());
}
void DebugPrinter::PrintSymbol(SymbolId id, std::ostream& os, int depth)
{
const auto* sym = table_.definition(id);
if (!sym)
{
os << Indent(depth) << "❓ Unknown symbol: " << id << "\n";
return;
}
PrintSymbolData(*sym, os, depth);
}
void DebugPrinter::PrintSymbolWithChildren(SymbolId id, const std::unordered_multimap<SymbolId, SymbolId>& children, std::ostream& os, int depth, int current_depth)
{
if (options_.max_depth >= 0 && current_depth > options_.max_depth)
return;
PrintSymbol(id, os, depth);
if (!options_.show_children)
return;
auto range = children.equal_range(id);
std::vector<SymbolId> child_list;
for (auto it = range.first; it != range.second; ++it)
{
child_list.push_back(it->second);
}
// Sort children by location for consistent output
std::sort(child_list.begin(), child_list.end(), [this](SymbolId a, SymbolId b) {
const auto* sym_a = table_.definition(a);
const auto* sym_b = table_.definition(b);
if (!sym_a || !sym_b)
return a < b;
auto loc_a = sym_a->selection_range();
auto loc_b = sym_b->selection_range();
if (loc_a.start_line != loc_b.start_line)
return loc_a.start_line < loc_b.start_line;
return loc_a.start_column < loc_b.start_column;
});
for (auto child_id : child_list)
{
PrintSymbolWithChildren(child_id, children, os, depth + 1, current_depth + 1);
}
}
void DebugPrinter::PrintSymbolTree(SymbolId id, std::ostream& os, int depth)
{
std::unordered_multimap<SymbolId, SymbolId> children;
for (const auto& [scope_id, scope] : table_.scopes().all_scopes())
{
if (scope.owner)
{
for (const auto& [_, sym_ids] : scope.symbols)
{
for (auto sym_id : sym_ids)
{
children.emplace(*scope.owner, sym_id);
}
}
}
}
PrintSymbolWithChildren(id, children, os, depth, 0);
}
void DebugPrinter::PrintSymbolList(std::ostream& os)
{
PrintHeader("Symbols", os);
auto all_defs = table_.all_definitions();
// Group symbols by their parent (class/namespace)
std::unordered_multimap<SymbolId, SymbolId> children;
std::unordered_set<SymbolId> has_parent;
for (const auto& [scope_id, scope] : table_.scopes().all_scopes())
{
if (scope.owner)
{
for (const auto& [_, sym_ids] : scope.symbols)
{
for (auto sym_id : sym_ids)
{
children.emplace(*scope.owner, sym_id);
has_parent.insert(sym_id);
}
}
}
}
// Find top-level symbols (no parent)
std::vector<const Symbol*> top_level;
for (const auto& ref : all_defs)
{
const auto& sym = ref.get();
if (has_parent.find(sym.id()) == has_parent.end())
{
top_level.push_back(&sym);
}
}
// Sort top-level symbols by location
std::sort(top_level.begin(), top_level.end(), [](const Symbol* a, const Symbol* b) {
auto loc_a = a->selection_range();
auto loc_b = b->selection_range();
if (loc_a.start_line != loc_b.start_line)
return loc_a.start_line < loc_b.start_line;
return loc_a.start_column < loc_b.start_column;
});
// Print each top-level symbol with its children
for (const auto* sym : top_level)
{
PrintSymbolWithChildren(sym->id(), children, os, 0, 0);
}
}
void DebugPrinter::PrintSymbolsByKind(SymbolKind kind, std::ostream& os)
{
PrintSubHeader("Symbols of kind: " + FormatSymbolKind(kind), os);
auto all_defs = table_.all_definitions();
for (const auto& ref : all_defs)
{
const auto& sym = ref.get();
if (sym.kind() == kind)
{
PrintSymbolData(sym, os, 0);
}
}
}
void DebugPrinter::PrintScope(ScopeId id, std::ostream& os, int depth)
{
const auto* scope = table_.scopes().scope(id);
if (!scope)
{
os << Indent(depth) << "❓ Unknown scope: " << id << "\n";
return;
}
os << Indent(depth) << "📁 " << FormatScopeKind(scope->kind)
<< " (id=" << id << ")";
if (scope->owner)
{
os << " owner=" << *scope->owner;
}
os << "\n";
for (const auto& [name, sym_ids] : scope->symbols)
{
for (auto sym_id : sym_ids)
{
os << Indent(depth + 1) << "" << name << " (id=" << sym_id << ")\n";
}
}
}
void DebugPrinter::PrintScopeTree(ScopeId id, std::ostream& os, int depth)
{
const auto& all_scopes = table_.scopes().all_scopes();
std::unordered_multimap<ScopeId, ScopeId> children;
for (const auto& [scope_id, scope] : all_scopes)
{
if (scope.parent)
{
children.emplace(*scope.parent, scope_id);
}
}
std::function<void(ScopeId, int)> dfs = [&](ScopeId sid, int d) {
PrintScope(sid, os, d);
auto range = children.equal_range(sid);
for (auto it = range.first; it != range.second; ++it)
{
dfs(it->second, d + 1);
}
};
dfs(id, depth);
}
void DebugPrinter::PrintScopeHierarchy(std::ostream& os)
{
PrintHeader("Scopes", os);
const auto& scopes = table_.scopes().all_scopes();
if (scopes.empty())
{
os << "No scopes available\n";
return;
}
auto global = table_.scopes().global_scope();
if (global == kInvalidScopeId && !scopes.empty())
{
global = scopes.begin()->first;
}
PrintScopeTree(global, os, 0);
}
void DebugPrinter::FindAndPrint(const std::string& name, std::ostream& os)
{
PrintHeader("Search: " + name, os);
auto matches = table_.FindSymbolsByName(name);
if (matches.empty())
{
os << "No symbols found matching \"" << name << "\"\n";
return;
}
for (auto id : matches)
{
PrintSymbol(id, os);
}
}
void DebugPrinter::FindAtLocation(const ast::Location& loc, std::ostream& os)
{
auto id = table_.FindSymbolAt(loc);
if (!id)
{
os << "No symbol found at location " << FormatLocation(loc) << "\n";
return;
}
PrintSymbol(*id, os);
}
void DebugPrinter::PrintOverview(std::ostream& os)
{
PrintHeader("Overview", os);
os << "Symbols: " << stats_.total_symbols << "\n";
os << "Scopes: " << stats_.total_scopes << "\n";
}
void DebugPrinter::PrintStatistics(std::ostream& os)
{
stats_.Print(os, options_.use_color);
}
void DebugPrinter::PrintAll(std::ostream& os)
{
PrintOverview(os);
PrintSymbolList(os);
PrintScopeHierarchy(os);
PrintStatistics(os);
}
// ==================== Free functions ====================
void Print(const SymbolTable& table, std::ostream& os)
{
DebugPrinter printer(table, PrintOptions::Default());
printer.PrintAll(os);
}
void PrintOverview(const SymbolTable& table, std::ostream& os)
{
DebugPrinter printer(table, PrintOptions::Default());
printer.PrintOverview(os);
}
void PrintStats(const SymbolTable& table, std::ostream& os)
{
DebugPrinter printer(table, PrintOptions::Default());
printer.PrintStatistics(os);
}
void PrintSymbolTree(const SymbolTable& table, std::ostream& os)
{
DebugPrinter printer(table, PrintOptions::Default());
auto defs = table.all_definitions();
for (const auto& ref : defs)
{
printer.PrintSymbolTree(ref.get().id(), os);
}
}
void PrintScopeTree(const SymbolTable& table, std::ostream& os)
{
DebugPrinter printer(table, PrintOptions::Default());
printer.PrintScopeHierarchy(os);
}
void Find(const SymbolTable& table, const std::string& name, std::ostream& os)
{
DebugPrinter printer(table, PrintOptions::Default());
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);
}
} // namespace lsp::language::symbol::debug
@@ -0,0 +1,474 @@
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<SymbolKind, std::size_t> symbol_counts;
std::unordered_map<ScopeKind, std::size_t> 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<SymbolId, SymbolId>& 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) << "<invalid symbol>\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);
}
}
@@ -1,115 +0,0 @@
#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include "../../src/language/symbol/table.hpp"
#include "../../src/protocol/protocol.hpp"
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; // 最大深度 (-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;
std::unordered_map<SymbolKind, size_t> symbol_counts;
std::unordered_map<ScopeKind, size_t> 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<SymbolId, SymbolId>& 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 lsp::language::symbol::debug
@@ -1,26 +1,15 @@
#include <algorithm>
#include <chrono>
#include <cctype>
#include <fstream>
#include <iostream>
#include <optional>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <ctime>
module;
extern "C" {
#include <tree_sitter/api.h>
}
export module lsp.test.symbol.main;
import std;
import tree_sitter;
import lsp.language.ast;
import lsp.language.symbol;
import lsp.test.symbol.debug_printer;
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;
// ==================== 文件读取 ====================