aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src/utils.rs')
-rw-r--r--crates/ide_assists/src/utils.rs48
1 files changed, 24 insertions, 24 deletions
diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs
index 0dcf20c61..fc7caee04 100644
--- a/crates/ide_assists/src/utils.rs
+++ b/crates/ide_assists/src/utils.rs
@@ -17,7 +17,7 @@ use syntax::{
17 ast::AttrsOwner, 17 ast::AttrsOwner,
18 ast::NameOwner, 18 ast::NameOwner,
19 ast::{self, edit, make, ArgListOwner, GenericParamsOwner}, 19 ast::{self, edit, make, ArgListOwner, GenericParamsOwner},
20 AstNode, Direction, SmolStr, 20 ted, AstNode, Direction, SmolStr,
21 SyntaxKind::*, 21 SyntaxKind::*,
22 SyntaxNode, TextSize, T, 22 SyntaxNode, TextSize, T,
23}; 23};
@@ -128,43 +128,43 @@ pub fn add_trait_assoc_items_to_impl(
128 sema: &hir::Semantics<ide_db::RootDatabase>, 128 sema: &hir::Semantics<ide_db::RootDatabase>,
129 items: Vec<ast::AssocItem>, 129 items: Vec<ast::AssocItem>,
130 trait_: hir::Trait, 130 trait_: hir::Trait,
131 impl_def: ast::Impl, 131 impl_: ast::Impl,
132 target_scope: hir::SemanticsScope, 132 target_scope: hir::SemanticsScope,
133) -> (ast::Impl, ast::AssocItem) { 133) -> (ast::Impl, ast::AssocItem) {
134 let impl_item_list = impl_def.assoc_item_list().unwrap_or_else(make::assoc_item_list);
135
136 let n_existing_items = impl_item_list.assoc_items().count();
137 let source_scope = sema.scope_for_def(trait_); 134 let source_scope = sema.scope_for_def(trait_);
138 let ast_transform = QualifyPaths::new(&target_scope, &source_scope) 135 let ast_transform = QualifyPaths::new(&target_scope, &source_scope)
139 .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_def.clone())); 136 .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_.clone()));
140 137
141 let items = items 138 let items = items
142 .into_iter() 139 .into_iter()
143 .map(|it| it.clone_for_update()) 140 .map(|it| it.clone_for_update())
144 .inspect(|it| ast_transform::apply(&*ast_transform, it)) 141 .inspect(|it| ast_transform::apply(&*ast_transform, it))
145 .map(|it| match it { 142 .map(|it| edit::remove_attrs_and_docs(&it).clone_subtree().clone_for_update());
146 ast::AssocItem::Fn(def) => ast::AssocItem::Fn(add_body(def)), 143
147 ast::AssocItem::TypeAlias(def) => ast::AssocItem::TypeAlias(def.remove_bounds()), 144 let res = impl_.clone_for_update();
148 _ => it, 145
149 }) 146 let assoc_item_list = res.get_or_create_assoc_item_list();
150 .map(|it| edit::remove_attrs_and_docs(&it)); 147 let mut first_item = None;
151 148 for item in items {
152 let new_impl_item_list = impl_item_list.append_items(items); 149 first_item.get_or_insert_with(|| item.clone());
153 let new_impl_def = impl_def.with_assoc_item_list(new_impl_item_list); 150 match &item {
154 let first_new_item = 151 ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
155 new_impl_def.assoc_item_list().unwrap().assoc_items().nth(n_existing_items).unwrap();
156 return (new_impl_def, first_new_item);
157
158 fn add_body(fn_def: ast::Fn) -> ast::Fn {
159 match fn_def.body() {
160 Some(_) => fn_def,
161 None => {
162 let body = make::block_expr(None, Some(make::ext::expr_todo())) 152 let body = make::block_expr(None, Some(make::ext::expr_todo()))
163 .indent(edit::IndentLevel(1)); 153 .indent(edit::IndentLevel(1));
164 fn_def.with_body(body) 154 ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax())
165 } 155 }
156 ast::AssocItem::TypeAlias(type_alias) => {
157 if let Some(type_bound_list) = type_alias.type_bound_list() {
158 type_bound_list.remove()
159 }
160 }
161 _ => {}
166 } 162 }
163
164 assoc_item_list.add_item(item)
167 } 165 }
166
167 (res, first_item.unwrap())
168} 168}
169 169
170#[derive(Clone, Copy, Debug)] 170#[derive(Clone, Copy, Debug)]