Skip to content

Commit 8611b71

Browse files
authored
Merge pull request #20314 from Hmikihiro/Migrate_inline_type_alias_to_syntax_editor
Migrate `inline_type_alias` assist to use `syntax_editor`
2 parents b0d2487 + 8583e35 commit 8611b71

File tree

1 file changed

+54
-41
lines changed

1 file changed

+54
-41
lines changed

crates/ide-assists/src/handlers/inline_type_alias.rs

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ use ide_db::{
99
search::FileReference,
1010
};
1111
use itertools::Itertools;
12+
use syntax::ast::syntax_factory::SyntaxFactory;
13+
use syntax::syntax_editor::SyntaxEditor;
1214
use syntax::{
1315
AstNode, NodeOrToken, SyntaxNode,
14-
ast::{self, HasGenericParams, HasName, make},
15-
ted,
16+
ast::{self, HasGenericParams, HasName},
1617
};
1718

1819
use crate::{
@@ -68,37 +69,41 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>)
6869
let mut definition_deleted = false;
6970

7071
let mut inline_refs_for_file = |file_id, refs: Vec<FileReference>| {
71-
builder.edit_file(file_id);
72+
let source = ctx.sema.parse(file_id);
73+
let mut editor = builder.make_editor(source.syntax());
7274

7375
let (path_types, path_type_uses) =
7476
split_refs_and_uses(builder, refs, |path_type| {
7577
path_type.syntax().ancestors().nth(3).and_then(ast::PathType::cast)
7678
});
77-
7879
path_type_uses
7980
.iter()
8081
.flat_map(ast_to_remove_for_path_in_use_stmt)
81-
.for_each(|x| builder.delete(x.syntax().text_range()));
82+
.for_each(|x| editor.delete(x.syntax()));
83+
8284
for (target, replacement) in path_types.into_iter().filter_map(|path_type| {
83-
let replacement = inline(&ast_alias, &path_type)?.to_text(&concrete_type);
84-
let target = path_type.syntax().text_range();
85+
let replacement =
86+
inline(&ast_alias, &path_type)?.replace_generic(&concrete_type);
87+
let target = path_type.syntax().clone();
8588
Some((target, replacement))
8689
}) {
87-
builder.replace(target, replacement);
90+
editor.replace(target, replacement);
8891
}
8992

90-
if file_id == ctx.vfs_file_id() {
91-
builder.delete(ast_alias.syntax().text_range());
93+
if file_id.file_id(ctx.db()) == ctx.vfs_file_id() {
94+
editor.delete(ast_alias.syntax());
9295
definition_deleted = true;
9396
}
97+
builder.add_file_edits(file_id.file_id(ctx.db()), editor);
9498
};
9599

96100
for (file_id, refs) in usages.into_iter() {
97-
inline_refs_for_file(file_id.file_id(ctx.db()), refs);
101+
inline_refs_for_file(file_id, refs);
98102
}
99103
if !definition_deleted {
100-
builder.edit_file(ctx.vfs_file_id());
101-
builder.delete(ast_alias.syntax().text_range());
104+
let mut editor = builder.make_editor(ast_alias.syntax());
105+
editor.delete(ast_alias.syntax());
106+
builder.add_file_edits(ctx.vfs_file_id(), editor)
102107
}
103108
},
104109
)
@@ -146,23 +151,26 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
146151
}
147152
}
148153

149-
let target = alias_instance.syntax().text_range();
150-
151154
acc.add(
152155
AssistId::refactor_inline("inline_type_alias"),
153156
"Inline type alias",
154-
target,
155-
|builder| builder.replace(target, replacement.to_text(&concrete_type)),
157+
alias_instance.syntax().text_range(),
158+
|builder| {
159+
let mut editor = builder.make_editor(alias_instance.syntax());
160+
let replace = replacement.replace_generic(&concrete_type);
161+
editor.replace(alias_instance.syntax(), replace);
162+
builder.add_file_edits(ctx.vfs_file_id(), editor);
163+
},
156164
)
157165
}
158166

