migrate fn edit_struct_def in convert_tuple_struct_to_named_struct to SyntaxEditor

Signed-off-by: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com>
This commit is contained in:
Hayashi Mikihiro 2025-07-26 23:20:31 +09:00
parent 6e2306faaf
commit d02bf21c47

View File

@ -1,10 +1,10 @@
use either::Either; use either::Either;
use ide_db::defs::{Definition, NameRefClass}; use ide_db::defs::{Definition, NameRefClass};
use syntax::{ use syntax::{
SyntaxKind, SyntaxNode, SyntaxKind, SyntaxNode, T,
ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility}, ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility},
match_ast, match_ast,
syntax_editor::{Position, SyntaxEditor}, syntax_editor::{Element, Position, SyntaxEditor},
}; };
use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder}; use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder};
@ -72,7 +72,7 @@ pub(crate) fn convert_tuple_struct_to_named_struct(
Either::Right(v) => Either::Right(ctx.sema.to_def(v)?), Either::Right(v) => Either::Right(ctx.sema.to_def(v)?),
}; };
let target = strukt_or_variant.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();
let syntax = strukt_or_variant.as_ref().either(|s| s.syntax(), |v| v.syntax());
acc.add( acc.add(
AssistId::refactor_rewrite("convert_tuple_struct_to_named_struct"), AssistId::refactor_rewrite("convert_tuple_struct_to_named_struct"),
"Convert to named struct", "Convert to named struct",
@ -81,58 +81,53 @@ 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_or_variant, tuple_fields, names); let mut editor = edit.make_editor(syntax);
edit_struct_def(&mut editor, &strukt_or_variant, tuple_fields, names);
edit.add_file_edits(ctx.vfs_file_id(), editor);
}, },
) )
} }
fn edit_struct_def( fn edit_struct_def(
ctx: &AssistContext<'_>, editor: &mut SyntaxEditor,
edit: &mut SourceChangeBuilder,
strukt: &Either<ast::Struct, ast::Variant>, strukt: &Either<ast::Struct, ast::Variant>,
tuple_fields: ast::TupleFieldList, tuple_fields: ast::TupleFieldList,
names: Vec<ast::Name>, names: Vec<ast::Name>,
) { ) {
let record_fields = tuple_fields.fields().zip(names).filter_map(|(f, name)| { let record_fields = tuple_fields.fields().zip(names).filter_map(|(f, name)| {
let field = ast::make::record_field(f.visibility(), name, f.ty()?); let field = ast::make::record_field(f.visibility(), name, f.ty()?);
let mut editor = SyntaxEditor::new(field.syntax().clone()); let mut field_editor = SyntaxEditor::new(field.syntax().clone());
editor.insert_all( field_editor.insert_all(
Position::first_child_of(field.syntax()), Position::first_child_of(field.syntax()),
f.attrs().map(|attr| attr.syntax().clone_subtree().clone_for_update().into()).collect(), f.attrs().map(|attr| attr.syntax().clone_subtree().clone_for_update().into()).collect(),
); );
ast::RecordField::cast(editor.finish().new_root().clone()) ast::RecordField::cast(field_editor.finish().new_root().clone())
}); });
let record_fields = ast::make::record_field_list(record_fields); let record_fields = ast::make::record_field_list(record_fields).clone_for_update();
let tuple_fields_text_range = tuple_fields.syntax().text_range(); let tuple_fields_before = Position::before(tuple_fields.syntax());
edit.edit_file(ctx.vfs_file_id());
if let Either::Left(strukt) = strukt { if let Either::Left(strukt) = strukt {
if let Some(w) = strukt.where_clause() { if let Some(w) = strukt.where_clause() {
edit.delete(w.syntax().text_range()); editor.delete(w.syntax());
edit.insert( let mut insert_element = Vec::new();
tuple_fields_text_range.start(), insert_element.push(ast::make::tokens::single_newline().syntax_element());
ast::make::tokens::single_newline().text(), insert_element.push(w.syntax().clone_for_update().syntax_element());
);
edit.insert(tuple_fields_text_range.start(), w.syntax().text());
if w.syntax().last_token().is_none_or(|t| t.kind() != SyntaxKind::COMMA) { if w.syntax().last_token().is_none_or(|t| t.kind() != SyntaxKind::COMMA) {
edit.insert(tuple_fields_text_range.start(), ","); insert_element.push(ast::make::token(T![,]).into());
} }
edit.insert( insert_element.push(ast::make::tokens::single_newline().syntax_element());
tuple_fields_text_range.start(), editor.insert_all(tuple_fields_before, insert_element);
ast::make::tokens::single_newline().text(),
);
} else { } else {
edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_space().text()); editor.insert(tuple_fields_before, ast::make::tokens::single_space());
} }
if let Some(t) = strukt.semicolon_token() { if let Some(t) = strukt.semicolon_token() {
edit.delete(t.text_range()); editor.delete(t);
} }
} else { } else {
edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_space().text()); editor.insert(tuple_fields_before, ast::make::tokens::single_space());
} }
edit.replace(tuple_fields_text_range, record_fields.to_string()); editor.replace(tuple_fields.syntax(), record_fields.syntax());
} }
fn edit_struct_references( fn edit_struct_references(
@ -1015,8 +1010,7 @@ where
pub struct $0Foo(#[my_custom_attr] u32); pub struct $0Foo(#[my_custom_attr] u32);
"#, "#,
r#" r#"
pub struct Foo { #[my_custom_attr] pub struct Foo { #[my_custom_attr]field1: u32 }
field1: u32 }
"#, "#,
); );
} }