@@ -3,7 +3,7 @@ use ra_syntax::{
3
3
SyntaxKind , SyntaxNode , TextUnit ,
4
4
} ;
5
5
6
- use crate :: { Assist , AssistCtx , AssistId } ;
6
+ use crate :: { Assist , AssistCtx , AssistFile , AssistId } ;
7
7
use ast:: { edit:: IndentLevel , ArgListOwner , ModuleItemOwner } ;
8
8
use hir:: HirDisplay ;
9
9
use rustc_hash:: { FxHashMap , FxHashSet } ;
@@ -44,10 +44,10 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> {
44
44
}
45
45
46
46
let target_module = if let Some ( qualifier) = path. qualifier ( ) {
47
- if let Some ( hir:: PathResolution :: Def ( hir:: ModuleDef :: Module ( resolved ) ) ) =
47
+ if let Some ( hir:: PathResolution :: Def ( hir:: ModuleDef :: Module ( module ) ) ) =
48
48
ctx. sema . resolve_path ( & qualifier)
49
49
{
50
- Some ( resolved . definition_source ( ctx. sema . db ) . value )
50
+ Some ( module . definition_source ( ctx. sema . db ) )
51
51
} else {
52
52
return None ;
53
53
}
@@ -61,6 +61,7 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> {
61
61
edit. target ( call. syntax ( ) . text_range ( ) ) ;
62
62
63
63
if let Some ( function_template) = function_builder. render ( ) {
64
+ edit. set_file ( function_template. file ) ;
64
65
edit. set_cursor ( function_template. cursor_offset ) ;
65
66
edit. insert ( function_template. insert_offset , function_template. fn_def . to_string ( ) ) ;
66
67
}
@@ -71,13 +72,15 @@ struct FunctionTemplate {
71
72
insert_offset : TextUnit ,
72
73
cursor_offset : TextUnit ,
73
74
fn_def : ast:: SourceFile ,
75
+ file : AssistFile ,
74
76
}
75
77
76
78
struct FunctionBuilder {
77
79
target : GeneratedFunctionTarget ,
78
80
fn_name : ast:: Name ,
79
81
type_params : Option < ast:: TypeParamList > ,
80
82
params : ast:: ParamList ,
83
+ file : AssistFile ,
81
84
}
82
85
83
86
impl FunctionBuilder {
@@ -87,16 +90,19 @@ impl FunctionBuilder {
87
90
ctx : & AssistCtx ,
88
91
call : & ast:: CallExpr ,
89
92
path : & ast:: Path ,
90
- generate_in : Option < hir:: ModuleSource > ,
93
+ generate_in : Option < hir:: InFile < hir :: ModuleSource > > ,
91
94
) -> Option < Self > {
95
+ let mut file = AssistFile :: default ( ) ;
92
96
let target = if let Some ( generate_in_module) = generate_in {
93
- next_space_for_fn_in_module ( generate_in_module) ?
97
+ let ( in_file, target) = next_space_for_fn_in_module ( ctx. sema . db , generate_in_module) ?;
98
+ file = in_file;
99
+ target
94
100
} else {
95
101
next_space_for_fn_after_call_site ( & call) ?
96
102
} ;
97
103
let fn_name = fn_name ( & path) ?;
98
104
let ( type_params, params) = fn_args ( ctx, & call) ?;
99
- Some ( Self { target, fn_name, type_params, params } )
105
+ Some ( Self { target, fn_name, type_params, params, file } )
100
106
}
101
107
fn render ( self ) -> Option < FunctionTemplate > {
102
108
let placeholder_expr = ast:: make:: expr_todo ( ) ;
@@ -130,7 +136,7 @@ impl FunctionBuilder {
130
136
. text_range ( )
131
137
. start ( ) ;
132
138
let cursor_offset = insert_offset + cursor_offset_from_fn_start;
133
- Some ( FunctionTemplate { insert_offset, cursor_offset, fn_def } )
139
+ Some ( FunctionTemplate { insert_offset, cursor_offset, fn_def, file : self . file } )
134
140
}
135
141
}
136
142
@@ -250,23 +256,29 @@ fn next_space_for_fn_after_call_site(expr: &ast::CallExpr) -> Option<GeneratedFu
250
256
last_ancestor. map ( GeneratedFunctionTarget :: BehindItem )
251
257
}
252
258
253
- fn next_space_for_fn_in_module ( module : hir:: ModuleSource ) -> Option < GeneratedFunctionTarget > {
254
- match module {
259
+ fn next_space_for_fn_in_module (
260
+ db : & dyn hir:: db:: AstDatabase ,
261
+ module : hir:: InFile < hir:: ModuleSource > ,
262
+ ) -> Option < ( AssistFile , GeneratedFunctionTarget ) > {
263
+ let file = module. file_id . original_file ( db) ;
264
+ let assist_file = AssistFile :: TargetFile ( file) ;
265
+ let assist_item = match module. value {
255
266
hir:: ModuleSource :: SourceFile ( it) => {
256
267
if let Some ( last_item) = it. items ( ) . last ( ) {
257
- Some ( GeneratedFunctionTarget :: BehindItem ( last_item. syntax ( ) . clone ( ) ) )
268
+ GeneratedFunctionTarget :: BehindItem ( last_item. syntax ( ) . clone ( ) )
258
269
} else {
259
- Some ( GeneratedFunctionTarget :: BehindItem ( it. syntax ( ) . clone ( ) ) )
270
+ GeneratedFunctionTarget :: BehindItem ( it. syntax ( ) . clone ( ) )
260
271
}
261
272
}
262
273
hir:: ModuleSource :: Module ( it) => {
263
274
if let Some ( last_item) = it. item_list ( ) . and_then ( |it| it. items ( ) . last ( ) ) {
264
- Some ( GeneratedFunctionTarget :: BehindItem ( last_item. syntax ( ) . clone ( ) ) )
275
+ GeneratedFunctionTarget :: BehindItem ( last_item. syntax ( ) . clone ( ) )
265
276
} else {
266
- it. item_list ( ) . map ( GeneratedFunctionTarget :: InEmptyItemList )
277
+ GeneratedFunctionTarget :: InEmptyItemList ( it. item_list ( ) ? )
267
278
}
268
279
}
269
- }
280
+ } ;
281
+ Some ( ( assist_file, assist_item) )
270
282
}
271
283
272
284
#[ cfg( test) ]
@@ -884,6 +896,37 @@ fn foo() {
884
896
)
885
897
}
886
898
899
+ #[ test]
900
+ fn add_function_in_another_file ( ) {
901
+ check_assist (
902
+ add_function,
903
+ r"
904
+ //- /main.rs
905
+ mod foo;
906
+
907
+ fn main() {
908
+ foo::bar<|>()
909
+ }
910
+
911
+ //- /foo.rs
912
+
913
+ " ,
914
+ r"
915
+ //- /main.rs
916
+ mod foo;
917
+
918
+ fn main() {
919
+ foo::bar()
920
+ }
921
+
922
+ //- /foo.rs
923
+ fn bar() {
924
+ <|>todo!()
925
+ }
926
+ " ,
927
+ )
928
+ }
929
+
887
930
#[ test]
888
931
fn add_function_not_applicable_if_function_already_exists ( ) {
889
932
check_assist_not_applicable (
0 commit comments