Auto merge of #17993 - ChayimFriedman2:convert-to-tuple-attrs, r=Veykril

Consider field attributes when converting from tuple to named struct and the opposite

Fixes #17983.

I tried to use the `SourceChangeBuilder::make_mut()` API, but it duplicated the attribute...
This commit is contained in:
bors 2024-08-29 08:28:46 +00:00
commit d5a424f338
2 changed files with 49 additions and 11 deletions

View file

@ -2,8 +2,8 @@ use either::Either;
use ide_db::{defs::Definition, search::FileReference}; use ide_db::{defs::Definition, search::FileReference};
use itertools::Itertools; use itertools::Itertools;
use syntax::{ use syntax::{
ast::{self, AstNode, HasGenericParams, HasVisibility}, ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility},
match_ast, SyntaxKind, match_ast, ted, SyntaxKind,
}; };
use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists}; 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 // 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. // currently not triggered for struct definitions inside macro calls.
let tuple_fields = record_fields let tuple_fields = record_fields.fields().filter_map(|f| {
.fields() let field = ast::make::tuple_field(f.visibility(), f.ty()?).clone_for_update();
.filter_map(|f| Some(ast::make::tuple_field(f.visibility(), f.ty()?))); 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 tuple_fields = ast::make::tuple_field_list(tuple_fields);
let record_fields_text_range = record_fields.syntax().text_range(); let record_fields_text_range = record_fields.syntax().text_range();
@ -975,6 +980,22 @@ impl HasAssoc for Struct {
let Self::Assoc { value } = a; 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);
"#, "#,
); );
} }

View file

@ -1,8 +1,8 @@
use either::Either; use either::Either;
use ide_db::defs::{Definition, NameRefClass}; use ide_db::defs::{Definition, NameRefClass};
use syntax::{ use syntax::{
ast::{self, AstNode, HasGenericParams, HasVisibility}, ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility},
match_ast, SyntaxKind, SyntaxNode, match_ast, ted, SyntaxKind, SyntaxNode,
}; };
use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists}; use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists};
@ -83,10 +83,14 @@ fn edit_struct_def(
tuple_fields: ast::TupleFieldList, tuple_fields: ast::TupleFieldList,
names: Vec<ast::Name>, names: Vec<ast::Name>,
) { ) {
let record_fields = tuple_fields let record_fields = tuple_fields.fields().zip(names).filter_map(|(f, name)| {
.fields() let field = ast::make::record_field(f.visibility(), name, f.ty()?).clone_for_update();
.zip(names) ted::insert_all(
.filter_map(|(f, name)| Some(ast::make::record_field(f.visibility(), name, f.ty()?))); 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 record_fields = ast::make::record_field_list(record_fields);
let tuple_fields_text_range = tuple_fields.syntax().text_range(); let tuple_fields_text_range = tuple_fields.syntax().text_range();
@ -904,6 +908,19 @@ where
T: Foo, T: Foo,
{ pub field1: T } { 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 }
"#, "#,
); );
} }