Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/ide-assists/src/handlers/add_missing_impl_members.rs | 24 | ||||
| -rw-r--r-- | crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs | 21 | ||||
| -rw-r--r-- | crates/ide-assists/src/utils.rs | 10 | ||||
| -rw-r--r-- | crates/ide-assists/src/utils/gen_trait_fn_body.rs | 500 | ||||
| -rw-r--r-- | crates/syntax/src/ast/syntax_factory/constructors.rs | 11 |
5 files changed, 300 insertions, 266 deletions
diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index afdced4215..3689dc24b3 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -1,7 +1,7 @@ use hir::HasSource; use syntax::{ Edition, - ast::{self, AstNode, make}, + ast::{self, AstNode, syntax_factory::SyntaxFactory}, syntax_editor::{Position, SyntaxEditor}, }; @@ -9,8 +9,8 @@ use crate::{ AssistId, assist_context::{AssistContext, Assists}, utils::{ - DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items, - gen_trait_fn_body, + DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl_with_factory, + filter_assoc_items, gen_trait_fn_body, }, }; @@ -148,7 +148,9 @@ fn add_missing_impl_members_inner( let target = impl_def.syntax().text_range(); acc.add(AssistId::quick_fix(assist_id), label, target, |edit| { - let new_item = add_trait_assoc_items_to_impl( + let make = SyntaxFactory::with_mappings(); + let new_item = add_trait_assoc_items_to_impl_with_factory( + &make, &ctx.sema, ctx.config, &missing_items, @@ -164,6 +166,7 @@ fn add_missing_impl_members_inner( let mut first_new_item = if let DefaultMethods::No = mode && let ast::AssocItem::Fn(func) = &first_new_item && let Some(body) = try_gen_trait_body( + &make, ctx, func, trait_ref, @@ -189,10 +192,10 @@ fn add_missing_impl_members_inner( if let Some(assoc_item_list) = impl_def.assoc_item_list() { assoc_item_list.add_items(&mut editor, new_assoc_items); } else { - let assoc_item_list = make::assoc_item_list(Some(new_assoc_items)).clone_for_update(); + let assoc_item_list = make.assoc_item_list(new_assoc_items); editor.insert_all( Position::after(impl_def.syntax()), - vec![make::tokens::whitespace(" ").into(), assoc_item_list.syntax().clone().into()], + vec![make.whitespace(" ").into(), assoc_item_list.syntax().clone().into()], ); first_new_item = assoc_item_list.assoc_items().next(); } @@ -215,23 +218,24 @@ fn add_missing_impl_members_inner( editor.add_annotation(first_new_item.syntax(), tabstop); }; }; + editor.add_mappings(make.finish_with_mappings()); edit.add_file_edits(ctx.vfs_file_id(), editor); }) } fn try_gen_trait_body( + make: &SyntaxFactory, ctx: &AssistContext<'_>, func: &ast::Fn, trait_ref: hir::TraitRef<'_>, impl_def: &ast::Impl, edition: Edition, ) -> Option<ast::BlockExpr> { - let trait_path = make::ext::ident_path( - &trait_ref.trait_().name(ctx.db()).display(ctx.db(), edition).to_string(), - ); + let trait_path = + make.ident_path(&trait_ref.trait_().name(ctx.db()).display(ctx.db(), edition).to_string()); let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?; let adt = hir_ty.as_adt()?.source(ctx.db())?; - gen_trait_fn_body(func, &trait_path, &adt.value, Some(trait_ref)) + gen_trait_fn_body(make, func, &trait_path, &adt.value, Some(trait_ref)) } #[cfg(test)] diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index f54f7a02d2..f281fdf513 100644 --- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -13,7 +13,7 @@ use crate::{ assist_context::{AssistContext, Assists}, utils::{ DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl_with_factory, - filter_assoc_items, gen_trait_fn_body, generate_trait_impl, + filter_assoc_items, gen_trait_fn_body, generate_trait_impl, generate_trait_impl_with_item, }, }; @@ -127,7 +127,7 @@ fn add_assist( let label = format!("Convert to manual `impl {replace_trait_path} for {annotated_name}`"); acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| { - let make = SyntaxFactory::without_mappings(); + let make = SyntaxFactory::with_mappings(); let insert_after = Position::after(adt.syntax()); let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false); let impl_def = impl_def_from_trait( @@ -141,7 +141,7 @@ fn add_assist( ); let mut editor = builder.make_editor(attr.syntax()); - update_attribute(&mut editor, old_derives, old_tree, old_trait_path, attr); + update_attribute(&make, &mut editor, old_derives, old_tree, old_trait_path, attr); let trait_path = make.ty_path(replace_trait_path.clone()).into(); @@ -177,6 +177,7 @@ fn add_assist( insert_after, vec![make.whitespace("\n\n").into(), impl_def.syntax().clone().into()], ); + editor.add_mappings(make.finish_with_mappings()); builder.add_file_edits(ctx.vfs_file_id(), editor); }) } @@ -207,8 +208,8 @@ fn impl_def_from_trait( return None; } let make = SyntaxFactory::without_mappings(); - let trait_ty = make.ty_path(trait_path.clone()).into(); - let impl_def = generate_trait_impl(&make, impl_is_unsafe, adt, trait_ty); + let trait_ty: ast::Type = make.ty_path(trait_path.clone()).into(); + let impl_def = generate_trait_impl(&make, impl_is_unsafe, adt, trait_ty.clone()); let assoc_items = add_trait_assoc_items_to_impl_with_factory( &make, @@ -223,7 +224,7 @@ fn impl_def_from_trait( assoc_items.split_first().map(|(first, other)| (first.clone_subtree(), other)) { let first_item = if let ast::AssocItem::Fn(ref func) = first - && let Some(body) = gen_trait_fn_body(func, trait_path, adt, None) + && let Some(body) = gen_trait_fn_body(&make, func, trait_path, adt, None) && let Some(func_body) = func.body() { let mut editor = SyntaxEditor::new(first.syntax().clone()); @@ -239,21 +240,17 @@ fn impl_def_from_trait( make.assoc_item_list_empty() }; - let impl_def = impl_def.clone_subtree(); - let mut editor = SyntaxEditor::new(impl_def.syntax().clone()); - editor.replace(impl_def.assoc_item_list()?.syntax(), assoc_item_list.syntax()); - let impl_def = ast::Impl::cast(editor.finish().new_root().clone())?; - Some(impl_def) + Some(generate_trait_impl_with_item(&make, impl_is_unsafe, adt, trait_ty, assoc_item_list)) } fn update_attribute( + make: &SyntaxFactory, editor: &mut SyntaxEditor, old_derives: &[ast::Path], old_tree: &ast::TokenTree, old_trait_path: &ast::Path, attr: &ast::Attr, ) { - let make = SyntaxFactory::without_mappings(); let new_derives = old_derives .iter() .filter(|t| t.to_string() != old_trait_path.to_string()) diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs index 10057f8681..fee5014232 100644 --- a/crates/ide-assists/src/utils.rs +++ b/crates/ide-assists/src/utils.rs @@ -758,6 +758,16 @@ pub(crate) fn generate_trait_impl_intransitive_with_item( generate_impl_inner_with_factory(make, false, adt, Some(trait_), false, Some(body)) } +pub(crate) fn generate_trait_impl_with_item( + make: &SyntaxFactory, + is_unsafe: bool, + adt: &ast::Adt, + trait_: ast::Type, + body: ast::AssocItemList, +) -> ast::Impl { + generate_impl_inner_with_factory(make, is_unsafe, adt, Some(trait_), true, Some(body)) +} + fn generate_impl_inner( is_unsafe: bool, adt: &ast::Adt, diff --git a/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/crates/ide-assists/src/utils/gen_trait_fn_body.rs index 87e90e8519..b0d88737fe 100644 --- a/crates/ide-assists/src/utils/gen_trait_fn_body.rs +++ b/crates/ide-assists/src/utils/gen_trait_fn_body.rs @@ -1,7 +1,10 @@ //! This module contains functions to generate default trait impl function bodies where possible. use hir::TraitRef; -use syntax::ast::{self, AstNode, BinaryOp, CmpOp, HasName, LogicOp, edit::AstNodeEdit, make}; +use syntax::ast::{ + self, AstNode, BinaryOp, CmpOp, HasName, LogicOp, edit::AstNodeEdit, + syntax_factory::SyntaxFactory, +}; /// Generate custom trait bodies without default implementation where possible. /// @@ -11,6 +14,7 @@ use syntax::ast::{self, AstNode, BinaryOp, CmpOp, HasName, LogicOp, edit::AstNod /// `None` means that generating a custom trait body failed, and the body will remain /// as `todo!` instead. pub(crate) fn gen_trait_fn_body( + make: &SyntaxFactory, func: &ast::Fn, trait_path: &ast::Path, adt: &ast::Adt, @@ -20,32 +24,32 @@ pub(crate) fn gen_trait_fn_body( match trait_path.segment()?.name_ref()?.text().as_str() { "Clone" => { stdx::always!(func.name().is_some_and(|name| name.text() == "clone")); - gen_clone_impl(adt) + gen_clone_impl(make, adt) } - "Debug" => gen_debug_impl(adt), - "Default" => gen_default_impl(adt), + "Debug" => gen_debug_impl(make, adt), + "Default" => gen_default_impl(make, adt), "Hash" => { stdx::always!(func.name().is_some_and(|name| name.text() == "hash")); - gen_hash_impl(adt) + gen_hash_impl(make, adt) } "PartialEq" => { stdx::always!(func.name().is_some_and(|name| name.text() == "eq")); - gen_partial_eq(adt, trait_ref) + gen_partial_eq(make, adt, trait_ref) } "PartialOrd" => { stdx::always!(func.name().is_some_and(|name| name.text() == "partial_cmp")); - gen_partial_ord(adt, trait_ref) + gen_partial_ord(make, adt, trait_ref) } _ => None, } } /// Generate a `Clone` impl based on the fields and members of the target type. -fn gen_clone_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { - fn gen_clone_call(target: ast::Expr) -> ast::Expr { - let method = make::name_ref("clone"); - make::expr_method_call(target, method, make::arg_list(None)).into() - } +fn gen_clone_impl(make: &SyntaxFactory, adt: &ast::Adt) -> Option<ast::BlockExpr> { + let gen_clone_call = |target: ast::Expr| -> ast::Expr { + let method = make.name_ref("clone"); + make.expr_method_call(target, method, make.arg_list([])).into() + }; let expr = match adt { // `Clone` cannot be derived for unions, so no default impl can be provided. ast::Adt::Union(_) => return None, @@ -54,7 +58,7 @@ fn gen_clone_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { let mut arms = vec![]; for variant in list.variants() { let name = variant.name()?; - let variant_name = make::ext::path_from_idents(["Self", &format!("{name}")])?; + let variant_name = make.path_from_idents(["Self", &format!("{name}")])?; match variant.field_list() { // => match self { Self::Name { x } => Self::Name { x: x.clone() } } @@ -63,19 +67,20 @@ fn gen_clone_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { let mut fields = vec![]; for field in list.fields() { let field_name = field.name()?; - let pat = make::ident_pat(false, false, field_name.clone()); - pats.push(pat.into()); + let pat = make.ident_pat(false, false, field_name.clone()); + pats.push(make.record_pat_field_shorthand(pat.into())); - let path = make::ext::ident_path(&field_name.to_string()); - let method_call = gen_clone_call(make::expr_path(path)); - let name_ref = make::name_ref(&field_name.to_string()); - let field = make::record_expr_field(name_ref, Some(method_call)); + let path = make.ident_path(&field_name.to_string()); + let method_call = gen_clone_call(make.expr_path(path)); + let name_ref = make.name_ref(&field_name.to_string()); + let field = make.record_expr_field(name_ref, Some(method_call)); fields.push(field); } - let pat = make::record_pat(variant_name.clone(), pats.into_iter()); - let fields = make::record_expr_field_list(fields); - let record_expr = make::record_expr(variant_name, fields).into(); - arms.push(make::match_arm(pat.into(), None, record_expr)); + let pat_field_list = make.record_pat_field_list(pats, None); + let pat = make.record_pat_with_fields(variant_name.clone(), pat_field_list); + let fields = make.record_expr_field_list(fields); + let record_expr = make.record_expr(variant_name, fields).into(); + arms.push(make.match_arm(pat.into(), None, record_expr)); } // => match self { Self::Name(arg1) => Self::Name(arg1.clone()) } @@ -84,31 +89,30 @@ fn gen_clone_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { let mut fields = vec![]; for (i, _) in list.fields().enumerate() { let field_name = format!("arg{i}"); - let pat = make::ident_pat(false, false, make::name(&field_name)); + let pat = make.ident_pat(false, false, make.name(&field_name)); pats.push(pat.into()); - let f_path = make::expr_path(make::ext::ident_path(&field_name)); + let f_path = make.expr_path(make.ident_path(&field_name)); fields.push(gen_clone_call(f_path)); } - let pat = make::tuple_struct_pat(variant_name.clone(), pats.into_iter()); - let struct_name = make::expr_path(variant_name); - let tuple_expr = - make::expr_call(struct_name, make::arg_list(fields)).into(); - arms.push(make::match_arm(pat.into(), None, tuple_expr)); + let pat = make.tuple_struct_pat(variant_name.clone(), pats.into_iter()); + let struct_name = make.expr_path(variant_name); + let tuple_expr = make.expr_call(struct_name, make.arg_list(fields)).into(); + arms.push(make.match_arm(pat.into(), None, tuple_expr)); } // => match self { Self::Name => Self::Name } None => { - let pattern = make::path_pat(variant_name.clone()); - let variant_expr = make::expr_path(variant_name); - arms.push(make::match_arm(pattern, None, variant_expr)); + let pattern = make.path_pat(variant_name.clone()); + let variant_expr = make.expr_path(variant_name); + arms.push(make.match_arm(pattern, None, variant_expr)); } } } - let match_target = make::expr_path(make::ext::ident_path("self")); - let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); - make::expr_match(match_target, list).into() + let match_target = make.expr_path(make.ident_path("self")); + let list = make.match_arm_list(arms).indent(ast::edit::IndentLevel(1)); + make.expr_match(match_target, list).into() } ast::Adt::Struct(strukt) => { match strukt.field_list() { @@ -116,43 +120,43 @@ fn gen_clone_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { Some(ast::FieldList::RecordFieldList(field_list)) => { let mut fields = vec![]; for field in field_list.fields() { - let base = make::expr_path(make::ext::ident_path("self")); - let target = make::expr_field(base, &field.name()?.to_string()); + let base = make.expr_path(make.ident_path("self")); + let target = make.expr_field(base, &field.name()?.to_string()).into(); let method_call = gen_clone_call(target); - let name_ref = make::name_ref(&field.name()?.to_string()); - let field = make::record_expr_field(name_ref, Some(method_call)); + let name_ref = make.name_ref(&field.name()?.to_string()); + let field = make.record_expr_field(name_ref, Some(method_call)); fields.push(field); } - let struct_name = make::ext::ident_path("Self"); - let fields = make::record_expr_field_list(fields); - make::record_expr(struct_name, fields).into() + let struct_name = make.ident_path("Self"); + let fields = make.record_expr_field_list(fields); + make.record_expr(struct_name, fields).into() } // => Self(self.0.clone(), self.1.clone()) Some(ast::FieldList::TupleFieldList(field_list)) => { let mut fields = vec![]; for (i, _) in field_list.fields().enumerate() { - let f_path = make::expr_path(make::ext::ident_path("self")); - let target = make::expr_field(f_path, &format!("{i}")); + let f_path = make.expr_path(make.ident_path("self")); + let target = make.expr_field(f_path, &format!("{i}")).into(); fields.push(gen_clone_call(target)); } - let struct_name = make::expr_path(make::ext::ident_path("Self")); - make::expr_call(struct_name, make::arg_list(fields)).into() + let struct_name = make.expr_path(make.ident_path("Self")); + make.expr_call(struct_name, make.arg_list(fields)).into() } // => Self { } None => { - let struct_name = make::ext::ident_path("Self"); - let fields = make::record_expr_field_list(None); - make::record_expr(struct_name, fields).into() + let struct_name = make.ident_path("Self"); + let fields = make.record_expr_field_list([]); + make.record_expr(struct_name, fields).into() } } } }; - let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)); + let body = make.block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)); Some(body) } /// Generate a `Debug` impl based on the fields and members of the target type. -fn gen_debug_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { +fn gen_debug_impl(make: &SyntaxFactory, adt: &ast::Adt) -> Option<ast::BlockExpr> { let annotated_name = adt.name()?; match adt { // `Debug` cannot be derived for unions, so no default impl can be provided. @@ -164,156 +168,154 @@ fn gen_debug_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { let mut arms = vec![]; for variant in list.variants() { let name = variant.name()?; - let variant_name = make::ext::path_from_idents(["Self", &format!("{name}")])?; - let target = make::expr_path(make::ext::ident_path("f")); + let variant_name = make.path_from_idents(["Self", &format!("{name}")])?; + let target = make.expr_path(make.ident_path("f")); match variant.field_list() { Some(ast::FieldList::RecordFieldList(list)) => { // => f.debug_struct(name) - let target = make::expr_path(make::ext::ident_path("f")); - let method = make::name_ref("debug_struct"); + let target = make.expr_path(make.ident_path("f")); + let method = make.name_ref("debug_struct"); let struct_name = format!("\"{name}\""); - let args = make::arg_list(Some(make::expr_literal(&struct_name).into())); - let mut expr = make::expr_method_call(target, method, args).into(); + let args = make.arg_list([make.expr_literal(&struct_name).into()]); + let mut expr = make.expr_method_call(target, method, args).into(); let mut pats = vec![]; for field in list.fields() { let field_name = field.name()?; // create a field pattern for use in `MyStruct { fields.. }` - let pat = make::ident_pat(false, false, field_name.clone()); - pats.push(pat.into()); + let pat = make.ident_pat(false, false, field_name.clone()); + pats.push(make.record_pat_field_shorthand(pat.into())); // => <expr>.field("field_name", field) - let method_name = make::name_ref("field"); - let name = make::expr_literal(&(format!("\"{field_name}\""))).into(); + let method_name = make.name_ref("field"); + let name = make.expr_literal(&(format!("\"{field_name}\""))).into(); let path = &format!("{field_name}"); - let path = make::expr_path(make::ext::ident_path(path)); - let args = make::arg_list(vec![name, path]); - expr = make::expr_method_call(expr, method_name, args).into(); + let path = make.expr_path(make.ident_path(path)); + let args = make.arg_list([name, path]); + expr = make.expr_method_call(expr, method_name, args).into(); } // => <expr>.finish() - let method = make::name_ref("finish"); - let expr = - make::expr_method_call(expr, method, make::arg_list(None)).into(); + let method = make.name_ref("finish"); + let expr = make.expr_method_call(expr, method, make.arg_list([])).into(); // => MyStruct { fields.. } => f.debug_struct("MyStruct")...finish(), - let pat = make::record_pat(variant_name.clone(), pats.into_iter()); - arms.push(make::match_arm(pat.into(), None, expr)); + let pat_field_list = make.record_pat_field_list(pats, None); + let pat = make.record_pat_with_fields(variant_name.clone(), pat_field_list); + arms.push(make.match_arm(pat.into(), None, expr)); } Some(ast::FieldList::TupleFieldList(list)) => { // => f.debug_tuple(name) - let target = make::expr_path(make::ext::ident_path("f")); - let method = make::name_ref("debug_tuple"); + let target = make.expr_path(make.ident_path("f")); + let method = make.name_ref("debug_tuple"); let struct_name = format!("\"{name}\""); - let args = make::arg_list(Some(make::expr_literal(&struct_name).into())); - let mut expr = make::expr_method_call(target, method, args).into(); + let args = make.arg_list([make.expr_literal(&struct_name).into()]); + let mut expr = make.expr_method_call(target, method, args).into(); let mut pats = vec![]; for (i, _) in list.fields().enumerate() { let name = format!("arg{i}"); // create a field pattern for use in `MyStruct(fields..)` - let field_name = make::name(&name); - let pat = make::ident_pat(false, false, field_name.clone()); + let field_name = make.name(&name); + let pat = make.ident_pat(false, false, field_name.clone()); pats.push(pat.into()); // => <expr>.field(field) - let method_name = make::name_ref("field"); + let method_name = make.name_ref("field"); let field_path = &name.to_string(); - let field_path = make::expr_path(make::ext::ident_path(field_path)); - let args = make::arg_list(vec![field_path]); - expr = make::expr_method_call(expr, method_name, args).into(); + let field_path = make.expr_path(make.ident_path(field_path)); + let args = make.arg_list([field_path]); + expr = make.expr_method_call(expr, method_name, args).into(); } // => <expr>.finish() - let method = make::name_ref("finish"); - let expr = - make::expr_method_call(expr, method, make::arg_list(None)).into(); + let method = make.name_ref("finish"); + let expr = make.expr_method_call(expr, method, make.arg_list([])).into(); // => MyStruct (fields..) => f.debug_tuple("MyStruct")...finish(), - let pat = make::tuple_struct_pat(variant_name.clone(), pats.into_iter()); - arms.push(make::match_arm(pat.into(), None, expr)); + let pat = make.tuple_struct_pat(variant_name.clone(), pats.into_iter()); + arms.push(make.match_arm(pat.into(), None, expr)); } None => { - let fmt_string = make::expr_literal(&(format!("\"{name}\""))).into(); - let args = make::ext::token_tree_from_node( - make::arg_list([target, fmt_string]).syntax(), - ); - let macro_name = make::ext::ident_path("write"); - let macro_call = make::expr_macro(macro_name, args); - - let variant_name = make::path_pat(variant_name); - arms.push(make::match_arm(variant_name, None, macro_call.into())); + let fmt_string = make.expr_literal(&(format!("\"{name}\""))).into(); + let args = + make.token_tree_from_node(make.arg_list([target, fmt_string]).syntax()); + let macro_name = make.ident_path("write"); + let macro_call = make.expr_macro(macro_name, args); + + let variant_name = make.path_pat(variant_name); + arms.push(make.match_arm(variant_name, None, macro_call.into())); } } } - let match_target = make::expr_path(make::ext::ident_path("self")); - let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); - let match_expr = make::expr_match(match_target, list); + let match_target = make.expr_path(make.ident_path("self")); + let list = make.match_arm_list(arms).indent(ast::edit::IndentLevel(1)); + let match_expr = make.expr_match(match_target, list); - let body = make::block_expr(None, Some(match_expr.into())); + let body = make.block_expr(None::<ast::Stmt>, Some(match_expr.into())); let body = body.indent(ast::edit::IndentLevel(1)); Some(body) } ast::Adt::Struct(strukt) => { let name = format!("\"{annotated_name}\""); - let args = make::arg_list(Some(make::expr_literal(&name).into())); - let target = make::expr_path(make::ext::ident_path("f")); + let args = make.arg_list([make.expr_literal(&name).into()]); + let target = make.expr_path(make.ident_path("f")); let expr = match strukt.field_list() { // => f.debug_struct("Name").finish() - None => make::expr_method_call(target, make::name_ref("debug_struct"), args).into(), + None => make.expr_method_call(target, make.name_ref("debug_struct"), args).into(), // => f.debug_struct("Name").field("foo", &self.foo).finish() Some(ast::FieldList::RecordFieldList(field_list)) => { - let method = make::name_ref("debug_struct"); - let mut expr = make::expr_method_call(target, method, args).into(); + let method = make.name_ref("debug_struct"); + let mut expr = make.expr_method_call(target, method, args).into(); for field in field_list.fields() { let name = field.name()?; - let f_name = make::expr_literal(&(format!("\"{name}\""))).into(); - let f_path = make::expr_path(make::ext::ident_path("self")); - let f_path = make::expr_ref(f_path, false); - let f_path = make::expr_field(f_path, &format!("{name}")); - let args = make::arg_list([f_name, f_path]); - expr = make::expr_method_call(expr, make::name_ref("field"), args).into(); + let f_name = make.expr_literal(&(format!("\"{name}\""))).into(); + let f_path = make.expr_path(make.ident_path("self")); + let f_path = make.expr_field(f_path, &format!("{name}")).into(); + let f_path = make.expr_ref(f_path, false); + let args = make.arg_list([f_name, f_path]); + expr = make.expr_method_call(expr, make.name_ref("field"), args).into(); } expr } - // => f.debug_tuple("Name").field(self.0).finish() + // => f.debug_tuple("Name").field(&self.0).finish() Some(ast::FieldList::TupleFieldList(field_list)) => { - let method = make::name_ref("debug_tuple"); - let mut expr = make::expr_method_call(target, method, args).into(); + let method = make.name_ref("debug_tuple"); + let mut expr = make.expr_method_call(target, method, args).into(); for (i, _) in field_list.fields().enumerate() { - let f_path = make::expr_path(make::ext::ident_path("self")); - let f_path = make::expr_ref(f_path, false); - let f_path = make::expr_field(f_path, &format!("{i}")); - let method = make::name_ref("field"); - expr = make::expr_method_call(expr, method, make::arg_list(Some(f_path))) - .into(); + let f_path = make.expr_path(make.ident_path("self")); + let f_path = make.expr_field(f_path, &format!("{i}")).into(); + let f_path = make.expr_ref(f_path, false); + let method = make.name_ref("field"); + expr = make.expr_method_call(expr, method, make.arg_list([f_path])).into(); } expr } }; - let method = make::name_ref("finish"); - let expr = make::expr_method_call(expr, method, make::arg_list(None)).into(); - let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)); + let method = make.name_ref("finish"); + let expr = make.expr_method_call(expr, method, make.arg_list([])).into(); + let body = + make.block_expr(None::<ast::Stmt>, Some(expr)).indent(ast::edit::IndentLevel(1)); Some(body) } } } -/// Generate a `Debug` impl based on the fields and members of the target type. -fn gen_default_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { - fn gen_default_call() -> Option<ast::Expr> { - let fn_name = make::ext::path_from_idents(["Default", "default"])?; - Some(make::expr_call(make::expr_path(fn_name), make::arg_list(None)).into()) - } +/// Generate a `Default` impl based on the fields and members of the target type. +fn gen_default_impl(make: &SyntaxFactory, adt: &ast::Adt) -> Option<ast::BlockExpr> { + let gen_default_call = || -> Option<ast::Expr> { + let fn_name = make.path_from_idents(["Default", "default"])?; + Some(make.expr_call(make.expr_path(fn_name), make.arg_list([])).into()) + }; match adt { // `Debug` cannot be derived for unions, so no default impl can be provided. ast::Adt::Union(_) => None, @@ -325,42 +327,43 @@ fn gen_default_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { let mut fields = vec![]; for field in field_list.fields() { let method_call = gen_default_call()?; - let name_ref = make::name_ref(&field.name()?.to_string()); - let field = make::record_expr_field(name_ref, Some(method_call)); + let name_ref = make.name_ref(&field.name()?.to_string()); + let field = make.record_expr_field(name_ref, Some(method_call)); fields.push(field); } - let struct_name = make::ext::ident_path("Self"); - let fields = make::record_expr_field_list(fields); - make::record_expr(struct_name, fields).into() + let struct_name = make.ident_path("Self"); + let fields = make.record_expr_field_list(fields); + make.record_expr(struct_name, fields).into() } Some(ast::FieldList::TupleFieldList(field_list)) => { - let struct_name = make::expr_path(make::ext::ident_path("Self")); + let struct_name = make.expr_path(make.ident_path("Self")); let fields = field_list .fields() .map(|_| gen_default_call()) .collect::<Option<Vec<ast::Expr>>>()?; - make::expr_call(struct_name, make::arg_list(fields)).into() + make.expr_call(struct_name, make.arg_list(fields)).into() } None => { - let struct_name = make::ext::ident_path("Self"); - let fields = make::record_expr_field_list(None); - make::record_expr(struct_name, fields).into() + let struct_name = make.ident_path("Self"); + let fields = make.record_expr_field_list([]); + make.record_expr(struct_name, fields).into() } }; - let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)); + let body = + make.block_expr(None::<ast::Stmt>, Some(expr)).indent(ast::edit::IndentLevel(1)); Some(body) } } } /// Generate a `Hash` impl based on the fields and members of the target type. -fn gen_hash_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { - fn gen_hash_call(target: ast::Expr) -> ast::Stmt { - let method = make::name_ref("hash"); - let arg = make::expr_path(make::ext::ident_path("state")); - let expr = make::expr_method_call(target, method, make::arg_list(Some(arg))).into(); - make::expr_stmt(expr).into() - } +fn gen_hash_impl(make: &SyntaxFactory, adt: &ast::Adt) -> Option<ast::BlockExpr> { + let gen_hash_call = |target: ast::Expr| -> ast::Stmt { + let method = make.name_ref("hash"); + let arg = make.expr_path(make.ident_path("state")); + let expr = make.expr_method_call(target, method, make.arg_list([arg])).into(); + make.expr_stmt(expr).into() + }; let body = match adt { // `Hash` cannot be derived for unions, so no default impl can be provided. @@ -368,35 +371,35 @@ fn gen_hash_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { // => std::mem::discriminant(self).hash(state); ast::Adt::Enum(_) => { - let fn_name = make_discriminant()?; + let fn_name = make_discriminant(make)?; - let arg = make::expr_path(make::ext::ident_path("self")); - let fn_call = make::expr_call(fn_name, make::arg_list(Some(arg))).into(); + let arg = make.expr_path(make.ident_path("self")); + let fn_call: ast::Expr = make.expr_call(fn_name, make.arg_list([arg])).into(); let stmt = gen_hash_call(fn_call); - make::block_expr(Some(stmt), None).indent(ast::edit::IndentLevel(1)) + make.block_expr([stmt], None).indent(ast::edit::IndentLevel(1)) } ast::Adt::Struct(strukt) => match strukt.field_list() { // => self.<field>.hash(state); Some(ast::FieldList::RecordFieldList(field_list)) => { let mut stmts = vec![]; for field in field_list.fields() { - let base = make::expr_path(make::ext::ident_path("self")); - let target = make::expr_field(base, &field.name()?.to_string()); + let base = make.expr_path(make.ident_path("self")); + let target = make.expr_field(base, &field.name()?.to_string()).into(); stmts.push(gen_hash_call(target)); } - make::block_expr(stmts, None).indent(ast::edit::IndentLevel(1)) + make.block_expr(stmts, None).indent(ast::edit::IndentLevel(1)) } // => self.<field_index>.hash(state); Some(ast::FieldList::TupleFieldList(field_list)) => { let mut stmts = vec![]; for (i, _) in field_list.fields().enumerate() { - let base = make::expr_path(make::ext::ident_path("self")); - let target = make::expr_field(base, &format!("{i}")); + let base = make.expr_path(make.ident_path("self")); + let target = make.expr_field(base, &format!("{i}")).into(); stmts.push(gen_hash_call(target)); } - make::block_expr(stmts, None).indent(ast::edit::IndentLevel(1)) + make.block_expr(stmts, None).indent(ast::edit::IndentLevel(1)) } // No fields in the body means there's nothing to hash. @@ -408,32 +411,37 @@ fn gen_hash_impl(adt: &ast::Adt) -> Option<ast::BlockExpr> { } /// Generate a `PartialEq` impl based on the fields and members of the target type. -fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast::BlockExpr> { - fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> { +fn gen_partial_eq( + make: &SyntaxFactory, + adt: &ast::Adt, + trait_ref: Option<TraitRef<'_>>, +) -> Option<ast::BlockExpr> { + let gen_eq_chain = |expr: Option<ast::Expr>, cmp: ast::Expr| -> Option<ast::Expr> { match expr { - Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)), + Some(expr) => Some(make.expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)), None => Some(cmp), } - } + }; - fn gen_record_pat_field(field_name: &str, pat_name: &str) -> ast::RecordPatField { - let pat = make::ext::simple_ident_pat(make::name(pat_name)); - let name_ref = make::name_ref(field_name); - make::record_pat_field(name_ref, pat.into()) - } + let gen_record_pat_field = |field_name: &str, pat_name: &str| -> ast::RecordPatField { + let pat = make.ident_pat(false, false, make.name(pat_name)); + let name_ref = make.name_ref(field_name); + make.record_pat_field(name_ref, pat.into()) + }; - fn gen_record_pat(record_name: ast::Path, fields: Vec<ast::RecordPatField>) -> ast::RecordPat { - let list = make::record_pat_field_list(fields, None); - make::record_pat_with_fields(record_name, list) - } + let gen_record_pat = + |record_name: ast::Path, fields: Vec<ast::RecordPatField>| -> ast::RecordPat { + let list = make.record_pat_field_list(fields, None); + make.record_pat_with_fields(record_name, list) + }; - fn gen_variant_path(variant: &ast::Variant) -> Option<ast::Path> { - make::ext::path_from_idents(["Self", &variant.name()?.to_string()]) - } + let gen_variant_path = |variant: &ast::Variant| -> Option<ast::Path> { + make.path_from_idents(["Self", &variant.name()?.to_string()]) + }; - fn gen_tuple_field(field_name: &str) -> ast::Pat { - ast::Pat::IdentPat(make::ident_pat(false, false, make::name(field_name))) - } + let gen_tuple_field = |field_name: &str| -> ast::Pat { + ast::Pat::IdentPat(make.ident_pat(false, false, make.name(field_name))) + }; // Check that self type and rhs type match. We don't know how to implement the method // automatically otherwise. @@ -451,14 +459,14 @@ fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast ast::Adt::Enum(enum_) => { // => std::mem::discriminant(self) == std::mem::discriminant(other) - let lhs_name = make::expr_path(make::ext::ident_path("self")); - let lhs = make::expr_call(make_discriminant()?, make::arg_list(Some(lhs_name.clone()))) - .into(); - let rhs_name = make::expr_path(make::ext::ident_path("other")); - let rhs = make::expr_call(make_discriminant()?, make::arg_list(Some(rhs_name.clone()))) - .into(); + let lhs_name = make.expr_path(make.ident_path("self")); + let lhs = + make.expr_call(make_discriminant(make)?, make.arg_list([lhs_name.clone()])).into(); + let rhs_name = make.expr_path(make.ident_path("other")); + let rhs = + make.expr_call(make_discriminant(make)?, make.arg_list([rhs_name.clone()])).into(); let eq_check = - make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); + make.expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); let mut n_cases = 0; let mut arms = vec![]; @@ -480,9 +488,9 @@ fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast let r_name = &format!("r_{field_name}"); r_fields.push(gen_record_pat_field(&field_name, r_name)); - let lhs = make::expr_path(make::ext::ident_path(l_name)); - let rhs = make::expr_path(make::ext::ident_path(r_name)); - let cmp = make::expr_bin_op( + let lhs = make.expr_path(make.ident_path(l_name)); + let rhs = make.expr_path(make.ident_path(r_name)); + let cmp = make.expr_bin_op( lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs, @@ -492,10 +500,10 @@ fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast let left = gen_record_pat(gen_variant_path(&variant)?, l_fields); let right = gen_record_pat(gen_variant_path(&variant)?, r_fields); - let tuple = make::tuple_pat(vec![left.into(), right.into()]); + let tuple = make.tuple_pat(vec![left.into(), right.into()]); if let Some(expr) = expr { - arms.push(make::match_arm(tuple.into(), None, expr)); + arms.push(make.match_arm(tuple.into(), None, expr)); } } @@ -513,9 +521,9 @@ fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast let r_name = format!("r{field_name}"); r_fields.push(gen_tuple_field(&r_name)); - let lhs = make::expr_path(make::ext::ident_path(&l_name)); - let rhs = make::expr_path(make::ext::ident_path(&r_name)); - let cmp = make::expr_bin_op( + let lhs = make.expr_path(make.ident_path(&l_name)); + let rhs = make.expr_path(make.ident_path(&r_name)); + let cmp = make.expr_bin_op( lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs, @@ -523,12 +531,12 @@ fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast expr = gen_eq_chain(expr, cmp); } - let left = make::tuple_struct_pat(gen_variant_path(&variant)?, l_fields); - let right = make::tuple_struct_pat(gen_variant_path(&variant)?, r_fields); - let tuple = make::tuple_pat(vec![left.into(), right.into()]); + let left = make.tuple_struct_pat(gen_variant_path(&variant)?, l_fields); + let right = make.tuple_struct_pat(gen_variant_path(&variant)?, r_fields); + let tuple = make.tuple_pat(vec![left.into(), right.into()]); if let Some(expr) = expr { - arms.push(make::match_arm(tuple.into(), None, expr)); + arms.push(make.match_arm(tuple.into(), None, expr)); } } None => continue, @@ -542,57 +550,57 @@ fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast // The fallback arm will be `_ => false,` if we've already gone through every case where the variants of self and other match, // and `_ => std::mem::discriminant(self) == std::mem::discriminant(other),` otherwise. if n_cases > 1 { - let lhs = make::wildcard_pat().into(); + let lhs = make.wildcard_pat().into(); let rhs = if arms_len == n_cases { - make::expr_literal("false").into() + make.expr_literal("false").into() } else { eq_check }; - arms.push(make::match_arm(lhs, None, rhs)); + arms.push(make.match_arm(lhs, None, rhs)); } - let match_target = make::expr_tuple([lhs_name, rhs_name]).into(); - let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); - make::expr_match(match_target, list).into() + let match_target = make.expr_tuple([lhs_name, rhs_name]).into(); + let list = make.match_arm_list(arms).indent(ast::edit::IndentLevel(1)); + make.expr_match(match_target, list).into() } }; - make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)) + make.block_expr(None::<ast::Stmt>, Some(expr)).indent(ast::edit::IndentLevel(1)) } ast::Adt::Struct(strukt) => match strukt.field_list() { Some(ast::FieldList::RecordFieldList(field_list)) => { let mut expr = None; for field in field_list.fields() { - let lhs = make::expr_path(make::ext::ident_path("self")); - let lhs = make::expr_field(lhs, &field.name()?.to_string()); - let rhs = make::expr_path(make::ext::ident_path("other")); - let rhs = make::expr_field(rhs, &field.name()?.to_string()); + let lhs = make.expr_path(make.ident_path("self")); + let lhs = make.expr_field(lhs, &field.name()?.to_string()).into(); + let rhs = make.expr_path(make.ident_path("other")); + let rhs = make.expr_field(rhs, &field.name()?.to_string()).into(); let cmp = - make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); + make.expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); expr = gen_eq_chain(expr, cmp); } - make::block_expr(None, expr).indent(ast::edit::IndentLevel(1)) + make.block_expr(None, expr).indent(ast::edit::IndentLevel(1)) } Some(ast::FieldList::TupleFieldList(field_list)) => { let mut expr = None; for (i, _) in field_list.fields().enumerate() { let idx = format!("{i}"); - let lhs = make::expr_path(make::ext::ident_path("self")); - let lhs = make::expr_field(lhs, &idx); - let rhs = make::expr_path(make::ext::ident_path("other")); - let rhs = make::expr_field(rhs, &idx); + let lhs = make.expr_path(make.ident_path("self")); + let lhs = make.expr_field(lhs, &idx).into(); + let rhs = make.expr_path(make.ident_path("other")); + let rhs = make.expr_field(rhs, &idx).into(); let cmp = - make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); + make.expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); expr = gen_eq_chain(expr, cmp); } - make::block_expr(None, expr).indent(ast::edit::IndentLevel(1)) + make.block_expr(None::<ast::Stmt>, expr).indent(ast::edit::IndentLevel(1)) } // No fields in the body means there's nothing to compare. None => { - let expr = make::expr_literal("true").into(); - make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)) + let expr = make.expr_literal("true").into(); + make.block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)) } }, }; @@ -600,29 +608,33 @@ fn gen_partial_eq(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast Some(body) } -fn gen_partial_ord(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<ast::BlockExpr> { - fn gen_partial_eq_match(match_target: ast::Expr) -> Option<ast::Stmt> { +fn gen_partial_ord( + make: &SyntaxFactory, + adt: &ast::Adt, + trait_ref: Option<TraitRef<'_>>, +) -> Option<ast::BlockExpr> { + let gen_partial_eq_match = |match_target: ast::Expr| -> Option<ast::Stmt> { let mut arms = vec![]; let variant_name = - make::path_pat(make::ext::path_from_idents(["core", "cmp", "Ordering", "Equal"])?); - let lhs = make::tuple_struct_pat(make::ext::path_from_idents(["Some"])?, [variant_name]); - arms.push(make::match_arm(lhs.into(), None, make::expr_empty_block().into())); + make.path_pat(make.path_from_idents(["core", "cmp", "Ordering", "Equal"])?); + let lhs = make.tuple_struct_pat(make.path_from_idents(["Some"])?, [variant_name]); + arms.push(make.match_arm(lhs.into(), None, make.expr_empty_block().into())); - arms.push(make::match_arm( - make::ident_pat(false, false, make::name("ord")).into(), + arms.push(make.match_arm( + make.ident_pat(false, false, make.name("ord")).into(), None, - make::expr_return(Some(make::expr_path(make::ext::ident_path("ord")))), + make.expr_return(Some(make.expr_path(make.ident_path("ord")))).into(), )); - let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); - Some(make::expr_stmt(make::expr_match(match_target, list).into()).into()) - } + let list = make.match_arm_list(arms).indent(ast::edit::IndentLevel(1)); + Some(make.expr_stmt(make.expr_match(match_target, list).into()).into()) + }; - fn gen_partial_cmp_call(lhs: ast::Expr, rhs: ast::Expr) -> ast::Expr { - let rhs = make::expr_ref(rhs, false); - let method = make::name_ref("partial_cmp"); - make::expr_method_call(lhs, method, make::arg_list(Some(rhs))).into() - } + let gen_partial_cmp_call = |lhs: ast::Expr, rhs: ast::Expr| -> ast::Expr { + let rhs = make.expr_ref(rhs, false); + let method = make.name_ref("partial_cmp"); + make.expr_method_call(lhs, method, make.arg_list([rhs])).into() + }; // Check that self type and rhs type match. We don't know how to implement the method // automatically otherwise. @@ -643,10 +655,10 @@ fn gen_partial_ord(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<as Some(ast::FieldList::RecordFieldList(field_list)) => { let mut exprs = vec![]; for field in field_list.fields() { - let lhs = make::expr_path(make::ext::ident_path("self")); - let lhs = make::expr_field(lhs, &field.name()?.to_string()); - let rhs = make::expr_path(make::ext::ident_path("other")); - let rhs = make::expr_field(rhs, &field.name()?.to_string()); + let lhs = make.expr_path(make.ident_path("self")); + let lhs = make.expr_field(lhs, &field.name()?.to_string()).into(); + let rhs = make.expr_path(make.ident_path("other")); + let rhs = make.expr_field(rhs, &field.name()?.to_string()).into(); let ord = gen_partial_cmp_call(lhs, rhs); exprs.push(ord); } @@ -656,17 +668,17 @@ fn gen_partial_ord(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<as .into_iter() .map(gen_partial_eq_match) .collect::<Option<Vec<ast::Stmt>>>()?; - make::block_expr(stmts, tail).indent(ast::edit::IndentLevel(1)) + make.block_expr(stmts, tail).indent(ast::edit::IndentLevel(1)) } Some(ast::FieldList::TupleFieldList(field_list)) => { let mut exprs = vec![]; for (i, _) in field_list.fields().enumerate() { let idx = format!("{i}"); - let lhs = make::expr_path(make::ext::ident_path("self")); - let lhs = make::expr_field(lhs, &idx); - let rhs = make::expr_path(make::ext::ident_path("other")); - let rhs = make::expr_field(rhs, &idx); + let lhs = make.expr_path(make.ident_path("self")); + let lhs = make.expr_field(lhs, &idx).into(); + let rhs = make.expr_path(make.ident_path("other")); + let rhs = make.expr_field(rhs, &idx).into(); let ord = gen_partial_cmp_call(lhs, rhs); exprs.push(ord); } @@ -675,13 +687,13 @@ fn gen_partial_ord(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<as .into_iter() .map(gen_partial_eq_match) .collect::<Option<Vec<ast::Stmt>>>()?; - make::block_expr(stmts, tail).indent(ast::edit::IndentLevel(1)) + make.block_expr(stmts, tail).indent(ast::edit::IndentLevel(1)) } // No fields in the body means there's nothing to compare. None => { - let expr = make::expr_literal("true").into(); - make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)) + let expr = make.expr_literal("true").into(); + make.block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)) } }, }; @@ -689,6 +701,6 @@ fn gen_partial_ord(adt: &ast::Adt, trait_ref: Option<TraitRef<'_>>) -> Option<as Some(body) } -fn make_discriminant() -> Option<ast::Expr> { - Some(make::expr_path(make::ext::path_from_idents(["core", "mem", "discriminant"])?)) +fn make_discriminant(make: &SyntaxFactory) -> Option<ast::Expr> { + Some(make.expr_path(make.path_from_idents(["core", "mem", "discriminant"])?)) } diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs index 44114a7802..44ab64d4f6 100644 --- a/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -2053,6 +2053,17 @@ impl SyntaxFactory { self.path_unqualified(self.path_segment(self.name_ref(ident))) } + pub fn path_from_idents<'a>( + &self, + parts: impl IntoIterator<Item = &'a str>, + ) -> Option<ast::Path> { + make::ext::path_from_idents(parts).map(|path| path.clone_for_update()) + } + + pub fn token_tree_from_node(&self, node: &SyntaxNode) -> ast::TokenTree { + make::ext::token_tree_from_node(node).clone_for_update() + } + pub fn expr_unit(&self) -> ast::Expr { self.expr_tuple([]).into() } |