use crate::rubase::{BaseEntity, ruentity};
use crate::rudi::didto;
use syn::{File, Item, ItemImpl, Type, parse_file, visit::Visit};
use crate::rubase::rutils::jsonutils;
use crate::rulog;
pub struct RuAst {
baseentity: Vec<String>,
baseentitysingle: Vec<String>,
}
impl ruentity::BaseEntitySingle for RuAst {
}
impl RuAst {
pub fn new() -> RuAst {
Self {
baseentity: Vec::new(),
baseentitysingle: Vec::new(),
}
}
pub fn parse_file(file: &str) -> syn::Result<File> {
parse_file("content")
}
pub fn parse_file_content(mut content: &str) -> syn::Result<File> {
parse_file(content)
}
pub fn find_base_entity(&self, file: &File) -> Vec<String> {
self.find_trait(file, "BaseEntity")
}
pub fn find_base_entity_single(&self, file: &File) -> Vec<String> {
self.find_trait(file, "BaseEntitySingle")
}
pub fn find_trait_default(&self, file: &File ) -> Vec<String> {
self.find_trait(file, "Default")
}
pub fn find_trait(&self, file: &File,traitName:&str) -> 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 == traitName {
if let Some(name) = type_to_string(&item_impl.self_ty) {
results.push(name);
}
}
}
}
}
}
results
}
pub fn find_all_default_content(&self, content: &str) -> Vec<String> {
let ast = RuAst::parse_file_content(content).expect("parse failed");
let ra = RuAst::new();
ra.find_all_default(&ast)
}
pub fn find_base_entity_content(&self, content: &str) -> Vec<String> {
let ast = RuAst::parse_file_content(content).expect("parse failed");
let ra = RuAst::new();
ra.find_base_entity(&ast)
}
pub fn find_base_entity_single_content(&self, content: &str) -> Vec<String> {
let ast = RuAst::parse_file_content(content).expect("parse failed");
let ra = RuAst::new();
ra.find_base_entity_single(&ast)
}
fn type_to_string(&self, ty: &Type) -> Option<String> {
match ty {
Type::Path(type_path) => {
type_path.path.segments.last().map(|s| s.ident.to_string())
}
Type::Reference(r) => self.type_to_string(&r.elem), Type::Paren(p) => self.type_to_string(&p.elem), _ => None, }
}
pub fn find_base_entity_all(&self, file: &File) -> Vec<String> {
let mut results = Vec::new();
results.extend(self.find_base_entity(file));
results.extend(self.find_base_entity_single(file));
results
}
pub fn has_derive_default(&self, attrs: &[syn::Attribute]) -> bool {
let mut has_default = false;
for attr in attrs {
if !attr.path().is_ident("derive") { continue; }
if let syn::Meta::List(list) = &attr.meta {
let _ = list.parse_nested_meta(|meta| {
if meta.path.is_ident("Default") { has_default = true; }
Ok(())
});
if has_default { return true; }
}
}
false
}
pub fn find_derive_default(&self, file: &File) -> Vec<String> {
let mut results = Vec::new();
for item in &file.items {
if let Item::Struct(item_struct) = item {
if self.has_derive_default(&item_struct.attrs) {
results.push(item_struct.ident.to_string());
}
}
}
results
}
pub fn find_all_default(&self, file: &File) -> Vec<String> {
let mut results = Vec::new();
results.extend(self.find_derive_default(file));
results.extend(self.find_trait(file, "Default"));
results.sort();
results.dedup();
results
}
pub fn find_entity_all(&self,fileName :&str, content: &str) -> Vec<didto::StructInfo> {
let mut results = Vec::<didto::StructInfo>::new();
let ast = RuAst::parse_file_content(content).expect("parse failed");
let default_set = self.find_all_default(&ast);
let s1 = self.find_base_entity(&ast);
for a in s1 {
let mut si = didto::StructInfo::new();
si.set_if_single(false);
si.set_struct_name(a);
si.set_path_file(fileName.to_string());
si.set_struct_ini_file(si.build_struct_ini_file());
si.set_path_pkg(si.get_ini_path());
si.set_struct_pkg(si.build_struct_pkg().unwrap());
si.modFile=si.build_struct_mod_file();
si.ifDefault = default_set.contains(&si.structName );
results.push(si);
}
let s2 = self.find_base_entity_single (&ast);
for a in s2 {
let mut si = didto::StructInfo::new();
si.set_if_single(true);
si.set_struct_name(a.clone());
si.set_path_file(fileName.to_string());
si.set_struct_ini_file(si.build_struct_ini_file());
si.set_path_pkg(si.get_ini_path());
si.set_struct_pkg(si.build_struct_pkg().unwrap());
si.modFile=si.build_struct_mod_file();
si.ifDefault = default_set.contains(&si.structName );
results.push(si);
}
results
}
}
struct BaseEntityImplVisitor {
results: Vec<String>,
}
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, }
}
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);
}
}
fn getCode() -> &'static str {
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 }
}
}
"#
}
#[test]
fn find01_base_entity() {
let ast = RuAst::parse_file_content(getCode()).expect("parse failed");
let ra = RuAst::new();
let found = ra.find_base_entity(&ast);
println!("简单遍历找到: {:?}", found);
let mut visitor = BaseEntityImplVisitor { results: vec![] };
visitor.visit_file(&ast);
println!("Visitor 找到: {:?}", visitor.results); let mut found1 = ra.find_base_entity(&ast);
println!("简单遍历找到:baseentity {:?}", found);
let found2 = ra.find_base_entity_single(&ast);
println!("简单遍历找到: baseentitysngle{:?}", found);
found1.extend(found2);
println!("简单遍历找到: baseentitysngle-all{:?}", found1);
}
#[test]
fn find021_base_entity_all() {
let ast = RuAst::parse_file_content(getCode()).expect("parse failed");
let ra = RuAst::new();
let found = ra.find_base_entity_all(&ast);
println!("简单遍历找到: {:?}", found);
}