diff options
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/src/assists/add_missing_impl_members.rs | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index f0dfe7780..2b0726869 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs | |||
@@ -139,6 +139,12 @@ fn add_missing_impl_members_inner( | |||
139 | 139 | ||
140 | ctx.add_assist(AssistId(assist_id), label, |edit| { | 140 | ctx.add_assist(AssistId(assist_id), label, |edit| { |
141 | let n_existing_items = impl_item_list.impl_items().count(); | 141 | let n_existing_items = impl_item_list.impl_items().count(); |
142 | let module = hir::SourceAnalyzer::new( | ||
143 | db, | ||
144 | hir::InFile::new(file_id.into(), impl_node.syntax()), | ||
145 | None, | ||
146 | ) | ||
147 | .module(); | ||
142 | let substs = get_syntactic_substs(impl_node).unwrap_or_default(); | 148 | let substs = get_syntactic_substs(impl_node).unwrap_or_default(); |
143 | let generic_def: hir::GenericDef = trait_.into(); | 149 | let generic_def: hir::GenericDef = trait_.into(); |
144 | let substs_by_param: HashMap<_, _> = generic_def | 150 | let substs_by_param: HashMap<_, _> = generic_def |
@@ -150,6 +156,10 @@ fn add_missing_impl_members_inner( | |||
150 | .collect(); | 156 | .collect(); |
151 | let items = missing_items | 157 | let items = missing_items |
152 | .into_iter() | 158 | .into_iter() |
159 | .map(|it| match module { | ||
160 | Some(module) => qualify_paths(db, hir::InFile::new(file_id.into(), it), module), | ||
161 | None => it, | ||
162 | }) | ||
153 | .map(|it| { | 163 | .map(|it| { |
154 | substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) | 164 | substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) |
155 | }) | 165 | }) |
@@ -227,6 +237,41 @@ fn substitute_type_params<N: AstNode>( | |||
227 | } | 237 | } |
228 | } | 238 | } |
229 | 239 | ||
240 | use hir::PathResolution; | ||
241 | |||
242 | // TODO handle partial paths, with generic args | ||
243 | // TODO handle value ns? | ||
244 | |||
245 | fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: hir::Module) -> N { | ||
246 | let path_replacements = node | ||
247 | .value | ||
248 | .syntax() | ||
249 | .descendants() | ||
250 | .filter_map(ast::Path::cast) | ||
251 | .filter_map(|p| { | ||
252 | let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None); | ||
253 | let resolution = analyzer.resolve_path(db, &p)?; | ||
254 | match resolution { | ||
255 | PathResolution::Def(def) => { | ||
256 | let found_path = from.find_path(db, def)?; | ||
257 | Some((p, found_path.to_ast())) | ||
258 | } | ||
259 | PathResolution::Local(_) | ||
260 | | PathResolution::TypeParam(_) | ||
261 | | PathResolution::SelfType(_) => None, | ||
262 | PathResolution::Macro(_) => None, | ||
263 | PathResolution::AssocItem(_) => None, | ||
264 | } | ||
265 | }) | ||
266 | .collect::<Vec<_>>(); | ||
267 | |||
268 | if path_replacements.is_empty() { | ||
269 | node.value | ||
270 | } else { | ||
271 | edit::replace_descendants(&node.value, path_replacements.into_iter()) | ||
272 | } | ||
273 | } | ||
274 | |||
230 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being | 275 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being |
231 | /// implemented) to a `ast::TraitDef`. | 276 | /// implemented) to a `ast::TraitDef`. |
232 | fn resolve_target_trait_def( | 277 | fn resolve_target_trait_def( |
@@ -406,14 +451,14 @@ impl Foo for S { | |||
406 | add_missing_impl_members, | 451 | add_missing_impl_members, |
407 | " | 452 | " |
408 | mod foo { | 453 | mod foo { |
409 | struct Bar; | 454 | pub struct Bar; |
410 | trait Foo { fn foo(&self, bar: Bar); } | 455 | trait Foo { fn foo(&self, bar: Bar); } |
411 | } | 456 | } |
412 | struct S; | 457 | struct S; |
413 | impl foo::Foo for S { <|> }", | 458 | impl foo::Foo for S { <|> }", |
414 | " | 459 | " |
415 | mod foo { | 460 | mod foo { |
416 | struct Bar; | 461 | pub struct Bar; |
417 | trait Foo { fn foo(&self, bar: Bar); } | 462 | trait Foo { fn foo(&self, bar: Bar); } |
418 | } | 463 | } |
419 | struct S; | 464 | struct S; |