diff options
Diffstat (limited to 'crates/ra_hir/src/generics.rs')
-rw-r--r-- | crates/ra_hir/src/generics.rs | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 5625c2459..1c71e21ea 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -5,11 +5,11 @@ | |||
5 | 5 | ||
6 | use std::sync::Arc; | 6 | use std::sync::Arc; |
7 | 7 | ||
8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; | 8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container | 12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef |
13 | }; | 13 | }; |
14 | 14 | ||
15 | /// Data about a generic parameter (to a function, struct, impl, ...). | 15 | /// Data about a generic parameter (to a function, struct, impl, ...). |
@@ -25,6 +25,15 @@ pub struct GenericParam { | |||
25 | pub struct GenericParams { | 25 | pub struct GenericParams { |
26 | pub(crate) parent_params: Option<Arc<GenericParams>>, | 26 | pub(crate) parent_params: Option<Arc<GenericParams>>, |
27 | pub(crate) params: Vec<GenericParam>, | 27 | pub(crate) params: Vec<GenericParam>, |
28 | pub(crate) where_predicates: Vec<WherePredicate>, | ||
29 | } | ||
30 | |||
31 | /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined | ||
32 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | ||
33 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
34 | pub struct WherePredicate { | ||
35 | type_ref: TypeRef, | ||
36 | trait_ref: Path, | ||
28 | } | 37 | } |
29 | 38 | ||
30 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) | 39 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) |
@@ -73,6 +82,9 @@ impl GenericParams { | |||
73 | if let Some(params) = node.type_param_list() { | 82 | if let Some(params) = node.type_param_list() { |
74 | self.fill_params(params, start) | 83 | self.fill_params(params, start) |
75 | } | 84 | } |
85 | if let Some(where_clause) = node.where_clause() { | ||
86 | self.fill_where_predicates(where_clause); | ||
87 | } | ||
76 | } | 88 | } |
77 | 89 | ||
78 | fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { | 90 | fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { |
@@ -83,6 +95,32 @@ impl GenericParams { | |||
83 | } | 95 | } |
84 | } | 96 | } |
85 | 97 | ||
98 | fn fill_where_predicates(&mut self, where_clause: &ast::WhereClause) { | ||
99 | for pred in where_clause.predicates() { | ||
100 | let type_ref = match pred.type_ref() { | ||
101 | Some(type_ref) => type_ref, | ||
102 | None => continue, | ||
103 | }; | ||
104 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | ||
105 | let path = bound | ||
106 | .type_ref() | ||
107 | .and_then(|tr| match tr.kind() { | ||
108 | ast::TypeRefKind::PathType(path) => path.path(), | ||
109 | _ => None, | ||
110 | }) | ||
111 | .and_then(Path::from_ast); | ||
112 | let path = match path { | ||
113 | Some(p) => p, | ||
114 | None => continue, | ||
115 | }; | ||
116 | self.where_predicates.push(WherePredicate { | ||
117 | type_ref: TypeRef::from_ast(type_ref), | ||
118 | trait_ref: path, | ||
119 | }); | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
86 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 124 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
87 | self.params.iter().find(|p| &p.name == name) | 125 | self.params.iter().find(|p| &p.name == name) |
88 | } | 126 | } |