mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
feat: allow for documentation and other attributes to fields in server fn (#2876)
This commit is contained in:
parent
4f1ee65e6c
commit
9fc26e609c
1 changed files with 108 additions and 23 deletions
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
use convert_case::{Case, Converter};
|
use convert_case::{Case, Converter};
|
||||||
use proc_macro2::{Literal, Span, TokenStream as TokenStream2};
|
use proc_macro2::{Literal, Span, TokenStream as TokenStream2};
|
||||||
use quote::{quote, quote_spanned, ToTokens};
|
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
|
@ -74,32 +74,117 @@ pub fn server_macro_impl(
|
||||||
ident.mutability = None;
|
ident.mutability = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow #[server(default)] on fields
|
fn rename_path(
|
||||||
let mut default = false;
|
path: Path,
|
||||||
let mut other_attrs = Vec::new();
|
from_ident: Ident,
|
||||||
for attr in typed_arg.attrs.iter() {
|
to_ident: Ident,
|
||||||
if !attr.path().is_ident("server") {
|
) -> Path {
|
||||||
other_attrs.push(attr.clone());
|
if path.is_ident(&from_ident) {
|
||||||
continue;
|
Path {
|
||||||
|
leading_colon: None,
|
||||||
|
segments: Punctuated::from_iter([PathSegment {
|
||||||
|
ident: to_ident,
|
||||||
|
arguments: PathArguments::None,
|
||||||
|
}]),
|
||||||
}
|
}
|
||||||
attr.parse_nested_meta(|meta| {
|
|
||||||
if meta.path.is_ident("default") && meta.input.is_empty() {
|
|
||||||
default = true;
|
|
||||||
Ok(())
|
|
||||||
} else {
|
} else {
|
||||||
Err(meta.error(
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let attrs = typed_arg
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|attr| {
|
||||||
|
if attr.path().is_ident("server") {
|
||||||
|
// Allow the following attributes:
|
||||||
|
// - #[server(default)]
|
||||||
|
// - #[server(rename = "fieldName")]
|
||||||
|
|
||||||
|
// Rename `server` to `serde`
|
||||||
|
let attr = Attribute {
|
||||||
|
meta: match attr.meta {
|
||||||
|
Meta::Path(path) => Meta::Path(rename_path(
|
||||||
|
path,
|
||||||
|
format_ident!("server"),
|
||||||
|
format_ident!("serde"),
|
||||||
|
)),
|
||||||
|
Meta::List(mut list) => {
|
||||||
|
list.path = rename_path(
|
||||||
|
list.path,
|
||||||
|
format_ident!("server"),
|
||||||
|
format_ident!("serde"),
|
||||||
|
);
|
||||||
|
Meta::List(list)
|
||||||
|
}
|
||||||
|
Meta::NameValue(mut name_value) => {
|
||||||
|
name_value.path = rename_path(
|
||||||
|
name_value.path,
|
||||||
|
format_ident!("server"),
|
||||||
|
format_ident!("serde"),
|
||||||
|
);
|
||||||
|
Meta::NameValue(name_value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
..attr
|
||||||
|
};
|
||||||
|
|
||||||
|
let args = attr.parse_args::<Meta>()?;
|
||||||
|
match args {
|
||||||
|
// #[server(default)]
|
||||||
|
Meta::Path(path) if path.is_ident("default") => {
|
||||||
|
Ok(attr.clone())
|
||||||
|
}
|
||||||
|
// #[server(flatten)]
|
||||||
|
Meta::Path(path) if path.is_ident("flatten") => {
|
||||||
|
Ok(attr.clone())
|
||||||
|
}
|
||||||
|
// #[server(default = "value")]
|
||||||
|
Meta::NameValue(name_value)
|
||||||
|
if name_value.path.is_ident("default") =>
|
||||||
|
{
|
||||||
|
Ok(attr.clone())
|
||||||
|
}
|
||||||
|
// #[server(skip)]
|
||||||
|
Meta::Path(path) if path.is_ident("skip") => {
|
||||||
|
Ok(attr.clone())
|
||||||
|
}
|
||||||
|
// #[server(rename = "value")]
|
||||||
|
Meta::NameValue(name_value)
|
||||||
|
if name_value.path.is_ident("rename") =>
|
||||||
|
{
|
||||||
|
Ok(attr.clone())
|
||||||
|
}
|
||||||
|
_ => Err(Error::new(
|
||||||
|
attr.span(),
|
||||||
"Unrecognized #[server] attribute, expected \
|
"Unrecognized #[server] attribute, expected \
|
||||||
#[server(default)]",
|
#[server(default)] or #[server(rename = \
|
||||||
|
\"fieldName\")]",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
} else if attr.path().is_ident("doc") {
|
||||||
|
// Allow #[doc = "documentation"]
|
||||||
|
Ok(attr.clone())
|
||||||
|
} else if attr.path().is_ident("allow") {
|
||||||
|
// Allow #[allow(...)]
|
||||||
|
Ok(attr.clone())
|
||||||
|
} else if attr.path().is_ident("deny") {
|
||||||
|
// Allow #[deny(...)]
|
||||||
|
Ok(attr.clone())
|
||||||
|
} else if attr.path().is_ident("ignore") {
|
||||||
|
// Allow #[ignore]
|
||||||
|
Ok(attr.clone())
|
||||||
|
} else {
|
||||||
|
Err(Error::new(
|
||||||
|
attr.span(),
|
||||||
|
"Unrecognized attribute, expected #[server(...)]",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})?;
|
})
|
||||||
}
|
.collect::<Result<Vec<_>>>()?;
|
||||||
typed_arg.attrs = other_attrs;
|
typed_arg.attrs = vec![];
|
||||||
if default {
|
Ok(quote! { #(#attrs ) * pub #typed_arg })
|
||||||
Ok(quote! { #[serde(default)] pub #typed_arg })
|
|
||||||
} else {
|
|
||||||
Ok(quote! { pub #typed_arg })
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue