Upgrading to syn v2 (#1713)
* resetted and re-did the changes * fmt * upgraded to syn2 for sea-orm-codegen * Rename `bae2` * Drop the use of `#[sea_orm(table_name = "col_name")]` in `DeriveColumn` * unified derived input metadata parsing filter * Propagate errors --------- Co-authored-by: Billy Chan <ccw.billy.123@gmail.com>
This commit is contained in:
parent
35c274818b
commit
64342b105c
@ -18,7 +18,7 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-query = { version = "0.29.0-rc.2", default-features = false, features = ["thread-safe"] }
|
sea-query = { version = "0.29.0-rc.2", default-features = false, features = ["thread-safe"] }
|
||||||
syn = { version = "1", default-features = false, features = ["parsing", "proc-macro", "derive", "printing"] }
|
syn = { version = "2", default-features = false, features = ["parsing", "proc-macro", "derive", "printing"] }
|
||||||
quote = { version = "1", default-features = false }
|
quote = { version = "1", default-features = false }
|
||||||
heck = { version = "0.4", default-features = false }
|
heck = { version = "0.4", default-features = false }
|
||||||
proc-macro2 = { version = "1", default-features = false }
|
proc-macro2 = { version = "1", default-features = false }
|
||||||
|
@ -18,8 +18,8 @@ path = "src/lib.rs"
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bae = { version = "0.1", default-features = false, optional = true }
|
bae = { version = "1", package = "bae2", default-features = false, optional = true }
|
||||||
syn = { version = "1", default-features = false, features = ["parsing", "proc-macro", "derive", "printing"] }
|
syn = { version = "2", default-features = false, features = ["parsing", "proc-macro", "derive", "printing"] }
|
||||||
quote = { version = "1", default-features = false }
|
quote = { version = "1", default-features = false }
|
||||||
heck = { version = "0.4", default-features = false }
|
heck = { version = "0.4", default-features = false }
|
||||||
proc-macro2 = { version = "1", default-features = false }
|
proc-macro2 = { version = "1", default-features = false }
|
||||||
|
@ -2,7 +2,7 @@ use super::util::camel_case_with_escaped_non_uax31;
|
|||||||
use heck::ToUpperCamelCase;
|
use heck::ToUpperCamelCase;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote, quote_spanned};
|
use quote::{format_ident, quote, quote_spanned};
|
||||||
use syn::{parse, punctuated::Punctuated, token::Comma, Expr, Lit, LitInt, LitStr, Meta, UnOp};
|
use syn::{parse, Expr, Lit, LitInt, LitStr, UnOp};
|
||||||
|
|
||||||
enum Error {
|
enum Error {
|
||||||
InputNotEnum,
|
InputNotEnum,
|
||||||
@ -37,51 +37,46 @@ impl ActiveEnum {
|
|||||||
let mut db_type = Err(Error::TT(quote_spanned! {
|
let mut db_type = Err(Error::TT(quote_spanned! {
|
||||||
ident_span => compile_error!("Missing macro attribute `db_type`");
|
ident_span => compile_error!("Missing macro attribute `db_type`");
|
||||||
}));
|
}));
|
||||||
for attr in input.attrs.iter() {
|
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
input
|
||||||
if ident != "sea_orm" {
|
.attrs
|
||||||
continue;
|
.iter()
|
||||||
}
|
.filter(|attr| attr.path().is_ident("sea_orm"))
|
||||||
} else {
|
.try_for_each(|attr| {
|
||||||
continue;
|
attr.parse_nested_meta(|meta| {
|
||||||
}
|
if meta.path.is_ident("rs_type") {
|
||||||
if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated) {
|
let litstr: LitStr = meta.value()?.parse()?;
|
||||||
for meta in list.iter() {
|
rs_type =
|
||||||
if let Meta::NameValue(nv) = meta {
|
syn::parse_str::<TokenStream>(&litstr.value()).map_err(Error::Syn);
|
||||||
if let Some(name) = nv.path.get_ident() {
|
} else if meta.path.is_ident("db_type") {
|
||||||
if name == "rs_type" {
|
let litstr: LitStr = meta.value()?.parse()?;
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
let s = litstr.value();
|
||||||
rs_type = syn::parse_str::<TokenStream>(&litstr.value())
|
match s.as_ref() {
|
||||||
.map_err(Error::Syn);
|
"Enum" => {
|
||||||
}
|
db_type = Ok(quote! {
|
||||||
} else if name == "db_type" {
|
Enum {
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
name: Self::name(),
|
||||||
let s = litstr.value();
|
variants: Self::iden_values(),
|
||||||
match s.as_ref() {
|
|
||||||
"Enum" => {
|
|
||||||
db_type = Ok(quote! {
|
|
||||||
Enum {
|
|
||||||
name: Self::name(),
|
|
||||||
variants: Self::iden_values(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
db_type = syn::parse_str::<TokenStream>(&s)
|
|
||||||
.map_err(Error::Syn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
} else if name == "enum_name" {
|
}
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
_ => {
|
||||||
enum_name = litstr.value();
|
db_type = syn::parse_str::<TokenStream>(&s).map_err(Error::Syn);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if meta.path.is_ident("enum_name") {
|
||||||
|
let litstr: LitStr = meta.value()?.parse()?;
|
||||||
|
enum_name = litstr.value();
|
||||||
|
} else {
|
||||||
|
return Err(meta.error(format!(
|
||||||
|
"Unknown attribute parameter found: {:?}",
|
||||||
|
meta.path.get_ident()
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
}
|
})
|
||||||
}
|
.map_err(Error::Syn)
|
||||||
|
})?;
|
||||||
|
|
||||||
let variant_vec = match input.data {
|
let variant_vec = match input.data {
|
||||||
syn::Data::Enum(syn::DataEnum { variants, .. }) => variants,
|
syn::Data::Enum(syn::DataEnum { variants, .. }) => variants,
|
||||||
@ -96,33 +91,26 @@ impl ActiveEnum {
|
|||||||
let mut string_value = None;
|
let mut string_value = None;
|
||||||
let mut num_value = None;
|
let mut num_value = None;
|
||||||
for attr in variant.attrs.iter() {
|
for attr in variant.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if !attr.path().is_ident("sea_orm") {
|
||||||
if ident != "sea_orm" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
|
attr.parse_nested_meta(|meta| {
|
||||||
{
|
if meta.path.is_ident("string_value") {
|
||||||
for meta in list {
|
is_string = true;
|
||||||
if let Meta::NameValue(nv) = meta {
|
string_value = Some(meta.value()?.parse::<LitStr>()?);
|
||||||
if let Some(name) = nv.path.get_ident() {
|
} else if meta.path.is_ident("num_value") {
|
||||||
if name == "string_value" {
|
is_int = true;
|
||||||
if let Lit::Str(lit) = nv.lit {
|
num_value = Some(meta.value()?.parse::<LitInt>()?);
|
||||||
is_string = true;
|
} else {
|
||||||
string_value = Some(lit);
|
return Err(meta.error(format!(
|
||||||
}
|
"Unknown attribute parameter found: {:?}",
|
||||||
} else if name == "num_value" {
|
meta.path.get_ident()
|
||||||
if let Lit::Int(lit) = nv.lit {
|
)));
|
||||||
is_int = true;
|
|
||||||
num_value = Some(lit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.map_err(Error::Syn)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_string && is_int {
|
if is_string && is_int {
|
||||||
|
@ -4,11 +4,7 @@ use super::util::{
|
|||||||
use heck::ToUpperCamelCase;
|
use heck::ToUpperCamelCase;
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote, quote_spanned};
|
use quote::{format_ident, quote, quote_spanned};
|
||||||
use syn::{
|
use syn::{punctuated::IntoIter, Data, DataStruct, Expr, Field, Fields, LitStr, Type};
|
||||||
punctuated::{IntoIter, Punctuated},
|
|
||||||
token::Comma,
|
|
||||||
Data, DataStruct, Field, Fields, Lit, Meta, Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Method to derive an [ActiveModel](sea_orm::ActiveModel)
|
/// Method to derive an [ActiveModel](sea_orm::ActiveModel)
|
||||||
pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<TokenStream> {
|
pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<TokenStream> {
|
||||||
@ -47,32 +43,28 @@ fn derive_active_model(all_fields: IntoIter<Field>) -> syn::Result<TokenStream>
|
|||||||
let ident = trim_starting_raw_identifier(ident).to_upper_camel_case();
|
let ident = trim_starting_raw_identifier(ident).to_upper_camel_case();
|
||||||
let ident = escape_rust_keyword(ident);
|
let ident = escape_rust_keyword(ident);
|
||||||
let mut ident = format_ident!("{}", &ident);
|
let mut ident = format_ident!("{}", &ident);
|
||||||
for attr in field.attrs.iter() {
|
field
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
.attrs
|
||||||
if ident != "sea_orm" {
|
.iter()
|
||||||
continue;
|
.filter(|attr| attr.path().is_ident("sea_orm"))
|
||||||
}
|
.try_for_each(|attr| {
|
||||||
} else {
|
attr.parse_nested_meta(|meta| {
|
||||||
continue;
|
if meta.path.is_ident("enum_name") {
|
||||||
}
|
let litstr: LitStr = meta.value()?.parse()?;
|
||||||
if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
|
ident = syn::parse_str(&litstr.value()).unwrap();
|
||||||
{
|
} else {
|
||||||
for meta in list.iter() {
|
// Reads the value expression to advance the parse stream.
|
||||||
if let Meta::NameValue(nv) = meta {
|
// Some parameters, such as `primary_key`, do not have any value,
|
||||||
if let Some(name) = nv.path.get_ident() {
|
// so ignoring an error occurred here.
|
||||||
if name == "enum_name" {
|
let _: Option<Expr> = meta.value().and_then(|v| v.parse()).ok();
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
|
||||||
ident = syn::parse_str(&litstr.value()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
Ok(())
|
||||||
}
|
})
|
||||||
ident
|
})?;
|
||||||
|
Ok::<Ident, syn::Error>(ident)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
let ty: Vec<Type> = fields.into_iter().map(|Field { ty, .. }| ty).collect();
|
let ty: Vec<Type> = fields.into_iter().map(|Field { ty, .. }| ty).collect();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use heck::{ToLowerCamelCase, ToSnakeCase};
|
use heck::{ToLowerCamelCase, ToSnakeCase};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
use syn::{punctuated::Punctuated, token::Comma, Data, DataEnum, Fields, Lit, Meta, Variant};
|
use syn::{Data, DataEnum, Expr, Fields, LitStr, Variant};
|
||||||
|
|
||||||
/// Derive a Column name for an enum type
|
/// Derive a Column name for an enum type
|
||||||
pub fn impl_default_as_str(ident: &Ident, data: &Data) -> syn::Result<TokenStream> {
|
pub fn impl_default_as_str(ident: &Ident, data: &Data) -> syn::Result<TokenStream> {
|
||||||
@ -28,36 +28,24 @@ pub fn impl_default_as_str(ident: &Ident, data: &Data) -> syn::Result<TokenStrea
|
|||||||
.map(|v| {
|
.map(|v| {
|
||||||
let mut column_name = v.ident.to_string().to_snake_case();
|
let mut column_name = v.ident.to_string().to_snake_case();
|
||||||
for attr in v.attrs.iter() {
|
for attr in v.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if !attr.path().is_ident("sea_orm") {
|
||||||
if ident != "sea_orm" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
|
attr.parse_nested_meta(|meta| {
|
||||||
{
|
if meta.path.is_ident("column_name") {
|
||||||
for meta in list.iter() {
|
column_name = meta.value()?.parse::<LitStr>()?.value();
|
||||||
if let Meta::NameValue(nv) = meta {
|
} else {
|
||||||
if let Some(name) = nv.path.get_ident() {
|
// Reads the value expression to advance the parse stream.
|
||||||
if name == "column_name" {
|
// Some parameters, such as `primary_key`, do not have any value,
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
// so ignoring an error occurred here.
|
||||||
column_name = litstr.value();
|
let _: Option<Expr> = meta.value().and_then(|v| v.parse()).ok();
|
||||||
}
|
|
||||||
}
|
|
||||||
if name == "table_name" {
|
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
|
||||||
column_name = litstr.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
quote! { #column_name }
|
Ok::<TokenStream, syn::Error>(quote! { #column_name })
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
Ok(quote!(
|
Ok(quote!(
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
@ -3,8 +3,8 @@ use heck::{ToSnakeCase, ToUpperCamelCase};
|
|||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::Error, punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, Fields,
|
punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, Expr, Fields, Lit,
|
||||||
Lit, LitStr, Meta, Type,
|
LitStr, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Method to derive an Model
|
/// Method to derive an Model
|
||||||
@ -13,32 +13,28 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
|
|||||||
let mut table_name = None;
|
let mut table_name = None;
|
||||||
let mut schema_name = quote! { None };
|
let mut schema_name = quote! { None };
|
||||||
let mut table_iden = false;
|
let mut table_iden = false;
|
||||||
attrs.iter().for_each(|attr| {
|
attrs
|
||||||
if attr.path.get_ident().map(|i| i == "sea_orm") != Some(true) {
|
.iter()
|
||||||
return;
|
.filter(|attr| attr.path().is_ident("sea_orm"))
|
||||||
}
|
.try_for_each(|attr| {
|
||||||
|
attr.parse_nested_meta(|meta| {
|
||||||
if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated) {
|
if meta.path.is_ident("table_name") {
|
||||||
for meta in list.iter() {
|
table_name = Some(meta.value()?.parse::<Lit>()?);
|
||||||
if let Meta::NameValue(nv) = meta {
|
} else if meta.path.is_ident("schema_name") {
|
||||||
if let Some(ident) = nv.path.get_ident() {
|
let name: Lit = meta.value()?.parse()?;
|
||||||
if ident == "table_name" {
|
schema_name = quote! { Some(#name) };
|
||||||
table_name = Some(nv.lit.clone());
|
} else if meta.path.is_ident("table_iden") {
|
||||||
} else if ident == "schema_name" {
|
table_iden = true;
|
||||||
let name = &nv.lit;
|
} else {
|
||||||
schema_name = quote! { Some(#name) };
|
// Reads the value expression to advance the parse stream.
|
||||||
}
|
// Some parameters, such as `primary_key`, do not have any value,
|
||||||
}
|
// so ignoring an error occurred here.
|
||||||
} else if let Meta::Path(path) = meta {
|
let _: Option<Expr> = meta.value().and_then(|v| v.parse()).ok();
|
||||||
if let Some(ident) = path.get_ident() {
|
|
||||||
if ident == "table_iden" {
|
|
||||||
table_iden = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
Ok(())
|
||||||
});
|
})
|
||||||
|
})?;
|
||||||
let entity_def = table_name
|
let entity_def = table_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|table_name| {
|
.map(|table_name| {
|
||||||
@ -114,111 +110,86 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
|
|||||||
let mut is_primary_key = false;
|
let mut is_primary_key = false;
|
||||||
// search for #[sea_orm(primary_key, auto_increment = false, column_type = "String(Some(255))", default_value = "new user", default_expr = "gen_random_uuid()", column_name = "name", enum_name = "Name", nullable, indexed, unique)]
|
// search for #[sea_orm(primary_key, auto_increment = false, column_type = "String(Some(255))", default_value = "new user", default_expr = "gen_random_uuid()", column_name = "name", enum_name = "Name", nullable, indexed, unique)]
|
||||||
for attr in field.attrs.iter() {
|
for attr in field.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if !attr.path().is_ident("sea_orm") {
|
||||||
if ident != "sea_orm" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// single param
|
// single param
|
||||||
if let Ok(list) =
|
attr.parse_nested_meta(|meta| {
|
||||||
attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
|
if meta.path.is_ident("column_type") {
|
||||||
{
|
let lit = meta.value()?.parse()?;
|
||||||
for meta in list.iter() {
|
if let Lit::Str(litstr) = lit {
|
||||||
match meta {
|
let ty: TokenStream = syn::parse_str(&litstr.value())?;
|
||||||
Meta::NameValue(nv) => {
|
sql_type = Some(ty);
|
||||||
if let Some(name) = nv.path.get_ident() {
|
} else {
|
||||||
if name == "column_type" {
|
return Err(
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
meta.error(format!("Invalid column_type {:?}", lit))
|
||||||
let ty: TokenStream =
|
);
|
||||||
syn::parse_str(&litstr.value())?;
|
|
||||||
sql_type = Some(ty);
|
|
||||||
} else {
|
|
||||||
return Err(Error::new(
|
|
||||||
field.span(),
|
|
||||||
format!("Invalid column_type {:?}", nv.lit),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else if name == "auto_increment" {
|
|
||||||
if let Lit::Bool(litbool) = &nv.lit {
|
|
||||||
auto_increment = litbool.value();
|
|
||||||
} else {
|
|
||||||
return Err(Error::new(
|
|
||||||
field.span(),
|
|
||||||
format!(
|
|
||||||
"Invalid auto_increment = {:?}",
|
|
||||||
nv.lit
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else if name == "default_value" {
|
|
||||||
default_value = Some(nv.lit.to_owned());
|
|
||||||
} else if name == "default_expr" {
|
|
||||||
default_expr = Some(nv.lit.to_owned());
|
|
||||||
} else if name == "column_name" {
|
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
|
||||||
column_name = Some(litstr.value());
|
|
||||||
} else {
|
|
||||||
return Err(Error::new(
|
|
||||||
field.span(),
|
|
||||||
format!("Invalid column_name {:?}", nv.lit),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else if name == "enum_name" {
|
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
|
||||||
let ty: Ident =
|
|
||||||
syn::parse_str(&litstr.value())?;
|
|
||||||
enum_name = Some(ty);
|
|
||||||
} else {
|
|
||||||
return Err(Error::new(
|
|
||||||
field.span(),
|
|
||||||
format!("Invalid enum_name {:?}", nv.lit),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else if name == "select_as" {
|
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
|
||||||
select_as = Some(litstr.value());
|
|
||||||
} else {
|
|
||||||
return Err(Error::new(
|
|
||||||
field.span(),
|
|
||||||
format!("Invalid select_as {:?}", nv.lit),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else if name == "save_as" {
|
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
|
||||||
save_as = Some(litstr.value());
|
|
||||||
} else {
|
|
||||||
return Err(Error::new(
|
|
||||||
field.span(),
|
|
||||||
format!("Invalid save_as {:?}", nv.lit),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Meta::Path(p) => {
|
|
||||||
if let Some(name) = p.get_ident() {
|
|
||||||
if name == "ignore" {
|
|
||||||
ignore = true;
|
|
||||||
break;
|
|
||||||
} else if name == "primary_key" {
|
|
||||||
is_primary_key = true;
|
|
||||||
primary_key_types.push(field.ty.clone());
|
|
||||||
} else if name == "nullable" {
|
|
||||||
nullable = true;
|
|
||||||
} else if name == "indexed" {
|
|
||||||
indexed = true;
|
|
||||||
} else if name == "unique" {
|
|
||||||
unique = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
} else if meta.path.is_ident("auto_increment") {
|
||||||
|
let lit = meta.value()?.parse()?;
|
||||||
|
if let Lit::Bool(litbool) = lit {
|
||||||
|
auto_increment = litbool.value();
|
||||||
|
} else {
|
||||||
|
return Err(
|
||||||
|
meta.error(format!("Invalid auto_increment = {:?}", lit))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if meta.path.is_ident("default_value") {
|
||||||
|
default_value = Some(meta.value()?.parse::<Lit>()?);
|
||||||
|
} else if meta.path.is_ident("default_expr") {
|
||||||
|
default_expr = Some(meta.value()?.parse::<Lit>()?);
|
||||||
|
} else if meta.path.is_ident("column_name") {
|
||||||
|
let lit = meta.value()?.parse()?;
|
||||||
|
if let Lit::Str(litstr) = lit {
|
||||||
|
column_name = Some(litstr.value());
|
||||||
|
} else {
|
||||||
|
return Err(
|
||||||
|
meta.error(format!("Invalid column_name {:?}", lit))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if meta.path.is_ident("enum_name") {
|
||||||
|
let lit = meta.value()?.parse()?;
|
||||||
|
if let Lit::Str(litstr) = lit {
|
||||||
|
let ty: Ident = syn::parse_str(&litstr.value())?;
|
||||||
|
enum_name = Some(ty);
|
||||||
|
} else {
|
||||||
|
return Err(meta.error(format!("Invalid enum_name {:?}", lit)));
|
||||||
|
}
|
||||||
|
} else if meta.path.is_ident("select_as") {
|
||||||
|
let lit = meta.value()?.parse()?;
|
||||||
|
if let Lit::Str(litstr) = lit {
|
||||||
|
select_as = Some(litstr.value());
|
||||||
|
} else {
|
||||||
|
return Err(meta.error(format!("Invalid select_as {:?}", lit)));
|
||||||
|
}
|
||||||
|
} else if meta.path.is_ident("save_as") {
|
||||||
|
let lit = meta.value()?.parse()?;
|
||||||
|
if let Lit::Str(litstr) = lit {
|
||||||
|
save_as = Some(litstr.value());
|
||||||
|
} else {
|
||||||
|
return Err(meta.error(format!("Invalid save_as {:?}", lit)));
|
||||||
|
}
|
||||||
|
} else if meta.path.is_ident("ignore") {
|
||||||
|
ignore = true;
|
||||||
|
} else if meta.path.is_ident("primary_key") {
|
||||||
|
is_primary_key = true;
|
||||||
|
primary_key_types.push(field.ty.clone());
|
||||||
|
} else if meta.path.is_ident("nullable") {
|
||||||
|
nullable = true;
|
||||||
|
} else if meta.path.is_ident("indexed") {
|
||||||
|
indexed = true;
|
||||||
|
} else if meta.path.is_ident("unique") {
|
||||||
|
unique = true;
|
||||||
|
} else {
|
||||||
|
// Reads the value expression to advance the parse stream.
|
||||||
|
// Some parameters, such as `primary_key`, do not have any value,
|
||||||
|
// so ignoring an error occurred here.
|
||||||
|
let _: Option<Expr> = meta.value().and_then(|v| v.parse()).ok();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(enum_name) = enum_name {
|
if let Some(enum_name) = enum_name {
|
||||||
|
@ -6,7 +6,7 @@ use heck::ToUpperCamelCase;
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote, quote_spanned};
|
use quote::{format_ident, quote, quote_spanned};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use syn::{punctuated::Punctuated, token::Comma, Ident, Lit, Meta};
|
use syn::{Expr, Ident, LitStr};
|
||||||
|
|
||||||
enum Error {
|
enum Error {
|
||||||
InputNotStruct,
|
InputNotStruct,
|
||||||
@ -50,33 +50,29 @@ impl DeriveModel {
|
|||||||
let ident = trim_starting_raw_identifier(ident).to_upper_camel_case();
|
let ident = trim_starting_raw_identifier(ident).to_upper_camel_case();
|
||||||
let ident = escape_rust_keyword(ident);
|
let ident = escape_rust_keyword(ident);
|
||||||
let mut ident = format_ident!("{}", &ident);
|
let mut ident = format_ident!("{}", &ident);
|
||||||
for attr in field.attrs.iter() {
|
field
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
.attrs
|
||||||
if ident != "sea_orm" {
|
.iter()
|
||||||
continue;
|
.filter(|attr| attr.path().is_ident("sea_orm"))
|
||||||
}
|
.try_for_each(|attr| {
|
||||||
} else {
|
attr.parse_nested_meta(|meta| {
|
||||||
continue;
|
if meta.path.is_ident("enum_name") {
|
||||||
}
|
ident = syn::parse_str(&meta.value()?.parse::<LitStr>()?.value())
|
||||||
if let Ok(list) =
|
.unwrap();
|
||||||
attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
|
} else {
|
||||||
{
|
// Reads the value expression to advance the parse stream.
|
||||||
for meta in list.iter() {
|
// Some parameters, such as `primary_key`, do not have any value,
|
||||||
if let Meta::NameValue(nv) = meta {
|
// so ignoring an error occurred here.
|
||||||
if let Some(name) = nv.path.get_ident() {
|
let _: Option<Expr> = meta.value().and_then(|v| v.parse()).ok();
|
||||||
if name == "enum_name" {
|
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
|
||||||
ident = syn::parse_str(&litstr.value()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
Ok(())
|
||||||
}
|
})
|
||||||
ident
|
.map_err(Error::Syn)
|
||||||
|
})?;
|
||||||
|
Ok(ident)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
let ignore_attrs = fields
|
let ignore_attrs = fields
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -50,11 +50,7 @@ impl DerivePartialModel {
|
|||||||
let mut entity_ident = None;
|
let mut entity_ident = None;
|
||||||
|
|
||||||
for attr in input.attrs.iter() {
|
for attr in input.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if !attr.path().is_ident("sea_orm") {
|
||||||
if ident != "sea_orm" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +73,7 @@ impl DerivePartialModel {
|
|||||||
let mut from_expr = None;
|
let mut from_expr = None;
|
||||||
|
|
||||||
for attr in field.attrs.iter() {
|
for attr in field.attrs.iter() {
|
||||||
if !attr.path.is_ident("sea_orm") {
|
if !attr.path().is_ident("sea_orm") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +188,7 @@ pub fn expand_derive_partial_model(input: syn::DeriveInput) -> syn::Result<Token
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod util {
|
mod util {
|
||||||
use syn::{Lit, Meta, MetaNameValue};
|
use syn::{Meta, MetaNameValue};
|
||||||
|
|
||||||
pub(super) trait GetAsKVMeta {
|
pub(super) trait GetAsKVMeta {
|
||||||
fn get_as_kv(&self, k: &str) -> Option<String>;
|
fn get_as_kv(&self, k: &str) -> Option<String>;
|
||||||
@ -200,12 +196,14 @@ mod util {
|
|||||||
|
|
||||||
impl GetAsKVMeta for Meta {
|
impl GetAsKVMeta for Meta {
|
||||||
fn get_as_kv(&self, k: &str) -> Option<String> {
|
fn get_as_kv(&self, k: &str) -> Option<String> {
|
||||||
let Meta::NameValue(MetaNameValue{path, lit:Lit::Str(lit), ..}) = self else {
|
let Meta::NameValue(MetaNameValue{path, value: syn::Expr::Lit(exprlit), ..}) = self else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let syn::Lit::Str(litstr) = &exprlit.lit else { return None; };
|
||||||
|
|
||||||
if path.is_ident(k) {
|
if path.is_ident(k) {
|
||||||
Some(lit.value())
|
Some(litstr.value())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
use syn::{punctuated::Punctuated, token::Comma, Data, DataEnum, Fields, Lit, Meta, Variant};
|
use syn::{Data, DataEnum, Expr, Fields, LitStr, Variant};
|
||||||
|
|
||||||
/// Method to derive a Primary Key for a Model using the [PrimaryKeyTrait](sea_orm::PrimaryKeyTrait)
|
/// Method to derive a Primary Key for a Model using the [PrimaryKeyTrait](sea_orm::PrimaryKeyTrait)
|
||||||
pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result<TokenStream> {
|
pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result<TokenStream> {
|
||||||
@ -34,31 +34,26 @@ pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result<TokenS
|
|||||||
.map(|v| {
|
.map(|v| {
|
||||||
let mut column_name = v.ident.to_string().to_snake_case();
|
let mut column_name = v.ident.to_string().to_snake_case();
|
||||||
for attr in v.attrs.iter() {
|
for attr in v.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if !attr.path().is_ident("sea_orm") {
|
||||||
if ident != "sea_orm" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
|
|
||||||
{
|
attr.parse_nested_meta(|meta| {
|
||||||
for meta in list.iter() {
|
if meta.path.is_ident("column_name") {
|
||||||
if let Meta::NameValue(nv) = meta {
|
column_name = meta.value()?.parse::<LitStr>()?.value();
|
||||||
if let Some(name) = nv.path.get_ident() {
|
} else {
|
||||||
if name == "column_name" {
|
// Reads the value expression to advance the parse stream.
|
||||||
if let Lit::Str(litstr) = &nv.lit {
|
// Some parameters, such as `primary_key`, do not have any value,
|
||||||
column_name = litstr.value();
|
// so ignoring an error occurred here.
|
||||||
}
|
let _: Option<Expr> = meta.value().and_then(|v| v.parse()).ok();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
quote! { #column_name }
|
Ok::<TokenStream, syn::Error>(quote! { #column_name })
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
Ok(quote!(
|
Ok(quote!(
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
@ -4,7 +4,7 @@ use syn::{punctuated::Punctuated, token::Comma, Field, Ident, Meta};
|
|||||||
|
|
||||||
pub(crate) fn field_not_ignored(field: &Field) -> bool {
|
pub(crate) fn field_not_ignored(field: &Field) -> bool {
|
||||||
for attr in field.attrs.iter() {
|
for attr in field.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if let Some(ident) = attr.path().get_ident() {
|
||||||
if ident != "sea_orm" {
|
if ident != "sea_orm" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::TokenStream;
|
||||||
use syn::{
|
use syn::{
|
||||||
parenthesized,
|
parenthesized,
|
||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
parse2, parse_str,
|
parse2, parse_str,
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
spanned::Spanned,
|
Attribute, DeriveInput, Expr, ExprLit, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue, Path,
|
||||||
Attribute, DeriveInput, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue, Path, Token, Variant,
|
Token, Variant, Visibility,
|
||||||
Visibility,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::case_style::CaseStyle;
|
use super::case_style::CaseStyle;
|
||||||
@ -76,17 +75,6 @@ impl Parse for EnumMeta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spanned for EnumMeta {
|
|
||||||
fn span(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
EnumMeta::SerializeAll { kw, .. } => kw.span(),
|
|
||||||
EnumMeta::AsciiCaseInsensitive(kw) => kw.span(),
|
|
||||||
EnumMeta::Crate { kw, .. } => kw.span(),
|
|
||||||
EnumMeta::UsePhf(use_phf) => use_phf.span(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum EnumDiscriminantsMeta {
|
pub enum EnumDiscriminantsMeta {
|
||||||
Derive { kw: kw::derive, paths: Vec<Path> },
|
Derive { kw: kw::derive, paths: Vec<Path> },
|
||||||
Name { kw: kw::name, name: Ident },
|
Name { kw: kw::name, name: Ident },
|
||||||
@ -100,7 +88,7 @@ impl Parse for EnumDiscriminantsMeta {
|
|||||||
let kw = input.parse()?;
|
let kw = input.parse()?;
|
||||||
let content;
|
let content;
|
||||||
parenthesized!(content in input);
|
parenthesized!(content in input);
|
||||||
let paths = content.parse_terminated::<_, Token![,]>(Path::parse)?;
|
let paths = content.parse_terminated(Path::parse, Token![,])?;
|
||||||
Ok(EnumDiscriminantsMeta::Derive {
|
Ok(EnumDiscriminantsMeta::Derive {
|
||||||
kw,
|
kw,
|
||||||
paths: paths.into_iter().collect(),
|
paths: paths.into_iter().collect(),
|
||||||
@ -127,17 +115,6 @@ impl Parse for EnumDiscriminantsMeta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spanned for EnumDiscriminantsMeta {
|
|
||||||
fn span(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
EnumDiscriminantsMeta::Derive { kw, .. } => kw.span,
|
|
||||||
EnumDiscriminantsMeta::Name { kw, .. } => kw.span,
|
|
||||||
EnumDiscriminantsMeta::Vis { kw, .. } => kw.span,
|
|
||||||
EnumDiscriminantsMeta::Other { path, .. } => path.span(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DeriveInputExt {
|
pub trait DeriveInputExt {
|
||||||
/// Get all the strum metadata associated with an enum.
|
/// Get all the strum metadata associated with an enum.
|
||||||
fn get_metadata(&self) -> syn::Result<Vec<EnumMeta>>;
|
fn get_metadata(&self) -> syn::Result<Vec<EnumMeta>>;
|
||||||
@ -228,7 +205,7 @@ impl Parse for VariantMeta {
|
|||||||
let kw = input.parse()?;
|
let kw = input.parse()?;
|
||||||
let content;
|
let content;
|
||||||
parenthesized!(content in input);
|
parenthesized!(content in input);
|
||||||
let props = content.parse_terminated::<_, Token![,]>(Prop::parse)?;
|
let props = content.parse_terminated(Prop::parse, Token![,])?;
|
||||||
Ok(VariantMeta::Props {
|
Ok(VariantMeta::Props {
|
||||||
kw,
|
kw,
|
||||||
props: props
|
props: props
|
||||||
@ -256,22 +233,6 @@ impl Parse for Prop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spanned for VariantMeta {
|
|
||||||
fn span(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
VariantMeta::Message { kw, .. } => kw.span,
|
|
||||||
VariantMeta::DetailedMessage { kw, .. } => kw.span,
|
|
||||||
VariantMeta::Documentation { value } => value.span(),
|
|
||||||
VariantMeta::Serialize { kw, .. } => kw.span,
|
|
||||||
VariantMeta::ToString { kw, .. } => kw.span,
|
|
||||||
VariantMeta::Disabled(kw) => kw.span,
|
|
||||||
VariantMeta::Default(kw) => kw.span,
|
|
||||||
VariantMeta::AsciiCaseInsensitive { kw, .. } => kw.span,
|
|
||||||
VariantMeta::Props { kw, .. } => kw.span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait VariantExt {
|
pub trait VariantExt {
|
||||||
/// Get all the metadata associated with an enum variant.
|
/// Get all the metadata associated with an enum variant.
|
||||||
fn get_metadata(&self) -> syn::Result<Vec<VariantMeta>>;
|
fn get_metadata(&self) -> syn::Result<Vec<VariantMeta>>;
|
||||||
@ -282,26 +243,32 @@ impl VariantExt for Variant {
|
|||||||
let result = get_metadata_inner("strum", &self.attrs)?;
|
let result = get_metadata_inner("strum", &self.attrs)?;
|
||||||
self.attrs
|
self.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|attr| attr.path.is_ident("doc"))
|
.filter(|attr| attr.path().is_ident("doc"))
|
||||||
.try_fold(result, |mut vec, attr| {
|
.try_fold(result, |mut vec, attr| {
|
||||||
if let Meta::NameValue(MetaNameValue {
|
if let Meta::NameValue(MetaNameValue {
|
||||||
lit: Lit::Str(value),
|
value:
|
||||||
|
Expr::Lit(ExprLit {
|
||||||
|
lit: Lit::Str(value),
|
||||||
|
..
|
||||||
|
}),
|
||||||
..
|
..
|
||||||
}) = attr.parse_meta()?
|
}) = &attr.meta
|
||||||
{
|
{
|
||||||
vec.push(VariantMeta::Documentation { value })
|
vec.push(VariantMeta::Documentation {
|
||||||
|
value: value.clone(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_metadata_inner<'a, T: Parse + Spanned>(
|
fn get_metadata_inner<'a, T: Parse>(
|
||||||
ident: &str,
|
ident: &str,
|
||||||
it: impl IntoIterator<Item = &'a Attribute>,
|
it: impl IntoIterator<Item = &'a Attribute>,
|
||||||
) -> syn::Result<Vec<T>> {
|
) -> syn::Result<Vec<T>> {
|
||||||
it.into_iter()
|
it.into_iter()
|
||||||
.filter(|attr| attr.path.is_ident(ident))
|
.filter(|attr| attr.path().is_ident(ident))
|
||||||
.try_fold(Vec::new(), |mut vec, attr| {
|
.try_fold(Vec::new(), |mut vec, attr| {
|
||||||
vec.extend(attr.parse_args_with(Punctuated::<T, Token![,]>::parse_terminated)?);
|
vec.extend(attr.parse_args_with(Punctuated::<T, Token![,]>::parse_terminated)?);
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user