diff options
-rw-r--r-- | crates/ra_assists/src/add_missing_impl_members.rs | 42 |
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); |