Вообщем поигрался с AST анализатором раста и выдает неплохие вещи, если вы пишите на нем, то сейчас это как-бы новый язык и инструментов под него маловато.
Мой код это анализатор дерева Rust кода, чтобы показать быстренько его структуру, то есть классы, функции, поля, ассоциации, трейты..
Думаю можно и запилить какие-то графики чтобы понятнее было!
Анализатор
Cargo.toml
Для этого кода https://pastebin.com/AbFzD17y сделает такой лог https://pastebin.com/ceJPY0tp
Мой код это анализатор дерева Rust кода, чтобы показать быстренько его структуру, то есть классы, функции, поля, ассоциации, трейты..
Думаю можно и запилить какие-то графики чтобы понятнее было!
Анализатор
Код:
extern crate tree_sitter;
extern crate tree_sitter_rust;
use std::fs;
use tree_sitter::{Node, Parser};
fn main() {
let code = match fs::read_to_string(r"C:\Users\WORKER\Desktop\RustDev\web3\src\code.txt") {
Ok(content) => content,
Err(err) => {
eprintln!("Error reading code.txt: {}", err);
return;
}
};
let mut parser = Parser::new();
parser.set_language(tree_sitter_rust::language()).expect("Error loading Rust grammar");
let parsed = parser.parse(&code, None).expect("Parsing error");
let root_node = parsed.root_node();
println!("Root node: {:?}", root_node);
// Обработка классов
process_classes(root_node, &code);
}
pub fn process_classes(node: Node, code: &str) {
let mut cursor = node.walk();
for child in node.named_children(&mut cursor) {
// println!("Child: {:?}", child.kind());
if child.kind() == "struct_item" || child.kind() == "enum_item" {
// Поиск узла с именем класса
if let Some(class_name_node) = child.child_by_field_name("name") {
let class_name = class_name_node.utf8_text(code.as_bytes()).unwrap().to_string();
let cll = class_name.clone();
println!("Class: {}", cll);
}
}
process_classes(child, code); // Рекурсивный вызов для вложенных классов
// Обработка функций
process_functions(child, code);
// Обработка ассоциаций и зависимостей
process_associations_and_dependencies(child, code);
// Обработка наследования
process_inheritance(child, code);
}
// Обработка интерфейсов
process_interfaces(node, code);
}
fn process_functions(class_node: Node, code: &str) {
fn process_parameters(node: Node, code: &str, arguments: &mut Vec<String>) {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if child.kind() == "parameter" {
if let Some(parameter_name_node) = child.child_by_field_name("name") {
let parameter_name = parameter_name_node.utf8_text(code.as_bytes()).unwrap().to_string();
arguments.push(parameter_name);
}
}
}
}
let mut cursor = class_node.walk();
for child in class_node.named_children(&mut cursor) {
// println!("Child: {:?}", child.kind());
if child.kind() == "function_item" {
// Получаем имя функции
if let Some(function_name_node) = child.child_by_field_name("name") {
let function_name = function_name_node.utf8_text(code.as_bytes()).unwrap().to_string();
// Получаем аргументы функции
let mut arguments = Vec::new();
if let Some(parameter_list_node) = child.child_by_field_name("parameters") {
process_parameters(parameter_list_node, code, &mut arguments);
}
// Получаем тип возвращаемого значения
let return_type = if let Some(return_type_node) = child.child_by_field_name("return_type") {
return_type_node.utf8_text(code.as_bytes()).unwrap().to_string()
} else {
"void".to_string() // Здесь можно задать значение по умолчанию
};
// Выводим информацию о функции
println!(" Function: {}({}) -> {}", function_name, arguments.join(", "), return_type);
}
}
}
}
fn process_inheritance(class_node: Node, code: &str) {
let mut cursor = class_node.walk();
for child in class_node.named_children(&mut cursor) {
if child.kind() == "trait_bound" {
// Handle inheritance clause if it exists
if let Some(inherited_type_node) = child.child_by_field_name("type") {
let inherited_type = inherited_type_node.utf8_text(code.as_bytes()).unwrap().to_string();
println!(" Inherits: {}", inherited_type);
}
}
}
}
fn process_associations_and_dependencies(class_node: Node, code: &str) {
let mut cursor = class_node.walk();
for child in class_node.named_children(&mut cursor) {
if child.kind() == "field_declaration" {
// Получаем имя поля
let field_name = child.utf8_text(code.as_bytes()).unwrap().to_string();
// Получаем тип поля
if let Some(field_type_node) = child.child_by_field_name("type") {
let field_type = field_type_node.utf8_text(code.as_bytes()).unwrap().to_string();
// Здесь вы можете анализировать тип поля и определить ассоциацию
println!(" Field - {}: Association with class {}", field_name, field_type);
}
}
}
}
fn process_interfaces(class_node: Node, code: &str) {
let mut cursor = class_node.walk();
for child in class_node.named_children(&mut cursor) {
if child.kind() == "impl_item" {
// Check if this is an implementation for a trait
if let Some(trait_name) = get_trait_name_from_impl(child, code) {
let type_name = get_type_name_from_impl(child, code);
println!("Trait '{}' implemented for type '{}'", trait_name, type_name);
// Process each function within the impl block
process_trait_functions(child, code, &trait_name, &type_name);
}
}
}
}
fn get_trait_name_from_impl(impl_node: Node, code: &str) -> Option<String> {
// This function extracts the trait name from an impl block
// Returns None if it's not a trait implementation
let mut cursor = impl_node.walk();
let option = impl_node.named_children(&mut cursor)
.find(|n| n.kind() == "type_identifier")
.and_then(|n| n.utf8_text(code.as_bytes()).ok())
.map(|s| s.to_string());
option
}
fn get_type_name_from_impl(impl_node: Node, code: &str) -> String {
// This function extracts the type name from an impl block
// Should be called after confirming it's a trait implementation
let mut cursor = impl_node.walk();
impl_node.named_children(&mut cursor)
.filter(|n| n.kind() == "type_identifier")
.last() // Getting the last type_identifier assuming it's the type name
.and_then(|n| n.utf8_text(code.as_bytes()).ok())
.unwrap_or_default()
.to_string()
}
fn process_trait_functions(impl_node: Node, code: &str, trait_name: &str, type_name: &str) {
let mut cursor = impl_node.walk();
// Find the declaration_list node within the impl block
for child in impl_node.named_children(&mut cursor) {
if child.kind() == "declaration_list" {
process_declaration_list(child, code, trait_name, type_name);
}
}
}
fn process_declaration_list(decl_list_node: Node, code: &str, trait_name: &str, type_name: &str) {
let mut cursor = decl_list_node.walk();
// Iterate over function items within the declaration list
for child in decl_list_node.named_children(&mut cursor) {
if child.kind() == "function_item" {
// Extract function name
if let Some(function_name_node) = child.child_by_field_name("name") {
let function_name = function_name_node.utf8_text(code.as_bytes()).unwrap().to_string();
// Output the trait implementation details
println!("Trait '{}' for type '{}' implements function '{}'", trait_name, type_name, function_name);
}
}
}
}
Cargo.toml
YAML:
[package]
name = "my_project"
version = "0.1.0"
edition = "2018"
[dependencies]
tree-sitter = "0.20.10"
tree-sitter-rust = "0.20.4"
Для этого кода https://pastebin.com/AbFzD17y сделает такой лог https://pastebin.com/ceJPY0tp