diff options
Diffstat (limited to 'crates/ra_hir/src/generics.rs')
-rw-r--r-- | crates/ra_hir/src/generics.rs | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index c72360f44..fcc513353 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -7,7 +7,7 @@ use std::sync::Arc; | |||
7 | 7 | ||
8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; | 8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; |
9 | 9 | ||
10 | use crate::{db::PersistentHirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type}; | 10 | use crate::{db::PersistentHirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type, ImplBlock}; |
11 | 11 | ||
12 | /// Data about a generic parameter (to a function, struct, impl, ...). | 12 | /// Data about a generic parameter (to a function, struct, impl, ...). |
13 | #[derive(Clone, PartialEq, Eq, Debug)] | 13 | #[derive(Clone, PartialEq, Eq, Debug)] |
@@ -20,6 +20,7 @@ pub struct GenericParam { | |||
20 | /// Data about the generic parameters of a function, struct, impl, etc. | 20 | /// Data about the generic parameters of a function, struct, impl, etc. |
21 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | 21 | #[derive(Clone, PartialEq, Eq, Debug, Default)] |
22 | pub struct GenericParams { | 22 | pub struct GenericParams { |
23 | pub(crate) parent_params: Option<Arc<GenericParams>>, | ||
23 | pub(crate) params: Vec<GenericParam>, | 24 | pub(crate) params: Vec<GenericParam>, |
24 | } | 25 | } |
25 | 26 | ||
@@ -30,8 +31,9 @@ pub enum GenericDef { | |||
30 | Enum(Enum), | 31 | Enum(Enum), |
31 | Trait(Trait), | 32 | Trait(Trait), |
32 | Type(Type), | 33 | Type(Type), |
34 | ImplBlock(ImplBlock), | ||
33 | } | 35 | } |
34 | impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type); | 36 | impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type, ImplBlock); |
35 | 37 | ||
36 | impl GenericParams { | 38 | impl GenericParams { |
37 | pub(crate) fn generic_params_query( | 39 | pub(crate) fn generic_params_query( |
@@ -39,27 +41,36 @@ impl GenericParams { | |||
39 | def: GenericDef, | 41 | def: GenericDef, |
40 | ) -> Arc<GenericParams> { | 42 | ) -> Arc<GenericParams> { |
41 | let mut generics = GenericParams::default(); | 43 | let mut generics = GenericParams::default(); |
44 | let parent = match def { | ||
45 | GenericDef::Function(it) => it.impl_block(db), | ||
46 | GenericDef::Type(it) => it.impl_block(db), | ||
47 | GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, | ||
48 | GenericDef::ImplBlock(_) => None, | ||
49 | }; | ||
50 | generics.parent_params = parent.map(|p| p.generic_params(db)); | ||
51 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | ||
42 | match def { | 52 | match def { |
43 | GenericDef::Function(it) => generics.fill(&*it.source(db).1), | 53 | GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), |
44 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1), | 54 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), |
45 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1), | 55 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), |
46 | GenericDef::Trait(it) => generics.fill(&*it.source(db).1), | 56 | GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start), |
47 | GenericDef::Type(it) => generics.fill(&*it.source(db).1), | 57 | GenericDef::Type(it) => generics.fill(&*it.source(db).1, start), |
58 | GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), | ||
48 | } | 59 | } |
49 | 60 | ||
50 | Arc::new(generics) | 61 | Arc::new(generics) |
51 | } | 62 | } |
52 | 63 | ||
53 | fn fill(&mut self, node: &impl TypeParamsOwner) { | 64 | fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { |
54 | if let Some(params) = node.type_param_list() { | 65 | if let Some(params) = node.type_param_list() { |
55 | self.fill_params(params) | 66 | self.fill_params(params, start) |
56 | } | 67 | } |
57 | } | 68 | } |
58 | 69 | ||
59 | fn fill_params(&mut self, params: &ast::TypeParamList) { | 70 | fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { |
60 | for (idx, type_param) in params.type_params().enumerate() { | 71 | for (idx, type_param) in params.type_params().enumerate() { |
61 | let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); | 72 | let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); |
62 | let param = GenericParam { idx: idx as u32, name }; | 73 | let param = GenericParam { idx: idx as u32 + start, name }; |
63 | self.params.push(param); | 74 | self.params.push(param); |
64 | } | 75 | } |
65 | } | 76 | } |
@@ -67,4 +78,13 @@ impl GenericParams { | |||
67 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 78 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
68 | self.params.iter().find(|p| &p.name == name) | 79 | self.params.iter().find(|p| &p.name == name) |
69 | } | 80 | } |
81 | |||
82 | pub fn count_parent_params(&self) -> usize { | ||
83 | self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) | ||
84 | } | ||
85 | |||
86 | pub fn count_params_including_parent(&self) -> usize { | ||
87 | let parent_count = self.count_parent_params(); | ||
88 | parent_count + self.params.len() | ||
89 | } | ||
70 | } | 90 | } |