diff options
Diffstat (limited to 'crates/ra_hir/src/generics.rs')
-rw-r--r-- | crates/ra_hir/src/generics.rs | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index d8248ad49..88c53705f 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -5,9 +5,9 @@ | |||
5 | 5 | ||
6 | use std::sync::Arc; | 6 | use std::sync::Arc; |
7 | 7 | ||
8 | use ra_syntax::ast::{TypeParamList, AstNode, NameOwner}; | 8 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; |
9 | 9 | ||
10 | use crate::{db::HirDatabase, DefId, Name, AsName}; | 10 | use crate::{db::HirDatabase, DefId, Name, AsName, Function}; |
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)] |
@@ -22,26 +22,62 @@ pub struct GenericParams { | |||
22 | pub(crate) params: Vec<GenericParam>, | 22 | pub(crate) params: Vec<GenericParam>, |
23 | } | 23 | } |
24 | 24 | ||
25 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||
26 | pub enum GenericDef { | ||
27 | Function(Function), | ||
28 | Def(DefId), | ||
29 | } | ||
30 | |||
31 | impl From<Function> for GenericDef { | ||
32 | fn from(func: Function) -> GenericDef { | ||
33 | GenericDef::Function(func) | ||
34 | } | ||
35 | } | ||
36 | |||
37 | impl From<DefId> for GenericDef { | ||
38 | fn from(def_id: DefId) -> GenericDef { | ||
39 | GenericDef::Def(def_id) | ||
40 | } | ||
41 | } | ||
42 | |||
25 | impl GenericParams { | 43 | impl GenericParams { |
26 | pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> { | 44 | pub(crate) fn generic_params_query( |
27 | let (_file_id, node) = def_id.source(db); | 45 | db: &impl HirDatabase, |
46 | def: GenericDef, | ||
47 | ) -> Arc<GenericParams> { | ||
28 | let mut generics = GenericParams::default(); | 48 | let mut generics = GenericParams::default(); |
29 | if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { | 49 | match def { |
30 | for (idx, type_param) in type_param_list.type_params().enumerate() { | 50 | GenericDef::Function(func) => { |
31 | let name = type_param | 51 | let (_, fn_def) = func.source(db); |
32 | .name() | 52 | if let Some(type_param_list) = fn_def.type_param_list() { |
33 | .map(AsName::as_name) | 53 | generics.fill(type_param_list) |
34 | .unwrap_or_else(Name::missing); | 54 | } |
35 | let param = GenericParam { | 55 | } |
36 | idx: idx as u32, | 56 | GenericDef::Def(def_id) => { |
37 | name, | 57 | let (_file_id, node) = def_id.source(db); |
38 | }; | 58 | if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { |
39 | generics.params.push(param); | 59 | generics.fill(type_param_list) |
60 | } | ||
40 | } | 61 | } |
41 | } | 62 | } |
63 | |||
42 | Arc::new(generics) | 64 | Arc::new(generics) |
43 | } | 65 | } |
44 | 66 | ||
67 | fn fill(&mut self, params: &ast::TypeParamList) { | ||
68 | for (idx, type_param) in params.type_params().enumerate() { | ||
69 | let name = type_param | ||
70 | .name() | ||
71 | .map(AsName::as_name) | ||
72 | .unwrap_or_else(Name::missing); | ||
73 | let param = GenericParam { | ||
74 | idx: idx as u32, | ||
75 | name, | ||
76 | }; | ||
77 | self.params.push(param); | ||
78 | } | ||
79 | } | ||
80 | |||
45 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 81 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
46 | self.params.iter().find(|p| &p.name == name) | 82 | self.params.iter().find(|p| &p.name == name) |
47 | } | 83 | } |