Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21867 from Shourya742/2026-03-25-migrate-from-generate-impl
Replace direct use of make in generate_impl with SyntaxFactory
Chayim Refael Friedman 8 weeks ago
parent 71d06e7 · parent 596f1ec · commit afa488c
-rw-r--r--crates/ide-assists/src/handlers/generate_impl.rs41
-rw-r--r--crates/ide-assists/src/utils.rs18
2 files changed, 39 insertions, 20 deletions
diff --git a/crates/ide-assists/src/handlers/generate_impl.rs b/crates/ide-assists/src/handlers/generate_impl.rs
index bbd42481ef..2d1235792d 100644
--- a/crates/ide-assists/src/handlers/generate_impl.rs
+++ b/crates/ide-assists/src/handlers/generate_impl.rs
@@ -1,15 +1,21 @@
use syntax::{
- ast::{self, AstNode, HasGenericParams, HasName, edit::AstNodeEdit, make},
+ ast::{
+ self, AstNode, HasGenericParams, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory,
+ },
syntax_editor::{Position, SyntaxEditor},
};
use crate::{
AssistContext, AssistId, Assists,
- utils::{self, DefaultMethods, IgnoreAssocItems},
+ utils::{
+ self, DefaultMethods, IgnoreAssocItems, generate_impl_with_factory,
+ generate_trait_impl_intransitive,
+ },
};
fn insert_impl(
editor: &mut SyntaxEditor,
+ make: &SyntaxFactory,
impl_: &ast::Impl,
nominal: &impl AstNodeEdit,
) -> ast::Impl {
@@ -20,7 +26,7 @@ fn insert_impl(
Position::after(nominal.syntax()),
vec![
// Add a blank line after the ADT, and indentation for the impl to match the ADT
- make::tokens::whitespace(&format!("\n\n{indent}")).into(),
+ make.whitespace(&format!("\n\n{indent}")).into(),
impl_.syntax().clone().into(),
],
);
@@ -59,12 +65,13 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
format!("Generate impl for `{name}`"),
target,
|edit| {
+ let make = SyntaxFactory::with_mappings();
// Generate the impl
- let impl_ = utils::generate_impl(&nominal);
+ let impl_ = generate_impl_with_factory(&make, &nominal);
let mut editor = edit.make_editor(nominal.syntax());
- let impl_ = insert_impl(&mut editor, &impl_, &nominal);
+ let impl_ = insert_impl(&mut editor, &make, &impl_, &nominal);
// Add a tabstop after the left curly brace
if let Some(cap) = ctx.config.snippet_cap
&& let Some(l_curly) = impl_.assoc_item_list().and_then(|it| it.l_curly_token())
@@ -73,6 +80,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
editor.add_annotation(l_curly, tabstop);
}
+ editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -109,12 +117,13 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
format!("Generate trait impl for `{name}`"),
target,
|edit| {
+ let make = SyntaxFactory::with_mappings();
// Generate the impl
- let impl_ = utils::generate_trait_impl_intransitive(&nominal, make::ty_placeholder());
+ let impl_ = generate_trait_impl_intransitive(&make, &nominal, make.ty_placeholder());
let mut editor = edit.make_editor(nominal.syntax());
- let impl_ = insert_impl(&mut editor, &impl_, &nominal);
+ let impl_ = insert_impl(&mut editor, &make, &impl_, &nominal);
// Make the trait type a placeholder snippet
if let Some(cap) = ctx.config.snippet_cap {
if let Some(trait_) = impl_.trait_() {
@@ -128,6 +137,7 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
}
}
+ editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -166,9 +176,10 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
format!("Generate `{name}` impl for type"),
target,
|edit| {
+ let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(trait_.syntax());
- let holder_arg = ast::GenericArg::TypeArg(make::type_arg(make::ty_placeholder()));
+ let holder_arg = ast::GenericArg::TypeArg(make.type_arg(make.ty_placeholder()));
let missing_items = utils::filter_assoc_items(
&ctx.sema,
&hir_trait.items(ctx.db()),
@@ -177,11 +188,11 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
);
let trait_gen_args = trait_.generic_param_list().map(|list| {
- make::generic_arg_list(list.generic_params().map(|_| holder_arg.clone()))
+ make.generic_arg_list(list.generic_params().map(|_| holder_arg.clone()), false)
});
let make_impl_ = |body| {
- make::impl_trait(
+ make.impl_trait(
None,
trait_.unsafe_token().is_some(),
None,
@@ -189,13 +200,12 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
None,
None,
false,
- make::ty(&name.text()),
- make::ty_placeholder(),
+ make.ty(&name.text()),
+ make.ty_placeholder(),
None,
None,
body,
)
- .clone_for_update()
};
let impl_ = if missing_items.is_empty() {
@@ -210,11 +220,12 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
&impl_,
&target_scope,
);
- let assoc_item_list = make::assoc_item_list(Some(assoc_items));
+ let assoc_item_list = make.assoc_item_list(assoc_items);
make_impl_(Some(assoc_item_list))
};
- let impl_ = insert_impl(&mut editor, &impl_, &trait_);
+ let impl_ = insert_impl(&mut editor, &make, &impl_, &trait_);
+ editor.add_mappings(make.finish_with_mappings());
if let Some(cap) = ctx.config.snippet_cap {
if let Some(generics) = impl_.trait_().and_then(|it| it.generic_arg_list()) {
diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index a85a89efb4..cfbb5a17eb 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/crates/ide-assists/src/utils.rs
@@ -103,11 +103,11 @@ pub(crate) fn wrap_paren(expr: ast::Expr, make: &SyntaxFactory, prec: ExprPreced
}
pub(crate) fn wrap_paren_in_call(expr: ast::Expr, make: &SyntaxFactory) -> ast::Expr {
- if needs_parens_in_call(&expr) { make.expr_paren(expr).into() } else { expr }
+ if needs_parens_in_call(make, &expr) { make.expr_paren(expr).into() } else { expr }
}
-fn needs_parens_in_call(param: &ast::Expr) -> bool {
- let call = make::expr_call(make::ext::expr_unit(), make::arg_list(Vec::new()));
+fn needs_parens_in_call(make: &SyntaxFactory, param: &ast::Expr) -> bool {
+ let call = make.expr_call(make.expr_unit(), make.arg_list(Vec::new()));
let callable = call.expr().expect("invalid make call");
param.needs_parens_in_place_of(call.syntax(), callable.syntax())
}
@@ -739,6 +739,10 @@ pub(crate) fn generate_impl_with_item(
generate_impl_inner(false, adt, None, true, body)
}
+pub(crate) fn generate_impl_with_factory(make: &SyntaxFactory, adt: &ast::Adt) -> ast::Impl {
+ generate_impl_inner_with_factory(make, false, adt, None, true, None)
+}
+
pub(crate) fn generate_impl(adt: &ast::Adt) -> ast::Impl {
generate_impl_inner(false, adt, None, true, None)
}
@@ -760,8 +764,12 @@ pub(crate) fn generate_trait_impl(
/// and lifetime parameters, with `impl`'s generic parameters' bounds kept as-is.
///
/// This is useful for traits like `From<T>`, since `impl<T> From<T> for U<T>` doesn't require `T: From<T>`.
-pub(crate) fn generate_trait_impl_intransitive(adt: &ast::Adt, trait_: ast::Type) -> ast::Impl {
- generate_impl_inner(false, adt, Some(trait_), false, None)
+pub(crate) fn generate_trait_impl_intransitive(
+ make: &SyntaxFactory,
+ adt: &ast::Adt,
+ trait_: ast::Type,
+) -> ast::Impl {
+ generate_impl_inner_with_factory(make, false, adt, Some(trait_), false, None)
}
fn generate_impl_inner(