From 4d75430e912491c19fb1a7b1a95ee812f6a8a124 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 31 Dec 2019 16:17:08 +0100 Subject: Qualify some paths in 'add missing impl members' --- .../src/assists/add_missing_impl_members.rs | 49 +++++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'crates/ra_assists/src/assists') 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( ctx.add_assist(AssistId(assist_id), label, |edit| { let n_existing_items = impl_item_list.impl_items().count(); + let module = hir::SourceAnalyzer::new( + db, + hir::InFile::new(file_id.into(), impl_node.syntax()), + None, + ) + .module(); let substs = get_syntactic_substs(impl_node).unwrap_or_default(); let generic_def: hir::GenericDef = trait_.into(); let substs_by_param: HashMap<_, _> = generic_def @@ -150,6 +156,10 @@ fn add_missing_impl_members_inner( .collect(); let items = missing_items .into_iter() + .map(|it| match module { + Some(module) => qualify_paths(db, hir::InFile::new(file_id.into(), it), module), + None => it, + }) .map(|it| { substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) }) @@ -227,6 +237,41 @@ fn substitute_type_params( } } +use hir::PathResolution; + +// TODO handle partial paths, with generic args +// TODO handle value ns? + +fn qualify_paths(db: &impl HirDatabase, node: hir::InFile, from: hir::Module) -> N { + let path_replacements = node + .value + .syntax() + .descendants() + .filter_map(ast::Path::cast) + .filter_map(|p| { + let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None); + let resolution = analyzer.resolve_path(db, &p)?; + match resolution { + PathResolution::Def(def) => { + let found_path = from.find_path(db, def)?; + Some((p, found_path.to_ast())) + } + PathResolution::Local(_) + | PathResolution::TypeParam(_) + | PathResolution::SelfType(_) => None, + PathResolution::Macro(_) => None, + PathResolution::AssocItem(_) => None, + } + }) + .collect::>(); + + if path_replacements.is_empty() { + node.value + } else { + edit::replace_descendants(&node.value, path_replacements.into_iter()) + } +} + /// Given an `ast::ImplBlock`, resolves the target trait (the one being /// implemented) to a `ast::TraitDef`. fn resolve_target_trait_def( @@ -406,14 +451,14 @@ impl Foo for S { add_missing_impl_members, " mod foo { - struct Bar; + pub struct Bar; trait Foo { fn foo(&self, bar: Bar); } } struct S; impl foo::Foo for S { <|> }", " mod foo { - struct Bar; + pub struct Bar; trait Foo { fn foo(&self, bar: Bar); } } struct S; -- cgit v1.2.3