aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model_impl
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model_impl')
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs81
1 files changed, 44 insertions, 37 deletions
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index e5394d440..73c212de8 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -95,7 +95,7 @@ impl Module {
95 } 95 }
96 96
97 /// Finds a child module with the specified name. 97 /// Finds a child module with the specified name.
98 pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { 98 pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
99 let loc = self.def_id.loc(db); 99 let loc = self.def_id.loc(db);
100 let module_tree = db.module_tree(loc.source_root_id); 100 let module_tree = db.module_tree(loc.source_root_id);
101 let child_id = loc.module_id.child(&module_tree, name)?; 101 let child_id = loc.module_id.child(&module_tree, name)?;
@@ -103,7 +103,7 @@ impl Module {
103 } 103 }
104 104
105 /// Iterates over all child modules. 105 /// Iterates over all child modules.
106 pub fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> { 106 pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> {
107 // FIXME this should be implementable without collecting into a vec, but 107 // FIXME this should be implementable without collecting into a vec, but
108 // it's kind of hard since the iterator needs to keep a reference to the 108 // it's kind of hard since the iterator needs to keep a reference to the
109 // module tree. 109 // module tree.
@@ -117,7 +117,7 @@ impl Module {
117 children.into_iter() 117 children.into_iter()
118 } 118 }
119 119
120 pub fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> { 120 pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> {
121 let loc = self.def_id.loc(db); 121 let loc = self.def_id.loc(db);
122 let module_tree = db.module_tree(loc.source_root_id); 122 let module_tree = db.module_tree(loc.source_root_id);
123 let parent_id = loc.module_id.parent(&module_tree)?; 123 let parent_id = loc.module_id.parent(&module_tree)?;
@@ -125,13 +125,13 @@ impl Module {
125 } 125 }
126 126
127 /// Returns a `ModuleScope`: a set of items, visible in this module. 127 /// Returns a `ModuleScope`: a set of items, visible in this module.
128 pub fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope { 128 pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope {
129 let loc = self.def_id.loc(db); 129 let loc = self.def_id.loc(db);
130 let item_map = db.item_map(loc.source_root_id); 130 let item_map = db.item_map(loc.source_root_id);
131 item_map.per_module[&loc.module_id].clone() 131 item_map.per_module[&loc.module_id].clone()
132 } 132 }
133 133
134 pub fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> { 134 pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> {
135 let mut curr_per_ns = PerNs::types( 135 let mut curr_per_ns = PerNs::types(
136 match path.kind { 136 match path.kind {
137 PathKind::Crate => self.crate_root(db), 137 PathKind::Crate => self.crate_root(db),
@@ -147,47 +147,54 @@ impl Module {
147 .def_id, 147 .def_id,
148 ); 148 );
149 149
150 let segments = &path.segments; 150 for segment in path.segments.iter() {
151 for (idx, name) in segments.iter().enumerate() { 151 let curr = match curr_per_ns.as_ref().take_types() {
152 let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { 152 Some(r) => r,
153 r 153 None => {
154 } else { 154 // we still have path segments left, but the path so far
155 return PerNs::none(); 155 // didn't resolve in the types namespace => no resolution
156 // (don't break here because curr_per_ns might contain
157 // something in the value namespace, and it would be wrong
158 // to return that)
159 return PerNs::none();
160 }
156 }; 161 };
157 let module = match curr.resolve(db) { 162 // resolve segment in curr
158 Def::Module(it) => it, 163 curr_per_ns = match curr.resolve(db) {
164 Def::Module(m) => {
165 let scope = m.scope(db);
166 match scope.get(&segment.name) {
167 Some(r) => r.def_id,
168 None => PerNs::none(),
169 }
170 }
159 Def::Enum(e) => { 171 Def::Enum(e) => {
160 if segments.len() == idx + 1 { 172 // enum variant
161 // enum variant 173 let matching_variant = e
162 let matching_variant = 174 .variants(db)
163 e.variants(db).into_iter().find(|(n, _variant)| n == name); 175 .into_iter()
164 176 .find(|(n, _variant)| n == &segment.name);
165 if let Some((_n, variant)) = matching_variant { 177
166 return PerNs::both(variant.def_id(), e.def_id()); 178 match matching_variant {
167 } else { 179 Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()),
168 return PerNs::none(); 180 None => PerNs::none(),
169 }
170 } else if segments.len() == idx {
171 // enum
172 return PerNs::types(e.def_id());
173 } else {
174 // malformed enum?
175 return PerNs::none();
176 } 181 }
177 } 182 }
178 _ => return PerNs::none(), 183 _ => {
179 }; 184 // could be an inherent method call in UFCS form
180 let scope = module.scope(db); 185 // (`Struct::method`), or some other kind of associated
181 curr_per_ns = if let Some(r) = scope.get(&name) { 186 // item... Which we currently don't handle (TODO)
182 r.def_id 187 PerNs::none()
183 } else { 188 }
184 return PerNs::none();
185 }; 189 };
186 } 190 }
187 curr_per_ns 191 curr_per_ns
188 } 192 }
189 193
190 pub fn problems_impl(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { 194 pub(crate) fn problems_impl(
195 &self,
196 db: &impl HirDatabase,
197 ) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
191 let loc = self.def_id.loc(db); 198 let loc = self.def_id.loc(db);
192 let module_tree = db.module_tree(loc.source_root_id); 199 let module_tree = db.module_tree(loc.source_root_id);
193 loc.module_id.problems(&module_tree, db) 200 loc.module_id.problems(&module_tree, db)