api-macro: support raw method parameters

Support raw parameter name identifiers (eg. `r#type`)

    #[api(
        input: {
            properties: {
                type: {
                    type: String,
                    description: "Foo",
                },
            },
        },
    )]
    fn foo(r#type: String) { code... }

The "r#type" parameter in the fn decl will match the "type"
parameter name in the input property list.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-11-10 13:53:06 +01:00
parent 0c816fe383
commit 055793c481
2 changed files with 41 additions and 3 deletions

View File

@ -12,6 +12,7 @@ use anyhow::Error;
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned}; use quote::{quote, quote_spanned};
use syn::ext::IdentExt;
use syn::spanned::Spanned; use syn::spanned::Spanned;
use syn::visit_mut::{self, VisitMut}; use syn::visit_mut::{self, VisitMut};
use syn::Ident; use syn::Ident;
@ -251,9 +252,10 @@ fn handle_function_signature(
// //
// 5) Finally, if none of the above conditions are met, we do not know what to do and // 5) Finally, if none of the above conditions are met, we do not know what to do and
// bail out with an error. // bail out with an error.
let mut param_name: FieldName = pat.ident.clone().into(); let pat_ident = pat.ident.unraw();
let mut param_name: FieldName = pat_ident.clone().into();
let param_type = if let Some((name, optional, schema)) = let param_type = if let Some((name, optional, schema)) =
input_schema.find_obj_property_by_ident(&pat.ident.to_string()) input_schema.find_obj_property_by_ident(&pat_ident.to_string())
{ {
if let SchemaItem::Inferred(span) = &schema.item { if let SchemaItem::Inferred(span) = &schema.item {
bail!(*span, "failed to infer type"); bail!(*span, "failed to infer type");
@ -280,7 +282,7 @@ fn handle_function_signature(
value_param = Some(param_list.len()); value_param = Some(param_list.len());
ParameterType::Value ParameterType::Value
} else { } else {
bail!(&pat.ident => "unexpected parameter"); bail!(&pat_ident => "unexpected parameter {:?}", pat_ident.to_string());
}; };
param_list.push((param_name, param_type)); param_list.push((param_name, param_type));

View File

@ -97,3 +97,39 @@ fn more_async_params_schema_check() {
assert_eq!(TEST_METHOD, API_METHOD_MORE_ASYNC_PARAMS); assert_eq!(TEST_METHOD, API_METHOD_MORE_ASYNC_PARAMS);
} }
#[api(
input: {
properties: {
type: {
type: String,
description: "The great Foo",
},
},
},
)]
/// Returns nothing.
pub async fn keyword_named_parameters(r#type: String) -> Result<(), Error> {
let _ = r#type;
Ok(())
}
#[test]
fn keyword_named_parameters_check() {
const TEST_METHOD: ::proxmox::api::ApiMethod = ::proxmox::api::ApiMethod::new(
&::proxmox::api::ApiHandler::Async(&api_function_keyword_named_parameters),
&::proxmox::api::schema::ObjectSchema::new(
"Returns nothing.",
&[
(
"type",
false,
&::proxmox::api::schema::StringSchema::new("The great Foo").schema(),
),
],
),
)
.protected(false);
assert_eq!(TEST_METHOD, API_METHOD_KEYWORD_NAMED_PARAMETERS);
}