Skip to content

Commit 97ec6a2

Browse files
committed
add make::ext::path_from_idents
1 parent df19895 commit 97ec6a2

File tree

2 files changed

+39
-22
lines changed

2 files changed

+39
-22
lines changed

crates/ide_assists/src/utils/gen_trait_fn_body.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
3838
let list = enum_.variant_list()?;
3939
let mut arms = vec![];
4040
for variant in list.variants() {
41-
let variant_name = make_variant_path(&variant)?;
41+
let name = variant.name()?;
42+
let variant_name = make::ext::path_from_idents(["Self", &format!("{}", name)])?;
4243

4344
match variant.field_list() {
4445
// => match self { Self::Name { x } => Self::Name { x: x.clone() } }
@@ -148,7 +149,8 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
148149
let mut arms = vec![];
149150
for variant in list.variants() {
150151
let name = variant.name()?;
151-
let variant_name = make::path_pat(make::path_from_text(&format!("Self::{}", name)));
152+
let variant_name =
153+
make::path_pat(make::ext::path_from_idents(["Self", &format!("{}", name)])?);
152154

153155
let target = make::expr_path(make::ext::ident_path("f").into());
154156
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
@@ -220,9 +222,9 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
220222

221223
/// Generate a `Debug` impl based on the fields and members of the target type.
222224
fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
223-
fn gen_default_call() -> ast::Expr {
224-
let fn_name = make::path_from_text(&"Default::default");
225-
make::expr_call(make::expr_path(fn_name), make::arg_list(None))
225+
fn gen_default_call() -> Option<ast::Expr> {
226+
let fn_name = make::ext::path_from_idents(["Default", "default"])?;
227+
Some(make::expr_call(make::expr_path(fn_name), make::arg_list(None)))
226228
}
227229
match adt {
228230
// `Debug` cannot be derived for unions, so no default impl can be provided.
@@ -234,7 +236,7 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
234236
Some(ast::FieldList::RecordFieldList(field_list)) => {
235237
let mut fields = vec![];
236238
for field in field_list.fields() {
237-
let method_call = gen_default_call();
239+
let method_call = gen_default_call()?;
238240
let name_ref = make::name_ref(&field.name()?.to_string());
239241
let field = make::record_expr_field(name_ref, Some(method_call));
240242
fields.push(field);
@@ -245,7 +247,10 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
245247
}
246248
Some(ast::FieldList::TupleFieldList(field_list)) => {
247249
let struct_name = make::expr_path(make::ext::ident_path("Self"));
248-
let fields = field_list.fields().map(|_| gen_default_call());
250+
let fields = field_list
251+
.fields()
252+
.map(|_| gen_default_call())
253+
.collect::<Option<Vec<ast::Expr>>>()?;
249254
make::expr_call(struct_name, make::arg_list(fields))
250255
}
251256
None => {
@@ -276,7 +281,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
276281

277282
// => std::mem::discriminant(self).hash(state);
278283
ast::Adt::Enum(_) => {
279-
let fn_name = make_discriminant();
284+
let fn_name = make_discriminant()?;
280285

281286
let arg = make::expr_path(make::ext::ident_path("self"));
282287
let fn_call = make::expr_call(fn_name, make::arg_list(Some(arg)));
@@ -336,6 +341,10 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
336341
make::record_pat_with_fields(record_name, list)
337342
}
338343

344+
fn gen_variant_path(variant: &ast::Variant) -> Option<ast::Path> {
345+
make::ext::path_from_idents(["Self", &variant.name()?.to_string()])
346+
}
347+
339348
fn gen_tuple_field(field_name: &String) -> ast::Pat {
340349
ast::Pat::IdentPat(make::ident_pat(false, false, make::name(field_name)))
341350
}
@@ -344,15 +353,15 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
344353
// generate this code `Self` for the time being.
345354

346355
let body = match adt {
347-
// `PartialEq` cannot be derived for unions, so no default impl can be provided.
356+
// `Hash` cannot be derived for unions, so no default impl can be provided.
348357
ast::Adt::Union(_) => return None,
349358

350359
ast::Adt::Enum(enum_) => {
351360
// => std::mem::discriminant(self) == std::mem::discriminant(other)
352361
let lhs_name = make::expr_path(make::ext::ident_path("self"));
353-
let lhs = make::expr_call(make_discriminant(), make::arg_list(Some(lhs_name.clone())));
362+
let lhs = make::expr_call(make_discriminant()?, make::arg_list(Some(lhs_name.clone())));
354363
let rhs_name = make::expr_path(make::ext::ident_path("other"));
355-
let rhs = make::expr_call(make_discriminant(), make::arg_list(Some(rhs_name.clone())));
364+
let rhs = make::expr_call(make_discriminant()?, make::arg_list(Some(rhs_name.clone())));
356365
let eq_check = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
357366

358367
let mut case_count = 0;
@@ -381,8 +390,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
381390
expr = gen_eq_chain(expr, cmp);
382391
}
383392

384-
let left = gen_record_pat(make_variant_path(&variant)?, l_fields);
385-
let right = gen_record_pat(make_variant_path(&variant)?, r_fields);
393+
let left = gen_record_pat(gen_variant_path(&variant)?, l_fields);
394+
let right = gen_record_pat(gen_variant_path(&variant)?, r_fields);
386395
let tuple = make::tuple_pat(vec![left.into(), right.into()]);
387396

388397
if let Some(expr) = expr {
@@ -410,8 +419,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
410419
expr = gen_eq_chain(expr, cmp);
411420
}
412421

413-
let left = make::tuple_struct_pat(make_variant_path(&variant)?, l_fields);
414-
let right = make::tuple_struct_pat(make_variant_path(&variant)?, r_fields);
422+
let left = make::tuple_struct_pat(gen_variant_path(&variant)?, l_fields);
423+
let right = make::tuple_struct_pat(gen_variant_path(&variant)?, r_fields);
415424
let tuple = make::tuple_pat(vec![left.into(), right.into()]);
416425

417426
if let Some(expr) = expr {
@@ -466,7 +475,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
466475
make::block_expr(None, expr).indent(ast::edit::IndentLevel(1))
467476
}
468477

469-
// No fields in the body means there's nothing to compare.
478+
// No fields in the body means there's nothing to hash.
470479
None => {
471480
let expr = make::expr_literal("true").into();
472481
make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1))
@@ -478,10 +487,6 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
478487
Some(())
479488
}
480489

481-
fn make_discriminant() -> ast::Expr {
482-
make::expr_path(make::path_from_text("core::mem::discriminant"))
483-
}
484-
485-
fn make_variant_path(variant: &ast::Variant) -> Option<ast::Path> {
486-
Some(make::path_from_text(&format!("Self::{}", &variant.name()?)))
490+
fn make_discriminant() -> Option<ast::Expr> {
491+
Some(make::expr_path(make::ext::path_from_idents(["core", "mem", "discriminant"])?))
487492
}

crates/syntax/src/ast/make.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ pub mod ext {
3232
path_unqualified(path_segment(name_ref(ident)))
3333
}
3434

35+
pub fn path_from_idents<'a>(
36+
parts: impl std::iter::IntoIterator<Item = &'a str>,
37+
) -> Option<ast::Path> {
38+
let mut iter = parts.into_iter();
39+
let base = ext::ident_path(iter.next()?);
40+
let path = iter.fold(base, |base, s| {
41+
let path = ext::ident_path(s);
42+
path_concat(base, path)
43+
});
44+
Some(path)
45+
}
46+
3547
pub fn expr_unreachable() -> ast::Expr {
3648
expr_from_text("unreachable!()")
3749
}

0 commit comments

Comments
 (0)