@@ -6,7 +6,7 @@ use syntax::{
66 ast:: {
77 self ,
88 edit:: { AstNodeEdit , IndentLevel } ,
9- make, ArgListOwner , AstNode , ModuleItemOwner ,
9+ make, ArgListOwner , AstNode , CallExpr , ModuleItemOwner ,
1010 } ,
1111 SyntaxKind , SyntaxNode , TextRange , TextSize ,
1212} ;
@@ -85,10 +85,10 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
8585 None => None ,
8686 } ;
8787
88- let ( function_builder , inserting_offset , file ) =
89- FunctionBuilder :: from_call ( ctx, & call, & path, target_module) ?;
88+ let ( target , file , insert_offset ) = get_fn_target ( ctx , & target_module , call . clone ( ) ) ? ;
89+ let function_builder = FunctionBuilder :: from_call ( ctx, & call, & path, target_module, target ) ?;
9090 let target = call. syntax ( ) . text_range ( ) ;
91- add_func_to_accumulator ( acc, ctx, target, function_builder, inserting_offset , file, None )
91+ add_func_to_accumulator ( acc, ctx, target, function_builder, insert_offset , file, None )
9292}
9393
9494fn gen_method ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
@@ -109,24 +109,26 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
109109 ctx. sema . find_node_at_offset_with_macros ( file. syntax ( ) , range. range . start ( ) ) ?;
110110 let impl_ = find_struct_impl ( ctx, & adt_source, fn_name. text ( ) . as_str ( ) ) ?;
111111
112- let ( function_builder, inserting_offset, file) = FunctionBuilder :: from_method_call (
112+ let ( target, insert_offset) = get_method_target ( ctx, & target_module, & impl_) ?;
113+ let function_builder =
114+ FunctionBuilder :: from_method_call ( ctx, & call, & fn_name, target_module, target) ?;
115+ let text_range = call. syntax ( ) . text_range ( ) ;
116+ let adt_name = if impl_. is_none ( ) { Some ( adt. name ( ctx. sema . db ) ) } else { None } ;
117+ add_func_to_accumulator (
118+ acc,
113119 ctx,
114- & call ,
115- & fn_name ,
116- & impl_ ,
120+ text_range ,
121+ function_builder ,
122+ insert_offset ,
117123 range. file_id ,
118- target_module,
119- current_module,
120- ) ?;
121- let target = call. syntax ( ) . text_range ( ) ;
122- let adt_name = if impl_. is_none ( ) { Some ( adt. name ( ctx. sema . db ) ) } else { None } ;
123- add_func_to_accumulator ( acc, ctx, target, function_builder, inserting_offset, file, adt_name)
124+ adt_name,
125+ )
124126}
125127
126128fn add_func_to_accumulator (
127129 acc : & mut Assists ,
128130 ctx : & AssistContext ,
129- target : TextRange ,
131+ text_range : TextRange ,
130132 function_builder : FunctionBuilder ,
131133 insert_offset : TextSize ,
132134 file : FileId ,
@@ -135,7 +137,7 @@ fn add_func_to_accumulator(
135137 acc. add (
136138 AssistId ( "generate_function" , AssistKind :: Generate ) ,
137139 format ! ( "Generate `{}` method" , function_builder. fn_name) ,
138- target ,
140+ text_range ,
139141 |builder| {
140142 let function_template = function_builder. render ( ) ;
141143 let mut func = function_template. to_string ( ctx. config . snippet_cap ) ;
@@ -194,7 +196,6 @@ struct FunctionBuilder {
194196 params : ast:: ParamList ,
195197 ret_type : Option < ast:: RetType > ,
196198 should_focus_return_type : bool ,
197- file : FileId ,
198199 needs_pub : bool ,
199200 is_async : bool ,
200201}
@@ -207,17 +208,8 @@ impl FunctionBuilder {
207208 call : & ast:: CallExpr ,
208209 path : & ast:: Path ,
209210 target_module : Option < hir:: Module > ,
210- ) -> Option < ( Self , TextSize , FileId ) > {
211- let mut file = ctx. frange . file_id ;
212- let target = match & target_module {
213- Some ( target_module) => {
214- let module_source = target_module. definition_source ( ctx. db ( ) ) ;
215- let ( in_file, target) = next_space_for_fn_in_module ( ctx. sema . db , & module_source) ?;
216- file = in_file;
217- target
218- }
219- None => next_space_for_fn_after_call_site ( FuncExpr :: Func ( call. clone ( ) ) ) ?,
220- } ;
211+ target : GeneratedFunctionTarget ,
212+ ) -> Option < Self > {
221213 let needs_pub = target_module. is_some ( ) ;
222214 let target_module = target_module. or_else ( || current_module ( target. syntax ( ) , ctx) ) ?;
223215 let fn_name = fn_name ( path) ?;
@@ -229,51 +221,27 @@ impl FunctionBuilder {
229221 let ( ret_type, should_focus_return_type) =
230222 make_return_type ( ctx, & ast:: Expr :: CallExpr ( call. clone ( ) ) , target_module) ;
231223
232- let insert_offset = match & target {
233- GeneratedFunctionTarget :: BehindItem ( it) => it. text_range ( ) . end ( ) ,
234- GeneratedFunctionTarget :: InEmptyItemList ( it) => {
235- it. text_range ( ) . start ( ) + TextSize :: of ( '{' )
236- }
237- } ;
238-
239- Some ( (
240- Self {
241- target,
242- fn_name,
243- type_params,
244- params,
245- ret_type,
246- should_focus_return_type,
247- file,
248- needs_pub,
249- is_async,
250- } ,
251- insert_offset,
252- file,
253- ) )
224+ Some ( Self {
225+ target,
226+ fn_name,
227+ type_params,
228+ params,
229+ ret_type,
230+ should_focus_return_type,
231+ needs_pub,
232+ is_async,
233+ } )
254234 }
255235
256236 fn from_method_call (
257237 ctx : & AssistContext ,
258238 call : & ast:: MethodCallExpr ,
259239 name : & ast:: NameRef ,
260- impl_ : & Option < ast:: Impl > ,
261- file : FileId ,
262240 target_module : Module ,
263- current_module : Module ,
264- ) -> Option < ( Self , TextSize , FileId ) > {
265- let target = match impl_ {
266- Some ( impl_) => next_space_for_fn_in_impl ( & impl_) ?,
267- None => {
268- next_space_for_fn_in_module (
269- ctx. sema . db ,
270- & target_module. definition_source ( ctx. sema . db ) ,
271- ) ?
272- . 1
273- }
274- } ;
275- let needs_pub = !module_is_descendant ( & current_module, & target_module, ctx) ;
276-
241+ target : GeneratedFunctionTarget ,
242+ ) -> Option < Self > {
243+ let needs_pub =
244+ !module_is_descendant ( & current_module ( call. syntax ( ) , ctx) ?, & target_module, ctx) ;
277245 let fn_name = make:: name ( & name. text ( ) ) ;
278246 let ( type_params, params) = fn_args ( ctx, target_module, FuncExpr :: Method ( call. clone ( ) ) ) ?;
279247
@@ -283,28 +251,16 @@ impl FunctionBuilder {
283251 let ( ret_type, should_focus_return_type) =
284252 make_return_type ( ctx, & ast:: Expr :: MethodCallExpr ( call. clone ( ) ) , target_module) ;
285253
286- let insert_offset = match & target {
287- GeneratedFunctionTarget :: BehindItem ( it) => it. text_range ( ) . end ( ) ,
288- GeneratedFunctionTarget :: InEmptyItemList ( it) => {
289- it. text_range ( ) . start ( ) + TextSize :: of ( '{' )
290- }
291- } ;
292-
293- Some ( (
294- Self {
295- target,
296- fn_name,
297- type_params,
298- params,
299- ret_type,
300- should_focus_return_type,
301- file,
302- needs_pub,
303- is_async,
304- } ,
305- insert_offset,
306- file,
307- ) )
254+ Some ( Self {
255+ target,
256+ fn_name,
257+ type_params,
258+ params,
259+ ret_type,
260+ should_focus_return_type,
261+ needs_pub,
262+ is_async,
263+ } )
308264 }
309265
310266 fn render ( self ) -> FunctionTemplate {
@@ -382,6 +338,47 @@ fn make_return_type(
382338 ( ret_type, should_focus_return_type)
383339}
384340
341+ fn get_fn_target (
342+ ctx : & AssistContext ,
343+ target_module : & Option < Module > ,
344+ call : CallExpr ,
345+ ) -> Option < ( GeneratedFunctionTarget , FileId , TextSize ) > {
346+ let mut file = ctx. frange . file_id ;
347+ let target = match target_module {
348+ Some ( target_module) => {
349+ let module_source = target_module. definition_source ( ctx. db ( ) ) ;
350+ let ( in_file, target) = next_space_for_fn_in_module ( ctx. sema . db , & module_source) ?;
351+ file = in_file;
352+ target
353+ }
354+ None => next_space_for_fn_after_call_site ( FuncExpr :: Func ( call. clone ( ) ) ) ?,
355+ } ;
356+ Some ( ( target. clone ( ) , file, get_insert_offset ( & target) ) )
357+ }
358+
359+ fn get_method_target (
360+ ctx : & AssistContext ,
361+ target_module : & Module ,
362+ impl_ : & Option < ast:: Impl > ,
363+ ) -> Option < ( GeneratedFunctionTarget , TextSize ) > {
364+ let target = match impl_ {
365+ Some ( impl_) => next_space_for_fn_in_impl ( & impl_) ?,
366+ None => {
367+ next_space_for_fn_in_module ( ctx. sema . db , & target_module. definition_source ( ctx. sema . db ) ) ?
368+ . 1
369+ }
370+ } ;
371+ Some ( ( target. clone ( ) , get_insert_offset ( & target) ) )
372+ }
373+
374+ fn get_insert_offset ( target : & GeneratedFunctionTarget ) -> TextSize {
375+ match & target {
376+ GeneratedFunctionTarget :: BehindItem ( it) => it. text_range ( ) . end ( ) ,
377+ GeneratedFunctionTarget :: InEmptyItemList ( it) => it. text_range ( ) . start ( ) + TextSize :: of ( '{' ) ,
378+ }
379+ }
380+
381+ #[ derive( Clone ) ]
385382enum GeneratedFunctionTarget {
386383 BehindItem ( SyntaxNode ) ,
387384 InEmptyItemList ( SyntaxNode ) ,
0 commit comments