@@ -71,12 +71,13 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
7171 let path_expr: ast:: PathExpr = ctx. find_node_at_offset ( ) ?;
7272 let call = path_expr. syntax ( ) . parent ( ) . and_then ( ast:: CallExpr :: cast) ?;
7373 let path = path_expr. path ( ) ?;
74- let fn_name = fn_name ( & path) ?;
74+ let name_ref = path. segment ( ) ? . name_ref ( ) ?;
7575 if ctx. sema . resolve_path ( & path) . is_some ( ) {
7676 // The function call already resolves, no need to add a function
7777 return None ;
7878 }
7979
80+ let fn_name = & * name_ref. text ( ) ;
8081 let target_module;
8182 let mut adt_name = None ;
8283
@@ -93,7 +94,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
9394 if current_module. krate ( ) != module. krate ( ) {
9495 return None ;
9596 }
96- let ( impl_, file) = get_adt_source ( ctx, & adt, fn_name. text ( ) . as_str ( ) ) ?;
97+ let ( impl_, file) = get_adt_source ( ctx, & adt, fn_name) ?;
9798 let ( target, insert_offset) = get_method_target ( ctx, & module, & impl_) ?;
9899 adt_name = if impl_. is_none ( ) { Some ( adt. name ( ctx. sema . db ) ) } else { None } ;
99100 ( target, file, insert_offset)
@@ -107,7 +108,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
107108 get_fn_target ( ctx, & target_module, call. clone ( ) ) ?
108109 }
109110 } ;
110- let function_builder = FunctionBuilder :: from_call ( ctx, & call, & path , target_module, target) ?;
111+ let function_builder = FunctionBuilder :: from_call ( ctx, & call, fn_name , target_module, target) ?;
111112 let text_range = call. syntax ( ) . text_range ( ) ;
112113 let label = format ! ( "Generate {} function" , function_builder. fn_name) ;
113114 add_func_to_accumulator (
@@ -241,13 +242,13 @@ impl FunctionBuilder {
241242 fn from_call (
242243 ctx : & AssistContext ,
243244 call : & ast:: CallExpr ,
244- path : & ast :: Path ,
245+ fn_name : & str ,
245246 target_module : Option < hir:: Module > ,
246247 target : GeneratedFunctionTarget ,
247248 ) -> Option < Self > {
248249 let needs_pub = target_module. is_some ( ) ;
249250 let target_module = target_module. or_else ( || current_module ( target. syntax ( ) , ctx) ) ?;
250- let fn_name = fn_name ( path ) ? ;
251+ let fn_name = make :: name ( fn_name ) ;
251252 let ( type_params, params) = fn_args ( ctx, target_module, FuncExpr :: Func ( call. clone ( ) ) ) ?;
252253
253254 let await_expr = call. syntax ( ) . parent ( ) . and_then ( ast:: AwaitExpr :: cast) ;
@@ -428,11 +429,6 @@ impl GeneratedFunctionTarget {
428429 }
429430}
430431
431- fn fn_name ( call : & ast:: Path ) -> Option < ast:: Name > {
432- let name = call. segment ( ) ?. syntax ( ) . to_string ( ) ;
433- Some ( make:: name ( & name) )
434- }
435-
436432/// Computes the type variables and arguments required for the generated function
437433fn fn_args (
438434 ctx : & AssistContext ,
@@ -442,10 +438,7 @@ fn fn_args(
442438 let mut arg_names = Vec :: new ( ) ;
443439 let mut arg_types = Vec :: new ( ) ;
444440 for arg in call. arg_list ( ) ?. args ( ) {
445- arg_names. push ( match fn_arg_name ( & arg) {
446- Some ( name) => name,
447- None => String :: from ( "arg" ) ,
448- } ) ;
441+ arg_names. push ( fn_arg_name ( & arg) ) ;
449442 arg_types. push ( match fn_arg_type ( ctx, target_module, & arg) {
450443 Some ( ty) => {
451444 if !ty. is_empty ( ) && ty. starts_with ( '&' ) {
@@ -510,18 +503,21 @@ fn deduplicate_arg_names(arg_names: &mut Vec<String>) {
510503 }
511504}
512505
513- fn fn_arg_name ( fn_arg : & ast:: Expr ) -> Option < String > {
514- match fn_arg {
515- ast:: Expr :: CastExpr ( cast_expr) => fn_arg_name ( & cast_expr. expr ( ) ?) ,
516- _ => {
517- let s = fn_arg
518- . syntax ( )
519- . descendants ( )
520- . filter ( |d| ast:: NameRef :: can_cast ( d. kind ( ) ) )
521- . last ( ) ?
522- . to_string ( ) ;
506+ fn fn_arg_name ( arg_expr : & ast:: Expr ) -> String {
507+ let name = ( || match arg_expr {
508+ ast:: Expr :: CastExpr ( cast_expr) => Some ( fn_arg_name ( & cast_expr. expr ( ) ?) ) ,
509+ expr => {
510+ let s = expr. syntax ( ) . descendants ( ) . filter_map ( ast:: NameRef :: cast) . last ( ) ?. to_string ( ) ;
523511 Some ( to_lower_snake_case ( & s) )
524512 }
513+ } ) ( ) ;
514+ match name {
515+ Some ( mut name) if name. starts_with ( |c : char | c. is_ascii_digit ( ) ) => {
516+ name. insert_str ( 0 , "arg" ) ;
517+ name
518+ }
519+ Some ( name) => name,
520+ None => "arg" . to_string ( ) ,
525521 }
526522}
527523
@@ -1643,6 +1639,50 @@ fn bar() ${0:-> _} {
16431639 todo!()
16441640}
16451641}
1642+ " ,
1643+ )
1644+ }
1645+
1646+ #[ test]
1647+ fn no_panic_on_invalid_global_path ( ) {
1648+ check_assist (
1649+ generate_function,
1650+ r"
1651+ fn main() {
1652+ ::foo$0();
1653+ }
1654+ " ,
1655+ r"
1656+ fn main() {
1657+ ::foo();
1658+ }
1659+
1660+ fn foo() ${0:-> _} {
1661+ todo!()
1662+ }
1663+ " ,
1664+ )
1665+ }
1666+
1667+ #[ test]
1668+ fn handle_tuple_indexing ( ) {
1669+ check_assist (
1670+ generate_function,
1671+ r"
1672+ fn main() {
1673+ let a = ((),);
1674+ foo$0(a.0);
1675+ }
1676+ " ,
1677+ r"
1678+ fn main() {
1679+ let a = ((),);
1680+ foo(a.0);
1681+ }
1682+
1683+ fn foo(arg0: ()) ${0:-> _} {
1684+ todo!()
1685+ }
16461686" ,
16471687 )
16481688 }
0 commit comments