diff options
author | Fedor Sakharov <[email protected]> | 2020-05-13 14:06:42 +0100 |
---|---|---|
committer | Fedor Sakharov <[email protected]> | 2020-05-13 14:07:44 +0100 |
commit | 00f3b6c59ae3df9a7bfb1cd8b694d5f9b6a78be4 (patch) | |
tree | 847a60e19f55dd8da4e819bd1a76b23588fb9f76 /crates | |
parent | 88d3959c33c3b8729cecbe062cff8474516df29f (diff) |
Correctly fill default type parameters
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_assists/src/ast_transform.rs | 20 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/add_missing_impl_members.rs | 50 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 5 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 4 |
5 files changed, 79 insertions, 1 deletions
diff --git a/crates/ra_assists/Cargo.toml b/crates/ra_assists/Cargo.toml index 3bcf58ba4..488ab7bc8 100644 --- a/crates/ra_assists/Cargo.toml +++ b/crates/ra_assists/Cargo.toml | |||
@@ -21,4 +21,5 @@ ra_prof = { path = "../ra_prof" } | |||
21 | ra_db = { path = "../ra_db" } | 21 | ra_db = { path = "../ra_db" } |
22 | ra_ide_db = { path = "../ra_ide_db" } | 22 | ra_ide_db = { path = "../ra_ide_db" } |
23 | hir = { path = "../ra_hir", package = "ra_hir" } | 23 | hir = { path = "../ra_hir", package = "ra_hir" } |
24 | hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } | ||
24 | test_utils = { path = "../test_utils" } | 25 | test_utils = { path = "../test_utils" } |
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs index 9ac65ab39..d81218bc8 100644 --- a/crates/ra_assists/src/ast_transform.rs +++ b/crates/ra_assists/src/ast_transform.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | use rustc_hash::FxHashMap; | 2 | use rustc_hash::FxHashMap; |
3 | 3 | ||
4 | use hir::{PathResolution, SemanticsScope}; | 4 | use hir::{PathResolution, SemanticsScope}; |
5 | use hir_def::type_ref::TypeRef; | ||
5 | use ra_ide_db::RootDatabase; | 6 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{ | 7 | use ra_syntax::{ |
7 | algo::SyntaxRewriter, | 8 | algo::SyntaxRewriter, |
@@ -51,7 +52,24 @@ impl<'a> SubstituteTypeParams<'a> { | |||
51 | .into_iter() | 52 | .into_iter() |
52 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky | 53 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky |
53 | .skip(1) | 54 | .skip(1) |
54 | .zip(substs.into_iter()) | 55 | // The actual list of trait type parameters may be longer than the one |
56 | // used in the `impl` block due to trailing default type parametrs. | ||
57 | // For that case we extend the `substs` with an empty iterator so we | ||
58 | // can still hit those trailing values and check if they actually have | ||
59 | // a default type. If they do, go for that type from `hir` to `ast` so | ||
60 | // the resulting change can be applied correctly. | ||
61 | .zip(substs.into_iter().map(Some).chain(std::iter::repeat(None))) | ||
62 | .filter_map(|(k, v)| match v { | ||
63 | Some(v) => Some((k, v)), | ||
64 | None => match k.default(source_scope.db)? { | ||
65 | TypeRef::Path(path) => Some(( | ||
66 | k, | ||
67 | ast::make::type_arg(&format!("{}", path.mod_path().as_ident()?)) | ||
68 | .type_ref()?, | ||
69 | )), | ||
70 | _ => None, | ||
71 | }, | ||
72 | }) | ||
55 | .collect(); | 73 | .collect(); |
56 | return SubstituteTypeParams { | 74 | return SubstituteTypeParams { |
57 | source_scope, | 75 | source_scope, |
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index c1ce87914..22e1156d2 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs | |||
@@ -618,4 +618,54 @@ impl Foo for S { | |||
618 | }"#, | 618 | }"#, |
619 | ) | 619 | ) |
620 | } | 620 | } |
621 | |||
622 | #[test] | ||
623 | fn test_generic_single_default_parameter() { | ||
624 | check_assist( | ||
625 | add_missing_impl_members, | ||
626 | r#" | ||
627 | trait Foo<T = Self> { | ||
628 | fn bar(&self, other: &T); | ||
629 | } | ||
630 | |||
631 | struct S; | ||
632 | impl Foo for S { <|> }"#, | ||
633 | r#" | ||
634 | trait Foo<T = Self> { | ||
635 | fn bar(&self, other: &T); | ||
636 | } | ||
637 | |||
638 | struct S; | ||
639 | impl Foo for S { | ||
640 | <|>fn bar(&self, other: &Self) { | ||
641 | todo!() | ||
642 | } | ||
643 | }"#, | ||
644 | ) | ||
645 | } | ||
646 | |||
647 | #[test] | ||
648 | fn test_generic_default_parameter_is_second() { | ||
649 | check_assist( | ||
650 | add_missing_impl_members, | ||
651 | r#" | ||
652 | trait Foo<T1, T2 = Self> { | ||
653 | fn bar(&self, this: &T1, that: &T2); | ||
654 | } | ||
655 | |||
656 | struct S<T>; | ||
657 | impl Foo<T> for S<T> { <|> }"#, | ||
658 | r#" | ||
659 | trait Foo<T1, T2 = Self> { | ||
660 | fn bar(&self, this: &T1, that: &T2); | ||
661 | } | ||
662 | |||
663 | struct S<T>; | ||
664 | impl Foo<T> for S<T> { | ||
665 | <|>fn bar(&self, this: &T, that: &Self) { | ||
666 | todo!() | ||
667 | } | ||
668 | }"#, | ||
669 | ) | ||
670 | } | ||
621 | } | 671 | } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e8e3211fc..3c56f39c1 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -989,6 +989,11 @@ impl TypeParam { | |||
989 | ty: InEnvironment { value: ty, environment }, | 989 | ty: InEnvironment { value: ty, environment }, |
990 | } | 990 | } |
991 | } | 991 | } |
992 | |||
993 | pub fn default(self, db: &dyn HirDatabase) -> Option<TypeRef> { | ||
994 | let params = db.generic_params(self.id.parent); | ||
995 | params.types[self.id.local_id].default.clone() | ||
996 | } | ||
992 | } | 997 | } |
993 | 998 | ||
994 | // FIXME: rename from `ImplDef` to `Impl` | 999 | // FIXME: rename from `ImplDef` to `Impl` |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 12c5228f5..8981cbe33 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -13,6 +13,10 @@ pub fn name_ref(text: &str) -> ast::NameRef { | |||
13 | ast_from_text(&format!("fn f() {{ {}; }}", text)) | 13 | ast_from_text(&format!("fn f() {{ {}; }}", text)) |
14 | } | 14 | } |
15 | 15 | ||
16 | pub fn type_arg(text: &str) -> ast::TypeArg { | ||
17 | ast_from_text(&format!("impl F<{}> for G {{}}", text)) | ||
18 | } | ||
19 | |||
16 | pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { | 20 | pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { |
17 | ast_from_text(&format!("use {};", name_ref)) | 21 | ast_from_text(&format!("use {};", name_ref)) |
18 | } | 22 | } |