diff options
Diffstat (limited to 'crates/ra_hir/src/generics.rs')
-rw-r--r-- | crates/ra_hir/src/generics.rs | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index d8248ad49..64c20a462 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, NameOwner, TypeParamsOwner}; |
9 | 9 | ||
10 | use crate::{db::HirDatabase, DefId, Name, AsName}; | 10 | use crate::{db::HirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type}; |
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,53 @@ 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 | Struct(Struct), | ||
29 | Enum(Enum), | ||
30 | Trait(Trait), | ||
31 | Type(Type), | ||
32 | } | ||
33 | impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type); | ||
34 | |||
25 | impl GenericParams { | 35 | impl GenericParams { |
26 | pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> { | 36 | pub(crate) fn generic_params_query( |
27 | let (_file_id, node) = def_id.source(db); | 37 | db: &impl HirDatabase, |
38 | def: GenericDef, | ||
39 | ) -> Arc<GenericParams> { | ||
28 | let mut generics = GenericParams::default(); | 40 | let mut generics = GenericParams::default(); |
29 | if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { | 41 | match def { |
30 | for (idx, type_param) in type_param_list.type_params().enumerate() { | 42 | GenericDef::Function(it) => generics.fill(&*it.source(db).1), |
31 | let name = type_param | 43 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1), |
32 | .name() | 44 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1), |
33 | .map(AsName::as_name) | 45 | GenericDef::Trait(it) => generics.fill(&*it.source(db).1), |
34 | .unwrap_or_else(Name::missing); | 46 | GenericDef::Type(it) => generics.fill(&*it.source(db).1), |
35 | let param = GenericParam { | ||
36 | idx: idx as u32, | ||
37 | name, | ||
38 | }; | ||
39 | generics.params.push(param); | ||
40 | } | ||
41 | } | 47 | } |
48 | |||
42 | Arc::new(generics) | 49 | Arc::new(generics) |
43 | } | 50 | } |
44 | 51 | ||
52 | fn fill(&mut self, node: &impl TypeParamsOwner) { | ||
53 | if let Some(params) = node.type_param_list() { | ||
54 | self.fill_params(params) | ||
55 | } | ||
56 | } | ||
57 | |||
58 | fn fill_params(&mut self, params: &ast::TypeParamList) { | ||
59 | for (idx, type_param) in params.type_params().enumerate() { | ||
60 | let name = type_param | ||
61 | .name() | ||
62 | .map(AsName::as_name) | ||
63 | .unwrap_or_else(Name::missing); | ||
64 | let param = GenericParam { | ||
65 | idx: idx as u32, | ||
66 | name, | ||
67 | }; | ||
68 | self.params.push(param); | ||
69 | } | ||
70 | } | ||
71 | |||
45 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 72 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
46 | self.params.iter().find(|p| &p.name == name) | 73 | self.params.iter().find(|p| &p.name == name) |
47 | } | 74 | } |