tsl-devkit/lsp-server/test/test_ast/debug_printer.cpp

1904 lines
53 KiB
C++

#include <sstream>
#include <cctype>
#include "./debug_printer.hpp"
namespace lsp::language::ast
{
// ===== 辅助函数实现 =====
const char* DebugPrinter::GetColor(const char* color) const
{
return options_.use_colors ? color : "";
}
void DebugPrinter::PrintColored(const std::string& text, const char* color)
{
os_ << GetColor(color) << text << GetColor(Color::Reset);
}
std::string DebugPrinter::GetIndent() const
{
return std::string(current_indent_, ' ');
}
void DebugPrinter::PrintIndent(bool is_last)
{
if (options_.use_tree_chars && current_indent_ > 0)
{
PrintTreePrefix(is_last);
}
else
{
os_ << GetIndent();
}
}
void DebugPrinter::PrintTreePrefix(bool is_last)
{
std::string prefix;
for (size_t i = 0; i < is_last_child_stack_.size(); ++i)
{
if (is_last_child_stack_[i])
{
prefix += " ";
}
else
{
prefix += "";
}
}
if (is_last)
{
prefix += "└── ";
}
else
{
prefix += "├── ";
}
os_ << GetColor(Color::Gray) << prefix << GetColor(Color::Reset);
}
std::string DebugPrinter::EscapeString(const std::string& str) const
{
std::string result;
for (char c : str)
{
switch (c)
{
case '\n':
result += "\\n";
break;
case '\r':
result += "\\r";
break;
case '\t':
result += "\\t";
break;
case '\\':
result += "\\\\";
break;
case '"':
result += "\\\"";
break;
default:
if (c >= 32 && c < 127)
result += c;
else
{
char buf[5];
snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
result += buf;
}
}
}
return result;
}
std::string DebugPrinter::TruncateString(const std::string& str, size_t max_len) const
{
if (str.length() <= max_len)
return str;
return str.substr(0, max_len - 3) + "...";
}
std::string DebugPrinter::GetSourceText(const Location& loc) const
{
if (!source_code_ || source_code_->empty())
return "";
size_t start = loc.start_byte;
size_t end = loc.end_byte;
if (start >= source_code_->length() || end > source_code_->length() || start >= end)
return "";
std::string text = source_code_->substr(start, end - start);
// 移除首尾空白
size_t first = text.find_first_not_of(" \t\n\r");
if (first == std::string::npos)
return "";
size_t last = text.find_last_not_of(" \t\n\r");
text = text.substr(first, last - first + 1);
// 压缩多个空白为单个空格
bool prev_space = false;
std::string result;
for (char c : text)
{
if (std::isspace(c))
{
if (!prev_space)
result += ' ';
prev_space = true;
}
else
{
result += c;
prev_space = false;
}
}
return TruncateString(result, options_.max_source_length);
}
void DebugPrinter::PrintLocation(const Location& loc)
{
if (!options_.show_location)
return;
os_ << GetColor(Color::Gray) << "@";
os_ << loc.start_line << ":" << loc.start_column;
if (loc.end_line != loc.start_line || loc.end_column != loc.start_column)
{
os_ << "-" << loc.end_line << ":" << loc.end_column;
}
os_ << GetColor(Color::Reset);
}
void DebugPrinter::PrintSourceSnippet(const Location& loc)
{
if (!options_.show_source_code)
return;
std::string source = GetSourceText(loc);
if (!source.empty())
{
os_ << " " << GetColor(Color::Dim) << "«" << source << "»" << GetColor(Color::Reset);
}
}
void DebugPrinter::PrintNodeHeader(const std::string& type_name, const Location& loc)
{
PrintIndent();
// 打印节点类型
PrintColored(type_name, Color::BrightCyan);
// 打印位置
if (options_.show_location || options_.show_source_code)
{
os_ << " ";
PrintLocation(loc);
PrintSourceSnippet(loc);
}
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const char* value_color)
{
if (options_.compact_mode && value.empty())
return;
PrintIndent();
PrintColored(key + ": ", Color::Yellow);
if (value_color)
PrintColored(value, value_color);
else
os_ << value;
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, int value)
{
PrintIndent();
PrintColored(key + ": ", Color::Yellow);
PrintColored(std::to_string(value), Color::BrightGreen);
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, bool value)
{
PrintIndent();
PrintColored(key + ": ", Color::Yellow);
PrintColored(value ? "true" : "false", value ? Color::Green : Color::Red);
os_ << "\n";
}
// ===== 打印主函数 =====
void DebugPrinter::Print(const ASTNode* node)
{
if (!node)
{
os_ << GetColor(Color::Red) << "(null)" << GetColor(Color::Reset) << "\n";
return;
}
const_cast<ASTNode*>(node)->Accept(*this);
}
void DebugPrinter::PrintStatements(const std::vector<StatementPtr>& statements)
{
for (size_t i = 0; i < statements.size(); ++i)
{
if (statements[i])
{
bool is_last = (i == statements.size() - 1);
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
statements[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
else
{
statements[i]->Accept(*this);
}
}
}
}
void DebugPrinter::PrintParseResult(const ParseResult& result)
{
// 打印头部
PrintColored("╔═══════════════════════════════════════════════════════════════\n", Color::BrightBlue);
PrintColored("", Color::BrightBlue);
PrintColored("AST Parse Result", Color::BrightCyan);
os_ << "\n";
PrintColored("╠═══════════════════════════════════════════════════════════════\n", Color::BrightBlue);
// 打印统计信息
if (result.root)
{
PrintColored("", Color::BrightBlue);
PrintColored("Statements: ", Color::Yellow);
PrintColored(std::to_string(result.root->statements.size()), Color::BrightGreen);
os_ << "\n";
}
PrintColored("", Color::BrightBlue);
PrintColored("Errors: ", Color::Yellow);
if (result.errors.empty())
{
PrintColored("0", Color::Green);
os_ << " ";
PrintColored("", Color::BrightGreen);
}
else
{
PrintColored(std::to_string(result.errors.size()), Color::BrightRed);
os_ << " ";
PrintColored("", Color::BrightRed);
}
os_ << "\n";
PrintColored("╚═══════════════════════════════════════════════════════════════\n", Color::BrightBlue);
// 打印错误
if (!result.errors.empty())
{
os_ << "\n";
PrintColored("Errors:\n", Color::BrightRed);
for (const auto& error : result.errors)
{
PrintError(error);
}
os_ << "\n";
}
// 打印AST
if (result.root)
{
os_ << "\n";
PrintColored("AST Tree:\n", Color::BrightCyan);
Print(result.root.get());
}
}
void DebugPrinter::PrintError(const ParseError& error)
{
PrintIndent();
// 错误级别
const char* severity_color = Color::Red;
std::string severity_text = "ERROR";
switch (error.severity)
{
case ErrorSeverity::Warning:
severity_color = Color::Yellow;
severity_text = "WARNING";
break;
case ErrorSeverity::Fatal:
severity_color = Color::BrightRed;
severity_text = "FATAL";
break;
default:
break;
}
PrintColored(severity_text, severity_color);
os_ << " ";
// 位置
PrintLocation(error.location);
os_ << " ";
// 消息
os_ << error.message << "\n";
}
void DebugPrinter::PrintExpression(const Expression* expr, const std::string& label, bool is_last)
{
if (!label.empty())
{
PrintIndent();
PrintColored(label + ":\n", Color::Yellow);
}
IncreaseIndent();
if (expr)
{
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
const_cast<Expression*>(expr)->Accept(*this);
is_last_child_stack_.pop_back();
}
else
{
const_cast<Expression*>(expr)->Accept(*this);
}
}
else
{
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
}
PrintIndent(is_last);
PrintColored("(null)", Color::Red);
os_ << "\n";
if (options_.use_tree_chars)
{
is_last_child_stack_.pop_back();
}
}
DecreaseIndent();
}
void DebugPrinter::PrintStatement(const Statement* stmt, const std::string& label, bool is_last)
{
if (!label.empty())
{
PrintIndent();
PrintColored(label + ":\n", Color::Yellow);
}
IncreaseIndent();
if (stmt)
{
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
const_cast<Statement*>(stmt)->Accept(*this);
is_last_child_stack_.pop_back();
}
else
{
const_cast<Statement*>(stmt)->Accept(*this);
}
}
else
{
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
}
PrintIndent(is_last);
PrintColored("(null)", Color::Red);
os_ << "\n";
if (options_.use_tree_chars)
{
is_last_child_stack_.pop_back();
}
}
DecreaseIndent();
}
void DebugPrinter::PrintSignature(const Signature& sig)
{
if (!sig.parameters.empty())
{
PrintIndent();
PrintColored("parameters", Color::Yellow);
PrintColored(" (" + std::to_string(sig.parameters.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < sig.parameters.size(); ++i)
{
bool is_last = (i == sig.parameters.size() - 1);
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
PrintParameter(sig.parameters[i], is_last);
is_last_child_stack_.pop_back();
}
else
{
PrintParameter(sig.parameters[i], is_last);
}
}
DecreaseIndent();
}
if (sig.return_type)
{
PrintKeyValue("return_type", *sig.return_type, Color::BrightMagenta);
}
}
void DebugPrinter::PrintParameter(const Parameter& param, bool is_last)
{
PrintIndent(is_last);
PrintColored(param.name, Color::BrightGreen);
if (param.is_var)
os_ << " " << GetColor(Color::Cyan) << "[var]" << GetColor(Color::Reset);
if (param.is_out)
os_ << " " << GetColor(Color::Cyan) << "[out]" << GetColor(Color::Reset);
if (param.type_name)
os_ << GetColor(Color::Gray) << ": " << GetColor(Color::BrightMagenta)
<< *param.type_name << GetColor(Color::Reset);
if (param.default_value)
{
os_ << " " << GetColor(Color::Gray) << "= " << GetColor(Color::Reset);
os_ << "..."; // 简化显示
}
os_ << "\n";
}
void DebugPrinter::PrintLeftHandSide(const LeftHandSide& lhs, const std::string& label, bool is_last)
{
if (!label.empty())
{
PrintIndent();
PrintColored(label + ":\n", Color::Yellow);
IncreaseIndent();
}
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
}
std::visit([this](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::unique_ptr<Identifier>> ||
std::is_same_v<T, std::unique_ptr<AttributeExpression>> ||
std::is_same_v<T, std::unique_ptr<SubscriptExpression>> ||
std::is_same_v<T, std::unique_ptr<UnpackPattern>> ||
std::is_same_v<T, std::unique_ptr<VarDeclaration>> ||
std::is_same_v<T, std::unique_ptr<StaticDeclaration>> ||
std::is_same_v<T, std::unique_ptr<GlobalDeclaration>> ||
std::is_same_v<T, std::unique_ptr<FieldDeclaration>>)
{
if (arg)
{
arg->Accept(*this);
}
else
{
PrintIndent();
PrintColored("(null)", Color::Red);
os_ << "\n";
}
}
},
lhs);
if (options_.use_tree_chars)
{
is_last_child_stack_.pop_back();
}
if (!label.empty())
{
DecreaseIndent();
}
}
// ===== 枚举打印实现 =====
void DebugPrinter::PrintOperator(BinaryOperator op)
{
PrintColored(GetBinaryOperatorSymbol(op), Color::BrightYellow);
}
void DebugPrinter::PrintOperator(UnaryOperator op)
{
const char* symbol = "";
switch (op)
{
case UnaryOperator::kPlus:
symbol = "+";
break;
case UnaryOperator::kMinus:
symbol = "-";
break;
case UnaryOperator::kNot:
symbol = "not";
break;
case UnaryOperator::kBitwiseNot:
symbol = ".!";
break;
case UnaryOperator::kDotNot:
symbol = ".!!";
break;
case UnaryOperator::kMatrixTranspose:
symbol = "`";
break;
case UnaryOperator::kDerivative:
symbol = "!";
break;
case UnaryOperator::kExprAt:
symbol = "@";
break;
case UnaryOperator::kExprRef:
symbol = "&";
break;
}
PrintColored(symbol, Color::BrightYellow);
}
void DebugPrinter::PrintOperator(AssignmentOperator op)
{
PrintColored(GetAssignmentOperatorSymbol(op), Color::BrightYellow);
}
void DebugPrinter::PrintLiteralKind(LiteralKind kind)
{
const char* kind_str = "";
const char* color = Color::Magenta;
switch (kind)
{
case LiteralKind::kNumber:
kind_str = "number";
break;
case LiteralKind::kString:
kind_str = "string";
color = Color::Green;
break;
case LiteralKind::kBoolean:
kind_str = "boolean";
break;
case LiteralKind::kNil:
kind_str = "nil";
color = Color::Gray;
break;
case LiteralKind::kInfinity:
kind_str = "infinity";
break;
case LiteralKind::kEllipsis:
kind_str = "ellipsis";
break;
}
PrintColored(kind_str, color);
}
void DebugPrinter::PrintAccessModifier(AccessModifier modifier)
{
const char* mod_str = "";
const char* color = Color::Cyan;
switch (modifier)
{
case AccessModifier::kPublic:
mod_str = "public";
break;
case AccessModifier::kProtected:
mod_str = "protected";
color = Color::Yellow;
break;
case AccessModifier::kPrivate:
mod_str = "private";
color = Color::Red;
break;
}
PrintColored(mod_str, color);
}
void DebugPrinter::PrintMethodModifier(MethodModifier modifier)
{
const char* mod_str = "";
switch (modifier)
{
case MethodModifier::kNone:
mod_str = "none";
break;
case MethodModifier::kVirtual:
mod_str = "virtual";
break;
case MethodModifier::kOverride:
mod_str = "override";
break;
case MethodModifier::kOverload:
mod_str = "overload";
break;
}
PrintColored(mod_str, Color::Magenta);
}
void DebugPrinter::PrintReferenceModifier(ReferenceModifier modifier)
{
const char* mod_str = "";
switch (modifier)
{
case ReferenceModifier::kNone:
mod_str = "none";
break;
case ReferenceModifier::kWeakRef:
mod_str = "weakref";
break;
case ReferenceModifier::kAutoRef:
mod_str = "autoref";
break;
}
PrintColored(mod_str, Color::Cyan);
}
// ===== Visitor 实现 =====
void DebugPrinter::VisitProgram(Program& node)
{
PrintNodeHeader("Program", node.location);
if (!node.statements.empty())
{
IncreaseIndent();
PrintIndent();
PrintColored("statements ", Color::Yellow);
PrintColored("(" + std::to_string(node.statements.size()) + "):\n", Color::Gray);
IncreaseIndent();
PrintStatements(node.statements);
DecreaseIndent();
DecreaseIndent();
}
}
void DebugPrinter::VisitIdentifier(Identifier& node)
{
PrintNodeHeader("Identifier", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightGreen);
DecreaseIndent();
}
void DebugPrinter::VisitLiteral(Literal& node)
{
PrintNodeHeader("Literal", node.location);
IncreaseIndent();
PrintIndent();
PrintColored("kind: ", Color::Yellow);
PrintLiteralKind(node.literal_kind);
os_ << "\n";
PrintIndent();
PrintColored("value: ", Color::Yellow);
if (node.literal_kind == LiteralKind::kString)
{
PrintColored("\"" + EscapeString(node.value) + "\"", Color::Green);
}
else
{
PrintColored(node.value, Color::BrightGreen);
}
os_ << "\n";
DecreaseIndent();
}
void DebugPrinter::VisitBinaryExpression(BinaryExpression& node)
{
PrintNodeHeader("BinaryExpression", node.location);
IncreaseIndent();
PrintIndent();
PrintColored("operator: ", Color::Yellow);
PrintOperator(node.op);
os_ << "\n";
PrintExpression(node.left.get(), "left", false);
PrintExpression(node.right.get(), "right", true);
DecreaseIndent();
}
void DebugPrinter::VisitComparisonExpression(ComparisonExpression& node)
{
PrintNodeHeader("ComparisonExpression", node.location);
IncreaseIndent();
PrintExpression(node.left.get(), "left", false);
if (!node.comparisons.empty())
{
PrintIndent();
PrintColored("comparisons ", Color::Yellow);
PrintColored("(" + std::to_string(node.comparisons.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.comparisons.size(); ++i)
{
const auto& comp = node.comparisons[i];
PrintIndent();
PrintColored("[" + std::to_string(i) + "] ", Color::Gray);
PrintOperator(comp.op);
os_ << "\n";
if (comp.right)
{
IncreaseIndent();
PrintExpression(comp.right.get());
DecreaseIndent();
}
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitUnaryExpression(UnaryExpression& node)
{
PrintNodeHeader("UnaryExpression", node.location);
IncreaseIndent();
PrintIndent();
PrintColored("operator: ", Color::Yellow);
PrintOperator(node.op);
os_ << "\n";
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitTernaryExpression(TernaryExpression& node)
{
PrintNodeHeader("TernaryExpression", node.location);
IncreaseIndent();
PrintExpression(node.condition.get(), "condition", false);
PrintExpression(node.consequence.get(), "consequence", false);
PrintExpression(node.alternative.get(), "alternative", true);
DecreaseIndent();
}
void DebugPrinter::VisitCallExpression(CallExpression& node)
{
PrintNodeHeader("CallExpression", node.location);
IncreaseIndent();
bool has_arguments = !node.arguments.empty();
PrintExpression(node.callee.get(), "callee", !has_arguments);
if (has_arguments)
{
PrintIndent();
PrintColored("arguments ", Color::Yellow);
PrintColored("(" + std::to_string(node.arguments.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.arguments.size(); ++i)
{
const auto& arg = node.arguments[i];
bool is_last = (i == node.arguments.size() - 1);
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
}
PrintIndent(is_last);
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
if (arg.name)
{
os_ << " " << GetColor(Color::Yellow) << *arg.name << GetColor(Color::Reset) << ":";
}
if (arg.is_spread)
{
os_ << " " << GetColor(Color::Magenta) << "..." << GetColor(Color::Reset);
}
os_ << "\n";
if (arg.value)
{
IncreaseIndent();
arg.value->Accept(*this);
DecreaseIndent();
}
if (options_.use_tree_chars)
{
is_last_child_stack_.pop_back();
}
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitAttributeExpression(AttributeExpression& node)
{
PrintNodeHeader("AttributeExpression", node.location);
IncreaseIndent();
PrintExpression(node.object.get(), "object", false);
PrintKeyValue("attribute", node.attribute, Color::BrightGreen);
DecreaseIndent();
}
void DebugPrinter::VisitSubscriptExpression(SubscriptExpression& node)
{
PrintNodeHeader("SubscriptExpression", node.location);
IncreaseIndent();
PrintExpression(node.value.get(), "value");
if (!node.indices.empty())
{
PrintIndent();
PrintColored("indices ", Color::Yellow);
PrintColored("(" + std::to_string(node.indices.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.indices.size(); ++i)
{
const auto& idx = node.indices[i];
PrintIndent();
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
if (idx.is_slice)
{
os_ << " " << GetColor(Color::Cyan) << "[slice]" << GetColor(Color::Reset);
}
if (idx.is_empty_slice)
{
os_ << " " << GetColor(Color::Cyan) << "[empty]" << GetColor(Color::Reset);
}
os_ << "\n";
IncreaseIndent();
if (idx.start)
{
PrintExpression(idx.start.get(), "start");
}
if (idx.end)
{
PrintExpression(idx.end.get(), "end");
}
if (idx.step)
{
PrintExpression(idx.step.get(), "step");
}
DecreaseIndent();
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitArrayExpression(ArrayExpression& node)
{
PrintNodeHeader("ArrayExpression", node.location);
IncreaseIndent();
if (!node.elements.empty())
{
PrintIndent();
PrintColored("elements ", Color::Yellow);
PrintColored("(" + std::to_string(node.elements.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.elements.size(); ++i)
{
const auto& elem = node.elements[i];
PrintIndent();
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
if (elem.is_nested)
{
os_ << " " << GetColor(Color::Cyan) << "[nested]" << GetColor(Color::Reset);
}
os_ << "\n";
IncreaseIndent();
if (elem.key)
{
PrintExpression(elem.key.get(), "key");
}
if (elem.value)
{
PrintExpression(elem.value.get(), "value");
}
DecreaseIndent();
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node)
{
PrintNodeHeader("AnonymousFunction", node.location);
IncreaseIndent();
PrintSignature(node.signature);
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
PrintStatement(node.body.get(), "body", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitPrefixIncrementExpression(PrefixIncrementExpression& node)
{
PrintNodeHeader("PrefixIncrement", node.location);
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitPrefixDecrementExpression(PrefixDecrementExpression& node)
{
PrintNodeHeader("PrefixDecrement", node.location);
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitPostfixIncrementExpression(PostfixIncrementExpression& node)
{
PrintNodeHeader("PostfixIncrement", node.location);
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitPostfixDecrementExpression(PostfixDecrementExpression& node)
{
PrintNodeHeader("PostfixDecrement", node.location);
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitFunctionPointerExpression(FunctionPointerExpression& node)
{
PrintNodeHeader("FunctionPointer", node.location);
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitAssignmentExpression(AssignmentExpression& node)
{
PrintNodeHeader("AssignmentExpression", node.location);
IncreaseIndent();
PrintIndent();
PrintColored("operator: ", Color::Yellow);
PrintOperator(node.op);
os_ << "\n";
PrintLeftHandSide(node.left, "left", false);
PrintExpression(node.right.get(), "right", true);
DecreaseIndent();
}
void DebugPrinter::VisitExpressionStatement(ExpressionStatement& node)
{
PrintNodeHeader("ExpressionStatement", node.location);
IncreaseIndent();
PrintExpression(node.expression.get(), "", true);
DecreaseIndent();
}
void DebugPrinter::VisitVarStatement(VarStatement& node)
{
PrintNodeHeader("VarStatement", node.location);
IncreaseIndent();
if (!node.declarations.empty())
{
PrintIndent();
PrintColored("declarations ", Color::Yellow);
PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.declarations.size(); ++i)
{
bool is_last = (i == node.declarations.size() - 1);
if (node.declarations[i])
{
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
node.declarations[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
else
{
node.declarations[i]->Accept(*this);
}
}
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitStaticStatement(StaticStatement& node)
{
PrintNodeHeader("StaticStatement", node.location);
IncreaseIndent();
if (!node.declarations.empty())
{
PrintIndent();
PrintColored("declarations ", Color::Yellow);
PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.declarations.size(); ++i)
{
bool is_last = (i == node.declarations.size() - 1);
if (node.declarations[i])
{
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
node.declarations[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
else
{
node.declarations[i]->Accept(*this);
}
}
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitGlobalStatement(GlobalStatement& node)
{
PrintNodeHeader("GlobalStatement", node.location);
IncreaseIndent();
if (!node.declarations.empty())
{
PrintIndent();
PrintColored("declarations ", Color::Yellow);
PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.declarations.size(); ++i)
{
bool is_last = (i == node.declarations.size() - 1);
if (node.declarations[i])
{
if (options_.use_tree_chars)
{
is_last_child_stack_.push_back(is_last);
node.declarations[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
else
{
node.declarations[i]->Accept(*this);
}
}
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitConstStatement(ConstStatement& node)
{
PrintNodeHeader("ConstStatement", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightGreen);
if (node.type_name)
{
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
}
if (node.value)
{
PrintExpression(node.value.get(), "value", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitAssignmentStatement(AssignmentStatement& node)
{
PrintNodeHeader("AssignmentStatement", node.location);
IncreaseIndent();
PrintIndent();
PrintColored("operator: ", Color::Yellow);
PrintOperator(node.op);
os_ << "\n";
PrintLeftHandSide(node.left, "left", false);
PrintExpression(node.right.get(), "right", true);
DecreaseIndent();
}
void DebugPrinter::VisitBlockStatement(BlockStatement& node)
{
PrintNodeHeader("BlockStatement", node.location);
if (!node.statements.empty())
{
IncreaseIndent();
PrintStatements(node.statements);
DecreaseIndent();
}
}
void DebugPrinter::VisitIfStatement(IfStatement& node)
{
PrintNodeHeader("IfStatement", node.location);
IncreaseIndent();
if (!node.branches.empty())
{
PrintIndent();
PrintColored("branches ", Color::Yellow);
PrintColored("(" + std::to_string(node.branches.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.branches.size(); ++i)
{
const auto& branch = node.branches[i];
PrintIndent();
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
os_ << "\n";
IncreaseIndent();
if (branch.condition)
{
PrintExpression(branch.condition.get(), "condition");
}
if (branch.body)
{
PrintStatement(branch.body.get(), "body");
}
DecreaseIndent();
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitForInStatement(ForInStatement& node)
{
PrintNodeHeader("ForInStatement", node.location);
IncreaseIndent();
if (!node.key.empty())
{
PrintKeyValue("key", node.key, Color::BrightGreen);
}
if (!node.value.empty())
{
PrintKeyValue("value", node.value, Color::BrightGreen);
}
PrintExpression(node.collection.get(), "collection", false);
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitForToStatement(ForToStatement& node)
{
PrintNodeHeader("ForToStatement", node.location);
IncreaseIndent();
PrintKeyValue("counter", node.counter, Color::BrightGreen);
if (node.is_downto)
{
PrintKeyValue("direction", "downto", Color::Cyan);
}
PrintExpression(node.start.get(), "start", false);
PrintExpression(node.end.get(), "end", false);
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitWhileStatement(WhileStatement& node)
{
PrintNodeHeader("WhileStatement", node.location);
IncreaseIndent();
PrintExpression(node.condition.get(), "condition", false);
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitRepeatStatement(RepeatStatement& node)
{
PrintNodeHeader("RepeatStatement", node.location);
IncreaseIndent();
if (!node.body.empty())
{
PrintIndent();
PrintColored("body ", Color::Yellow);
PrintColored("(" + std::to_string(node.body.size()) + "):\n", Color::Gray);
IncreaseIndent();
PrintStatements(node.body);
DecreaseIndent();
}
PrintExpression(node.condition.get(), "condition", true);
DecreaseIndent();
}
void DebugPrinter::VisitCaseStatement(CaseStatement& node)
{
PrintNodeHeader("CaseStatement", node.location);
IncreaseIndent();
PrintExpression(node.discriminant.get(), "discriminant");
if (!node.branches.empty())
{
PrintIndent();
PrintColored("branches ", Color::Yellow);
PrintColored("(" + std::to_string(node.branches.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (size_t i = 0; i < node.branches.size(); ++i)
{
const auto& branch = node.branches[i];
PrintIndent();
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
os_ << "\n";
IncreaseIndent();
if (!branch.values.empty())
{
PrintIndent();
PrintColored("values ", Color::Yellow);
PrintColored("(" + std::to_string(branch.values.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (const auto& val : branch.values)
{
if (val)
val->Accept(*this);
}
DecreaseIndent();
}
if (branch.body)
{
PrintStatement(branch.body.get(), "body");
}
DecreaseIndent();
}
DecreaseIndent();
}
if (node.default_case)
{
PrintStatement(node.default_case.get(), "default_case");
}
DecreaseIndent();
}
void DebugPrinter::VisitTryStatement(TryStatement& node)
{
PrintNodeHeader("TryStatement", node.location);
IncreaseIndent();
if (node.try_body)
{
PrintStatement(node.try_body.get(), "try_body");
}
if (node.except_body)
{
PrintStatement(node.except_body.get(), "except_body");
}
DecreaseIndent();
}
void DebugPrinter::VisitBreakStatement(BreakStatement& node)
{
PrintNodeHeader("BreakStatement", node.location);
}
void DebugPrinter::VisitContinueStatement(ContinueStatement& node)
{
PrintNodeHeader("ContinueStatement", node.location);
}
void DebugPrinter::VisitReturnStatement(ReturnStatement& node)
{
PrintNodeHeader("ReturnStatement", node.location);
if (node.value)
{
IncreaseIndent();
PrintExpression(node.value.get(), "value", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitUsesStatement(UsesStatement& node)
{
PrintNodeHeader("UsesStatement", node.location);
IncreaseIndent();
if (!node.units.empty())
{
PrintIndent();
PrintColored("units: ", Color::Yellow);
os_ << "[";
for (size_t i = 0; i < node.units.size(); ++i)
{
if (i > 0)
os_ << ", ";
PrintColored(node.units[i], Color::BrightGreen);
}
os_ << "]\n";
}
DecreaseIndent();
}
void DebugPrinter::VisitFunctionDefinition(FunctionDefinition& node)
{
PrintNodeHeader("FunctionDefinition", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightCyan);
if (node.is_overload)
{
PrintKeyValue("overload", true);
}
PrintSignature(node.signature);
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitFunctionDeclaration(FunctionDeclaration& node)
{
PrintNodeHeader("FunctionDeclaration", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightCyan);
if (node.is_overload)
{
PrintKeyValue("overload", true);
}
PrintSignature(node.signature);
DecreaseIndent();
}
void DebugPrinter::VisitVarDeclaration(VarDeclaration& node)
{
PrintNodeHeader("VarDeclaration", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightGreen);
if (node.type_name)
{
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
}
if (node.initial_value)
{
PrintExpression(node.initial_value.get(), "initial_value");
}
DecreaseIndent();
}
void DebugPrinter::VisitStaticDeclaration(StaticDeclaration& node)
{
PrintNodeHeader("StaticDeclaration", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightGreen);
if (node.reference_modifier != ReferenceModifier::kNone)
{
PrintIndent();
PrintColored("reference: ", Color::Yellow);
PrintReferenceModifier(node.reference_modifier);
os_ << "\n";
}
if (node.type_name)
{
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
}
if (node.initial_value)
{
PrintExpression(node.initial_value.get(), "initial_value");
}
DecreaseIndent();
}
void DebugPrinter::VisitGlobalDeclaration(GlobalDeclaration& node)
{
PrintNodeHeader("GlobalDeclaration", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightGreen);
if (node.type_name)
{
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
}
if (node.initial_value)
{
PrintExpression(node.initial_value.get(), "initial_value");
}
DecreaseIndent();
}
void DebugPrinter::VisitFieldDeclaration(FieldDeclaration& node)
{
PrintNodeHeader("FieldDeclaration", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightGreen);
if (node.reference_modifier != ReferenceModifier::kNone)
{
PrintIndent();
PrintColored("reference: ", Color::Yellow);
PrintReferenceModifier(node.reference_modifier);
os_ << "\n";
}
if (node.type_name)
{
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
}
if (node.initial_value)
{
PrintExpression(node.initial_value.get(), "initial_value");
}
DecreaseIndent();
}
void DebugPrinter::VisitUnpackPattern(UnpackPattern& node)
{
PrintNodeHeader("UnpackPattern", node.location);
IncreaseIndent();
if (!node.names.empty())
{
PrintIndent();
PrintColored("names: ", Color::Yellow);
os_ << "[";
for (size_t i = 0; i < node.names.size(); ++i)
{
if (i > 0)
os_ << ", ";
PrintColored(node.names[i], Color::BrightGreen);
}
os_ << "]\n";
}
DecreaseIndent();
}
void DebugPrinter::VisitClassDefinition(ClassDefinition& node)
{
PrintNodeHeader("ClassDefinition", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightCyan);
if (!node.parent_classes.empty())
{
PrintIndent();
PrintColored("parents: ", Color::Yellow);
os_ << "[";
for (size_t i = 0; i < node.parent_classes.size(); ++i)
{
if (i > 0)
os_ << ", ";
PrintColored(node.parent_classes[i], Color::BrightCyan);
}
os_ << "]\n";
}
if (!node.members.empty())
{
PrintIndent();
PrintColored("members ", Color::Yellow);
PrintColored("(" + std::to_string(node.members.size()) + "):\n", Color::Gray);
IncreaseIndent();
for (const auto& member : node.members)
{
if (member)
member->Accept(*this);
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitClassMember(ClassMember& node)
{
PrintNodeHeader("ClassMember", node.location);
IncreaseIndent();
PrintIndent();
PrintColored("access: ", Color::Yellow);
PrintAccessModifier(node.access_modifier);
os_ << "\n";
std::visit([this](auto&& member) {
if (member)
{
member->Accept(*this);
}
},
node.member);
DecreaseIndent();
}
void DebugPrinter::VisitMethodDeclaration(MethodDeclaration& node)
{
PrintNodeHeader("MethodDeclaration", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightCyan);
if (node.method_type == MethodType::kConstructor)
{
PrintKeyValue("type", "constructor", Color::Magenta);
}
else if (node.method_type == MethodType::kDestructor)
{
PrintKeyValue("type", "destructor", Color::Magenta);
}
if (node.is_class_method)
{
PrintKeyValue("class_method", true);
}
if (node.is_operator_overload)
{
PrintKeyValue("operator", node.operator_symbol, Color::BrightYellow);
}
if (node.modifier != MethodModifier::kNone)
{
PrintIndent();
PrintColored("modifier: ", Color::Yellow);
PrintMethodModifier(node.modifier);
os_ << "\n";
}
PrintSignature(node.signature);
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitPropertyDeclaration(PropertyDeclaration& node)
{
PrintNodeHeader("PropertyDeclaration", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightCyan);
if (node.type_name)
{
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
}
if (node.index_value)
{
PrintKeyValue("index", *node.index_value);
}
if (node.read_accessor)
{
PrintKeyValue("read", *node.read_accessor, Color::Green);
}
if (node.write_accessor)
{
PrintKeyValue("write", *node.write_accessor, Color::Green);
}
DecreaseIndent();
}
void DebugPrinter::VisitExternalMethodDefinition(ExternalMethodDefinition& node)
{
PrintNodeHeader("ExternalMethodDefinition", node.location);
IncreaseIndent();
PrintKeyValue("class", node.owner_class, Color::BrightCyan);
PrintKeyValue("method", node.name, Color::BrightCyan);
if (node.method_type == MethodType::kConstructor)
{
PrintKeyValue("type", "constructor", Color::Magenta);
}
else if (node.method_type == MethodType::kDestructor)
{
PrintKeyValue("type", "destructor", Color::Magenta);
}
if (node.is_class_method)
{
PrintKeyValue("class_method", true);
}
if (node.is_operator_overload)
{
PrintKeyValue("operator", node.operator_symbol, Color::BrightYellow);
}
if (node.modifier != MethodModifier::kNone)
{
PrintIndent();
PrintColored("modifier: ", Color::Yellow);
PrintMethodModifier(node.modifier);
os_ << "\n";
}
PrintSignature(node.signature);
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitUnitDefinition(UnitDefinition& node)
{
PrintNodeHeader("UnitDefinition", node.location);
IncreaseIndent();
PrintKeyValue("name", node.name, Color::BrightCyan);
if (!node.interface_statements.empty())
{
PrintIndent();
PrintColored("interface ", Color::Yellow);
PrintColored("(" + std::to_string(node.interface_statements.size()) + "):\n", Color::Gray);
IncreaseIndent();
PrintStatements(node.interface_statements);
DecreaseIndent();
}
if (!node.implementation_statements.empty())
{
PrintIndent();
PrintColored("implementation ", Color::Yellow);
PrintColored("(" + std::to_string(node.implementation_statements.size()) + "):\n", Color::Gray);
IncreaseIndent();
PrintStatements(node.implementation_statements);
DecreaseIndent();
}
if (!node.initialization_statements.empty())
{
PrintIndent();
PrintColored("initialization ", Color::Yellow);
PrintColored("(" + std::to_string(node.initialization_statements.size()) + "):\n", Color::Gray);
IncreaseIndent();
PrintStatements(node.initialization_statements);
DecreaseIndent();
}
if (!node.finalization_statements.empty())
{
PrintIndent();
PrintColored("finalization ", Color::Yellow);
PrintColored("(" + std::to_string(node.finalization_statements.size()) + "):\n", Color::Gray);
IncreaseIndent();
PrintStatements(node.finalization_statements);
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitTSSQLExpression(TSSQLExpression& node)
{
PrintNodeHeader("TSSQLExpression", node.location);
IncreaseIndent();
const char* type_str = "";
switch (node.sql_type)
{
case TSSQLExpressionType::kSelect:
type_str = "SELECT";
break;
case TSSQLExpressionType::kSSelect:
type_str = "SSELECT";
break;
case TSSQLExpressionType::kVSelect:
type_str = "VSELECT";
break;
case TSSQLExpressionType::kMSelect:
type_str = "MSELECT";
break;
case TSSQLExpressionType::kUpdate:
type_str = "UPDATE";
break;
case TSSQLExpressionType::kDelete:
type_str = "DELETE";
break;
case TSSQLExpressionType::kInsert:
type_str = "INSERT";
break;
}
PrintKeyValue("sql_type", type_str, Color::BrightMagenta);
PrintKeyValue("raw_sql", node.raw_sql, Color::Green);
DecreaseIndent();
}
// ===== 便捷函数实现 =====
std::string DebugString(const ASTNode* node, const PrintOptions& opts)
{
std::ostringstream oss;
DebugPrinter printer(oss, opts);
printer.Print(node);
return oss.str();
}
std::string DebugString(const ParseResult& result, const PrintOptions& opts)
{
std::ostringstream oss;
DebugPrinter printer(oss, opts);
printer.PrintParseResult(result);
return oss.str();
}
void DebugPrint(const ASTNode* node, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
printer.Print(node);
}
void DebugPrint(const ParseResult& result, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
printer.PrintParseResult(result);
}
void DebugPrint(const ASTNode* node, const std::string& source, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
printer.SetSourceCode(&source);
printer.Print(node);
}
void DebugPrint(const ParseResult& result, const std::string& source, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
printer.SetSourceCode(&source);
printer.PrintParseResult(result);
}
}