Fix incorrectly replacing method calls in "Convert to named struct" assist

This commit is contained in:
unexge 2021-04-21 10:27:26 +03:00
parent 8d4be829e0
commit 53599d11f6

View File

@ -1,5 +1,5 @@
use hir::{Adt, ModuleDef}; use hir::{Adt, ModuleDef};
use ide_db::defs::Definition; use ide_db::defs::{Definition, NameRefClass};
use syntax::{ use syntax::{
ast::{self, AstNode, GenericParamsOwner, VisibilityOwner}, ast::{self, AstNode, GenericParamsOwner, VisibilityOwner},
match_ast, match_ast,
@ -80,11 +80,9 @@ fn edit_struct_references(
strukt: &ast::Struct, strukt: &ast::Struct,
names: &[ast::Name], names: &[ast::Name],
) { ) {
let strukt_def = ctx.sema.to_def(strukt).unwrap(); let strukt = ctx.sema.to_def(strukt).unwrap();
let usages = Definition::ModuleDef(ModuleDef::Adt(Adt::Struct(strukt_def))) let strukt_def = Definition::ModuleDef(ModuleDef::Adt(Adt::Struct(strukt)));
.usages(&ctx.sema) let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all();
.include_self_kw_refs(true)
.all();
for (file_id, refs) in usages { for (file_id, refs) in usages {
edit.edit_file(file_id); edit.edit_file(file_id);
@ -109,16 +107,26 @@ fn edit_struct_references(
.to_string(), .to_string(),
); );
}, },
// for tuple struct creations like: Foo(42) // for tuple struct creations like Foo(42)
ast::CallExpr(call_expr) => { ast::CallExpr(call_expr) => {
let path = call_expr.syntax().descendants().find_map(ast::PathExpr::cast).unwrap(); let path = call_expr.syntax().descendants().find_map(ast::PathExpr::cast).unwrap().path().unwrap();
// this also includes method calls like Foo::new(42), we should skip them
if let Some(Some(name_ref)) = path.segment().map(|s| s.name_ref()) {
match NameRefClass::classify(&ctx.sema, &name_ref) {
Some(NameRefClass::Definition(Definition::SelfType(_))) => {},
Some(NameRefClass::Definition(def)) if def == strukt_def => {},
_ => continue,
};
}
let arg_list = let arg_list =
call_expr.syntax().descendants().find_map(ast::ArgList::cast).unwrap(); call_expr.syntax().descendants().find_map(ast::ArgList::cast).unwrap();
edit.replace( edit.replace(
call_expr.syntax().text_range(), call_expr.syntax().text_range(),
ast::make::record_expr( ast::make::record_expr(
path.path().unwrap(), path,
ast::make::record_expr_field_list(arg_list.args().zip(names).map( ast::make::record_expr_field_list(arg_list.args().zip(names).map(
|(expr, name)| { |(expr, name)| {
ast::make::record_expr_field( ast::make::record_expr_field(
@ -191,8 +199,12 @@ fn convert_simple_struct() {
struct A$0(Inner); struct A$0(Inner);
impl A { impl A {
fn new() -> A { fn new(inner: Inner) -> A {
A(Inner) A(inner)
}
fn new_with_default() -> A {
A::new(Inner)
} }
fn into_inner(self) -> Inner { fn into_inner(self) -> Inner {
@ -204,8 +216,12 @@ fn into_inner(self) -> Inner {
struct A { field1: Inner } struct A { field1: Inner }
impl A { impl A {
fn new() -> A { fn new(inner: Inner) -> A {
A { field1: Inner } A { field1: inner }
}
fn new_with_default() -> A {
A::new(Inner)
} }
fn into_inner(self) -> Inner { fn into_inner(self) -> Inner {
@ -224,8 +240,12 @@ fn convert_struct_referenced_via_self_kw() {
struct A$0(Inner); struct A$0(Inner);
impl A { impl A {
fn new() -> Self { fn new(inner: Inner) -> Self {
Self(Inner) Self(inner)
}
fn new_with_default() -> Self {
Self::new(Inner)
} }
fn into_inner(self) -> Inner { fn into_inner(self) -> Inner {
@ -237,8 +257,12 @@ fn into_inner(self) -> Inner {
struct A { field1: Inner } struct A { field1: Inner }
impl A { impl A {
fn new() -> Self { fn new(inner: Inner) -> Self {
Self { field1: Inner } Self { field1: inner }
}
fn new_with_default() -> Self {
Self::new(Inner)
} }
fn into_inner(self) -> Inner { fn into_inner(self) -> Inner {