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

229 lines
5.5 KiB
C++

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
extern "C" {
#include <tree_sitter/api.h>
}
extern "C" const TSLanguage* tree_sitter_tsf(void);
#include "../../src/language/ast/deserializer.hpp"
#include "./debug_printer.hpp"
using namespace lsp::language::ast;
// ==================== 文件读取 ====================
std::string ReadFile(const std::string& filepath)
{
std::ifstream file(filepath);
if (!file.is_open())
{
throw std::runtime_error("Cannot open file: " + filepath);
}
std::ostringstream oss;
oss << file.rdbuf();
return oss.str();
}
// ==================== Tree-Sitter 解析 ====================
class TreeSitterParser
{
public:
TreeSitterParser()
{
parser_ = ts_parser_new();
if (!parser_)
{
throw std::runtime_error("Failed to create parser");
}
// 设置语言
if (!ts_parser_set_language(parser_, tree_sitter_tsf()))
{
ts_parser_delete(parser_);
throw std::runtime_error("Failed to set language");
}
}
~TreeSitterParser()
{
if (tree_)
{
ts_tree_delete(tree_);
}
if (parser_)
{
ts_parser_delete(parser_);
}
}
TSTree* Parse(const std::string& source)
{
if (tree_)
{
ts_tree_delete(tree_);
tree_ = nullptr;
}
tree_ = ts_parser_parse_string(
parser_,
nullptr,
source.c_str(),
source.length());
if (!tree_)
{
throw std::runtime_error("Failed to parse source");
}
return tree_;
}
TSNode GetRootNode()
{
if (!tree_)
{
throw std::runtime_error("No tree available");
}
return ts_tree_root_node(tree_);
}
private:
TSParser* parser_ = nullptr;
TSTree* tree_ = nullptr;
};
// ==================== 主程序 ====================
void PrintUsage(const char* program_name)
{
std::cout << "Usage: " << program_name << " <file_path> [options]\n";
std::cout << "\nOptions:\n";
std::cout << " -v, --verbose Print verbose output\n";
std::cout << " -i, --incremental Test incremental parsing\n";
std::cout << " -h, --help Show this help message\n";
std::cout << "\nExample:\n";
std::cout << " " << program_name << " test.tsf\n";
std::cout << " " << program_name << " test.tsf -v -s\n";
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
PrintUsage(argv[0]);
return 1;
}
std::string filepath;
bool verbose = false;
bool test_incremental = false;
// 解析命令行参数
for (int i = 1; i < argc; ++i)
{
std::string arg = argv[i];
if (arg == "-h" || arg == "--help")
{
PrintUsage(argv[0]);
return 0;
}
else if (arg == "-v" || arg == "--verbose")
{
verbose = true;
}
else if (arg == "-i" || arg == "--incremental")
{
test_incremental = true;
}
else if (filepath.empty())
{
filepath = arg;
}
else
{
std::cerr << "Unknown argument: " << arg << "\n";
return 1;
}
}
try
{
// 读取文件
std::cout << "Reading file: " << filepath << "\n";
std::string source = ReadFile(filepath);
if (verbose)
{
std::cout << "File size: " << source.length() << " bytes\n";
std::cout << "----------------------------------------\n";
std::cout << source << "\n";
std::cout << "----------------------------------------\n\n";
}
// 创建 Tree-Sitter 解析器
std::cout << "Parsing with Tree-Sitter...\n";
TreeSitterParser ts_parser;
TSTree* tree = ts_parser.Parse(source);
TSNode root = ts_parser.GetRootNode();
if (verbose)
{
std::cout << "Root node type: " << ts_node_type(root) << "\n";
std::cout << "Root node child count: " << ts_node_child_count(root) << "\n\n";
}
// 创建 AST 反序列化器
Deserializer deserializer;
ParseResult result;
if (test_incremental)
{
std::cout << "Using incremental parsing...\n";
auto inc_result = deserializer.ParseIncremental(root, source);
result = std::move(inc_result.result);
}
else
{
std::cout << "Using full parsing...\n";
result = deserializer.Parse(root, source);
}
// 打印解析结果
std::cout << "\n";
DebugPrint(result);
// 打印摘要
std::cout << "\n========================================\n";
std::cout << "Summary:\n";
std::cout << " File: " << filepath << "\n";
std::cout << " Size: " << source.length() << " bytes\n";
std::cout << " AST Nodes: " << result.statements.size() << "\n";
std::cout << " Errors: " << result.errors.size() << "\n";
if (result.HasErrors())
{
std::cout << " Status: FAILED (with errors)\n";
return 1;
}
else
{
std::cout << " Status: SUCCESS\n";
return 0;
}
}
catch (const std::exception& e)
{
std::cerr << "Error: " << e.what() << "\n";
return 1;
}
}