diff options
author | Florian Diebold <[email protected]> | 2020-01-03 18:58:56 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-01-11 22:33:04 +0000 |
commit | 4545f289a991ec3888896aac0e0bcbfac9061e80 (patch) | |
tree | 968011283d685f325f980459c6f4f5ba1d5d1bc9 | |
parent | 5cb1f7132277e16ec4eecafbc274563c4d27158e (diff) |
Handle type args
-rw-r--r-- | crates/ra_assists/src/assists/add_missing_impl_members.rs | 21 | ||||
-rw-r--r-- | 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 dd62b1b78..7b50fb422 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( | |||
156 | .collect(); | 156 | .collect(); |
157 | let items = missing_items | 157 | let items = missing_items |
158 | .into_iter() | 158 | .into_iter() |
159 | .map(|it| { | ||
160 | substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) | ||
161 | }) | ||
159 | .map(|it| match module { | 162 | .map(|it| match module { |
160 | Some(module) => qualify_paths(db, hir::InFile::new(file_id.into(), it), module), | 163 | Some(module) => qualify_paths(db, hir::InFile::new(file_id.into(), it), module), |
161 | None => it, | 164 | None => it, |
162 | }) | 165 | }) |
163 | .map(|it| { | ||
164 | substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) | ||
165 | }) | ||
166 | .map(|it| match it { | 166 | .map(|it| match it { |
167 | ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), | 167 | ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), |
168 | _ => it, | 168 | _ => it, |
@@ -239,11 +239,9 @@ fn substitute_type_params<N: AstNode>( | |||
239 | 239 | ||
240 | use hir::PathResolution; | 240 | use hir::PathResolution; |
241 | 241 | ||
242 | // TODO handle generic args | ||
243 | // TODO handle associated item paths | ||
244 | // TODO handle value ns? | ||
245 | |||
246 | // FIXME extract this to a general utility as well | 242 | // FIXME extract this to a general utility as well |
243 | // FIXME handle value ns? | ||
244 | // 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 | ||
247 | fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: hir::Module) -> N { | 245 | fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: hir::Module) -> N { |
248 | let path_replacements = node | 246 | let path_replacements = node |
249 | .value | 247 | .value |
@@ -255,12 +253,17 @@ fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: | |||
255 | // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway | 253 | // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway |
256 | return None; | 254 | return None; |
257 | } | 255 | } |
256 | // FIXME check if some ancestor is already being replaced, if so skip this | ||
258 | let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None); | 257 | let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None); |
259 | let resolution = analyzer.resolve_path(db, &p)?; | 258 | let resolution = analyzer.resolve_path(db, &p)?; |
260 | match resolution { | 259 | match resolution { |
261 | PathResolution::Def(def) => { | 260 | PathResolution::Def(def) => { |
262 | let found_path = from.find_path(db, def)?; | 261 | let found_path = from.find_path(db, def)?; |
263 | Some((p, found_path.to_ast())) | 262 | let args = p |
263 | .segment() | ||
264 | .and_then(|s| s.type_arg_list()) | ||
265 | .map(|arg_list| qualify_paths(db, node.with_value(arg_list), from)); | ||
266 | Some((p, make::path_with_type_arg_list(found_path.to_ast(), args))) | ||
264 | } | 267 | } |
265 | PathResolution::Local(_) | 268 | PathResolution::Local(_) |
266 | | PathResolution::TypeParam(_) | 269 | | PathResolution::TypeParam(_) |
@@ -535,7 +538,7 @@ impl foo::Foo for S { <|> }", | |||
535 | " | 538 | " |
536 | mod foo { | 539 | mod foo { |
537 | pub struct Bar<T>; | 540 | pub struct Bar<T>; |
538 | impl Bar { type Assoc = u32; } | 541 | impl Bar<T> { type Assoc = u32; } |
539 | trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } | 542 | trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } |
540 | } | 543 | } |
541 | struct S; | 544 | struct S; |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 04a5408fe..68d64a0cc 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 { | |||
21 | fn path_from_text(text: &str) -> ast::Path { | 21 | fn path_from_text(text: &str) -> ast::Path { |
22 | ast_from_text(text) | 22 | ast_from_text(text) |
23 | } | 23 | } |
24 | pub fn path_with_type_arg_list(path: ast::Path, args: Option<ast::TypeArgList>) -> ast::Path { | ||
25 | if let Some(args) = args { | ||
26 | ast_from_text(&format!("const X: {}{}", path.syntax(), args.syntax())) | ||
27 | } else { | ||
28 | path | ||
29 | } | ||
30 | } | ||
24 | 31 | ||
25 | pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordField { | 32 | pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordField { |
26 | return match expr { | 33 | return match expr { |