mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 10:58:02 +00:00
Merge pull request #19901 from BazookaMusic/master
Enable Assist edit for tuple<->named struct for the struct and visiblity keywords
This commit is contained in:
commit
9edac77f48
2 changed files with 192 additions and 12 deletions
|
|
@ -56,14 +56,22 @@ pub(crate) fn convert_named_struct_to_tuple_struct(
|
||||||
// XXX: We don't currently provide this assist for struct definitions inside macros, but if we
|
// XXX: We don't currently provide this assist for struct definitions inside macros, but if we
|
||||||
// are to lift this limitation, don't forget to make `edit_struct_def()` consider macro files
|
// are to lift this limitation, don't forget to make `edit_struct_def()` consider macro files
|
||||||
// too.
|
// too.
|
||||||
let name = ctx.find_node_at_offset::<ast::Name>()?;
|
let strukt_or_variant = ctx
|
||||||
let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?;
|
.find_node_at_offset::<ast::Struct>()
|
||||||
let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
|
.map(Either::Left)
|
||||||
|
.or_else(|| ctx.find_node_at_offset::<ast::Variant>().map(Either::Right))?;
|
||||||
|
let field_list = strukt_or_variant.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
|
||||||
|
|
||||||
|
if ctx.offset() > field_list.syntax().text_range().start() {
|
||||||
|
// Assist could be distracting after the braces
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let record_fields = match field_list {
|
let record_fields = match field_list {
|
||||||
ast::FieldList::RecordFieldList(it) => it,
|
ast::FieldList::RecordFieldList(it) => it,
|
||||||
ast::FieldList::TupleFieldList(_) => return None,
|
ast::FieldList::TupleFieldList(_) => return None,
|
||||||
};
|
};
|
||||||
let strukt_def = match &strukt {
|
let strukt_def = match &strukt_or_variant {
|
||||||
Either::Left(s) => Either::Left(ctx.sema.to_def(s)?),
|
Either::Left(s) => Either::Left(ctx.sema.to_def(s)?),
|
||||||
Either::Right(v) => Either::Right(ctx.sema.to_def(v)?),
|
Either::Right(v) => Either::Right(ctx.sema.to_def(v)?),
|
||||||
};
|
};
|
||||||
|
|
@ -71,11 +79,11 @@ pub(crate) fn convert_named_struct_to_tuple_struct(
|
||||||
acc.add(
|
acc.add(
|
||||||
AssistId::refactor_rewrite("convert_named_struct_to_tuple_struct"),
|
AssistId::refactor_rewrite("convert_named_struct_to_tuple_struct"),
|
||||||
"Convert to tuple struct",
|
"Convert to tuple struct",
|
||||||
strukt.syntax().text_range(),
|
strukt_or_variant.syntax().text_range(),
|
||||||
|edit| {
|
|edit| {
|
||||||
edit_field_references(ctx, edit, record_fields.fields());
|
edit_field_references(ctx, edit, record_fields.fields());
|
||||||
edit_struct_references(ctx, edit, strukt_def);
|
edit_struct_references(ctx, edit, strukt_def);
|
||||||
edit_struct_def(ctx, edit, &strukt, record_fields);
|
edit_struct_def(ctx, edit, &strukt_or_variant, record_fields);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -277,6 +285,88 @@ impl A {
|
||||||
struct Inner;
|
struct Inner;
|
||||||
struct A(Inner);
|
struct A(Inner);
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A(inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_simple_struct_cursor_on_struct_keyword() {
|
||||||
|
check_assist(
|
||||||
|
convert_named_struct_to_tuple_struct,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
struct$0 A { inner: Inner }
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A { inner }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
struct A(Inner);
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A(inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_simple_struct_cursor_on_visibility_keyword() {
|
||||||
|
check_assist(
|
||||||
|
convert_named_struct_to_tuple_struct,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
pub$0 struct A { inner: Inner }
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A { inner }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
pub struct A(Inner);
|
||||||
|
|
||||||
impl A {
|
impl A {
|
||||||
fn new(inner: Inner) -> A {
|
fn new(inner: Inner) -> A {
|
||||||
A(inner)
|
A(inner)
|
||||||
|
|
|
||||||
|
|
@ -51,18 +51,26 @@ pub(crate) fn convert_tuple_struct_to_named_struct(
|
||||||
acc: &mut Assists,
|
acc: &mut Assists,
|
||||||
ctx: &AssistContext<'_>,
|
ctx: &AssistContext<'_>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let name = ctx.find_node_at_offset::<ast::Name>()?;
|
let strukt_or_variant = ctx
|
||||||
let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?;
|
.find_node_at_offset::<ast::Struct>()
|
||||||
let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
|
.map(Either::Left)
|
||||||
|
.or_else(|| ctx.find_node_at_offset::<ast::Variant>().map(Either::Right))?;
|
||||||
|
let field_list = strukt_or_variant.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
|
||||||
|
|
||||||
|
if ctx.offset() > field_list.syntax().text_range().start() {
|
||||||
|
// Assist could be distracting after the braces
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let tuple_fields = match field_list {
|
let tuple_fields = match field_list {
|
||||||
ast::FieldList::TupleFieldList(it) => it,
|
ast::FieldList::TupleFieldList(it) => it,
|
||||||
ast::FieldList::RecordFieldList(_) => return None,
|
ast::FieldList::RecordFieldList(_) => return None,
|
||||||
};
|
};
|
||||||
let strukt_def = match &strukt {
|
let strukt_def = match &strukt_or_variant {
|
||||||
Either::Left(s) => Either::Left(ctx.sema.to_def(s)?),
|
Either::Left(s) => Either::Left(ctx.sema.to_def(s)?),
|
||||||
Either::Right(v) => Either::Right(ctx.sema.to_def(v)?),
|
Either::Right(v) => Either::Right(ctx.sema.to_def(v)?),
|
||||||
};
|
};
|
||||||
let target = strukt.as_ref().either(|s| s.syntax(), |v| v.syntax()).text_range();
|
let target = strukt_or_variant.as_ref().either(|s| s.syntax(), |v| v.syntax()).text_range();
|
||||||
|
|
||||||
acc.add(
|
acc.add(
|
||||||
AssistId::refactor_rewrite("convert_tuple_struct_to_named_struct"),
|
AssistId::refactor_rewrite("convert_tuple_struct_to_named_struct"),
|
||||||
|
|
@ -72,7 +80,7 @@ pub(crate) fn convert_tuple_struct_to_named_struct(
|
||||||
let names = generate_names(tuple_fields.fields());
|
let names = generate_names(tuple_fields.fields());
|
||||||
edit_field_references(ctx, edit, tuple_fields.fields(), &names);
|
edit_field_references(ctx, edit, tuple_fields.fields(), &names);
|
||||||
edit_struct_references(ctx, edit, strukt_def, &names);
|
edit_struct_references(ctx, edit, strukt_def, &names);
|
||||||
edit_struct_def(ctx, edit, &strukt, tuple_fields, names);
|
edit_struct_def(ctx, edit, &strukt_or_variant, tuple_fields, names);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -300,6 +308,88 @@ impl A {
|
||||||
struct Inner;
|
struct Inner;
|
||||||
struct A { field1: Inner }
|
struct A { field1: Inner }
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A { field1: inner }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.field1
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_simple_struct_cursor_on_struct_keyword() {
|
||||||
|
check_assist(
|
||||||
|
convert_tuple_struct_to_named_struct,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
struct$0 A(Inner);
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A(inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
struct A { field1: Inner }
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A { field1: inner }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.field1
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_simple_struct_cursor_on_visibility_keyword() {
|
||||||
|
check_assist(
|
||||||
|
convert_tuple_struct_to_named_struct,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
pub$0 struct A(Inner);
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn new(inner: Inner) -> A {
|
||||||
|
A(inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_default() -> A {
|
||||||
|
A::new(Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_inner(self) -> Inner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
r#"
|
||||||
|
struct Inner;
|
||||||
|
pub struct A { field1: Inner }
|
||||||
|
|
||||||
impl A {
|
impl A {
|
||||||
fn new(inner: Inner) -> A {
|
fn new(inner: Inner) -> A {
|
||||||
A { field1: inner }
|
A { field1: inner }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue