@@ -14,16 +14,16 @@ use ide_db::{
14
14
use itertools:: Itertools ;
15
15
use rustc_hash:: FxHashSet ;
16
16
use syntax:: {
17
- algo:: find_node_at_offset,
18
17
ast:: {
19
18
self , make, AstNode , AttrsOwner , GenericParamsOwner , NameOwner , TypeBoundsOwner ,
20
19
VisibilityOwner ,
21
20
} ,
21
+ match_ast,
22
22
ted:: { self , Position } ,
23
23
SyntaxNode , T ,
24
24
} ;
25
25
26
- use crate :: { AssistContext , AssistId , AssistKind , Assists } ;
26
+ use crate :: { assist_context :: AssistBuilder , AssistContext , AssistId , AssistKind , Assists } ;
27
27
28
28
// Assist: extract_struct_from_enum_variant
29
29
//
@@ -75,11 +75,10 @@ pub(crate) fn extract_struct_from_enum_variant(
75
75
continue ;
76
76
}
77
77
builder. edit_file ( file_id) ;
78
- let source_file = builder. make_mut ( ctx. sema . parse ( file_id) ) ;
79
78
let processed = process_references (
80
79
ctx,
80
+ builder,
81
81
& mut visited_modules_set,
82
- source_file. syntax ( ) ,
83
82
& enum_module_def,
84
83
& variant_hir_name,
85
84
references,
@@ -89,13 +88,12 @@ pub(crate) fn extract_struct_from_enum_variant(
89
88
} ) ;
90
89
}
91
90
builder. edit_file ( ctx. frange . file_id ) ;
92
- let source_file = builder. make_mut ( ctx. sema . parse ( ctx. frange . file_id ) ) ;
93
91
let variant = builder. make_mut ( variant. clone ( ) ) ;
94
92
if let Some ( references) = def_file_references {
95
93
let processed = process_references (
96
94
ctx,
95
+ builder,
97
96
& mut visited_modules_set,
98
- source_file. syntax ( ) ,
99
97
& enum_module_def,
100
98
& variant_hir_name,
101
99
references,
@@ -248,8 +246,8 @@ fn apply_references(
248
246
249
247
fn process_references (
250
248
ctx : & AssistContext ,
249
+ builder : & mut AssistBuilder ,
251
250
visited_modules : & mut FxHashSet < Module > ,
252
- source_file : & SyntaxNode ,
253
251
enum_module_def : & ModuleDef ,
254
252
variant_hir_name : & Name ,
255
253
refs : Vec < FileReference > ,
@@ -258,8 +256,9 @@ fn process_references(
258
256
// and corresponding nodes up front
259
257
refs. into_iter ( )
260
258
. flat_map ( |reference| {
261
- let ( segment, scope_node, module) =
262
- reference_to_node ( & ctx. sema , source_file, reference) ?;
259
+ let ( segment, scope_node, module) = reference_to_node ( & ctx. sema , reference) ?;
260
+ let segment = builder. make_mut ( segment) ;
261
+ let scope_node = builder. make_syntax_mut ( scope_node) ;
263
262
if !visited_modules. contains ( & module) {
264
263
let mod_path = module. find_use_path_prefixed (
265
264
ctx. sema . db ,
@@ -281,23 +280,22 @@ fn process_references(
281
280
282
281
fn reference_to_node (
283
282
sema : & hir:: Semantics < RootDatabase > ,
284
- source_file : & SyntaxNode ,
285
283
reference : FileReference ,
286
284
) -> Option < ( ast:: PathSegment , SyntaxNode , hir:: Module ) > {
287
- let offset = reference . range . start ( ) ;
288
- if let Some ( path_expr ) = find_node_at_offset :: < ast :: PathExpr > ( source_file , offset ) {
289
- // tuple variant
290
- Some ( ( path_expr . path ( ) ? . segment ( ) ? , path_expr . syntax ( ) . parent ( ) ? ) )
291
- } else if let Some ( record_expr ) = find_node_at_offset :: < ast :: RecordExpr > ( source_file , offset ) {
292
- // record variant
293
- Some ( ( record_expr . path ( ) ? . segment ( ) ? , record_expr . syntax ( ) . clone ( ) ) )
294
- } else {
295
- None
296
- }
297
- . and_then ( | ( segment , expr ) | {
298
- let module = sema . scope ( & expr ) . module ( ) ? ;
299
- Some ( ( segment , expr , module) )
300
- } )
285
+ let segment =
286
+ reference . name . as_name_ref ( ) ? . syntax ( ) . parent ( ) . and_then ( ast :: PathSegment :: cast ) ? ;
287
+ let parent = segment . parent_path ( ) . syntax ( ) . parent ( ) ? ;
288
+ let expr_or_pat = match_ast ! {
289
+ match parent {
290
+ ast :: PathExpr ( _it ) => parent . parent ( ) ? ,
291
+ ast :: RecordExpr ( _it ) => parent ,
292
+ ast :: TupleStructPat ( _it ) => parent ,
293
+ ast :: RecordPat ( _it ) => parent ,
294
+ _ => return None ,
295
+ }
296
+ } ;
297
+ let module = sema . scope ( & expr_or_pat ) . module ( ) ? ;
298
+ Some ( ( segment , expr_or_pat , module ) )
301
299
}
302
300
303
301
#[ cfg( test) ]
@@ -558,7 +556,7 @@ enum E {
558
556
}
559
557
560
558
fn f() {
561
- let e = E::V { i: 9, j: 2 };
559
+ let E::V { i, j } = E::V { i: 9, j: 2 };
562
560
}
563
561
"# ,
564
562
r#"
@@ -569,7 +567,34 @@ enum E {
569
567
}
570
568
571
569
fn f() {
572
- let e = E::V(V { i: 9, j: 2 });
570
+ let E::V(V { i, j }) = E::V(V { i: 9, j: 2 });
571
+ }
572
+ "# ,
573
+ )
574
+ }
575
+
576
+ #[ test]
577
+ fn extract_record_fix_references2 ( ) {
578
+ check_assist (
579
+ extract_struct_from_enum_variant,
580
+ r#"
581
+ enum E {
582
+ $0V(i32, i32)
583
+ }
584
+
585
+ fn f() {
586
+ let E::V(i, j) = E::V(9, 2);
587
+ }
588
+ "# ,
589
+ r#"
590
+ struct V(pub i32, pub i32);
591
+
592
+ enum E {
593
+ V(V)
594
+ }
595
+
596
+ fn f() {
597
+ let E::V(V(i, j)) = E::V(V(9, 2));
573
598
}
574
599
"# ,
575
600
)
0 commit comments