Skip to content

Commit 59cdb51

Browse files
committed
Remove unwraps
1 parent f424cd9 commit 59cdb51

File tree

1 file changed

+65
-48
lines changed

1 file changed

+65
-48
lines changed

crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -168,76 +168,92 @@ fn impl_def_from_trait(
168168
add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
169169

170170
// Generate a default `impl` function body for the derived trait.
171-
if let ast::AssocItem::Fn(func) = &first_assoc_item {
172-
match trait_path.segment().unwrap().name_ref().unwrap().text().as_str() {
173-
"Debug" => gen_debug_impl(adt, func, annotated_name),
174-
_ => {}
175-
};
176-
}
171+
if let ast::AssocItem::Fn(ref func) = first_assoc_item {
172+
let _ = gen_default_impl(func, trait_path, adt, annotated_name);
173+
};
174+
177175
Some((impl_def, first_assoc_item))
178176
}
179177

178+
/// Generate custom trait bodies where possible.
179+
///
180+
/// Returns `Option` so that we can use `?` rather than `if let Some`. Returning
181+
/// `None` means that generating a custom trait body failed, and the body will remain
182+
/// as `todo!` instead.
183+
fn gen_default_impl(
184+
func: &ast::Fn,
185+
trait_path: &ast::Path,
186+
adt: &ast::Adt,
187+
annotated_name: &ast::Name,
188+
) -> Option<()> {
189+
match trait_path.segment()?.name_ref()?.text().as_str() {
190+
"Debug" => gen_debug_impl(adt, func, annotated_name),
191+
_ => Some(()),
192+
}
193+
}
194+
180195
/// Generate a `Debug` impl based on the fields and members of the target type.
181-
fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) {
196+
fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) -> Option<()> {
182197
match adt {
183-
ast::Adt::Union(_) => {} // `Debug` cannot be derived for unions, so no default impl can be provided.
198+
// `Debug` cannot be derived for unions, so no default impl can be provided.
199+
ast::Adt::Union(_) => Some(()),
200+
201+
// => match self { Self::Variant => write!(f, "Variant") }
184202
ast::Adt::Enum(enum_) => {
185-
// => match self { Self::Variant => write!(f, "Variant") }
186-
if let Some(list) = enum_.variant_list() {
187-
let mut arms = vec![];
188-
for variant in list.variants() {
189-
let name = variant.name().unwrap();
190-
191-
let left = make::ext::ident_path("Self");
192-
let right = make::ext::ident_path(&format!("{}", name));
193-
let variant_name = make::path_pat(make::path_concat(left, right));
194-
195-
let target = make::expr_path(make::ext::ident_path("f").into());
196-
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
197-
let args = make::arg_list(vec![target, fmt_string]);
198-
let macro_name = make::expr_path(make::ext::ident_path("write"));
199-
let macro_call = make::expr_macro_call(macro_name, args);
200-
201-
arms.push(make::match_arm(Some(variant_name.into()), None, macro_call.into()));
202-
}
203+
let list = enum_.variant_list()?;
204+
let mut arms = vec![];
205+
for variant in list.variants() {
206+
let name = variant.name()?;
207+
let left = make::ext::ident_path("Self");
208+
let right = make::ext::ident_path(&format!("{}", name));
209+
let variant_name = make::path_pat(make::path_concat(left, right));
210+
211+
let target = make::expr_path(make::ext::ident_path("f").into());
212+
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
213+
let args = make::arg_list(vec![target, fmt_string]);
214+
let macro_name = make::expr_path(make::ext::ident_path("write"));
215+
let macro_call = make::expr_macro_call(macro_name, args);
216+
217+
arms.push(make::match_arm(Some(variant_name.into()), None, macro_call.into()));
218+
}
203219

204-
let match_target = make::expr_path(make::ext::ident_path("self"));
205-
let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1));
206-
let match_expr = make::expr_match(match_target, list);
220+
let match_target = make::expr_path(make::ext::ident_path("self"));
221+
let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1));
222+
let match_expr = make::expr_match(match_target, list);
207223

208-
let body = make::block_expr(None, Some(match_expr));
209-
let body = body.indent(ast::edit::IndentLevel(1));
210-
ted::replace(func.body().unwrap().syntax(), body.clone_for_update().syntax());
211-
}
224+
let body = make::block_expr(None, Some(match_expr));
225+
let body = body.indent(ast::edit::IndentLevel(1));
226+
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
227+
Some(())
212228
}
229+
213230
ast::Adt::Struct(strukt) => {
214231
let name = format!("\"{}\"", annotated_name);
215232
let args = make::arg_list(Some(make::expr_literal(&name).into()));
216233
let target = make::expr_path(make::ext::ident_path("f"));
217234

218235
let expr = match strukt.field_list() {
219-
None => {
220-
// => f.debug_struct("Name").finish()
221-
make::expr_method_call(target, make::name_ref("debug_struct"), args)
222-
}
236+
// => f.debug_struct("Name").finish()
237+
None => make::expr_method_call(target, make::name_ref("debug_struct"), args),
238+
239+
// => f.debug_struct("Name").field("foo", &self.foo).finish()
223240
Some(ast::FieldList::RecordFieldList(field_list)) => {
224-
// => f.debug_struct("Name").field("foo", &self.foo).finish()
225241
let method = make::name_ref("debug_struct");
226242
let mut expr = make::expr_method_call(target, method, args);
227243
for field in field_list.fields() {
228-
if let Some(name) = field.name() {
229-
let f_name = make::expr_literal(&(format!("\"{}\"", name))).into();
230-
let f_path = make::expr_path(make::ext::ident_path("self"));
231-
let f_path = make::expr_ref(f_path, false);
232-
let f_path = make::expr_field(f_path, &format!("{}", name)).into();
233-
let args = make::arg_list(vec![f_name, f_path]);
234-
expr = make::expr_method_call(expr, make::name_ref("field"), args);
235-
}
244+
let name = field.name()?;
245+
let f_name = make::expr_literal(&(format!("\"{}\"", name))).into();
246+
let f_path = make::expr_path(make::ext::ident_path("self"));
247+
let f_path = make::expr_ref(f_path, false);
248+
let f_path = make::expr_field(f_path, &format!("{}", name)).into();
249+
let args = make::arg_list(vec![f_name, f_path]);
250+
expr = make::expr_method_call(expr, make::name_ref("field"), args);
236251
}
237252
expr
238253
}
254+
255+
// => f.debug_tuple("Name").field(self.0).finish()
239256
Some(ast::FieldList::TupleFieldList(field_list)) => {
240-
// => f.debug_tuple("Name").field(self.0).finish()
241257
let method = make::name_ref("debug_tuple");
242258
let mut expr = make::expr_method_call(target, method, args);
243259
for (idx, _) in field_list.fields().enumerate() {
@@ -254,7 +270,8 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) {
254270
let method = make::name_ref("finish");
255271
let expr = make::expr_method_call(expr, method, make::arg_list(None));
256272
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
257-
ted::replace(func.body().unwrap().syntax(), body.clone_for_update().syntax());
273+
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
274+
Some(())
258275
}
259276
}
260277
}

0 commit comments

Comments
 (0)