♻️ 重构符号表相关内容
🚀 优化`ast`相关代码
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include "../../src/language/ast/types.hpp"
|
||||
#include "../../src/language/ast/deserializer.hpp"
|
||||
|
||||
@@ -188,6 +189,7 @@ namespace lsp::language::ast::debug
|
||||
void PrintIndent(std::optional<bool> is_last = std::nullopt);
|
||||
void PrintTreePrefix(bool is_last = false);
|
||||
std::string GetIndent() const;
|
||||
void EmitChildren(std::vector<std::function<void(bool)>>&& children);
|
||||
|
||||
// 颜色辅助
|
||||
const char* GetColor(const char* color) const;
|
||||
@@ -196,11 +198,11 @@ namespace lsp::language::ast::debug
|
||||
// 节点信息输出
|
||||
void PrintNodeHeader(const std::string& type_name, const Location& loc);
|
||||
void PrintLocation(const Location& loc);
|
||||
void PrintSourceSnippet(const Location& loc);
|
||||
void PrintKeyValue(const std::string& key, const std::string& value, const Location& location, const char* value_color);
|
||||
void PrintKeyValue(const std::string& key, const std::string& value, const char* value_color = nullptr);
|
||||
void PrintKeyValue(const std::string& key, int value);
|
||||
void PrintKeyValue(const std::string& key, bool value);
|
||||
void PrintSourceSnippet(const Location& loc, bool is_last_child);
|
||||
void PrintKeyValue(const std::string& key, const std::string& value, const Location& location, const char* value_color, std::optional<bool> is_last = std::nullopt);
|
||||
void PrintKeyValue(const std::string& key, const std::string& value, const char* value_color = nullptr, std::optional<bool> is_last = std::nullopt);
|
||||
void PrintKeyValue(const std::string& key, int value, std::optional<bool> is_last = std::nullopt);
|
||||
void PrintKeyValue(const std::string& key, bool value, std::optional<bool> is_last = std::nullopt);
|
||||
|
||||
// 表达式和语句打印
|
||||
void PrintExpression(const Expression* expr, const std::string& label = "", bool is_last = false);
|
||||
|
||||
@@ -68,17 +68,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
set(SOURCES
|
||||
./test.cpp
|
||||
./debug_printer.cpp
|
||||
../../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/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/scanner.c
|
||||
../../src/tree-sitter/parser.c)
|
||||
|
||||
@@ -104,4 +98,3 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
$<$<CONFIG:Release>:-O3>
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,39 +2,11 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#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";
|
||||
}
|
||||
|
||||
// ==================== 打印选项 ====================
|
||||
|
||||
@@ -134,32 +106,21 @@ namespace lsp::language::symbol::debug
|
||||
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,8 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cctype>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
|
||||
extern "C" {
|
||||
#include <tree_sitter/api.h>
|
||||
@@ -256,17 +263,28 @@ 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::kVarDeclaration: return "VarDeclaration";
|
||||
case ast::NodeKind::kConstDeclaration: return "ConstDeclaration";
|
||||
case ast::NodeKind::kIfStatement: return "IfStatement";
|
||||
case ast::NodeKind::kForInStatement: return "ForInStatement";
|
||||
case ast::NodeKind::kWhileStatement: return "WhileStatement";
|
||||
// ... 添加其他类型
|
||||
default: return "Unknown";
|
||||
case ast::NodeKind::kProgram:
|
||||
return "Program";
|
||||
case ast::NodeKind::kFunctionDefinition:
|
||||
return "FunctionDefinition";
|
||||
case ast::NodeKind::kFunctionDeclaration:
|
||||
return "FunctionDeclaration";
|
||||
case ast::NodeKind::kClassDefinition:
|
||||
return "ClassDefinition";
|
||||
case ast::NodeKind::kUnitDefinition:
|
||||
return "UnitDefinition";
|
||||
case ast::NodeKind::kVarDeclaration:
|
||||
return "VarDeclaration";
|
||||
case ast::NodeKind::kConstDeclaration:
|
||||
return "ConstDeclaration";
|
||||
case ast::NodeKind::kIfStatement:
|
||||
return "IfStatement";
|
||||
case ast::NodeKind::kForInStatement:
|
||||
return "ForInStatement";
|
||||
case ast::NodeKind::kWhileStatement:
|
||||
return "WhileStatement";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,11 +302,9 @@ void PrintASTStructure(const ast::ParseResult& parse_result, std::ostream& os)
|
||||
if (!stmt)
|
||||
continue;
|
||||
|
||||
// 修复:使用 kind 和 span
|
||||
os << "[" << i << "] " << NodeKindToString(stmt->kind)
|
||||
<< " at [" << stmt->span.start_line << ":" << stmt->span.start_column << "]";
|
||||
|
||||
// 打印特定类型的详细信息
|
||||
if (auto* func_def = dynamic_cast<ast::FunctionDefinition*>(stmt.get()))
|
||||
{
|
||||
os << " - Function: " << func_def->name;
|
||||
@@ -308,11 +324,591 @@ void PrintASTStructure(const ast::ParseResult& parse_result, std::ostream& os)
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
// ==================== 符号表构建器 ====================
|
||||
|
||||
class SymbolBuilder
|
||||
{
|
||||
public:
|
||||
explicit SymbolBuilder(symbol::SymbolTable& table) : table_(table) {}
|
||||
|
||||
void Build(const ast::Program& program)
|
||||
{
|
||||
EnterScope(symbol::ScopeKind::kGlobal, program.span, std::nullopt);
|
||||
|
||||
for (const auto& stmt : program.statements)
|
||||
{
|
||||
HandleStatement(stmt);
|
||||
}
|
||||
|
||||
LeaveScope();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string ToLower(std::string s)
|
||||
{
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
|
||||
return s;
|
||||
}
|
||||
|
||||
std::optional<std::string> ExtractTypeName(const std::optional<ast::TypeAnnotation>& type) const
|
||||
{
|
||||
if (type)
|
||||
return type->name;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<symbol::Parameter> BuildParameters(const std::vector<std::unique_ptr<ast::Parameter>>& parameters) const
|
||||
{
|
||||
std::vector<symbol::Parameter> result;
|
||||
result.reserve(parameters.size());
|
||||
|
||||
for (const auto& param : parameters)
|
||||
{
|
||||
if (!param)
|
||||
continue;
|
||||
|
||||
symbol::Parameter p;
|
||||
p.name = param->name;
|
||||
if (param->type)
|
||||
{
|
||||
p.type = param->type->name;
|
||||
}
|
||||
if (param->default_value)
|
||||
{
|
||||
p.default_value = "<expr>";
|
||||
}
|
||||
result.push_back(std::move(p));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
symbol::SymbolId AddSymbol(symbol::Symbol symbol, const std::string& name)
|
||||
{
|
||||
auto id = table_.CreateSymbol(std::move(symbol));
|
||||
auto scope = CurrentScope();
|
||||
if (scope != symbol::kInvalidScopeId)
|
||||
{
|
||||
table_.AddSymbolToScope(scope, name, id);
|
||||
}
|
||||
name_index_[ToLower(name)] = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
void EnterScope(symbol::ScopeKind kind, const ast::Location& range, std::optional<symbol::SymbolId> owner)
|
||||
{
|
||||
std::optional<symbol::ScopeId> parent_scope = std::nullopt;
|
||||
if (!scope_stack_.empty())
|
||||
{
|
||||
parent_scope = scope_stack_.back();
|
||||
}
|
||||
auto id = table_.CreateScope(kind, range, parent_scope, owner);
|
||||
if (owner)
|
||||
{
|
||||
scope_by_owner_[*owner] = id;
|
||||
}
|
||||
scope_stack_.push_back(id);
|
||||
}
|
||||
|
||||
void LeaveScope()
|
||||
{
|
||||
if (!scope_stack_.empty())
|
||||
{
|
||||
scope_stack_.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
symbol::ScopeId CurrentScope() const
|
||||
{
|
||||
return scope_stack_.empty() ? symbol::kInvalidScopeId : scope_stack_.back();
|
||||
}
|
||||
|
||||
void HandleStatement(const ast::StatementPtr& stmt)
|
||||
{
|
||||
if (!stmt)
|
||||
return;
|
||||
|
||||
switch (stmt->kind)
|
||||
{
|
||||
case ast::NodeKind::kFunctionDefinition:
|
||||
HandleFunctionDefinition(*static_cast<ast::FunctionDefinition*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kFunctionDeclaration:
|
||||
HandleFunctionDeclaration(*static_cast<ast::FunctionDeclaration*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kMethodDeclaration:
|
||||
HandleMethodDeclaration(*static_cast<ast::MethodDeclaration*>(stmt.get()), std::nullopt, ast::AccessModifier::kPublic);
|
||||
break;
|
||||
case ast::NodeKind::kPropertyDeclaration:
|
||||
HandlePropertyDeclaration(*static_cast<ast::PropertyDeclaration*>(stmt.get()), std::nullopt, ast::AccessModifier::kPublic);
|
||||
break;
|
||||
case ast::NodeKind::kClassDefinition:
|
||||
HandleClassDefinition(*static_cast<ast::ClassDefinition*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kUnitDefinition:
|
||||
HandleUnitDefinition(*static_cast<ast::UnitDefinition*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kVarDeclaration:
|
||||
HandleVariable(*static_cast<ast::VarDeclaration*>(stmt.get()), symbol::VariableScope::kAutomatic);
|
||||
break;
|
||||
case ast::NodeKind::kStaticDeclaration:
|
||||
HandleStatic(*static_cast<ast::StaticDeclaration*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kGlobalDeclaration:
|
||||
HandleGlobalDeclaration(*static_cast<ast::GlobalDeclaration*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kConstDeclaration:
|
||||
HandleConstant(*static_cast<ast::ConstDeclaration*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kExternalMethodDefinition:
|
||||
HandleExternalMethod(*static_cast<ast::ExternalMethodDefinition*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kBlockStatement:
|
||||
HandleBlock(*static_cast<ast::BlockStatement*>(stmt.get()), true);
|
||||
break;
|
||||
case ast::NodeKind::kIfStatement:
|
||||
HandleIfStatement(*static_cast<ast::IfStatement*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kForInStatement:
|
||||
HandleForInStatement(*static_cast<ast::ForInStatement*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kForToStatement:
|
||||
HandleForToStatement(*static_cast<ast::ForToStatement*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kWhileStatement:
|
||||
HandleWhileStatement(*static_cast<ast::WhileStatement*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kRepeatStatement:
|
||||
HandleRepeatStatement(*static_cast<ast::RepeatStatement*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kCaseStatement:
|
||||
HandleCaseStatement(*static_cast<ast::CaseStatement*>(stmt.get()));
|
||||
break;
|
||||
case ast::NodeKind::kTryStatement:
|
||||
HandleTryStatement(*static_cast<ast::TryStatement*>(stmt.get()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleFunctionDeclaration(ast::FunctionDeclaration& node)
|
||||
{
|
||||
symbol::Function fn;
|
||||
fn.name = node.name;
|
||||
fn.selection_range = node.span;
|
||||
fn.range = node.span;
|
||||
fn.declaration_range = node.span;
|
||||
fn.parameters = BuildParameters(node.parameters);
|
||||
fn.return_type = ExtractTypeName(node.return_type);
|
||||
|
||||
AddSymbol(symbol::Symbol(std::move(fn)), node.name);
|
||||
}
|
||||
|
||||
void HandleFunctionDefinition(ast::FunctionDefinition& node)
|
||||
{
|
||||
symbol::Function fn;
|
||||
fn.name = node.name;
|
||||
fn.selection_range = node.location;
|
||||
fn.range = node.span;
|
||||
fn.declaration_range = node.location;
|
||||
fn.implementation_range = node.location;
|
||||
fn.parameters = BuildParameters(node.parameters);
|
||||
fn.return_type = ExtractTypeName(node.return_type);
|
||||
|
||||
auto fn_id = AddSymbol(symbol::Symbol(std::move(fn)), node.name);
|
||||
|
||||
if (node.body)
|
||||
{
|
||||
EnterScope(symbol::ScopeKind::kFunction, node.body->span, fn_id);
|
||||
for (const auto& param : node.parameters)
|
||||
{
|
||||
if (!param)
|
||||
continue;
|
||||
symbol::Variable var;
|
||||
var.name = param->name;
|
||||
var.selection_range = param->location;
|
||||
var.range = param->location;
|
||||
var.storage = symbol::VariableScope::kParameter;
|
||||
var.type = param->type ? std::optional<std::string>(param->type->name) : std::nullopt;
|
||||
AddSymbol(symbol::Symbol(std::move(var)), param->name);
|
||||
}
|
||||
|
||||
HandleBlock(*node.body, false);
|
||||
LeaveScope();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleClassDefinition(ast::ClassDefinition& node)
|
||||
{
|
||||
symbol::Class cls;
|
||||
cls.name = node.name;
|
||||
cls.selection_range = node.location;
|
||||
cls.range = node.span;
|
||||
|
||||
auto class_id = AddSymbol(symbol::Symbol(std::move(cls)), node.name);
|
||||
|
||||
EnterScope(symbol::ScopeKind::kClass, node.span, class_id);
|
||||
|
||||
for (const auto& parent : node.parent_classes)
|
||||
{
|
||||
auto it = name_index_.find(ToLower(parent.name));
|
||||
if (it != name_index_.end())
|
||||
{
|
||||
table_.AddInheritance(class_id, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& member : node.members)
|
||||
{
|
||||
if (member)
|
||||
HandleClassMember(*member);
|
||||
}
|
||||
|
||||
LeaveScope();
|
||||
}
|
||||
|
||||
void HandleClassMember(ast::ClassMember& member)
|
||||
{
|
||||
std::visit(
|
||||
[&](auto& ptr) {
|
||||
using T = std::decay_t<decltype(ptr)>;
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
if constexpr (std::is_same_v<T, std::unique_ptr<ast::FieldDeclaration>>)
|
||||
{
|
||||
HandleFieldDeclaration(*ptr, member.access_modifier, false);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::unique_ptr<ast::StaticDeclaration>>)
|
||||
{
|
||||
HandleStatic(*ptr, member.access_modifier, true);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::unique_ptr<ast::MethodDeclaration>>)
|
||||
{
|
||||
HandleMethodDeclaration(*ptr, CurrentScopeOwner(), member.access_modifier);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::unique_ptr<ast::PropertyDeclaration>>)
|
||||
{
|
||||
HandlePropertyDeclaration(*ptr, CurrentScopeOwner(), member.access_modifier);
|
||||
}
|
||||
},
|
||||
member.member);
|
||||
}
|
||||
|
||||
std::optional<symbol::SymbolId> CurrentScopeOwner() const
|
||||
{
|
||||
if (scope_stack_.empty())
|
||||
return std::nullopt;
|
||||
|
||||
auto current = scope_stack_.back();
|
||||
for (const auto& [owner, scope_id] : scope_by_owner_)
|
||||
{
|
||||
if (scope_id == current)
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void HandleMethodDeclaration(ast::MethodDeclaration& node, std::optional<symbol::SymbolId> /*owner*/, ast::AccessModifier access)
|
||||
{
|
||||
symbol::Method method;
|
||||
method.name = node.name;
|
||||
method.selection_range = node.location;
|
||||
method.range = node.span;
|
||||
method.declaration_range = node.location;
|
||||
if (node.body)
|
||||
{
|
||||
method.implementation_range = node.body->span;
|
||||
}
|
||||
method.method_kind = node.method_kind;
|
||||
method.method_modifier = node.modifier;
|
||||
method.is_static = node.is_static;
|
||||
method.access = access;
|
||||
method.parameters = BuildParameters(node.parameters);
|
||||
method.return_type = ExtractTypeName(node.return_type);
|
||||
|
||||
auto method_id = AddSymbol(symbol::Symbol(std::move(method)), node.name);
|
||||
|
||||
if (node.body)
|
||||
{
|
||||
EnterScope(symbol::ScopeKind::kFunction, node.body->span, method_id);
|
||||
for (const auto& param : node.parameters)
|
||||
{
|
||||
if (!param)
|
||||
continue;
|
||||
symbol::Variable var;
|
||||
var.name = param->name;
|
||||
var.selection_range = param->location;
|
||||
var.range = param->location;
|
||||
var.storage = symbol::VariableScope::kParameter;
|
||||
var.type = param->type ? std::optional<std::string>(param->type->name) : std::nullopt;
|
||||
AddSymbol(symbol::Symbol(std::move(var)), param->name);
|
||||
}
|
||||
|
||||
HandleBlock(*node.body, false);
|
||||
LeaveScope();
|
||||
}
|
||||
}
|
||||
|
||||
void HandlePropertyDeclaration(ast::PropertyDeclaration& node, std::optional<symbol::SymbolId>, ast::AccessModifier access)
|
||||
{
|
||||
symbol::Property property;
|
||||
property.name = node.name;
|
||||
property.selection_range = node.location;
|
||||
property.range = node.span;
|
||||
property.access = access;
|
||||
property.type = ExtractTypeName(node.type);
|
||||
|
||||
AddSymbol(symbol::Symbol(std::move(property)), node.name);
|
||||
}
|
||||
|
||||
void HandleFieldDeclaration(ast::FieldDeclaration& node, ast::AccessModifier access, bool is_static)
|
||||
{
|
||||
symbol::Field field;
|
||||
field.name = node.name;
|
||||
field.selection_range = node.location;
|
||||
field.range = node.span;
|
||||
field.access = access;
|
||||
field.reference_modifier = node.reference_modifier;
|
||||
field.type = ExtractTypeName(node.type);
|
||||
field.is_static = is_static;
|
||||
|
||||
AddSymbol(symbol::Symbol(std::move(field)), node.name);
|
||||
}
|
||||
|
||||
void HandleVariable(ast::VarDeclaration& node, symbol::VariableScope storage)
|
||||
{
|
||||
symbol::Variable var;
|
||||
var.name = node.name;
|
||||
var.selection_range = node.location;
|
||||
var.range = node.span;
|
||||
var.storage = storage;
|
||||
var.type = ExtractTypeName(node.type);
|
||||
var.has_initializer = node.initializer.has_value();
|
||||
|
||||
AddSymbol(symbol::Symbol(std::move(var)), node.name);
|
||||
}
|
||||
|
||||
void HandleStatic(ast::StaticDeclaration& node, ast::AccessModifier access = ast::AccessModifier::kPublic, bool is_class_member = false)
|
||||
{
|
||||
if (is_class_member)
|
||||
{
|
||||
symbol::Field field;
|
||||
field.name = node.name;
|
||||
field.selection_range = node.location;
|
||||
field.range = node.span;
|
||||
field.access = access;
|
||||
field.reference_modifier = node.reference_modifier;
|
||||
field.type = ExtractTypeName(node.type);
|
||||
field.is_static = true;
|
||||
AddSymbol(symbol::Symbol(std::move(field)), node.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol::Variable var;
|
||||
var.name = node.name;
|
||||
var.selection_range = node.location;
|
||||
var.range = node.span;
|
||||
var.storage = symbol::VariableScope::kStatic;
|
||||
var.reference_modifier = node.reference_modifier;
|
||||
var.type = ExtractTypeName(node.type);
|
||||
var.has_initializer = node.initializer.has_value();
|
||||
AddSymbol(symbol::Symbol(std::move(var)), node.name);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleConstant(ast::ConstDeclaration& node)
|
||||
{
|
||||
symbol::Constant constant;
|
||||
constant.name = node.name;
|
||||
constant.selection_range = node.location;
|
||||
constant.range = node.span;
|
||||
constant.type = ExtractTypeName(node.type);
|
||||
constant.value = "<const>";
|
||||
|
||||
AddSymbol(symbol::Symbol(std::move(constant)), node.name);
|
||||
}
|
||||
|
||||
void HandleGlobalDeclaration(ast::GlobalDeclaration& node)
|
||||
{
|
||||
symbol::Variable var;
|
||||
var.name = node.name;
|
||||
var.selection_range = node.location;
|
||||
var.range = node.span;
|
||||
var.storage = symbol::VariableScope::kGlobal;
|
||||
var.type = ExtractTypeName(node.type);
|
||||
var.has_initializer = node.initializer.has_value();
|
||||
|
||||
AddSymbol(symbol::Symbol(std::move(var)), node.name);
|
||||
}
|
||||
|
||||
void HandleExternalMethod(ast::ExternalMethodDefinition& node)
|
||||
{
|
||||
// Try to find owner class scope
|
||||
auto owner_it = name_index_.find(ToLower(node.owner_class.name));
|
||||
std::optional<symbol::SymbolId> owner_id;
|
||||
std::optional<symbol::ScopeId> owner_scope;
|
||||
if (owner_it != name_index_.end())
|
||||
{
|
||||
owner_id = owner_it->second;
|
||||
auto scope_it = scope_by_owner_.find(*owner_id);
|
||||
if (scope_it != scope_by_owner_.end())
|
||||
{
|
||||
owner_scope = scope_it->second;
|
||||
}
|
||||
}
|
||||
|
||||
symbol::Method method;
|
||||
method.name = node.name;
|
||||
method.selection_range = node.location;
|
||||
method.range = node.span;
|
||||
method.declaration_range = node.location;
|
||||
method.implementation_range = node.location;
|
||||
method.method_kind = node.method_kind;
|
||||
method.method_modifier = node.modifier;
|
||||
method.is_static = node.is_static;
|
||||
method.parameters = BuildParameters(node.parameters);
|
||||
method.return_type = ExtractTypeName(node.return_type);
|
||||
|
||||
bool pushed_owner = false;
|
||||
if (owner_scope)
|
||||
{
|
||||
scope_stack_.push_back(*owner_scope);
|
||||
pushed_owner = true;
|
||||
}
|
||||
|
||||
auto method_id = AddSymbol(symbol::Symbol(std::move(method)), node.name);
|
||||
|
||||
if (node.body)
|
||||
{
|
||||
EnterScope(symbol::ScopeKind::kFunction, node.body->span, method_id);
|
||||
HandleBlock(*node.body, false);
|
||||
LeaveScope();
|
||||
}
|
||||
|
||||
if (pushed_owner)
|
||||
{
|
||||
scope_stack_.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleUnitDefinition(ast::UnitDefinition& node)
|
||||
{
|
||||
symbol::Unit unit;
|
||||
unit.name = node.name;
|
||||
unit.selection_range = node.location;
|
||||
unit.range = node.span;
|
||||
|
||||
auto unit_id = AddSymbol(symbol::Symbol(std::move(unit)), node.name);
|
||||
EnterScope(symbol::ScopeKind::kUnit, node.span, unit_id);
|
||||
|
||||
for (auto& stmt : node.interface_statements)
|
||||
{
|
||||
HandleStatement(stmt);
|
||||
}
|
||||
for (auto& stmt : node.implementation_statements)
|
||||
{
|
||||
HandleStatement(stmt);
|
||||
}
|
||||
|
||||
LeaveScope();
|
||||
}
|
||||
|
||||
void HandleBlock(ast::BlockStatement& block, bool create_scope)
|
||||
{
|
||||
std::optional<symbol::ScopeId> scope_holder;
|
||||
if (create_scope)
|
||||
{
|
||||
EnterScope(symbol::ScopeKind::kBlock, block.span, std::nullopt);
|
||||
scope_holder = CurrentScope();
|
||||
}
|
||||
|
||||
for (auto& stmt : block.statements)
|
||||
{
|
||||
HandleStatement(stmt);
|
||||
}
|
||||
|
||||
if (scope_holder)
|
||||
{
|
||||
LeaveScope();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleIfStatement(ast::IfStatement& node)
|
||||
{
|
||||
for (auto& branch : node.branches)
|
||||
{
|
||||
if (branch.body)
|
||||
HandleStatement(branch.body);
|
||||
}
|
||||
|
||||
if (node.else_body && *node.else_body)
|
||||
{
|
||||
HandleStatement(*node.else_body);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleForInStatement(ast::ForInStatement& node)
|
||||
{
|
||||
if (node.body)
|
||||
HandleStatement(node.body);
|
||||
}
|
||||
|
||||
void HandleForToStatement(ast::ForToStatement& node)
|
||||
{
|
||||
if (node.body)
|
||||
HandleStatement(node.body);
|
||||
}
|
||||
|
||||
void HandleWhileStatement(ast::WhileStatement& node)
|
||||
{
|
||||
if (node.body)
|
||||
HandleStatement(node.body);
|
||||
}
|
||||
|
||||
void HandleRepeatStatement(ast::RepeatStatement& node)
|
||||
{
|
||||
for (auto& stmt : node.body)
|
||||
{
|
||||
HandleStatement(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleCaseStatement(ast::CaseStatement& node)
|
||||
{
|
||||
for (auto& branch : node.branches)
|
||||
{
|
||||
if (branch.body)
|
||||
HandleStatement(branch.body);
|
||||
}
|
||||
if (node.else_body && *node.else_body)
|
||||
{
|
||||
HandleStatement(*node.else_body);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleTryStatement(ast::TryStatement& node)
|
||||
{
|
||||
if (node.try_body)
|
||||
HandleBlock(*node.try_body, true);
|
||||
if (node.except_body)
|
||||
HandleBlock(*node.except_body, true);
|
||||
}
|
||||
|
||||
private:
|
||||
symbol::SymbolTable& table_;
|
||||
std::vector<symbol::ScopeId> scope_stack_;
|
||||
std::unordered_map<std::string, symbol::SymbolId> name_index_;
|
||||
std::unordered_map<symbol::SymbolId, symbol::ScopeId> scope_by_owner_;
|
||||
};
|
||||
|
||||
// ==================== 主分析函数 ====================
|
||||
|
||||
void AnalyzeFile(const Options& options)
|
||||
{
|
||||
// 打印头部
|
||||
if (!options.compact_mode)
|
||||
{
|
||||
std::cout << "\n╔════════════════════════════════════════════════════════════╗\n";
|
||||
@@ -321,7 +917,6 @@ void AnalyzeFile(const Options& options)
|
||||
std::cout << "Input file: " << options.input_file << "\n";
|
||||
}
|
||||
|
||||
// 1. 读取源文件
|
||||
if (options.verbose)
|
||||
std::cout << "Reading file...\n";
|
||||
|
||||
@@ -335,7 +930,6 @@ void AnalyzeFile(const Options& options)
|
||||
std::cout << "----------------------------------------\n\n";
|
||||
}
|
||||
|
||||
// 2. 使用 Tree-Sitter 解析
|
||||
if (options.verbose)
|
||||
std::cout << "Parsing with Tree-Sitter...\n";
|
||||
|
||||
@@ -349,7 +943,6 @@ void AnalyzeFile(const Options& options)
|
||||
std::cout << "Root node child count: " << ts_node_child_count(root) << "\n\n";
|
||||
}
|
||||
|
||||
// 3. 反序列化为 AST
|
||||
if (options.verbose)
|
||||
std::cout << "Deserializing to AST...\n";
|
||||
|
||||
@@ -373,14 +966,14 @@ void AnalyzeFile(const Options& options)
|
||||
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);
|
||||
SymbolBuilder builder(table);
|
||||
builder.Build(*parse_result.root);
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
@@ -388,7 +981,6 @@ void AnalyzeFile(const Options& options)
|
||||
if (options.verbose)
|
||||
std::cout << "Symbol table built in " << duration.count() << " ms\n\n";
|
||||
|
||||
// 5. 准备输出流
|
||||
std::ostream* out = &std::cout;
|
||||
std::ofstream file_out;
|
||||
|
||||
@@ -402,7 +994,6 @@ void AnalyzeFile(const Options& options)
|
||||
}
|
||||
out = &file_out;
|
||||
|
||||
// 写入文件头
|
||||
*out << "Symbol Table Analysis\n";
|
||||
*out << "Source: " << options.input_file << "\n";
|
||||
auto now = std::chrono::system_clock::now();
|
||||
@@ -411,9 +1002,6 @@ void AnalyzeFile(const Options& options)
|
||||
*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();
|
||||
@@ -427,38 +1015,30 @@ void AnalyzeFile(const Options& options)
|
||||
|
||||
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)
|
||||
@@ -491,7 +1071,6 @@ void AnalyzeFile(const Options& options)
|
||||
printed_anything = true;
|
||||
}
|
||||
|
||||
// 总是打印统计信息
|
||||
if (printed_anything)
|
||||
{
|
||||
*out << "\n";
|
||||
@@ -499,24 +1078,22 @@ void AnalyzeFile(const Options& options)
|
||||
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 << "Smary:\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 << " Symbols: " << table.all_definitions().size() << "\n";
|
||||
std::cout << " Scopes: " << table.scopes().all_scopes().size() << "\n";
|
||||
std::cout << " Parse Errors: " << parse_result.errors.size() << "\n";
|
||||
std::cout << " Build Time: " << duration.count() << " ms\n";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user