use syn::{parse_file, visit::Visit, File, Item, ItemImpl, Type};
fn find_base_entity_impls(file: &File) -> Vec<String> {
let mut results = Vec::new();
for item in &file.items {
if let Item::Impl(item_impl) = item {
if let Some((_, trait_path, _)) = &item_impl.trait_ {
if let Some(seg) = trait_path.segments.last() {
if seg.ident == "BaseEntity" {
if let Some(name) = type_to_string(&item_impl.self_ty) {
results.push(name);
}
}
}
}
}
}
results
}
fn find_base_entity_impls_single(file: &File) -> Vec<String> {
let mut results = Vec::new();
for item in &file.items {
if let Item::Impl(item_impl) = item {
if let Some((_, trait_path, _)) = &item_impl.trait_ {
if let Some(seg) = trait_path.segments.last() {
if seg.ident == "BaseEntitySingle" {
if let Some(name) = type_to_string(&item_impl.self_ty) {
results.push(name);
}
}
}
}
}
}
results
}
fn type_to_string(ty: &Type) -> Option<String> {
match ty {
Type::Path(type_path) => {
type_path.path.segments.last().map(|s| s.ident.to_string())
}
Type::Reference(r) => type_to_string(&r.elem), Type::Paren(p) => type_to_string(&p.elem), _ => None, }
}
struct BaseEntityImplVisitor {
results: Vec<String>,
}
impl<'ast> Visit<'ast> for BaseEntityImplVisitor {
fn visit_item_impl(&mut self, node: &'ast ItemImpl) {
if let Some((_, trait_path, _)) = &node.trait_ {
if let Some(seg) = trait_path.segments.last() {
if seg.ident == "BaseEntity" {
if let Some(name) = type_to_string(&node.self_ty) {
self.results.push(name);
}
}
}
}
syn::visit::visit_item_impl(self, node);
}
}
#[test]
fn main() {
let code = r#"
trait BaseEntity { fn id(&self) -> u64; }
trait BaseEntitySingle { fn id(&self) -> u64; }
struct User { id: u64 }
struct Order { id: u64 }
impl BaseEntity for User {
fn id(&self) -> u64 { self.id }
}
impl BaseEntitySingle for User {
fn id(&self) -> u64 { self.id }
}
// 这个不是 BaseEntity
impl Clone for Order {
fn clone(&self) -> Self { todo!() }
}
mod inner {
use super::BaseEntity;
struct Admin;
impl BaseEntity for Admin {
fn id(&self) -> u64 { 0 }
}
}
"#;
let ast = parse_file(code).expect("parse failed");
let found = find_base_entity_impls(&ast);
println!("简单遍历找到: {:?}", found);
let mut visitor = BaseEntityImplVisitor { results: vec![] };
visitor.visit_file(&ast);
println!("Visitor 找到: {:?}", visitor.results); let found = find_base_entity_impls(&ast);
println!("简单遍历找到:baseentity {:?}", found);
let found = find_base_entity_impls_single(&ast);
println!("简单遍历找到: baseentitysngle{:?}", found);
}