1
1
mod invoker;
2
2
mod output_bindings;
3
3
4
- use crate :: { attribute_args_from_name , parse_attribute_args} ;
4
+ use crate :: { create_name_attribute_arg , parse_attribute_args} ;
5
5
use azure_functions_shared:: codegen:: {
6
6
bindings:: {
7
7
Binding , BindingFactory , INPUT_BINDINGS , INPUT_OUTPUT_BINDINGS , OUTPUT_BINDINGS , TRIGGERS ,
@@ -335,47 +335,59 @@ fn get_input_binding_factory(
335
335
}
336
336
}
337
337
338
- fn bind_input_type (
339
- pattern : & Pat ,
340
- tp : & TypePath ,
341
- mutability : Option < Mut > ,
342
- has_trigger : bool ,
343
- binding_args : & mut HashMap < String , ( AttributeArgs , Span ) > ,
344
- ) -> Binding {
345
- let factory = get_input_binding_factory ( tp, mutability, has_trigger) ;
338
+ fn drain_argument_binding_attribute (
339
+ attrs : & mut Vec < Attribute > ,
340
+ name : & str ,
341
+ ) -> Option < ( AttributeArgs , Span ) > {
342
+ let mut result = None ;
343
+ for attr in attrs
344
+ . iter ( )
345
+ . filter ( |a| last_segment_in_path ( & a. path ) . ident == "binding" )
346
+ {
347
+ if result. is_some ( ) {
348
+ macro_panic (
349
+ attr. span ( ) ,
350
+ "parameters cannot have more than one binding attribute" ,
351
+ ) ;
352
+ }
346
353
347
- match pattern {
348
- Pat :: Ident ( name) => {
349
- let name_str = name. ident . to_string ( ) ;
350
- match binding_args. remove ( & name_str) {
351
- Some ( args) => ( * factory) ( args. 0 , args. 1 ) ,
352
- None => {
353
- let name_span = name. ident . span ( ) ;
354
- ( * factory) ( attribute_args_from_name ( & name_str, name_span) , name_span)
355
- }
354
+ let mut args = parse_attribute_args ( & attr) ;
355
+
356
+ iter_attribute_args ( & args, |key, _| {
357
+ if key == "name" {
358
+ macro_panic (
359
+ attr. span ( ) ,
360
+ "parameter binding attributes cannot have a 'name' argument" ,
361
+ ) ;
356
362
}
357
- }
358
- _ => macro_panic ( pattern. span ( ) , "bindings must have a named identifier" ) ,
363
+ true
364
+ } ) ;
365
+
366
+ args. push ( create_name_attribute_arg ( name, attr. span ( ) ) ) ;
367
+
368
+ result = Some ( ( args, attr. span ( ) ) ) ;
359
369
}
370
+
371
+ attrs. retain ( |a| last_segment_in_path ( & a. path ) . ident != "binding" ) ;
372
+
373
+ result
360
374
}
361
375
362
376
fn bind_argument (
363
- arg : & FnArg ,
377
+ arg : & mut FnArg ,
364
378
has_trigger : bool ,
365
379
binding_args : & mut HashMap < String , ( AttributeArgs , Span ) > ,
366
380
) -> Binding {
367
- match arg {
381
+ let ( pat , tp , mutability , attrs ) = match arg {
368
382
FnArg :: Typed ( arg) => match & * arg. ty {
369
383
Type :: Reference ( tr) => match & * tr. elem {
370
- Type :: Path ( tp) => {
371
- bind_input_type ( & * arg. pat , tp, tr. mutability , has_trigger, binding_args)
372
- }
384
+ Type :: Path ( tp) => ( & * arg. pat , tp, tr. mutability , & mut arg. attrs ) ,
373
385
_ => macro_panic (
374
386
arg. ty . span ( ) ,
375
387
"expected an Azure Functions trigger or input binding type" ,
376
388
) ,
377
389
} ,
378
- Type :: Path ( tp) => bind_input_type ( & * arg. pat , tp, None , has_trigger , binding_args ) ,
390
+ Type :: Path ( tp) => ( & * arg. pat , tp, None , & mut arg . attrs ) ,
379
391
_ => macro_panic (
380
392
arg. ty . span ( ) ,
381
393
"expected an Azure Functions trigger or input binding type" ,
@@ -384,6 +396,40 @@ fn bind_argument(
384
396
FnArg :: Receiver ( _) => {
385
397
macro_panic ( arg. span ( ) , "Azure Functions cannot have self parameters" )
386
398
}
399
+ } ;
400
+
401
+ let factory = get_input_binding_factory ( tp, mutability, has_trigger) ;
402
+
403
+ match pat {
404
+ Pat :: Ident ( name) => {
405
+ let name_str = name. ident . to_string ( ) ;
406
+ let binding_attr = drain_argument_binding_attribute ( attrs, & name_str) ;
407
+
408
+ let binding_args = match binding_args. remove ( & name_str) {
409
+ Some ( args) => {
410
+ if let Some ( binding_attr) = binding_attr {
411
+ macro_panic (
412
+ binding_attr. 1 ,
413
+ "parameter already has a binding attribute at the function level" ,
414
+ ) ;
415
+ }
416
+ args
417
+ }
418
+ None => binding_attr. unwrap_or_else ( || {
419
+ let name_span = name. ident . span ( ) ;
420
+ (
421
+ vec ! [ create_name_attribute_arg( & name_str, name_span) ] ,
422
+ name_span,
423
+ )
424
+ } ) ,
425
+ } ;
426
+
427
+ ( * factory) ( binding_args. 0 , binding_args. 1 )
428
+ }
429
+ _ => macro_panic (
430
+ pat. span ( ) ,
431
+ "parameter bindings must have a named identifier" ,
432
+ ) ,
387
433
}
388
434
}
389
435
@@ -409,7 +455,7 @@ fn bind_output_type(
409
455
Some ( args) => ( * factory) ( args. 0 , args. 1 ) ,
410
456
None => {
411
457
let span = tp. span ( ) ;
412
- ( * factory) ( attribute_args_from_name ( name, span) , span)
458
+ ( * factory) ( vec ! [ create_name_attribute_arg ( name, span) ] , span)
413
459
}
414
460
}
415
461
}
@@ -472,27 +518,30 @@ fn drain_binding_attributes(attrs: &mut Vec<Attribute>) -> HashMap<String, (Attr
472
518
. iter ( )
473
519
. filter ( |a| last_segment_in_path ( & a. path ) . ident == "binding" )
474
520
{
475
- let attr_span = attr. span ( ) ;
476
521
let args = parse_attribute_args ( & attr) ;
477
522
let mut name = None ;
478
- let mut name_span = None ;
479
523
480
524
iter_attribute_args ( & args, |key, value| {
481
525
if key != "name" {
482
526
return true ;
483
527
}
484
528
485
529
name = Some ( get_string_value ( "name" , value) ) ;
486
- name_span = Some ( key. span ( ) ) ;
487
530
false
488
531
} ) ;
489
532
490
533
if name. is_none ( ) {
491
- macro_panic ( attr_span, "binding attributes must have a 'name' argument" ) ;
534
+ macro_panic (
535
+ attr. span ( ) ,
536
+ "binding attributes must have a 'name' argument" ,
537
+ ) ;
492
538
}
493
539
494
540
if map. insert ( name. unwrap ( ) , ( args, attr. span ( ) ) ) . is_some ( ) {
495
- macro_panic ( attr_span, "binding attributes must have a 'name' argument" ) ;
541
+ macro_panic (
542
+ attr. span ( ) ,
543
+ "binding attributes must have a 'name' argument" ,
544
+ ) ;
496
545
}
497
546
}
498
547
@@ -535,8 +584,8 @@ pub fn func_impl(
535
584
let mut binding_args = drain_binding_attributes ( & mut target. attrs ) ;
536
585
let mut names = HashSet :: new ( ) ;
537
586
let mut has_trigger = false ;
538
- for arg in & target. sig . inputs {
539
- let binding = bind_argument ( & arg, has_trigger, & mut binding_args) ;
587
+ for arg in target. sig . inputs . iter_mut ( ) {
588
+ let binding = bind_argument ( arg, has_trigger, & mut binding_args) ;
540
589
has_trigger |= binding. is_trigger ( ) ;
541
590
542
591
if let Some ( name) = binding. name ( ) {
0 commit comments