@@ -797,15 +797,21 @@ impl FunctionBody {
797797 ) -> ( FxIndexSet < Local > , Option < ast:: SelfParam > ) {
798798 let mut self_param = None ;
799799 let mut res = FxIndexSet :: default ( ) ;
800- let mut add_name_if_local = |name_ref : Option < _ > | {
801- let local_ref =
802- match name_ref. and_then ( |name_ref| NameRefClass :: classify ( sema, & name_ref) ) {
803- Some (
804- NameRefClass :: Definition ( Definition :: Local ( local_ref) , _)
805- | NameRefClass :: FieldShorthand { local_ref, field_ref : _, adt_subst : _ } ,
806- ) => local_ref,
807- _ => return ,
808- } ;
800+
801+ fn local_from_name_ref (
802+ sema : & Semantics < ' _ , RootDatabase > ,
803+ name_ref : ast:: NameRef ,
804+ ) -> Option < hir:: Local > {
805+ match NameRefClass :: classify ( sema, & name_ref) {
806+ Some (
807+ NameRefClass :: Definition ( Definition :: Local ( local_ref) , _)
808+ | NameRefClass :: FieldShorthand { local_ref, field_ref : _, adt_subst : _ } ,
809+ ) => Some ( local_ref) ,
810+ _ => None ,
811+ }
812+ }
813+
814+ let mut add_name_if_local = |local_ref : Local | {
809815 let InFile { file_id, value } = local_ref. primary_source ( sema. db ) . source ;
810816 // locals defined inside macros are not relevant to us
811817 if !file_id. is_macro ( ) {
@@ -821,13 +827,20 @@ impl FunctionBody {
821827 } ;
822828 self . walk_expr ( & mut |expr| match expr {
823829 ast:: Expr :: PathExpr ( path_expr) => {
824- add_name_if_local ( path_expr. path ( ) . and_then ( |it| it. as_single_name_ref ( ) ) )
830+ if let Some ( local) = path_expr
831+ . path ( )
832+ . and_then ( |it| it. as_single_name_ref ( ) )
833+ . and_then ( |name_ref| local_from_name_ref ( sema, name_ref) )
834+ {
835+ add_name_if_local ( local) ;
836+ }
825837 }
826838 ast:: Expr :: ClosureExpr ( closure_expr) => {
827839 if let Some ( body) = closure_expr. body ( ) {
828840 body. syntax ( )
829841 . descendants ( )
830- . map ( ast:: NameRef :: cast)
842+ . filter_map ( ast:: NameRef :: cast)
843+ . filter_map ( |name_ref| local_from_name_ref ( sema, name_ref) )
831844 . for_each ( & mut add_name_if_local) ;
832845 }
833846 }
@@ -836,9 +849,31 @@ impl FunctionBody {
836849 tt. syntax ( )
837850 . descendants_with_tokens ( )
838851 . filter_map ( SyntaxElement :: into_token)
839- . filter ( |it| matches ! ( it. kind( ) , SyntaxKind :: IDENT | T ![ self ] ) )
840- . flat_map ( |t| sema. descend_into_macros_exact ( t) )
841- . for_each ( |t| add_name_if_local ( t. parent ( ) . and_then ( ast:: NameRef :: cast) ) ) ;
852+ . filter ( |it| {
853+ matches ! ( it. kind( ) , SyntaxKind :: STRING | SyntaxKind :: IDENT | T ![ self ] )
854+ } )
855+ . for_each ( |t| {
856+ if ast:: String :: can_cast ( t. kind ( ) ) {
857+ if let Some ( parts) =
858+ ast:: String :: cast ( t) . and_then ( |s| sema. as_format_args_parts ( & s) )
859+ {
860+ parts
861+ . into_iter ( )
862+ . filter_map ( |( _, value) | value. and_then ( |it| it. left ( ) ) )
863+ . filter_map ( |path| match path {
864+ PathResolution :: Local ( local) => Some ( local) ,
865+ _ => None ,
866+ } )
867+ . for_each ( & mut add_name_if_local) ;
868+ }
869+ } else {
870+ sema. descend_into_macros_exact ( t)
871+ . into_iter ( )
872+ . filter_map ( |t| t. parent ( ) . and_then ( ast:: NameRef :: cast) )
873+ . filter_map ( |name_ref| local_from_name_ref ( sema, name_ref) )
874+ . for_each ( & mut add_name_if_local) ;
875+ }
876+ } ) ;
842877 }
843878 }
844879 _ => ( ) ,
@@ -6130,6 +6165,28 @@ fn $0fun_name(a: i32, b: i32, c: i32, x: i32) -> i32 {
61306165 ) ;
61316166 }
61326167
6168+ #[ test]
6169+ fn fmt_macro_argument ( ) {
6170+ check_assist (
6171+ extract_function,
6172+ r#"
6173+ //- minicore: fmt
6174+ fn existing(a: i32, b: i32, c: i32) {
6175+ $0print!("{a}{}{}", b, "{c}");$0
6176+ }
6177+ "# ,
6178+ r#"
6179+ fn existing(a: i32, b: i32, c: i32) {
6180+ fun_name(a, b);
6181+ }
6182+
6183+ fn $0fun_name(a: i32, b: i32) {
6184+ print!("{a}{}{}", b, "{c}");
6185+ }
6186+ "# ,
6187+ ) ;
6188+ }
6189+
61336190 #[ test]
61346191 fn in_left_curly_is_not_applicable ( ) {
61356192 cov_mark:: check!( extract_function_in_braces_is_not_applicable) ;
0 commit comments