Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/utils/gen_trait_fn_body.rs')
-rw-r--r--crates/ide-assists/src/utils/gen_trait_fn_body.rs500
1 files changed, 256 insertions, 244 deletions
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"])?))
}