Skip to content

Commit 225988b

Browse files
committed
migrate_replace_derive_with_manual_impl
1 parent 3c8fdcb commit 225988b

File tree

2 files changed

+45
-60
lines changed

2 files changed

+45
-60
lines changed

src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ fn add_missing_impl_members_inner(
158158
&target_scope,
159159
);
160160

161-
let mut editor = edit.make_editor(impl_def.syntax());
162161
if let Some(cap) = ctx.config.snippet_cap {
163162
let mut placeholder = None;
164163
if let DefaultMethods::No = mode {
@@ -172,13 +171,11 @@ fn add_missing_impl_members_inner(
172171
) && let Some(func_body) = func.body()
173172
{
174173
ted::replace(func_body.syntax(), body.syntax());
175-
} else {
176-
if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
177-
{
178-
if m.syntax().text() == "todo!()" {
179-
placeholder = Some(m);
180-
}
181-
}
174+
} else if let Some(m) =
175+
func.syntax().descendants().find_map(ast::MacroCall::cast)
176+
&& m.syntax().text() == "todo!()"
177+
{
178+
placeholder = Some(m);
182179
}
183180
}
184181
}

src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ use syntax::{
55
SyntaxKind::WHITESPACE,
66
T,
77
ast::{self, AstNode, HasName, make},
8-
ted::{self, Position},
8+
syntax_editor::{Position, SyntaxEditor},
99
};
1010

