Skip to content

Commit d48a923

Browse files
committed
Add wrong testcase
1 parent f69b0e4 commit d48a923

1 file changed

Lines changed: 82 additions & 7 deletions

File tree

crates/vespera_macro/src/parser/parameters.rs

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,11 @@ pub fn parse_function_parameter(
119119
}
120120
} else {
121121
// Single path parameter
122-
// If there's exactly one path parameter, use its name
123-
let name = if path_params.len() == 1 {
124-
path_params[0].clone()
125-
} else {
126-
// Otherwise use the parameter name from the pattern
127-
param_name
128-
};
122+
// Allow only when exactly one path parameter is provided
123+
if path_params.len() != 1 {
124+
return None;
125+
}
126+
let name = path_params[0].clone();
129127
return Some(vec![Parameter {
130128
name,
131129
r#in: ParameterLocation::Path,
@@ -161,6 +159,11 @@ pub fn parse_function_parameter(
161159
return Some(struct_params);
162160
}
163161

162+
// Ignore primitive-like query params (including Vec/Option of primitive)
163+
if is_primitive_like(inner_ty) {
164+
return None;
165+
}
166+
164167
// Check if it's a known type (primitive or known schema)
165168
// If unknown, don't add parameter
166169
if !is_known_type(inner_ty, known_schemas, struct_definitions) {
@@ -188,6 +191,10 @@ pub fn parse_function_parameter(
188191
&& let Some(syn::GenericArgument::Type(inner_ty)) =
189192
args.args.first()
190193
{
194+
// Ignore primitive-like headers
195+
if is_primitive_like(inner_ty) {
196+
return None;
197+
}
191198
return Some(vec![Parameter {
192199
name: param_name.clone(),
193200
r#in: ParameterLocation::Header,
@@ -257,6 +264,25 @@ fn is_map_type(ty: &Type) -> bool {
257264
false
258265
}
259266

267+
fn is_primitive_like(ty: &Type) -> bool {
268+
if is_primitive_type(ty) {
269+
return true;
270+
}
271+
if let Type::Path(type_path) = ty {
272+
if let Some(seg) = type_path.path.segments.last() {
273+
let ident = seg.ident.to_string();
274+
if let syn::PathArguments::AngleBracketed(args) = &seg.arguments {
275+
if let Some(syn::GenericArgument::Type(inner_ty)) = args.args.first() {
276+
if (ident == "Vec" || ident == "Option") && is_primitive_like(inner_ty) {
277+
return true;
278+
}
279+
}
280+
}
281+
}
282+
}
283+
false
284+
}
285+
260286
fn is_known_type(
261287
ty: &Type,
262288
known_schemas: &HashMap<String, String>,
@@ -591,6 +617,55 @@ mod tests {
591617
assert_debug_snapshot!(parameters);
592618
}
593619

620+
#[rstest]
621+
#[case(
622+
"fn test(id: Query<i32>) {}",
623+
vec![],
624+
)]
625+
#[case(
626+
"fn test(auth: Header<String>) {}",
627+
vec![],
628+
)]
629+
#[case(
630+
"fn test(params: Query<Vec<i32>>) {}",
631+
vec![],
632+
)]
633+
#[case(
634+
"fn test(params: Query<Option<String>>) {}",
635+
vec![],
636+
)]
637+
#[case(
638+
"fn test(Path([a]): Path<[i32; 1]>) {}",
639+
vec![],
640+
)]
641+
#[case(
642+
"fn test(id: Path<i32>) {}",
643+
vec!["user_id".to_string(), "post_id".to_string()],
644+
)]
645+
fn test_parse_function_parameter_wrong_cases(
646+
#[case] func_src: &str,
647+
#[case] path_params: Vec<String>,
648+
) {
649+
let func: syn::ItemFn = syn::parse_str(func_src).unwrap();
650+
let (known_schemas, struct_definitions) = setup_test_data(func_src);
651+
652+
for (idx, arg) in func.sig.inputs.iter().enumerate() {
653+
let result = parse_function_parameter(
654+
arg,
655+
&path_params,
656+
&known_schemas,
657+
&struct_definitions,
658+
);
659+
assert!(
660+
result.is_none(),
661+
"Expected None at arg index {}, func: {}, got: {:?}",
662+
idx,
663+
func_src,
664+
result
665+
);
666+
}
667+
}
668+
594669
#[test]
595670
fn test_is_map_type() {
596671
// Test HashMap

0 commit comments

Comments
 (0)