mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #20371 from Hmikihiro/migrate_generate_trait_from_impl
Migrate `generate_trait_from_impl` assist to use `SyntaxEditor`
This commit is contained in:
commit
531a02c824
@ -2,12 +2,8 @@ use crate::assist_context::{AssistContext, Assists};
|
|||||||
use ide_db::assists::AssistId;
|
use ide_db::assists::AssistId;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
AstNode, SyntaxKind, T,
|
AstNode, SyntaxKind, T,
|
||||||
ast::{
|
ast::{self, HasGenericParams, HasName, HasVisibility, edit_in_place::Indent, make},
|
||||||
self, HasGenericParams, HasName, HasVisibility,
|
syntax_editor::{Position, SyntaxEditor},
|
||||||
edit_in_place::{HasVisibilityEdit, Indent},
|
|
||||||
make,
|
|
||||||
},
|
|
||||||
ted::{self, Position},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTES :
|
// NOTES :
|
||||||
@ -88,8 +84,8 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let assoc_items = impl_ast.assoc_item_list()?;
|
let impl_assoc_items = impl_ast.assoc_item_list()?;
|
||||||
let first_element = assoc_items.assoc_items().next();
|
let first_element = impl_assoc_items.assoc_items().next();
|
||||||
first_element.as_ref()?;
|
first_element.as_ref()?;
|
||||||
|
|
||||||
let impl_name = impl_ast.self_ty()?;
|
let impl_name = impl_ast.self_ty()?;
|
||||||
@ -99,20 +95,16 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
|
|||||||
"Generate trait from impl",
|
"Generate trait from impl",
|
||||||
impl_ast.syntax().text_range(),
|
impl_ast.syntax().text_range(),
|
||||||
|builder| {
|
|builder| {
|
||||||
let impl_ast = builder.make_mut(impl_ast);
|
let trait_items: ast::AssocItemList = {
|
||||||
let trait_items = assoc_items.clone_for_update();
|
let trait_items = impl_assoc_items.clone_subtree();
|
||||||
let impl_items = builder.make_mut(assoc_items);
|
let mut trait_items_editor = SyntaxEditor::new(trait_items.syntax().clone());
|
||||||
let impl_name = builder.make_mut(impl_name);
|
|
||||||
|
|
||||||
trait_items.assoc_items().for_each(|item| {
|
|
||||||
strip_body(&item);
|
|
||||||
remove_items_visibility(&item);
|
|
||||||
});
|
|
||||||
|
|
||||||
impl_items.assoc_items().for_each(|item| {
|
|
||||||
remove_items_visibility(&item);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
trait_items.assoc_items().for_each(|item| {
|
||||||
|
strip_body(&mut trait_items_editor, &item);
|
||||||
|
remove_items_visibility(&mut trait_items_editor, &item);
|
||||||
|
});
|
||||||
|
ast::AssocItemList::cast(trait_items_editor.finish().new_root().clone()).unwrap()
|
||||||
|
};
|
||||||
let trait_ast = make::trait_(
|
let trait_ast = make::trait_(
|
||||||
false,
|
false,
|
||||||
"NewTrait",
|
"NewTrait",
|
||||||
@ -130,6 +122,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
|
|||||||
trait_name_ref.syntax().clone().into(),
|
trait_name_ref.syntax().clone().into(),
|
||||||
make::tokens::single_space().into(),
|
make::tokens::single_space().into(),
|
||||||
make::token(T![for]).into(),
|
make::token(T![for]).into(),
|
||||||
|
make::tokens::single_space().into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if let Some(params) = impl_ast.generic_param_list() {
|
if let Some(params) = impl_ast.generic_param_list() {
|
||||||
@ -137,10 +130,15 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
|
|||||||
elements.insert(1, gen_args.syntax().clone().into());
|
elements.insert(1, gen_args.syntax().clone().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
ted::insert_all(Position::before(impl_name.syntax()), elements);
|
let mut editor = builder.make_editor(impl_ast.syntax());
|
||||||
|
impl_assoc_items.assoc_items().for_each(|item| {
|
||||||
|
remove_items_visibility(&mut editor, &item);
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.insert_all(Position::before(impl_name.syntax()), elements);
|
||||||
|
|
||||||
// Insert trait before TraitImpl
|
// Insert trait before TraitImpl
|
||||||
ted::insert_all_raw(
|
editor.insert_all(
|
||||||
Position::before(impl_ast.syntax()),
|
Position::before(impl_ast.syntax()),
|
||||||
vec![
|
vec![
|
||||||
trait_ast.syntax().clone().into(),
|
trait_ast.syntax().clone().into(),
|
||||||
@ -150,11 +148,12 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
|
|||||||
|
|
||||||
// Link the trait name & trait ref names together as a placeholder snippet group
|
// Link the trait name & trait ref names together as a placeholder snippet group
|
||||||
if let Some(cap) = ctx.config.snippet_cap {
|
if let Some(cap) = ctx.config.snippet_cap {
|
||||||
builder.add_placeholder_snippet_group(
|
let placeholder = builder.make_placeholder_snippet(cap);
|
||||||
cap,
|
editor.add_annotation(trait_name.syntax(), placeholder);
|
||||||
vec![trait_name.syntax().clone(), trait_name_ref.syntax().clone()],
|
editor.add_annotation(trait_name_ref.syntax(), placeholder);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.add_file_edits(ctx.vfs_file_id(), editor);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -162,19 +161,21 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// `E0449` Trait items always share the visibility of their trait
|
/// `E0449` Trait items always share the visibility of their trait
|
||||||
fn remove_items_visibility(item: &ast::AssocItem) {
|
fn remove_items_visibility(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
|
||||||
if let Some(has_vis) = ast::AnyHasVisibility::cast(item.syntax().clone()) {
|
if let Some(has_vis) = ast::AnyHasVisibility::cast(item.syntax().clone()) {
|
||||||
if let Some(vis) = has_vis.visibility()
|
if let Some(vis) = has_vis.visibility()
|
||||||
&& let Some(token) = vis.syntax().next_sibling_or_token()
|
&& let Some(token) = vis.syntax().next_sibling_or_token()
|
||||||
&& token.kind() == SyntaxKind::WHITESPACE
|
&& token.kind() == SyntaxKind::WHITESPACE
|
||||||
{
|
{
|
||||||
ted::remove(token);
|
editor.delete(token);
|
||||||
|
}
|
||||||
|
if let Some(vis) = has_vis.visibility() {
|
||||||
|
editor.delete(vis.syntax());
|
||||||
}
|
}
|
||||||
has_vis.set_visibility(None);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strip_body(item: &ast::AssocItem) {
|
fn strip_body(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
|
||||||
if let ast::AssocItem::Fn(f) = item
|
if let ast::AssocItem::Fn(f) = item
|
||||||
&& let Some(body) = f.body()
|
&& let Some(body) = f.body()
|
||||||
{
|
{
|
||||||
@ -183,10 +184,10 @@ fn strip_body(item: &ast::AssocItem) {
|
|||||||
if let Some(prev) = body.syntax().prev_sibling_or_token()
|
if let Some(prev) = body.syntax().prev_sibling_or_token()
|
||||||
&& prev.kind() == SyntaxKind::WHITESPACE
|
&& prev.kind() == SyntaxKind::WHITESPACE
|
||||||
{
|
{
|
||||||
ted::remove(prev);
|
editor.delete(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
ted::replace(body.syntax(), make::tokens::semicolon());
|
editor.replace(body.syntax(), make::tokens::semicolon());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user