1111
use crate::{
1212
AssistConfig, AssistId,
13-
assist_context::{AssistContext, Assists, SourceChangeBuilder},
13+
assist_context::{AssistContext, Assists},
1414
utils::{
1515
DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items,
1616
gen_trait_fn_body, generate_trait_impl,
@@ -126,9 +126,9 @@ fn add_assist(
126126
let label = format!("Convert to manual `impl {replace_trait_path} for {annotated_name}`");
127127

128128
acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| {
129-
let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax());
129+
let insert_after = Position::after(adt.syntax());
130130
let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false);
131-
let impl_def_with_items = impl_def_from_trait(
131+
let impl_def = impl_def_from_trait(
132132
&ctx.sema,
133133
ctx.config,
134134
adt,
@@ -137,39 +137,23 @@ fn add_assist(
137137
replace_trait_path,
138138
impl_is_unsafe,
139139
);
140-
update_attribute(builder, old_derives, old_tree, old_trait_path, attr);
141140

142-
let trait_path = make::ty_path(replace_trait_path.clone());
143-
144-
match (ctx.config.snippet_cap, impl_def_with_items) {
145-
(None, None) => {
146-
let impl_def = generate_trait_impl(impl_is_unsafe, adt, trait_path);
141+
let mut editor = builder.make_editor(attr.syntax());
142+
update_attribute(&mut editor, old_derives, old_tree, old_trait_path, attr);
147143

148-
ted::insert_all(
149-
insert_after,
150-
vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
151-
);
152-
}
153-
(None, Some((impl_def, _))) => {
154-
ted::insert_all(
155-
insert_after,
156-
vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
157-
);
158-
}
159-
(Some(cap), None) => {
160-
let impl_def = generate_trait_impl(impl_is_unsafe, adt, trait_path);
144+
let trait_path = make::ty_path(replace_trait_path.clone());
161145

162-
if let Some(l_curly) = impl_def.assoc_item_list().and_then(|it| it.l_curly_token())
163-
{
164-
builder.add_tabstop_after_token(cap, l_curly);
165-
}
146+
let (impl_def, first_assoc_item) = if let Some(impl_def) = impl_def {
147+
(
148+
impl_def.clone(),
149+
impl_def.assoc_item_list().and_then(|list| list.assoc_items().next()),
150+
)
151+
} else {
152+
(generate_trait_impl(impl_is_unsafe, adt, trait_path), None)
153+
};
166154

167-
ted::insert_all(
168-
insert_after,
169-
vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
170-
);
171-
}
172-
(Some(cap), Some((impl_def, first_assoc_item))) => {
155+
if let Some(cap) = ctx.config.snippet_cap {
156+
if let Some(first_assoc_item) = first_assoc_item {
173157
if let ast::AssocItem::Fn(ref func) = first_assoc_item
174158
&& let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
175159
&& m.syntax().text() == "todo!()"
@@ -180,13 +164,18 @@ fn add_assist(
180164
// If we haven't already added a snippet, add a tabstop before the generated function
181165
builder.add_tabstop_before(cap, first_assoc_item);
182166
}
183-
184-
ted::insert_all(
185-
insert_after,
186-
vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
187-
);
167+
} else if let Some(l_curly) =
168+
impl_def.assoc_item_list().and_then(|it| it.l_curly_token())
169+
{
170+
builder.add_tabstop_after_token(cap, l_curly);
188171
}
189-
};
172+
}
173+
174+
editor.insert_all(
175+
insert_after,
176+
vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
177+
);
178+
builder.add_file_edits(ctx.vfs_file_id(), editor);
190179
})
191180
}
192181

@@ -198,7 +187,7 @@ fn impl_def_from_trait(
198187
trait_: Option<hir::Trait>,
199188
trait_path: &ast::Path,
200189
impl_is_unsafe: bool,
201-
) -> Option<(ast::Impl, ast::AssocItem)> {
190+
) -> Option<ast::Impl> {
202191
let trait_ = trait_?;
203192
let target_scope = sema.scope(annotated_name.syntax())?;
204193

@@ -217,23 +206,25 @@ fn impl_def_from_trait(
217206
}
218207
let impl_def = generate_trait_impl(impl_is_unsafe, adt, make::ty_path(trait_path.clone()));
219208

220-
let first_assoc_item =
209+
let _ =
221210
add_trait_assoc_items_to_impl(sema, config, &trait_items, trait_, &impl_def, &target_scope);
222-
211+
let impl_def = impl_def.clone_subtree();
212+
let mut editor = SyntaxEditor::new(impl_def.syntax().clone());
213+
let first_assoc_item = impl_def.assoc_item_list().and_then(|item| item.assoc_items().next())?;
223214
// Generate a default `impl` function body for the derived trait.
224215
if let ast::AssocItem::Fn(ref func) = first_assoc_item {
225216
if let Some(body) = gen_trait_fn_body(func, trait_path, adt, None)
226217
&& let Some(func_body) = func.body()
227218
{
228-
ted::replace(func_body.syntax(), body.syntax());
219+
editor.replace(func_body.syntax(), body.syntax());
229220
}
230221
};
231-
232-
Some((impl_def, first_assoc_item))
222+
let impl_def = ast::Impl::cast(editor.finish().new_root().clone())?;
223+
Some(impl_def)
233224
}
234225

235226
fn update_attribute(
236-
builder: &mut SourceChangeBuilder,
227+
editor: &mut SyntaxEditor,
237228
old_derives: &[ast::Path],
238229
old_tree: &ast::TokenTree,
239230
old_trait_path: &ast::Path,
@@ -246,8 +237,6 @@ fn update_attribute(
246237
let has_more_derives = !new_derives.is_empty();
247238

248239
if has_more_derives {
249-
let old_tree = builder.make_mut(old_tree.clone());
250-
251240
// Make the paths into flat lists of tokens in a vec
252241
let tt = new_derives.iter().map(|path| path.syntax().clone()).map(|node| {
253242
node.descendants_with_tokens()
@@ -262,18 +251,17 @@ fn update_attribute(
262251
let tt = tt.collect::<Vec<_>>();
263252

264253
let new_tree = make::token_tree(T!['('], tt).clone_for_update();
265-
ted::replace(old_tree.syntax(), new_tree.syntax());
254+
editor.replace(old_tree.syntax(), new_tree.syntax());
266255
} else {
267256
// Remove the attr and any trailing whitespace
268-
let attr = builder.make_mut(attr.clone());
269257

270258
if let Some(line_break) =
271259
attr.syntax().next_sibling_or_token().filter(|t| t.kind() == WHITESPACE)
272260
{
273-
ted::remove(line_break)
261+
editor.delete(line_break)
274262
}
275263

276-
ted::remove(attr.syntax())
264+
editor.delete(attr.syntax())
277265
}
278266
}
279267

0 commit comments

Comments
 (0)