@@ -5,10 +5,9 @@ use hir::{AsName, EnumVariant, Module, ModuleDef, Name};
55use ide_db:: { defs:: Definition , search:: Reference , RootDatabase } ;
66use rustc_hash:: { FxHashMap , FxHashSet } ;
77use syntax:: {
8- algo:: find_node_at_offset,
9- algo:: SyntaxRewriter ,
10- ast:: { self , edit:: IndentLevel , make, ArgListOwner , AstNode , NameOwner , VisibilityOwner } ,
11- SourceFile , SyntaxElement ,
8+ algo:: { find_node_at_offset, SyntaxRewriter } ,
9+ ast:: { self , edit:: IndentLevel , make, AstNode , NameOwner , VisibilityOwner } ,
10+ SourceFile , SyntaxElement , SyntaxNode , T ,
1211} ;
1312
1413use crate :: {
@@ -130,17 +129,21 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &En
130129fn insert_import (
131130 ctx : & AssistContext ,
132131 rewriter : & mut SyntaxRewriter ,
133- path : & ast :: PathExpr ,
132+ scope_node : & SyntaxNode ,
134133 module : & Module ,
135134 enum_module_def : & ModuleDef ,
136135 variant_hir_name : & Name ,
137136) -> Option < ( ) > {
138137 let db = ctx. db ( ) ;
139- let mod_path = module. find_use_path ( db, enum_module_def. clone ( ) ) ;
138+ let mod_path = module. find_use_path_prefixed (
139+ db,
140+ enum_module_def. clone ( ) ,
141+ ctx. config . insert_use . prefix_kind ,
142+ ) ;
140143 if let Some ( mut mod_path) = mod_path {
141144 mod_path. segments . pop ( ) ;
142145 mod_path. segments . push ( variant_hir_name. clone ( ) ) ;
143- let scope = ImportScope :: find_insert_use_container ( path . syntax ( ) , ctx) ?;
146+ let scope = ImportScope :: find_insert_use_container ( scope_node , ctx) ?;
144147
145148 * rewriter += insert_use ( & scope, mod_path_to_ast ( & mod_path) , ctx. config . insert_use . merge ) ;
146149 }
@@ -204,27 +207,31 @@ fn update_reference(
204207 variant_hir_name : & Name ,
205208 visited_modules_set : & mut FxHashSet < Module > ,
206209) -> Option < ( ) > {
207- let path_expr: ast:: PathExpr = find_node_at_offset :: < ast:: PathExpr > (
208- source_file. syntax ( ) ,
209- reference. file_range . range . start ( ) ,
210- ) ?;
211- let call = path_expr. syntax ( ) . parent ( ) . and_then ( ast:: CallExpr :: cast) ?;
212- let list = call. arg_list ( ) ?;
213- let segment = path_expr. path ( ) ?. segment ( ) ?;
214- let module = ctx. sema . scope ( & path_expr. syntax ( ) ) . module ( ) ?;
210+ let offset = reference. file_range . range . start ( ) ;
211+ let ( segment, expr) = if let Some ( path_expr) =
212+ find_node_at_offset :: < ast:: PathExpr > ( source_file. syntax ( ) , offset)
213+ {
214+ // tuple variant
215+ ( path_expr. path ( ) ?. segment ( ) ?, path_expr. syntax ( ) . parent ( ) ?. clone ( ) )
216+ } else if let Some ( record_expr) =
217+ find_node_at_offset :: < ast:: RecordExpr > ( source_file. syntax ( ) , offset)
218+ {
219+ // record variant
220+ ( record_expr. path ( ) ?. segment ( ) ?, record_expr. syntax ( ) . clone ( ) )
221+ } else {
222+ return None ;
223+ } ;
224+
225+ let module = ctx. sema . scope ( & expr) . module ( ) ?;
215226 if !visited_modules_set. contains ( & module) {
216- if insert_import ( ctx, rewriter, & path_expr, & module, enum_module_def, variant_hir_name)
217- . is_some ( )
227+ if insert_import ( ctx, rewriter, & expr, & module, enum_module_def, variant_hir_name) . is_some ( )
218228 {
219229 visited_modules_set. insert ( module) ;
220230 }
221231 }
222-
223- let lparen = syntax:: SyntaxElement :: from ( list. l_paren_token ( ) ?) ;
224- let rparen = syntax:: SyntaxElement :: from ( list. r_paren_token ( ) ?) ;
225- rewriter. insert_after ( & lparen, segment. syntax ( ) ) ;
226- rewriter. insert_after ( & lparen, & lparen) ;
227- rewriter. insert_before ( & rparen, & rparen) ;
232+ rewriter. insert_after ( segment. syntax ( ) , & make:: token ( T ! [ '(' ] ) ) ;
233+ rewriter. insert_after ( segment. syntax ( ) , segment. syntax ( ) ) ;
234+ rewriter. insert_after ( & expr, & make:: token ( T ! [ ')' ] ) ) ;
228235 Some ( ( ) )
229236}
230237
@@ -320,7 +327,7 @@ fn another_fn() {
320327 r#"use my_mod::my_other_mod::MyField;
321328
322329mod my_mod {
323- use my_other_mod::MyField;
330+ use self:: my_other_mod::MyField;
324331
325332 fn another_fn() {
326333 let m = my_other_mod::MyEnum::MyField(MyField(1, 1));
@@ -345,6 +352,33 @@ fn another_fn() {
345352 ) ;
346353 }
347354
355+ #[ test]
356+ fn extract_record_fix_references ( ) {
357+ check_assist (
358+ extract_struct_from_enum_variant,
359+ r#"
360+ enum E {
361+ <|>V { i: i32, j: i32 }
362+ }
363+
364+ fn f() {
365+ let e = E::V { i: 9, j: 2 };
366+ }
367+ "# ,
368+ r#"
369+ struct V{ pub i: i32, pub j: i32 }
370+
371+ enum E {
372+ V(V)
373+ }
374+
375+ fn f() {
376+ let e = E::V(V { i: 9, j: 2 });
377+ }
378+ "# ,
379+ )
380+ }
381+
348382 #[ test]
349383 fn test_several_files ( ) {
350384 check_assist (
@@ -372,9 +406,7 @@ enum E {
372406mod foo;
373407
374408//- /foo.rs
375- use V;
376-
377- use crate::E;
409+ use crate::{E, V};
378410fn f() {
379411 let e = E::V(V(9, 2));
380412}
@@ -384,7 +416,6 @@ fn f() {
384416
385417 #[ test]
386418 fn test_several_files_record ( ) {
387- // FIXME: this should fix the usage as well!
388419 check_assist (
389420 extract_struct_from_enum_variant,
390421 r#"
@@ -401,17 +432,50 @@ fn f() {
401432}
402433"# ,
403434 r#"
435+ //- /main.rs
404436struct V{ pub i: i32, pub j: i32 }
405437
406438enum E {
407439 V(V)
408440}
409441mod foo;
410442
443+ //- /foo.rs
444+ use crate::{E, V};
445+ fn f() {
446+ let e = E::V(V { i: 9, j: 2 });
447+ }
411448"# ,
412449 )
413450 }
414451
452+ #[ test]
453+ fn test_extract_struct_record_nested_call_exp ( ) {
454+ check_assist (
455+ extract_struct_from_enum_variant,
456+ r#"
457+ enum A { <|>One { a: u32, b: u32 } }
458+
459+ struct B(A);
460+
461+ fn foo() {
462+ let _ = B(A::One { a: 1, b: 2 });
463+ }
464+ "# ,
465+ r#"
466+ struct One{ pub a: u32, pub b: u32 }
467+
468+ enum A { One(One) }
469+
470+ struct B(A);
471+
472+ fn foo() {
473+ let _ = B(A::One(One { a: 1, b: 2 }));
474+ }
475+ "# ,
476+ ) ;
477+ }
478+
415479 fn check_not_applicable ( ra_fixture : & str ) {
416480 let fixture =
417481 format ! ( "//- /main.rs crate:main deps:core\n {}\n {}" , ra_fixture, FamousDefs :: FIXTURE ) ;
0 commit comments