Skip to content

Commit 6ffe1d9

Browse files
committed
Fix references to patterns in extract_struct_from_enum_variant assist
1 parent 9ff7ab6 commit 6ffe1d9

File tree

1 file changed

+51
-26
lines changed

1 file changed

+51
-26
lines changed

crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@ use ide_db::{
1414
use itertools::Itertools;
1515
use rustc_hash::FxHashSet;
1616
use syntax::{
17-
algo::find_node_at_offset,
1817
ast::{
1918
self, make, AstNode, AttrsOwner, GenericParamsOwner, NameOwner, TypeBoundsOwner,
2019
VisibilityOwner,
2120
},
21+
match_ast,
2222
ted::{self, Position},
2323
SyntaxNode, T,
2424
};
2525

26-
use crate::{AssistContext, AssistId, AssistKind, Assists};
26+
use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists};
2727

2828
// Assist: extract_struct_from_enum_variant
2929
//
@@ -75,11 +75,10 @@ pub(crate) fn extract_struct_from_enum_variant(
7575
continue;
7676
}
7777
builder.edit_file(file_id);
78-
let source_file = builder.make_mut(ctx.sema.parse(file_id));
7978
let processed = process_references(
8079
ctx,
80+
builder,
8181
&mut visited_modules_set,
82-
source_file.syntax(),
8382
&enum_module_def,
8483
&variant_hir_name,
8584
references,
@@ -89,13 +88,12 @@ pub(crate) fn extract_struct_from_enum_variant(
8988
});
9089
}
9190
builder.edit_file(ctx.frange.file_id);
92-
let source_file = builder.make_mut(ctx.sema.parse(ctx.frange.file_id));
9391
let variant = builder.make_mut(variant.clone());
9492
if let Some(references) = def_file_references {
9593
let processed = process_references(
9694
ctx,
95+
builder,
9796
&mut visited_modules_set,
98-
source_file.syntax(),
9997
&enum_module_def,
10098
&variant_hir_name,
10199
references,
@@ -248,8 +246,8 @@ fn apply_references(
248246

249247
fn process_references(
250248
ctx: &AssistContext,
249+
builder: &mut AssistBuilder,
251250
visited_modules: &mut FxHashSet<Module>,
252-
source_file: &SyntaxNode,
253251
enum_module_def: &ModuleDef,
254252
variant_hir_name: &Name,
255253
refs: Vec<FileReference>,
@@ -258,8 +256,9 @@ fn process_references(
258256
// and corresponding nodes up front
259257
refs.into_iter()
260258
.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);
263262
if !visited_modules.contains(&module) {
264263
let mod_path = module.find_use_path_prefixed(
265264
ctx.sema.db,
@@ -281,23 +280,22 @@ fn process_references(
281280

282281
fn reference_to_node(
283282
sema: &hir::Semantics<RootDatabase>,
284-
source_file: &SyntaxNode,
285283
reference: FileReference,
286284
) -> 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))
301299
}
302300

303301
#[cfg(test)]
@@ -558,7 +556,7 @@ enum E {
558556
}
559557
560558
fn f() {
561-
let e = E::V { i: 9, j: 2 };
559+
let E::V { i, j } = E::V { i: 9, j: 2 };
562560
}
563561
"#,
564562
r#"
@@ -569,7 +567,34 @@ enum E {
569567
}
570568
571569
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));
573598
}
574599
"#,
575600
)

0 commit comments

Comments
 (0)