Skip to content

Commit cf73b68

Browse files
bors[bot]Veykril
andauthored
Merge #6514
6514: Fix extract_struct_from_enum_variant not updating record references r=Veykril a=Veykril Related to #6510 Co-authored-by: Lukas Wirth <[email protected]>
2 parents 13cf3b4 + ccdcd52 commit cf73b68

File tree

1 file changed

+92
-28
lines changed

1 file changed

+92
-28
lines changed

crates/assists/src/handlers/extract_struct_from_enum_variant.rs

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ use hir::{AsName, EnumVariant, Module, ModuleDef, Name};
55
use ide_db::{defs::Definition, search::Reference, RootDatabase};
66
use rustc_hash::{FxHashMap, FxHashSet};
77
use 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

1413
use crate::{
@@ -130,17 +129,21 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &En
130129
fn 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
322329
mod 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 {
372406
mod foo;
373407
374408
//- /foo.rs
375-
use V;
376-
377-
use crate::E;
409+
use crate::{E, V};
378410
fn 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
404436
struct V{ pub i: i32, pub j: i32 }
405437
406438
enum E {
407439
V(V)
408440
}
409441
mod 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

Comments
 (0)