@@ -70,26 +70,56 @@ impl FuncExpr {
7070fn 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) ?;
73-
7473 let path = path_expr. path ( ) ?;
74+ let fn_name = fn_name ( & path) ?;
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 target_module = match path. qualifier ( ) {
80+ let target_module;
81+ let mut adt_name = None ;
82+
83+ let ( target, file, insert_offset) = match path. qualifier ( ) {
8184 Some ( qualifier) => match ctx. sema . resolve_path ( & qualifier) {
82- Some ( hir:: PathResolution :: Def ( hir:: ModuleDef :: Module ( module) ) ) => Some ( module) ,
83- _ => return None ,
85+ Some ( hir:: PathResolution :: Def ( hir:: ModuleDef :: Module ( module) ) ) => {
86+ target_module = Some ( module) ;
87+ get_fn_target ( ctx, & target_module, call. clone ( ) ) ?
88+ }
89+ Some ( hir:: PathResolution :: Def ( hir:: ModuleDef :: Adt ( adt) ) ) => {
90+ let current_module = current_module ( call. syntax ( ) , ctx) ?;
91+ let module = adt. module ( ctx. sema . db ) ;
92+ target_module = if current_module == module { None } else { Some ( module) } ;
93+ if current_module. krate ( ) != module. krate ( ) {
94+ return None ;
95+ }
96+ let ( impl_, file) = get_adt_source ( ctx, & adt, fn_name. text ( ) . as_str ( ) ) ?;
97+ let ( target, insert_offset) = get_method_target ( ctx, & module, & impl_) ?;
98+ adt_name = if impl_. is_none ( ) { Some ( adt. name ( ctx. sema . db ) ) } else { None } ;
99+ ( target, file, insert_offset)
100+ }
101+ _ => {
102+ return None ;
103+ }
84104 } ,
85- None => None ,
105+ _ => {
106+ target_module = None ;
107+ get_fn_target ( ctx, & target_module, call. clone ( ) ) ?
108+ }
86109 } ;
87-
88- let ( target, file, insert_offset) = get_fn_target ( ctx, & target_module, call. clone ( ) ) ?;
89110 let function_builder = FunctionBuilder :: from_call ( ctx, & call, & path, target_module, target) ?;
90- let target = call. syntax ( ) . text_range ( ) ;
111+ let text_range = call. syntax ( ) . text_range ( ) ;
91112 let label = format ! ( "Generate {} function" , function_builder. fn_name. clone( ) ) ;
92- add_func_to_accumulator ( acc, ctx, target, function_builder, insert_offset, file, None , label)
113+ add_func_to_accumulator (
114+ acc,
115+ ctx,
116+ text_range,
117+ function_builder,
118+ insert_offset,
119+ file,
120+ adt_name,
121+ label,
122+ )
93123}
94124
95125fn gen_method ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
@@ -103,13 +133,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
103133 if current_module. krate ( ) != target_module. krate ( ) {
104134 return None ;
105135 }
106-
107- let range = adt. source ( ctx. sema . db ) ?. syntax ( ) . original_file_range ( ctx. sema . db ) ;
108- let file = ctx. sema . parse ( range. file_id ) ;
109- let adt_source =
110- ctx. sema . find_node_at_offset_with_macros ( file. syntax ( ) , range. range . start ( ) ) ?;
111- let impl_ = find_struct_impl ( ctx, & adt_source, fn_name. text ( ) . as_str ( ) ) ?;
112-
136+ let ( impl_, file) = get_adt_source ( ctx, & adt, fn_name. text ( ) . as_str ( ) ) ?;
113137 let ( target, insert_offset) = get_method_target ( ctx, & target_module, & impl_) ?;
114138 let function_builder =
115139 FunctionBuilder :: from_method_call ( ctx, & call, & fn_name, target_module, target) ?;
@@ -122,7 +146,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
122146 text_range,
123147 function_builder,
124148 insert_offset,
125- range . file_id ,
149+ file ,
126150 adt_name,
127151 label,
128152 )
@@ -156,6 +180,18 @@ fn current_module(current_node: &SyntaxNode, ctx: &AssistContext) -> Option<Modu
156180 ctx. sema . scope ( current_node) . module ( )
157181}
158182
183+ fn get_adt_source (
184+ ctx : & AssistContext ,
185+ adt : & hir:: Adt ,
186+ fn_name : & str ,
187+ ) -> Option < ( Option < ast:: Impl > , FileId ) > {
188+ let range = adt. source ( ctx. sema . db ) ?. syntax ( ) . original_file_range ( ctx. sema . db ) ;
189+ let file = ctx. sema . parse ( range. file_id ) ;
190+ let adt_source =
191+ ctx. sema . find_node_at_offset_with_macros ( file. syntax ( ) , range. range . start ( ) ) ?;
192+ find_struct_impl ( ctx, & adt_source, fn_name) . map ( |impl_| ( impl_, range. file_id ) )
193+ }
194+
159195struct FunctionTemplate {
160196 leading_ws : String ,
161197 fn_def : ast:: Fn ,
@@ -1514,6 +1550,99 @@ fn bar(&self) ${0:-> ()} {
15141550 todo!()
15151551}
15161552}
1553+ " ,
1554+ )
1555+ }
1556+
1557+ #[ test]
1558+ fn create_static_method ( ) {
1559+ check_assist (
1560+ generate_function,
1561+ r"
1562+ struct S;
1563+ fn foo() {S::bar$0();}
1564+ " ,
1565+ r"
1566+ struct S;
1567+ fn foo() {S::bar();}
1568+ impl S {
1569+
1570+
1571+ fn bar() ${0:-> ()} {
1572+ todo!()
1573+ }
1574+ }
1575+ " ,
1576+ )
1577+ }
1578+
1579+ #[ test]
1580+ fn create_static_method_within_an_impl ( ) {
1581+ check_assist (
1582+ generate_function,
1583+ r"
1584+ struct S;
1585+ fn foo() {S::bar$0();}
1586+ impl S {}
1587+
1588+ " ,
1589+ r"
1590+ struct S;
1591+ fn foo() {S::bar();}
1592+ impl S {
1593+ fn bar() ${0:-> ()} {
1594+ todo!()
1595+ }
1596+ }
1597+
1598+ " ,
1599+ )
1600+ }
1601+
1602+ #[ test]
1603+ fn create_static_method_from_different_module ( ) {
1604+ check_assist (
1605+ generate_function,
1606+ r"
1607+ mod s {
1608+ pub struct S;
1609+ }
1610+ fn foo() {s::S::bar$0();}
1611+ " ,
1612+ r"
1613+ mod s {
1614+ pub struct S;
1615+ impl S {
1616+
1617+
1618+ pub(crate) fn bar() ${0:-> ()} {
1619+ todo!()
1620+ }
1621+ }
1622+ }
1623+ fn foo() {s::S::bar();}
1624+ " ,
1625+ )
1626+ }
1627+
1628+ #[ test]
1629+ fn create_static_method_with_cursor_anywhere_on_call_expresion ( ) {
1630+ check_assist (
1631+ generate_function,
1632+ r"
1633+ struct S;
1634+ fn foo() {$0S::bar();}
1635+ " ,
1636+ r"
1637+ struct S;
1638+ fn foo() {S::bar();}
1639+ impl S {
1640+
1641+
1642+ fn bar() ${0:-> ()} {
1643+ todo!()
1644+ }
1645+ }
15171646" ,
15181647 )
15191648 }
0 commit comments