Skip to content

Commit d56b49d

Browse files
authored
Merge pull request #21874 from Biruk-gebru/migrate-generate-default-from-new-to-syntax-editor
internal: Migrate `generate_default_from_new` assist to `SyntaxEditor`
2 parents 71682c9 + dff0d0c commit d56b49d

1 file changed

Lines changed: 65 additions & 42 deletions

File tree

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

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
use ide_db::famous_defs::FamousDefs;
2-
use stdx::format_to;
32
use syntax::{
43
AstNode,
5-
ast::{self, HasGenericParams, HasName, HasTypeBounds, Impl, syntax_factory::SyntaxFactory},
4+
ast::{
5+
self, HasGenericParams, HasName, HasTypeBounds, Impl,
6+
edit::{AstNodeEdit, IndentLevel},
7+
syntax_factory::SyntaxFactory,
8+
},
9+
syntax_editor::Position,
610
};
711

812
use crate::{
@@ -62,32 +66,32 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<'
6266
return None;
6367
}
6468

65-
let insert_location = impl_.syntax().text_range();
69+
let target = impl_.syntax().text_range();
6670

6771
acc.add(
6872
AssistId::generate("generate_default_from_new"),
6973
"Generate a Default impl from a new fn",
70-
insert_location,
74+
target,
7175
move |builder| {
72-
let default_code = " fn default() -> Self {
73-
Self::new()
74-
}";
7576
let make = SyntaxFactory::without_mappings();
76-
let code =
77-
generate_trait_impl_text_from_impl(&impl_, self_ty, "Default", default_code, &make);
78-
builder.insert(insert_location.end(), code);
77+
let default_impl = generate_default_impl(&make, &impl_, self_ty);
78+
let indent = IndentLevel::from_node(impl_.syntax());
79+
let default_impl = default_impl.indent(indent);
80+
81+
let mut editor = builder.make_editor(impl_.syntax());
82+
editor.insert_all(
83+
Position::after(impl_.syntax()),
84+
vec![
85+
make.whitespace(&format!("\n\n{indent}")).into(),
86+
default_impl.syntax().clone().into(),
87+
],
88+
);
89+
builder.add_file_edits(ctx.vfs_file_id(), editor);
7990
},
8091
)
8192
}
8293

83-
// FIXME: based on from utils::generate_impl_text_inner
84-
fn generate_trait_impl_text_from_impl(
85-
impl_: &ast::Impl,
86-
self_ty: ast::Type,
87-
trait_text: &str,
88-
code: &str,
89-
make: &SyntaxFactory,
90-
) -> String {
94+
fn generate_default_impl(make: &SyntaxFactory, impl_: &ast::Impl, self_ty: ast::Type) -> ast::Impl {
9195
let generic_params = impl_.generic_param_list().map(|generic_params| {
9296
let lifetime_params =
9397
generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam);
@@ -109,26 +113,45 @@ fn generate_trait_impl_text_from_impl(
109113
make.generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
110114
});
111115

112-
let mut buf = String::with_capacity(code.len());
113-
buf.push_str("\n\n");
114-
115-
// `impl{generic_params} {trait_text} for {impl_.self_ty()}`
116-
buf.push_str("impl");
117-
if let Some(generic_params) = &generic_params {
118-
format_to!(buf, "{generic_params}")
119-
}
120-
format_to!(buf, " {trait_text} for {self_ty}");
121-
122-
match impl_.where_clause() {
123-
Some(where_clause) => {
124-
format_to!(buf, "\n{where_clause}\n{{\n{code}\n}}");
125-
}
126-
None => {
127-
format_to!(buf, " {{\n{code}\n}}");
128-
}
129-
}
130-
131-
buf
116+
let trait_ty: ast::Type = make.ty_path(make.ident_path("Default")).into();
117+
118+
let self_new_path = make.path_concat(make.ident_path("Self"), make.ident_path("new"));
119+
let self_new_call =
120+
make.expr_call(make.expr_path(self_new_path), make.arg_list(std::iter::empty()));
121+
let fn_body = make.block_expr(std::iter::empty(), Some(self_new_call.into()));
122+
let self_ty_ret: ast::Type = make.ty_path(make.ident_path("Self")).into();
123+
let default_fn = make
124+
.fn_(
125+
[],
126+
None,
127+
make.name("default"),
128+
None,
129+
None,
130+
make.param_list(None, std::iter::empty()),
131+
fn_body,
132+
Some(make.ret_type(self_ty_ret)),
133+
false,
134+
false,
135+
false,
136+
false,
137+
)
138+
.indent(1.into());
139+
let body = make.assoc_item_list(Some(ast::AssocItem::from(default_fn)));
140+
141+
make.impl_trait(
142+
[],
143+
false,
144+
None,
145+
None,
146+
generic_params,
147+
None,
148+
false,
149+
trait_ty,
150+
self_ty,
151+
None,
152+
impl_.where_clause(),
153+
Some(body),
154+
)
132155
}
133156

134157
fn is_default_implemented(ctx: &AssistContext<'_>, impl_: &Impl) -> bool {
@@ -631,12 +654,12 @@ mod test {
631654
}
632655
}
633656
634-
impl Default for Example {
635-
fn default() -> Self {
636-
Self::new()
657+
impl Default for Example {
658+
fn default() -> Self {
659+
Self::new()
660+
}
637661
}
638662
}
639-
}
640663
"#,
641664
);
642665
}

0 commit comments

Comments
 (0)