159167
impl Replacement {
160-
fn to_text(&self, concrete_type: &ast::Type) -> String {
168+
fn replace_generic(&self, concrete_type: &ast::Type) -> SyntaxNode {
161169
match self {
162170
Replacement::Generic { lifetime_map, const_and_type_map } => {
163171
create_replacement(lifetime_map, const_and_type_map, concrete_type)
164172
}
165-
Replacement::Plain => concrete_type.to_string(),
173+
Replacement::Plain => concrete_type.syntax().clone_subtree().clone_for_update(),
166174
}
167175
}
168176
}
@@ -199,8 +207,8 @@ impl LifetimeMap {
199207
alias_generics: &ast::GenericParamList,
200208
) -> Option<Self> {
201209
let mut inner = FxHashMap::default();
202-
203-
let wildcard_lifetime = make::lifetime("'_");
210+
let make = SyntaxFactory::without_mappings();
211+
let wildcard_lifetime = make.lifetime("'_");
204212
let lifetimes = alias_generics
205213
.lifetime_params()
206214
.filter_map(|lp| lp.lifetime())
@@ -299,15 +307,14 @@ fn create_replacement(
299307
lifetime_map: &LifetimeMap,
300308
const_and_type_map: &ConstAndTypeMap,
301309
concrete_type: &ast::Type,
302-
) -> String {
303-
let updated_concrete_type = concrete_type.clone_for_update();
304-
let mut replacements = Vec::new();
305-
let mut removals = Vec::new();
310+
) -> SyntaxNode {
311+
let updated_concrete_type = concrete_type.syntax().clone_subtree();
312+
let mut editor = SyntaxEditor::new(updated_concrete_type.clone());
306313

307-
for syntax in updated_concrete_type.syntax().descendants() {
308-
let syntax_string = syntax.to_string();
309-
let syntax_str = syntax_string.as_str();
314+
let mut replacements: Vec<(SyntaxNode, SyntaxNode)> = Vec::new();
315+
let mut removals: Vec<NodeOrToken<SyntaxNode, _>> = Vec::new();
310316

317+
for syntax in updated_concrete_type.descendants() {
311318
if let Some(old_lifetime) = ast::Lifetime::cast(syntax.clone()) {
312319
if let Some(new_lifetime) = lifetime_map.0.get(&old_lifetime.to_string()) {
313320
if new_lifetime.text() == "'_" {
@@ -322,27 +329,30 @@ fn create_replacement(
322329

323330
replacements.push((syntax.clone(), new_lifetime.syntax().clone_for_update()));
324331
}
325-
} else if let Some(replacement_syntax) = const_and_type_map.0.get(syntax_str) {
332+
} else if let Some(name_ref) = ast::NameRef::cast(syntax.clone()) {
333+
let Some(replacement_syntax) = const_and_type_map.0.get(&name_ref.to_string()) else {
334+
continue;
335+
};
326336
let new_string = replacement_syntax.to_string();
327337
let new = if new_string == "_" {
328-
make::wildcard_pat().syntax().clone_for_update()
338+
let make = SyntaxFactory::without_mappings();
339+
make.wildcard_pat().syntax().clone()
329340
} else {
330-
replacement_syntax.clone_for_update()
341+
replacement_syntax.clone()
331342
};
332343

333344
replacements.push((syntax.clone(), new));
334345
}
335346
}
336347

337348
for (old, new) in replacements {
338-
ted::replace(old, new);
349+
editor.replace(old, new);
339350
}
340351

341352
for syntax in removals {
342-
ted::remove(syntax);
353+
editor.delete(syntax);
343354
}
344-
345-
updated_concrete_type.to_string()
355+
editor.finish().new_root().clone()
346356
}
347357

348358
fn get_type_alias(ctx: &AssistContext<'_>, path: &ast::PathType) -> Option<ast::TypeAlias> {
@@ -377,12 +387,15 @@ impl ConstOrTypeGeneric {
377387
}
378388

379389
fn replacement_value(&self) -> Option<SyntaxNode> {
380-
Some(match self {
381-
ConstOrTypeGeneric::ConstArg(ca) => ca.expr()?.syntax().clone(),
382-
ConstOrTypeGeneric::TypeArg(ta) => ta.syntax().clone(),
383-
ConstOrTypeGeneric::ConstParam(cp) => cp.default_val()?.syntax().clone(),
384-
ConstOrTypeGeneric::TypeParam(tp) => tp.default_type()?.syntax().clone(),
385-
})
390+
Some(
391+
match self {
392+
ConstOrTypeGeneric::ConstArg(ca) => ca.expr()?.syntax().clone(),
393+
ConstOrTypeGeneric::TypeArg(ta) => ta.syntax().clone(),
394+
ConstOrTypeGeneric::ConstParam(cp) => cp.default_val()?.syntax().clone(),
395+
ConstOrTypeGeneric::TypeParam(tp) => tp.default_type()?.syntax().clone(),
396+
}
397+
.clone_for_update(),
398+
)
386399
}
387400
}
388401

0 commit comments

Comments
 (0)