Migrate inline_type_alias assist to use SyntaxEditor

This commit is contained in:
Hmikihiro 2025-07-27 22:04:25 +09:00
parent feaf647b06
commit 96f619d0d0

View file

@ -9,10 +9,10 @@ use ide_db::{
search::FileReference, search::FileReference,
}; };
use itertools::Itertools; use itertools::Itertools;
use syntax::syntax_editor::SyntaxEditor;
use syntax::{ use syntax::{
AstNode, NodeOrToken, SyntaxNode, AstNode, NodeOrToken, SyntaxNode,
ast::{self, HasGenericParams, HasName, make}, ast::{self, HasGenericParams, HasName, make},
ted,
}; };
use crate::{ use crate::{
@ -68,37 +68,41 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>)
let mut definition_deleted = false; let mut definition_deleted = false;
let mut inline_refs_for_file = |file_id, refs: Vec<FileReference>| { let mut inline_refs_for_file = |file_id, refs: Vec<FileReference>| {
builder.edit_file(file_id); let source = ctx.sema.parse(file_id);
let mut editor = builder.make_editor(source.syntax());
let (path_types, path_type_uses) = let (path_types, path_type_uses) =
split_refs_and_uses(builder, refs, |path_type| { split_refs_and_uses(builder, refs, |path_type| {
path_type.syntax().ancestors().nth(3).and_then(ast::PathType::cast) path_type.syntax().ancestors().nth(3).and_then(ast::PathType::cast)
}); });
path_type_uses path_type_uses
.iter() .iter()
.flat_map(ast_to_remove_for_path_in_use_stmt) .flat_map(ast_to_remove_for_path_in_use_stmt)
.for_each(|x| builder.delete(x.syntax().text_range())); .for_each(|x| editor.delete(x.syntax()));
for (target, replacement) in path_types.into_iter().filter_map(|path_type| { for (target, replacement) in path_types.into_iter().filter_map(|path_type| {
let replacement = inline(&ast_alias, &path_type)?.to_text(&concrete_type); let replacement =
let target = path_type.syntax().text_range(); inline(&ast_alias, &path_type)?.replace_generic(&concrete_type);
let target = path_type.syntax().clone();
Some((target, replacement)) Some((target, replacement))
}) { }) {
builder.replace(target, replacement); editor.replace(target, replacement);
} }
if file_id == ctx.vfs_file_id() { if file_id.file_id(ctx.db()) == ctx.vfs_file_id() {
builder.delete(ast_alias.syntax().text_range()); editor.delete(ast_alias.syntax());
definition_deleted = true; definition_deleted = true;
} }
builder.add_file_edits(file_id.file_id(ctx.db()), editor);
}; };
for (file_id, refs) in usages.into_iter() { for (file_id, refs) in usages.into_iter() {
inline_refs_for_file(file_id.file_id(ctx.db()), refs); inline_refs_for_file(file_id, refs);
} }
if !definition_deleted { if !definition_deleted {
builder.edit_file(ctx.vfs_file_id()); let mut editor = builder.make_editor(ast_alias.syntax());
builder.delete(ast_alias.syntax().text_range()); editor.delete(ast_alias.syntax());
builder.add_file_edits(ctx.vfs_file_id(), editor)
} }
}, },
) )
@ -146,23 +150,26 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
} }
} }
let target = alias_instance.syntax().text_range();
acc.add( acc.add(
AssistId::refactor_inline("inline_type_alias"), AssistId::refactor_inline("inline_type_alias"),
"Inline type alias", "Inline type alias",
target, alias_instance.syntax().text_range(),
|builder| builder.replace(target, replacement.to_text(&concrete_type)), |builder| {
let mut editor = builder.make_editor(alias_instance.syntax());
let replace = replacement.replace_generic(&concrete_type);
editor.replace(alias_instance.syntax(), replace);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
) )
} }
impl Replacement { impl Replacement {
fn to_text(&self, concrete_type: &ast::Type) -> String { fn replace_generic(&self, concrete_type: &ast::Type) -> SyntaxNode {
match self { match self {
Replacement::Generic { lifetime_map, const_and_type_map } => { Replacement::Generic { lifetime_map, const_and_type_map } => {
create_replacement(lifetime_map, const_and_type_map, concrete_type) create_replacement(lifetime_map, const_and_type_map, concrete_type)
} }
Replacement::Plain => concrete_type.to_string(), Replacement::Plain => concrete_type.syntax().clone_subtree().clone_for_update(),
} }
} }
} }
@ -299,15 +306,14 @@ fn create_replacement(
lifetime_map: &LifetimeMap, lifetime_map: &LifetimeMap,
const_and_type_map: &ConstAndTypeMap, const_and_type_map: &ConstAndTypeMap,
concrete_type: &ast::Type, concrete_type: &ast::Type,
) -> String { ) -> SyntaxNode {
let updated_concrete_type = concrete_type.clone_for_update(); let updated_concrete_type = concrete_type.syntax().clone_subtree();
let mut replacements = Vec::new(); let mut editor = SyntaxEditor::new(updated_concrete_type.clone());
let mut removals = Vec::new();
for syntax in updated_concrete_type.syntax().descendants() { let mut replacements: Vec<(SyntaxNode, SyntaxNode)> = Vec::new();
let syntax_string = syntax.to_string(); let mut removals: Vec<NodeOrToken<SyntaxNode, _>> = Vec::new();
let syntax_str = syntax_string.as_str();
for syntax in updated_concrete_type.descendants() {
if let Some(old_lifetime) = ast::Lifetime::cast(syntax.clone()) { if let Some(old_lifetime) = ast::Lifetime::cast(syntax.clone()) {
if let Some(new_lifetime) = lifetime_map.0.get(&old_lifetime.to_string()) { if let Some(new_lifetime) = lifetime_map.0.get(&old_lifetime.to_string()) {
if new_lifetime.text() == "'_" { if new_lifetime.text() == "'_" {
@ -338,14 +344,13 @@ fn create_replacement(
} }
for (old, new) in replacements { for (old, new) in replacements {
ted::replace(old, new); editor.replace(old, new);
} }
for syntax in removals { for syntax in removals {
ted::remove(syntax); editor.delete(syntax);
} }
editor.finish().new_root().clone()
updated_concrete_type.to_string()
} }
fn get_type_alias(ctx: &AssistContext<'_>, path: &ast::PathType) -> Option<ast::TypeAlias> { fn get_type_alias(ctx: &AssistContext<'_>, path: &ast::PathType) -> Option<ast::TypeAlias> {