mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 07:04:22 +00:00
Consider field attributes when converting from tuple to named struct and the opposite
This commit is contained in:
parent
f454ea8771
commit
1fc6cbc6f1
2 changed files with 49 additions and 11 deletions
|
@ -2,8 +2,8 @@ use either::Either;
|
|||
use ide_db::{defs::Definition, search::FileReference};
|
||||
use itertools::Itertools;
|
||||
use syntax::{
|
||||
ast::{self, AstNode, HasGenericParams, HasVisibility},
|
||||
match_ast, SyntaxKind,
|
||||
ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility},
|
||||
match_ast, ted, SyntaxKind,
|
||||
};
|
||||
|
||||
use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists};
|
||||
|
@ -87,9 +87,14 @@ fn edit_struct_def(
|
|||
) {
|
||||
// Note that we don't need to consider macro files in this function because this is
|
||||
// currently not triggered for struct definitions inside macro calls.
|
||||
let tuple_fields = record_fields
|
||||
.fields()
|
||||
.filter_map(|f| Some(ast::make::tuple_field(f.visibility(), f.ty()?)));
|
||||
let tuple_fields = record_fields.fields().filter_map(|f| {
|
||||
let field = ast::make::tuple_field(f.visibility(), f.ty()?).clone_for_update();
|
||||
ted::insert_all(
|
||||
ted::Position::first_child_of(field.syntax()),
|
||||
f.attrs().map(|attr| attr.syntax().clone_subtree().clone_for_update().into()).collect(),
|
||||
);
|
||||
Some(field)
|
||||
});
|
||||
let tuple_fields = ast::make::tuple_field_list(tuple_fields);
|
||||
let record_fields_text_range = record_fields.syntax().text_range();
|
||||
|
||||
|
@ -975,6 +980,22 @@ impl HasAssoc for Struct {
|
|||
let Self::Assoc { value } = a;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fields_with_attrs() {
|
||||
check_assist(
|
||||
convert_named_struct_to_tuple_struct,
|
||||
r#"
|
||||
pub struct $0Foo {
|
||||
#[my_custom_attr]
|
||||
value: u32,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
pub struct Foo(#[my_custom_attr] u32);
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use either::Either;
|
||||
use ide_db::defs::{Definition, NameRefClass};
|
||||
use syntax::{
|
||||
ast::{self, AstNode, HasGenericParams, HasVisibility},
|
||||
match_ast, SyntaxKind, SyntaxNode,
|
||||
ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility},
|
||||
match_ast, ted, SyntaxKind, SyntaxNode,
|
||||
};
|
||||
|
||||
use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists};
|
||||
|
@ -83,10 +83,14 @@ fn edit_struct_def(
|
|||
tuple_fields: ast::TupleFieldList,
|
||||
names: Vec<ast::Name>,
|
||||
) {
|
||||
let record_fields = tuple_fields
|
||||
.fields()
|
||||
.zip(names)
|
||||
.filter_map(|(f, name)| Some(ast::make::record_field(f.visibility(), name, f.ty()?)));
|
||||
let record_fields = tuple_fields.fields().zip(names).filter_map(|(f, name)| {
|
||||
let field = ast::make::record_field(f.visibility(), name, f.ty()?).clone_for_update();
|
||||
ted::insert_all(
|
||||
ted::Position::first_child_of(field.syntax()),
|
||||
f.attrs().map(|attr| attr.syntax().clone_subtree().clone_for_update().into()).collect(),
|
||||
);
|
||||
Some(field)
|
||||
});
|
||||
let record_fields = ast::make::record_field_list(record_fields);
|
||||
let tuple_fields_text_range = tuple_fields.syntax().text_range();
|
||||
|
||||
|
@ -904,6 +908,19 @@ where
|
|||
T: Foo,
|
||||
{ pub field1: T }
|
||||
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fields_with_attrs() {
|
||||
check_assist(
|
||||
convert_tuple_struct_to_named_struct,
|
||||
r#"
|
||||
pub struct $0Foo(#[my_custom_attr] u32);
|
||||
"#,
|
||||
r#"
|
||||
pub struct Foo { #[my_custom_attr] field1: u32 }
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue