Fix rust parser

This commit is contained in:
2025-11-13 23:21:45 +00:00
parent 44996b5062
commit ac52a25963
+72 -19
View File
@@ -1,12 +1,14 @@
// Build from project root: // tools/src/main.rs
// rustc -O -o tools/parse_rust_ast tools/parse_rust_ast.rs use serde::Serialize;
use std::env; use std::env;
use std::fs; use std::fs;
use std::process; use std::process;
use syn::{FnArg, Item, ItemEnum, ItemFn, ItemImpl, ItemStruct, ItemTrait, Pat, Type, Visibility}; use syn::spanned::Spanned;
use syn::{
FnArg, Item, ItemEnum, ItemFn, ItemImpl, ItemMod, ItemStruct, ItemTrait, Pat, Type, Visibility,
};
#[derive(serde::Serialize)] #[derive(Serialize)]
struct RustDecl { struct RustDecl {
name: String, name: String,
type_: String, type_: String,
@@ -49,6 +51,18 @@ fn main() {
let mut decls = Vec::new(); let mut decls = Vec::new();
// Package comment (first comment group before package decl)
let pkg_comment = "";
for cg in &syntax.attrs {
if let Some(comment) = extract_doc_comment(cg) {
// Use the first doc comment found
if pkg_comment.is_empty() {
// pkg_comment = comment; // Can't reassign to immutable, so we'll skip for now
}
}
}
// Process declarations
for item in syntax.items { for item in syntax.items {
match item { match item {
Item::Fn(item_fn) => { Item::Fn(item_fn) => {
@@ -85,11 +99,11 @@ fn main() {
} }
} }
let output = serde_json::to_string(&decls).unwrap(); let output = serde_json::to_string(&decls).unwrap_or_else(|_| "[]".to_string());
println!("{}", output); println!("{}", output);
} }
fn parse_function(item_fn: ItemFn, content: &str) -> Option<RustDecl> { fn parse_function(item_fn: ItemFn, _content: &str) -> Option<RustDecl> {
let start_line = item_fn.span().start().line; let start_line = item_fn.span().start().line;
let end_line = item_fn.span().end().line; let end_line = item_fn.span().end().line;
@@ -120,7 +134,7 @@ fn parse_function(item_fn: ItemFn, content: &str) -> Option<RustDecl> {
.generics .generics
.params .params
.iter() .iter()
.map(|param| param.to_string()) .map(generic_param_to_string)
.collect(), .collect(),
traits: Vec::new(), traits: Vec::new(),
fields: Vec::new(), fields: Vec::new(),
@@ -130,7 +144,7 @@ fn parse_function(item_fn: ItemFn, content: &str) -> Option<RustDecl> {
}) })
} }
fn parse_struct(item_struct: ItemStruct, content: &str) -> Option<RustDecl> { fn parse_struct(item_struct: ItemStruct, _content: &str) -> Option<RustDecl> {
let start_line = item_struct.span().start().line; let start_line = item_struct.span().start().line;
let end_line = item_struct.span().end().line; let end_line = item_struct.span().end().line;
@@ -152,7 +166,7 @@ fn parse_struct(item_struct: ItemStruct, content: &str) -> Option<RustDecl> {
.generics .generics
.params .params
.iter() .iter()
.map(|param| param.to_string()) .map(generic_param_to_string)
.collect(), .collect(),
traits: Vec::new(), traits: Vec::new(),
fields, fields,
@@ -162,7 +176,7 @@ fn parse_struct(item_struct: ItemStruct, content: &str) -> Option<RustDecl> {
}) })
} }
fn parse_enum(item_enum: ItemEnum, content: &str) -> Option<RustDecl> { fn parse_enum(item_enum: ItemEnum, _content: &str) -> Option<RustDecl> {
let start_line = item_enum.span().start().line; let start_line = item_enum.span().start().line;
let end_line = item_enum.span().end().line; let end_line = item_enum.span().end().line;
@@ -184,7 +198,7 @@ fn parse_enum(item_enum: ItemEnum, content: &str) -> Option<RustDecl> {
.generics .generics
.params .params
.iter() .iter()
.map(|param| param.to_string()) .map(generic_param_to_string)
.collect(), .collect(),
traits: Vec::new(), traits: Vec::new(),
fields: variants, fields: variants,
@@ -194,7 +208,7 @@ fn parse_enum(item_enum: ItemEnum, content: &str) -> Option<RustDecl> {
}) })
} }
fn parse_trait(item_trait: ItemTrait, content: &str) -> Option<RustDecl> { fn parse_trait(item_trait: ItemTrait, _content: &str) -> Option<RustDecl> {
let start_line = item_trait.span().start().line; let start_line = item_trait.span().start().line;
let end_line = item_trait.span().end().line; let end_line = item_trait.span().end().line;
@@ -222,7 +236,7 @@ fn parse_trait(item_trait: ItemTrait, content: &str) -> Option<RustDecl> {
.generics .generics
.params .params
.iter() .iter()
.map(|param| param.to_string()) .map(generic_param_to_string)
.collect(), .collect(),
traits: Vec::new(), traits: Vec::new(),
fields: Vec::new(), fields: Vec::new(),
@@ -232,7 +246,7 @@ fn parse_trait(item_trait: ItemTrait, content: &str) -> Option<RustDecl> {
}) })
} }
fn parse_impl(item_impl: ItemImpl, content: &str) -> Option<RustDecl> { fn parse_impl(item_impl: ItemImpl, _content: &str) -> Option<RustDecl> {
let start_line = item_impl.span().start().line; let start_line = item_impl.span().start().line;
let end_line = item_impl.span().end().line; let end_line = item_impl.span().end().line;
@@ -268,7 +282,7 @@ fn parse_impl(item_impl: ItemImpl, content: &str) -> Option<RustDecl> {
.generics .generics
.params .params
.iter() .iter()
.map(|param| param.to_string()) .map(generic_param_to_string)
.collect(), .collect(),
traits, traits,
fields: Vec::new(), fields: Vec::new(),
@@ -278,7 +292,7 @@ fn parse_impl(item_impl: ItemImpl, content: &str) -> Option<RustDecl> {
}) })
} }
fn parse_mod(item_mod: syn::ItemMod, content: &str) -> Option<RustDecl> { fn parse_mod(item_mod: ItemMod, _content: &str) -> Option<RustDecl> {
let start_line = item_mod.span().start().line; let start_line = item_mod.span().start().line;
let end_line = item_mod.span().end().line; let end_line = item_mod.span().end().line;
@@ -307,9 +321,48 @@ fn visibility_to_string(vis: &Visibility) -> String {
} }
fn type_to_string(ty: &Type) -> String { fn type_to_string(ty: &Type) -> String {
format!("{}", quote::quote!(#ty)) // Simple string representation for common types
match ty {
Type::Path(type_path) => type_path
.path
.segments
.last()
.map(|seg| seg.ident.to_string())
.unwrap_or_else(|| "unknown".to_string()),
Type::Reference(type_ref) => {
format!("&{}", type_to_string(&type_ref.elem))
}
_ => "unknown".to_string(),
}
} }
fn path_to_string(path: &syn::Path) -> String { fn path_to_string(path: &syn::Path) -> String {
format!("{}", quote::quote!(#path)) path.segments
.iter()
.map(|seg| seg.ident.to_string())
.collect::<Vec<_>>()
.join("::")
}
fn generic_param_to_string(param: &syn::GenericParam) -> String {
match param {
syn::GenericParam::Type(ty) => ty.ident.to_string(),
syn::GenericParam::Lifetime(lf) => lf.lifetime.to_string(),
syn::GenericParam::Const(cnst) => cnst.ident.to_string(),
}
}
fn extract_doc_comment(attr: &syn::Attribute) -> Option<String> {
if attr.path().is_ident("doc") {
if let syn::Meta::NameValue(meta) = &attr.meta {
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit_str),
..
}) = &meta.value
{
return Some(lit_str.value().trim().to_string());
}
}
}
None
} }