mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
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:
commit
d5a424f338
2 changed files with 49 additions and 11 deletions
|
@ -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);
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue