use crate::rubase::BaseEntitySingle;
use crate::rudi::didto;
use syn::{File, Item, ItemImpl, Type, parse_file, visit::Visit};
#[derive(Default)]
pub struct RuAst {
}
impl BaseEntitySingle for RuAst {}
impl RuAst {
pub fn new() -> RuAst {
Default::default()
}
pub fn parse_file(file: &str) -> syn::Result<File> {
println!("file: {}", file);
parse_file("content")
}
pub fn parse_file_content( 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)
}
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 baseVec = self.find_base_entity(&ast);
for structName in baseVec {
let structInfo = didto::StructInfo::new();
let mut ss = structInfo.InitNew(
false,
default_set.contains(&structInfo.structName),
structName,
fileName.to_string(),
);
ss.ifDefault = default_set.contains(&ss.structName);
results.push(ss);
}
let singleName = self.find_base_entity_single(&ast);
for structName in singleName {
let structInfo = didto::StructInfo::new();
let mut ss = structInfo.InitNew(
true,
default_set.contains(&structInfo.structName),
structName,
fileName.to_string(),
);
ss.ifDefault = default_set.contains(&ss.structName);
results.push(ss);
}
results
}
}
#[allow(dead_code)]
pub struct BaseEntityImplVisitor {
pub 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);
}
}