From 4545f289a991ec3888896aac0e0bcbfac9061e80 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 3 Jan 2020 19:58:56 +0100 Subject: [PATCH] Handle type args --- .../src/assists/add_missing_impl_members.rs | 21 +++++++++++-------- crates/ra_syntax/src/ast/make.rs | 7 +++++++ 2 files changed, 19 insertions(+), 9 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 dd62b1b78a5..7b50fb422fc 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs @@ -156,13 +156,13 @@ fn add_missing_impl_members_inner( .collect(); let items = missing_items .into_iter() + .map(|it| { + substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) + }) .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) - }) .map(|it| match it { ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), _ => it, @@ -239,11 +239,9 @@ fn substitute_type_params( use hir::PathResolution; -// TODO handle generic args -// TODO handle associated item paths -// TODO handle value ns? - // FIXME extract this to a general utility as well +// FIXME handle value ns? +// FIXME this doesn't 'commute' with `substitute_type_params`, since type params in newly generated type arg lists don't resolve. Currently we can avoid this problem, but it's worth thinking about a solution fn qualify_paths(db: &impl HirDatabase, node: hir::InFile, from: hir::Module) -> N { let path_replacements = node .value @@ -255,12 +253,17 @@ fn qualify_paths(db: &impl HirDatabase, node: hir::InFile, from: // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway return None; } + // FIXME check if some ancestor is already being replaced, if so skip this 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())) + let args = p + .segment() + .and_then(|s| s.type_arg_list()) + .map(|arg_list| qualify_paths(db, node.with_value(arg_list), from)); + Some((p, make::path_with_type_arg_list(found_path.to_ast(), args))) } PathResolution::Local(_) | PathResolution::TypeParam(_) @@ -535,7 +538,7 @@ impl foo::Foo for S { <|> }", " mod foo { pub struct Bar; - impl Bar { type Assoc = u32; } + impl Bar { type Assoc = u32; } trait Foo { fn foo(&self, bar: Bar::Assoc); } } struct S; diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 04a5408fefa..68d64a0cc42 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs @@ -21,6 +21,13 @@ pub fn path_qualified(qual: ast::Path, name_ref: ast::NameRef) -> ast::Path { fn path_from_text(text: &str) -> ast::Path { ast_from_text(text) } +pub fn path_with_type_arg_list(path: ast::Path, args: Option) -> ast::Path { + if let Some(args) = args { + ast_from_text(&format!("const X: {}{}", path.syntax(), args.syntax())) + } else { + path + } +} pub fn record_field(name: ast::NameRef, expr: Option) -> ast::RecordField { return match expr {