use crate::entity::Entity;
use crate::TableDef;
use quote::quote;
use proc_macro::{TokenStream};
#[derive(Clone, Debug)]
pub struct EntityPrinter {
pub(crate) entities: Vec<TableDef>,
}
pub struct PrinterOutput {
pub files: Vec<OutputFile>,
}
pub struct OutputFile {
pub name: String,
pub content: String,
}
impl EntityPrinter {
pub fn generate(self, ) {
}
pub fn write_entities(&self, expanded_format: bool) -> Vec<OutputFile> {
self.entities
.iter()
.map(|entity| {
let mut lines = Vec::new();
Self::write_doc_comment(&mut lines);
let code_blocks = if expanded_format {
Self::gen_expanded_code_blocks(entity)
} else {
Self::gen_compact_code_blocks(entity)
};
Self::write(&mut lines, code_blocks);
OutputFile {
name: format!("{}.rs", entity.get_table_name_snake_case()),
content: lines.join("\n\n"),
}
})
.collect()
}
pub fn write_doc_comment(lines: &mut Vec<String>) {
let ver = env!("CARGO_PKG_VERSION");
let comments = vec![format!(
"//! Akita Entity. Generated by akita_codegen {}",
ver
)];
lines.extend(comments);
lines.push("".to_owned());
}
pub fn gen_compact_code_blocks(entity: &Entity) -> Vec<TokenStream> {
let mut imports = Self::gen_import();
imports.extend(Self::gen_import_active_enum(entity));
let mut code_blocks = vec![imports, Self::gen_compact_model_struct(entity)];
code_blocks.extend(Self::gen_impl_conjunct_related(entity));
code_blocks.extend(vec![Self::gen_impl_active_model_behavior()]);
code_blocks
}
pub fn gen_compact_model_struct(entity: &Entity) -> TokenStream {
let table_name = entity.table_name().as_str();
let column_names_snake_case = entity.get_column_names_snake_case();
let column_rs_types = entity.get_column_rs_types();
let primary_keys: Vec<String> = entity
.primary_keys
.iter()
.map(|pk| pk.name.clone())
.collect();
let attrs: Vec<TokenStream> = entity
.columns
.iter()
.map(|col| {
let mut attrs: Punctuated<_, Comma> = Punctuated::new();
if primary_keys.contains(&col.name) {
attrs.push(quote! { primary_key });
if !col.auto_increment {
attrs.push(quote! { auto_increment = false });
}
}
if let Some(ts) = col.get_col_type_attrs() {
attrs.extend(vec![ts]);
if !col.not_null {
attrs.push(quote! { nullable });
}
};
if col.unique {
attrs.push(quote! { unique });
}
if !attrs.is_empty() {
let mut ts = TokenStream::new();
for (i, attr) in attrs.into_iter().enumerate() {
if i > 0 {
ts = quote! { #ts, };
}
ts = quote! { #ts #attr };
}
quote! {
#[sea_orm(#ts)]
}
} else {
TokenStream::new()
}
})
.collect();
let extra_derive = with_serde.extra_derive();
quote! {
#[derive(Clone, Debug, PartialEq, DeriveEntityModel #extra_derive)]
#[sea_orm(table_name = #table_name)]
pub struct Model {
#(
#attrs
pub #column_names_snake_case: #column_rs_types,
)*
}
}
}
pub fn gen_import() -> TokenStream {
let prelude_import = quote!(
use akiata::*;
);
prelude_import
}
pub fn gen_expanded_code_blocks(entity: &Entity) -> Vec<TokenStream> {
let mut imports = Self::gen_import();
let mut code_blocks = vec![
imports,
Self::gen_entity_struct(),
];
code_blocks
}
pub fn gen_entity_struct() -> TokenStream {
quote! {
#[derive(Copy, Clone, Default, Debug, AkitaTable, ToAkita, FromAkita)]
pub struct Entity;
}
}
}