From e24cc77cd147b710a0ca161acd2e8d6922e067bd Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Nov 2020 17:13:33 +0100 Subject: Fix extract_struct_from_enum_variant not updating record references --- .../handlers/extract_struct_from_enum_variant.rs | 85 +++++++++++++++------- 1 file changed, 59 insertions(+), 26 deletions(-) (limited to 'crates') diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index 84662d832..38ecf5065 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs @@ -5,10 +5,9 @@ use hir::{AsName, EnumVariant, Module, ModuleDef, Name}; use ide_db::{defs::Definition, search::Reference, RootDatabase}; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ - algo::find_node_at_offset, - algo::SyntaxRewriter, - ast::{self, edit::IndentLevel, make, ArgListOwner, AstNode, NameOwner, VisibilityOwner}, - SourceFile, SyntaxElement, + algo::{find_node_at_offset, SyntaxRewriter}, + ast::{self, edit::IndentLevel, make, AstNode, NameOwner, VisibilityOwner}, + SourceFile, SyntaxElement, SyntaxNode, T, }; use crate::{ @@ -130,17 +129,17 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &En fn insert_import( ctx: &AssistContext, rewriter: &mut SyntaxRewriter, - path: &ast::PathExpr, + scope_node: &SyntaxNode, module: &Module, enum_module_def: &ModuleDef, variant_hir_name: &Name, ) -> Option<()> { let db = ctx.db(); let mod_path = module.find_use_path(db, enum_module_def.clone()); - if let Some(mut mod_path) = mod_path { + if let Some(mut mod_path) = mod_path.filter(|path| path.len() > 1) { mod_path.segments.pop(); mod_path.segments.push(variant_hir_name.clone()); - let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?; + let scope = ImportScope::find_insert_use_container(scope_node, ctx)?; *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge); } @@ -204,27 +203,31 @@ fn update_reference( variant_hir_name: &Name, visited_modules_set: &mut FxHashSet, ) -> Option<()> { - let path_expr: ast::PathExpr = find_node_at_offset::( - source_file.syntax(), - reference.file_range.range.start(), - )?; - let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?; - let list = call.arg_list()?; - let segment = path_expr.path()?.segment()?; - let module = ctx.sema.scope(&path_expr.syntax()).module()?; + let offset = reference.file_range.range.start(); + let (segment, expr) = if let Some(path_expr) = + find_node_at_offset::(source_file.syntax(), offset) + { + // tuple variant + (path_expr.path()?.segment()?, path_expr.syntax().parent()?.clone()) + } else if let Some(record_expr) = + find_node_at_offset::(source_file.syntax(), offset) + { + // record variant + (record_expr.path()?.segment()?, record_expr.syntax().clone()) + } else { + return None; + }; + + let module = ctx.sema.scope(&expr).module()?; if !visited_modules_set.contains(&module) { - if insert_import(ctx, rewriter, &path_expr, &module, enum_module_def, variant_hir_name) - .is_some() + if insert_import(ctx, rewriter, &expr, &module, enum_module_def, variant_hir_name).is_some() { visited_modules_set.insert(module); } } - - let lparen = syntax::SyntaxElement::from(list.l_paren_token()?); - let rparen = syntax::SyntaxElement::from(list.r_paren_token()?); - rewriter.insert_after(&lparen, segment.syntax()); - rewriter.insert_after(&lparen, &lparen); - rewriter.insert_before(&rparen, &rparen); + rewriter.insert_after(segment.syntax(), &make::token(T!['('])); + rewriter.insert_after(segment.syntax(), segment.syntax()); + rewriter.insert_after(&expr, &make::token(T![')'])); Some(()) } @@ -345,6 +348,33 @@ fn another_fn() { ); } + #[test] + fn extract_record_fix_references() { + check_assist( + extract_struct_from_enum_variant, + r#" +enum E { + <|>V { i: i32, j: i32 } +} + +fn f() { + let e = E::V { i: 9, j: 2 }; +} +"#, + r#" +struct V{ pub i: i32, pub j: i32 } + +enum E { + V(V) +} + +fn f() { + let e = E::V(V { i: 9, j: 2 }); +} +"#, + ) + } + #[test] fn test_several_files() { check_assist( @@ -372,8 +402,6 @@ enum E { mod foo; //- /foo.rs -use V; - use crate::E; fn f() { let e = E::V(V(9, 2)); @@ -384,7 +412,6 @@ fn f() { #[test] fn test_several_files_record() { - // FIXME: this should fix the usage as well! check_assist( extract_struct_from_enum_variant, r#" @@ -401,6 +428,7 @@ fn f() { } "#, r#" +//- /main.rs struct V{ pub i: i32, pub j: i32 } enum E { @@ -408,6 +436,11 @@ enum E { } mod foo; +//- /foo.rs +use crate::E; +fn f() { + let e = E::V(V { i: 9, j: 2 }); +} "#, ) } -- cgit v1.2.3 From 9454a9e536d96c7e46378744b8d93cc039fa3b98 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Nov 2020 17:32:45 +0100 Subject: Use Module::find_use_path_prefixed in extract_struct_from_enum_variant assist --- .../src/handlers/extract_struct_from_enum_variant.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'crates') diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index 38ecf5065..ef4dce477 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs @@ -135,8 +135,12 @@ fn insert_import( variant_hir_name: &Name, ) -> Option<()> { let db = ctx.db(); - let mod_path = module.find_use_path(db, enum_module_def.clone()); - if let Some(mut mod_path) = mod_path.filter(|path| path.len() > 1) { + let mod_path = module.find_use_path_prefixed( + db, + enum_module_def.clone(), + ctx.config.insert_use.prefix_kind, + ); + if let Some(mut mod_path) = mod_path.filter(|path| !path.is_ident()) { mod_path.segments.pop(); mod_path.segments.push(variant_hir_name.clone()); let scope = ImportScope::find_insert_use_container(scope_node, ctx)?; @@ -323,7 +327,7 @@ fn another_fn() { r#"use my_mod::my_other_mod::MyField; mod my_mod { - use my_other_mod::MyField; + use self::my_other_mod::MyField; fn another_fn() { let m = my_other_mod::MyEnum::MyField(MyField(1, 1)); @@ -402,7 +406,7 @@ enum E { mod foo; //- /foo.rs -use crate::E; +use crate::{E, V}; fn f() { let e = E::V(V(9, 2)); } @@ -437,7 +441,7 @@ enum E { mod foo; //- /foo.rs -use crate::E; +use crate::{E, V}; fn f() { let e = E::V(V { i: 9, j: 2 }); } -- cgit v1.2.3 From ccdcd52975c16df217188ccb196f45041b6f0973 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Nov 2020 17:47:58 +0100 Subject: Add extra test to extract_struct_from_enum_variant --- .../handlers/extract_struct_from_enum_variant.rs | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'crates') diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index ef4dce477..067afabf2 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs @@ -140,7 +140,7 @@ fn insert_import( enum_module_def.clone(), ctx.config.insert_use.prefix_kind, ); - if let Some(mut mod_path) = mod_path.filter(|path| !path.is_ident()) { + if let Some(mut mod_path) = mod_path { mod_path.segments.pop(); mod_path.segments.push(variant_hir_name.clone()); let scope = ImportScope::find_insert_use_container(scope_node, ctx)?; @@ -449,6 +449,33 @@ fn f() { ) } + #[test] + fn test_extract_struct_record_nested_call_exp() { + check_assist( + extract_struct_from_enum_variant, + r#" +enum A { <|>One { a: u32, b: u32 } } + +struct B(A); + +fn foo() { + let _ = B(A::One { a: 1, b: 2 }); +} +"#, + r#" +struct One{ pub a: u32, pub b: u32 } + +enum A { One(One) } + +struct B(A); + +fn foo() { + let _ = B(A::One(One { a: 1, b: 2 })); +} +"#, + ); + } + fn check_not_applicable(ra_fixture: &str) { let fixture = format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE); -- cgit v1.2.3