diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-08 15:01:19 +0000 |
---|---|---|
committer | Marcus Klaas de Vries <[email protected]> | 2019-01-10 13:32:56 +0000 |
commit | 978de5cf8bfd2ff82696fc8d5369b41e147431c3 (patch) | |
tree | 27a25a5f2fb20a4afffed97cbb5b678b251d254b /crates/ra_hir/src/code_model_impl | |
parent | aca14c591fea40b2f803bbf5f02c1571732348fb (diff) |
Implement type inference for enum variants
Diffstat (limited to 'crates/ra_hir/src/code_model_impl')
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 1cb408cff..d7d62e863 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -13,6 +13,7 @@ impl Module { | |||
13 | pub(crate) fn new(def_id: DefId) -> Self { | 13 | pub(crate) fn new(def_id: DefId) -> Self { |
14 | crate::code_model_api::Module { def_id } | 14 | crate::code_model_api::Module { def_id } |
15 | } | 15 | } |
16 | |||
16 | pub(crate) fn from_module_id( | 17 | pub(crate) fn from_module_id( |
17 | db: &impl HirDatabase, | 18 | db: &impl HirDatabase, |
18 | source_root_id: SourceRootId, | 19 | source_root_id: SourceRootId, |
@@ -85,6 +86,7 @@ impl Module { | |||
85 | let module_id = loc.module_id.crate_root(&module_tree); | 86 | let module_id = loc.module_id.crate_root(&module_tree); |
86 | Module::from_module_id(db, loc.source_root_id, module_id) | 87 | Module::from_module_id(db, loc.source_root_id, module_id) |
87 | } | 88 | } |
89 | |||
88 | /// Finds a child module with the specified name. | 90 | /// Finds a child module with the specified name. |
89 | pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 91 | pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { |
90 | let loc = self.def_id.loc(db); | 92 | let loc = self.def_id.loc(db); |
@@ -92,12 +94,14 @@ impl Module { | |||
92 | let child_id = ctry!(loc.module_id.child(&module_tree, name)); | 94 | let child_id = ctry!(loc.module_id.child(&module_tree, name)); |
93 | Module::from_module_id(db, loc.source_root_id, child_id).map(Some) | 95 | Module::from_module_id(db, loc.source_root_id, child_id).map(Some) |
94 | } | 96 | } |
97 | |||
95 | pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | 98 | pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { |
96 | let loc = self.def_id.loc(db); | 99 | let loc = self.def_id.loc(db); |
97 | let module_tree = db.module_tree(loc.source_root_id)?; | 100 | let module_tree = db.module_tree(loc.source_root_id)?; |
98 | let parent_id = ctry!(loc.module_id.parent(&module_tree)); | 101 | let parent_id = ctry!(loc.module_id.parent(&module_tree)); |
99 | Module::from_module_id(db, loc.source_root_id, parent_id).map(Some) | 102 | Module::from_module_id(db, loc.source_root_id, parent_id).map(Some) |
100 | } | 103 | } |
104 | |||
101 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 105 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
102 | pub fn scope_impl(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { | 106 | pub fn scope_impl(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { |
103 | let loc = self.def_id.loc(db); | 107 | let loc = self.def_id.loc(db); |
@@ -105,6 +109,7 @@ impl Module { | |||
105 | let res = item_map.per_module[&loc.module_id].clone(); | 109 | let res = item_map.per_module[&loc.module_id].clone(); |
106 | Ok(res) | 110 | Ok(res) |
107 | } | 111 | } |
112 | |||
108 | pub fn resolve_path_impl( | 113 | pub fn resolve_path_impl( |
109 | &self, | 114 | &self, |
110 | db: &impl HirDatabase, | 115 | db: &impl HirDatabase, |
@@ -126,7 +131,7 @@ impl Module { | |||
126 | ); | 131 | ); |
127 | 132 | ||
128 | let segments = &path.segments; | 133 | let segments = &path.segments; |
129 | for name in segments.iter() { | 134 | for (idx, name) in segments.iter().enumerate() { |
130 | let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { | 135 | let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { |
131 | r | 136 | r |
132 | } else { | 137 | } else { |
@@ -134,7 +139,35 @@ impl Module { | |||
134 | }; | 139 | }; |
135 | let module = match curr.resolve(db)? { | 140 | let module = match curr.resolve(db)? { |
136 | Def::Module(it) => it, | 141 | Def::Module(it) => it, |
137 | // TODO here would be the place to handle enum variants... | 142 | Def::Enum(e) => { |
143 | if segments.len() == idx + 1 { | ||
144 | // enum variant | ||
145 | let matching_variant = e.variants(db)?.map(|variants| { | ||
146 | variants | ||
147 | .into_iter() | ||
148 | // FIXME: replace by match lol | ||
149 | .find(|variant| { | ||
150 | variant | ||
151 | .name(db) | ||
152 | .map(|o| o.map(|ref n| n == name)) | ||
153 | .unwrap_or(Some(false)) | ||
154 | .unwrap_or(false) | ||
155 | }) | ||
156 | }); | ||
157 | |||
158 | if let Some(Some(variant)) = matching_variant { | ||
159 | return Ok(PerNs::both(variant.def_id(), e.def_id())); | ||
160 | } else { | ||
161 | return Ok(PerNs::none()); | ||
162 | } | ||
163 | } else if segments.len() == idx { | ||
164 | // enum | ||
165 | return Ok(PerNs::types(e.def_id())); | ||
166 | } else { | ||
167 | // malformed enum? | ||
168 | return Ok(PerNs::none()); | ||
169 | } | ||
170 | } | ||
138 | _ => return Ok(PerNs::none()), | 171 | _ => return Ok(PerNs::none()), |
139 | }; | 172 | }; |
140 | let scope = module.scope(db)?; | 173 | let scope = module.scope(db)?; |
@@ -146,6 +179,7 @@ impl Module { | |||
146 | } | 179 | } |
147 | Ok(curr_per_ns) | 180 | Ok(curr_per_ns) |
148 | } | 181 | } |
182 | |||
149 | pub fn problems_impl( | 183 | pub fn problems_impl( |
150 | &self, | 184 | &self, |
151 | db: &impl HirDatabase, | 185 | db: &impl HirDatabase, |