@@ -797,15 +797,21 @@ impl FunctionBody {
797
797
) -> ( FxIndexSet < Local > , Option < ast:: SelfParam > ) {
798
798
let mut self_param = None ;
799
799
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 | {
809
815
let InFile { file_id, value } = local_ref. primary_source ( sema. db ) . source ;
810
816
// locals defined inside macros are not relevant to us
811
817
if !file_id. is_macro ( ) {
@@ -821,13 +827,20 @@ impl FunctionBody {
821
827
} ;
822
828
self . walk_expr ( & mut |expr| match expr {
823
829
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
+ }
825
837
}
826
838
ast:: Expr :: ClosureExpr ( closure_expr) => {
827
839
if let Some ( body) = closure_expr. body ( ) {
828
840
body. syntax ( )
829
841
. descendants ( )
830
- . map ( ast:: NameRef :: cast)
842
+ . filter_map ( ast:: NameRef :: cast)
843
+ . filter_map ( |name_ref| local_from_name_ref ( sema, name_ref) )
831
844
. for_each ( & mut add_name_if_local) ;
832
845
}
833
846
}
@@ -836,9 +849,31 @@ impl FunctionBody {
836
849
tt. syntax ( )
837
850
. descendants_with_tokens ( )
838
851
. 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
+ } ) ;
842
877
}
843
878
}
844
879
_ => ( ) ,
@@ -6130,6 +6165,28 @@ fn $0fun_name(a: i32, b: i32, c: i32, x: i32) -> i32 {
6130
6165
) ;
6131
6166
}
6132
6167
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
+
6133
6190
#[ test]
6134
6191
fn in_left_curly_is_not_applicable ( ) {
6135
6192
cov_mark:: check!( extract_function_in_braces_is_not_applicable) ;
0 commit comments