aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/add_missing_impl_members.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/add_missing_impl_members.rs')
-rw-r--r--crates/ra_assists/src/add_missing_impl_members.rs42
1 files changed, 21 insertions, 21 deletions
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index 8e8520c59..567fc9586 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -44,31 +44,35 @@ pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) ->
44 let impl_node = node.ancestors().find_map(ast::ImplBlock::cast)?; 44 let impl_node = node.ancestors().find_map(ast::ImplBlock::cast)?;
45 let impl_item_list = impl_node.item_list()?; 45 let impl_item_list = impl_node.item_list()?;
46 // Don't offer the assist when cursor is at the end, outside the block itself. 46 // Don't offer the assist when cursor is at the end, outside the block itself.
47 let cursor_range = TextRange::from_to(node.range().end(), node.range().end());
47 if node.range().end() == impl_node.syntax().range().end() { 48 if node.range().end() == impl_node.syntax().range().end() {
48 return None; 49 return None;
49 } 50 }
50 51
51 let trait_def = { 52 let trait_def = {
52 let position = FilePosition { file_id: ctx.frange.file_id, offset: node.range().end() }; 53 let position = FilePosition { file_id: ctx.frange.file_id, offset: cursor_range.end() };
53 let resolver = hir::source_binder::resolver_for_position(ctx.db, position); 54 let resolver = hir::source_binder::resolver_for_position(ctx.db, position);
54 55
55 resolve_target_trait_def(ctx.db, &resolver, impl_node)? 56 resolve_target_trait_def(ctx.db, &resolver, impl_node)?
56 }; 57 };
57 58
58 let fn_def_opt = |kind| if let ImplItemKind::FnDef(def) = kind { Some(def) } else { None }; 59 let missing_fns: Vec<_> = {
59 let def_name = |def| -> Option<&SmolStr> { FnDef::name(def).map(ast::Name::text) }; 60 let fn_def_opt = |kind| if let ImplItemKind::FnDef(def) = kind { Some(def) } else { None };
61 let def_name = |def| -> Option<&SmolStr> { FnDef::name(def).map(ast::Name::text) };
60 62
61 let trait_items = trait_def.syntax().descendants().find_map(ast::ItemList::cast)?.impl_items(); 63 let trait_items =
62 let impl_items = impl_item_list.impl_items(); 64 trait_def.syntax().descendants().find_map(ast::ItemList::cast)?.impl_items();
65 let impl_items = impl_item_list.impl_items();
63 66
64 let trait_fns = trait_items.map(ImplItem::kind).filter_map(fn_def_opt).collect::<Vec<_>>(); 67 let trait_fns = trait_items.map(ImplItem::kind).filter_map(fn_def_opt).collect::<Vec<_>>();
65 let impl_fns = impl_items.map(ImplItem::kind).filter_map(fn_def_opt).collect::<Vec<_>>(); 68 let impl_fns = impl_items.map(ImplItem::kind).filter_map(fn_def_opt).collect::<Vec<_>>();
66 69
67 let missing_fns: Vec<_> = trait_fns 70 trait_fns
68 .into_iter() 71 .into_iter()
69 .filter(|t| def_name(t).is_some()) 72 .filter(|t| def_name(t).is_some())
70 .filter(|t| impl_fns.iter().all(|i| def_name(i) != def_name(t))) 73 .filter(|t| impl_fns.iter().all(|i| def_name(i) != def_name(t)))
71 .collect(); 74 .collect()
75 };
72 if missing_fns.is_empty() { 76 if missing_fns.is_empty() {
73 return None; 77 return None;
74 } 78 }
@@ -89,21 +93,17 @@ pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) ->
89 ) 93 )
90 }; 94 };
91 95
92 let func_bodies = missing_fns.into_iter().map(build_func_body).join("\n");
93 let func_bodies = String::from("\n") + &func_bodies;
94 let trailing_whitespace = format!("\n{}", parent_indent);
95 let func_bodies = reindent(&func_bodies, &indent) + &trailing_whitespace;
96
97 let changed_range = { 96 let changed_range = {
98 let last_whitespace = impl_item_list.syntax().children(); 97 let last_whitespace = impl_item_list.syntax().children();
99 let last_whitespace = last_whitespace.filter_map(ast::Whitespace::cast).last(); 98 let last_whitespace = last_whitespace.filter_map(ast::Whitespace::cast).last();
100 let last_whitespace = last_whitespace.map(|w| w.syntax());
101 99
102 let cursor_range = TextRange::from_to(node.range().end(), node.range().end()); 100 last_whitespace.map(|w| w.syntax().range()).unwrap_or(cursor_range)
103
104 last_whitespace.map(|x| x.range()).unwrap_or(cursor_range)
105 }; 101 };
106 102
103 let func_bodies = format!("\n{}", missing_fns.into_iter().map(build_func_body).join("\n"));
104 let trailing_whitespace = format!("\n{}", parent_indent);
105 let func_bodies = reindent(&func_bodies, &indent) + &trailing_whitespace;
106
107 let replaced_text_range = TextUnit::of_str(&func_bodies); 107 let replaced_text_range = TextUnit::of_str(&func_bodies);
108 108
109 edit.replace(changed_range, func_bodies); 109 edit.replace(changed_range, func_bodies);