mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-13 16:08:00 +00:00
api-macro: refactoring: split api macro function
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
97c29f0db5
commit
7799deb095
@ -278,76 +278,8 @@ impl<T: Parse> Parse for BareAssignment<T> {
|
|||||||
pub(crate) fn api(_attr: TokenStream, item: TokenStream) -> Result<TokenStream, Error> {
|
pub(crate) fn api(_attr: TokenStream, item: TokenStream) -> Result<TokenStream, Error> {
|
||||||
let mut func: syn::ItemFn = syn::parse2(item)?;
|
let mut func: syn::ItemFn = syn::parse2(item)?;
|
||||||
|
|
||||||
let sig_span = func.sig.span();
|
let (input_schema, returns_schema, protected) =
|
||||||
|
api_function_attributes(&mut func.attrs, func.sig.span())?;
|
||||||
let mut protected = false;
|
|
||||||
|
|
||||||
let mut input_schema = None;
|
|
||||||
let mut returns_schema = None;
|
|
||||||
let mut doc_comment = String::new();
|
|
||||||
let doc_span = Span::call_site(); // FIXME: set to first doc comment
|
|
||||||
for attr in mem::replace(&mut func.attrs, Vec::new()) {
|
|
||||||
// don't mess with #![...]
|
|
||||||
if let syn::AttrStyle::Inner(_) = &attr.style {
|
|
||||||
func.attrs.push(attr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if attr.path.is_ident("doc") {
|
|
||||||
let doc: BareAssignment<syn::LitStr> = syn::parse2(attr.tokens.clone())?;
|
|
||||||
if !doc_comment.is_empty() {
|
|
||||||
doc_comment.push_str("\n");
|
|
||||||
}
|
|
||||||
doc_comment.push_str(doc.content.value().trim());
|
|
||||||
func.attrs.push(attr);
|
|
||||||
} else if attr.path.is_ident("input") {
|
|
||||||
let input: Parenthesized<Schema> = syn::parse2(attr.tokens)?;
|
|
||||||
input_schema = Some(input.content);
|
|
||||||
} else if attr.path.is_ident("returns") {
|
|
||||||
let input: Parenthesized<Schema> = syn::parse2(attr.tokens)?;
|
|
||||||
returns_schema = Some(input.content);
|
|
||||||
} else if attr.path.is_ident("protected") {
|
|
||||||
if attr.tokens.is_empty() {
|
|
||||||
protected = true;
|
|
||||||
} else {
|
|
||||||
let value: Parenthesized<syn::LitBool> = syn::parse2(attr.tokens)?;
|
|
||||||
protected = value.content.value;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
func.attrs.push(attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut input_schema =
|
|
||||||
input_schema.ok_or_else(|| format_err!(sig_span, "missing input schema"))?;
|
|
||||||
|
|
||||||
let mut returns_schema =
|
|
||||||
returns_schema.ok_or_else(|| format_err!(sig_span, "missing returns schema"))?;
|
|
||||||
|
|
||||||
// If we have a doc comment, allow automatically inferring the description for the input and
|
|
||||||
// output objects:
|
|
||||||
if !doc_comment.is_empty() {
|
|
||||||
let mut parts = doc_comment.split("\nReturns:");
|
|
||||||
|
|
||||||
if let Some(first) = parts.next() {
|
|
||||||
if input_schema.description.is_none() {
|
|
||||||
input_schema.description = Some(syn::LitStr::new(first.trim(), doc_span));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(second) = parts.next() {
|
|
||||||
if returns_schema.description.is_none() {
|
|
||||||
returns_schema.description = Some(syn::LitStr::new(second.trim(), doc_span));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts.next().is_some() {
|
|
||||||
bail!(
|
|
||||||
doc_span,
|
|
||||||
"multiple 'Returns:' sections found in doc comment!"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let input_schema = {
|
let input_schema = {
|
||||||
let mut ts = TokenStream::new();
|
let mut ts = TokenStream::new();
|
||||||
@ -368,7 +300,7 @@ pub(crate) fn api(_attr: TokenStream, item: TokenStream) -> Result<TokenStream,
|
|||||||
func.sig.ident.span(),
|
func.sig.ident.span(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(quote_spanned! { sig_span =>
|
Ok(quote_spanned! { func.sig.span() =>
|
||||||
#vis const #api_method_name: ::proxmox::api::ApiMethod =
|
#vis const #api_method_name: ::proxmox::api::ApiMethod =
|
||||||
::proxmox::api::ApiMethod::new(
|
::proxmox::api::ApiMethod::new(
|
||||||
&::proxmox::api::ApiHandler::Sync(&#func_name),
|
&::proxmox::api::ApiHandler::Sync(&#func_name),
|
||||||
@ -380,3 +312,97 @@ pub(crate) fn api(_attr: TokenStream, item: TokenStream) -> Result<TokenStream,
|
|||||||
})
|
})
|
||||||
//Ok(quote::quote!(#func))
|
//Ok(quote::quote!(#func))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn api_function_attributes(
|
||||||
|
attrs: &mut Vec<syn::Attribute>,
|
||||||
|
sig_span: Span,
|
||||||
|
) -> Result<(Schema, Schema, bool), Error> {
|
||||||
|
let mut protected = false;
|
||||||
|
let mut input_schema = None;
|
||||||
|
let mut returns_schema = None;
|
||||||
|
let mut doc_comment = String::new();
|
||||||
|
let doc_span = Span::call_site(); // FIXME: set to first doc comment
|
||||||
|
|
||||||
|
for attr in mem::replace(attrs, Vec::new()) {
|
||||||
|
// don't mess with #![...]
|
||||||
|
if let syn::AttrStyle::Inner(_) = &attr.style {
|
||||||
|
attrs.push(attr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr.path.is_ident("doc") {
|
||||||
|
let doc: BareAssignment<syn::LitStr> = syn::parse2(attr.tokens.clone())?;
|
||||||
|
if !doc_comment.is_empty() {
|
||||||
|
doc_comment.push_str("\n");
|
||||||
|
}
|
||||||
|
doc_comment.push_str(doc.content.value().trim());
|
||||||
|
attrs.push(attr);
|
||||||
|
} else if attr.path.is_ident("input") {
|
||||||
|
let input: Parenthesized<Schema> = syn::parse2(attr.tokens)?;
|
||||||
|
input_schema = Some(input.content);
|
||||||
|
} else if attr.path.is_ident("returns") {
|
||||||
|
let input: Parenthesized<Schema> = syn::parse2(attr.tokens)?;
|
||||||
|
returns_schema = Some(input.content);
|
||||||
|
} else if attr.path.is_ident("protected") {
|
||||||
|
if attr.tokens.is_empty() {
|
||||||
|
protected = true;
|
||||||
|
} else {
|
||||||
|
let value: Parenthesized<syn::LitBool> = syn::parse2(attr.tokens)?;
|
||||||
|
protected = value.content.value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attrs.push(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut input_schema =
|
||||||
|
input_schema.ok_or_else(|| format_err!(sig_span, "missing input schema"))?;
|
||||||
|
|
||||||
|
let mut returns_schema =
|
||||||
|
returns_schema.ok_or_else(|| format_err!(sig_span, "missing returns schema"))?;
|
||||||
|
|
||||||
|
derive_descriptions(
|
||||||
|
&mut input_schema,
|
||||||
|
&mut returns_schema,
|
||||||
|
&doc_comment,
|
||||||
|
doc_span,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok((input_schema, returns_schema, protected))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn derive_descriptions(
|
||||||
|
input_schema: &mut Schema,
|
||||||
|
returns_schema: &mut Schema,
|
||||||
|
doc_comment: &str,
|
||||||
|
doc_span: Span,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// If we have a doc comment, allow automatically inferring the description for the input and
|
||||||
|
// output objects:
|
||||||
|
if doc_comment.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut parts = doc_comment.split("\nReturns:");
|
||||||
|
|
||||||
|
if let Some(first) = parts.next() {
|
||||||
|
if input_schema.description.is_none() {
|
||||||
|
input_schema.description = Some(syn::LitStr::new(first.trim(), doc_span));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(second) = parts.next() {
|
||||||
|
if returns_schema.description.is_none() {
|
||||||
|
returns_schema.description = Some(syn::LitStr::new(second.trim(), doc_span));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if parts.next().is_some() {
|
||||||
|
bail!(
|
||||||
|
doc_span,
|
||||||
|
"multiple 'Returns:' sections found in doc comment!"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user