@@ -296,6 +296,35 @@ pub(crate) fn tool_impl_item(attr: TokenStream, mut input: ItemImpl) -> syn::Res
296
296
} )
297
297
}
298
298
299
+ fn extract_doc_line ( attr : & syn:: Attribute ) -> Option < String > {
300
+ if !attr. path ( ) . is_ident ( "doc" ) {
301
+ return None ;
302
+ }
303
+
304
+ let name_value = match & attr. meta {
305
+ syn:: Meta :: NameValue ( nv) => nv,
306
+ _ => return None ,
307
+ } ;
308
+
309
+ let expr_lit = match & name_value. value {
310
+ syn:: Expr :: Lit ( lit) => lit,
311
+ _ => return None ,
312
+ } ;
313
+
314
+ let lit_str = match & expr_lit. lit {
315
+ syn:: Lit :: Str ( s) => s,
316
+ _ => return None ,
317
+ } ;
318
+
319
+ let content = lit_str. value ( ) . trim ( ) . to_string ( ) ;
320
+
321
+ if content. is_empty ( ) {
322
+ None
323
+ } else {
324
+ Some ( content)
325
+ }
326
+ }
327
+
299
328
pub ( crate ) fn tool_fn_item ( attr : TokenStream , mut input_fn : ItemFn ) -> syn:: Result < TokenStream > {
300
329
let mut tool_macro_attrs = ToolAttrs :: default ( ) ;
301
330
let args: ToolFnItemAttrs = syn:: parse2 ( attr) ?;
@@ -405,10 +434,19 @@ pub(crate) fn tool_fn_item(attr: TokenStream, mut input_fn: ItemFn) -> syn::Resu
405
434
// generate get tool attr function
406
435
let tool_attr_fn = {
407
436
let description = if let Some ( expr) = tool_macro_attrs. fn_item . description {
437
+ // Use explicitly provided description if available
408
438
expr
409
439
} else {
440
+ // Try to extract documentation comments
441
+ let doc_content = input_fn
442
+ . attrs
443
+ . iter ( )
444
+ . filter_map ( extract_doc_line)
445
+ . collect :: < Vec < _ > > ( )
446
+ . join ( "\n " ) ;
447
+
410
448
parse_quote ! {
411
- ""
449
+ #doc_content . trim ( ) . to_string ( )
412
450
}
413
451
} ;
414
452
let schema = match & tool_macro_attrs. params {
@@ -657,4 +695,41 @@ mod test {
657
695
println ! ( "input: {:#}" , input) ;
658
696
Ok ( ( ) )
659
697
}
698
+ #[ test]
699
+ fn test_doc_comment_description ( ) -> syn:: Result < ( ) > {
700
+ let attr = quote ! { } ; // No explicit description
701
+ let input = quote ! {
702
+ /// This is a test description from doc comments
703
+ /// with multiple lines
704
+ fn test_function( & self ) -> Result <( ) , Error > {
705
+ Ok ( ( ) )
706
+ }
707
+ } ;
708
+ let result = tool ( attr, input) ?;
709
+
710
+ // The output should contain the description from doc comments
711
+ let result_str = result. to_string ( ) ;
712
+ assert ! ( result_str. contains( "This is a test description from doc comments" ) ) ;
713
+ assert ! ( result_str. contains( "with multiple lines" ) ) ;
714
+
715
+ Ok ( ( ) )
716
+ }
717
+ #[ test]
718
+ fn test_explicit_description_priority ( ) -> syn:: Result < ( ) > {
719
+ let attr = quote ! {
720
+ description = "Explicit description has priority"
721
+ } ;
722
+ let input = quote ! {
723
+ /// Doc comment description that should be ignored
724
+ fn test_function( & self ) -> Result <( ) , Error > {
725
+ Ok ( ( ) )
726
+ }
727
+ } ;
728
+ let result = tool ( attr, input) ?;
729
+
730
+ // The output should contain the explicit description
731
+ let result_str = result. to_string ( ) ;
732
+ assert ! ( result_str. contains( "Explicit description has priority" ) ) ;
733
+ Ok ( ( ) )
734
+ }
660
735
}
0 commit comments