aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs41
-rw-r--r--crates/hir_def/src/nameres/tests.rs62
-rw-r--r--crates/hir_def/src/nameres/tests/block.rs26
3 files changed, 109 insertions, 20 deletions
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index c1eded5f2..419e465ed 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -10,8 +10,6 @@
10//! 10//!
11//! `ReachedFixedPoint` signals about this. 11//! `ReachedFixedPoint` signals about this.
12 12
13use std::iter::successors;
14
15use base_db::Edition; 13use base_db::Edition;
16use hir_expand::name; 14use hir_expand::name;
17use hir_expand::name::Name; 15use hir_expand::name::Name;
@@ -131,8 +129,8 @@ impl DefMap {
131 result.krate = result.krate.or(new.krate); 129 result.krate = result.krate.or(new.krate);
132 result.segment_index = result.segment_index.min(new.segment_index); 130 result.segment_index = result.segment_index.min(new.segment_index);
133 131
134 match &current_map.parent { 132 match &current_map.block {
135 Some(map) => current_map = map, 133 Some(block) => current_map = &block.parent,
136 None => return result, 134 None => return result,
137 } 135 }
138 } 136 }
@@ -193,14 +191,35 @@ impl DefMap {
193 self.resolve_name_in_module(db, original_module, &segment, prefer_module) 191 self.resolve_name_in_module(db, original_module, &segment, prefer_module)
194 } 192 }
195 PathKind::Super(lvl) => { 193 PathKind::Super(lvl) => {
196 let m = successors(Some(original_module), |m| self.modules[*m].parent) 194 let mut module = original_module;
197 .nth(lvl as usize); 195 for i in 0..lvl {
198 if let Some(local_id) = m { 196 match self.modules[module].parent {
199 PerNs::types(self.module_id(local_id).into(), Visibility::Public) 197 Some(it) => module = it,
200 } else { 198 None => match &self.block {
201 log::debug!("super path in root module"); 199 Some(block) => {
202 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 200 // Look up remaining path in parent `DefMap`
201 let new_path = ModPath {
202 kind: PathKind::Super(lvl - i),
203 segments: path.segments.clone(),
204 };
205 log::debug!("`super` path: {} -> {} in parent map", path, new_path);
206 return block.parent.resolve_path_fp_with_macro(
207 db,
208 mode,
209 block.parent_module,
210 &new_path,
211 shadow,
212 );
213 }
214 None => {
215 log::debug!("super path in root module");
216 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
217 }
218 },
219 }
203 } 220 }
221
222 PerNs::types(self.module_id(module).into(), Visibility::Public)
204 } 223 }
205 PathKind::Abs => { 224 PathKind::Abs => {
206 // 2018-style absolute path -- only extern prelude 225 // 2018-style absolute path -- only extern prelude
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index 73e3a4702..b36d0b59b 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -8,12 +8,12 @@ mod block;
8 8
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use base_db::{fixture::WithFixture, SourceDatabase}; 11use base_db::{fixture::WithFixture, FilePosition, SourceDatabase};
12use expect_test::{expect, Expect}; 12use expect_test::{expect, Expect};
13use hir_expand::db::AstDatabase; 13use syntax::AstNode;
14use test_utils::mark; 14use test_utils::mark;
15 15
16use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 16use crate::{db::DefDatabase, nameres::*, test_db::TestDB, Lookup};
17 17
18fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { 18fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
19 let db = TestDB::with_files(ra_fixture); 19 let db = TestDB::with_files(ra_fixture);
@@ -23,14 +23,58 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
23 23
24fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { 24fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> {
25 let (db, position) = TestDB::with_position(ra_fixture); 25 let (db, position) = TestDB::with_position(ra_fixture);
26
27 // FIXME: perhaps we should make this use body lowering tests instead?
28
26 let module = db.module_for_file(position.file_id); 29 let module = db.module_for_file(position.file_id);
27 let ast_map = db.ast_id_map(position.file_id.into()); 30 let mut def_map = db.crate_def_map(module.krate);
28 let ast = db.parse(position.file_id); 31 while let Some(new_def_map) = descend_def_map_at_position(&db, position, def_map.clone()) {
29 let block: ast::BlockExpr = 32 def_map = new_def_map;
30 syntax::algo::find_node_at_offset(&ast.syntax_node(), position.offset).unwrap(); 33 }
31 let block_id = ast_map.ast_id(&block); 34
35 // FIXME: select the right module, not the root
36
37 def_map
38}
39
40fn descend_def_map_at_position(
41 db: &dyn DefDatabase,
42 position: FilePosition,
43 def_map: Arc<DefMap>,
44) -> Option<Arc<DefMap>> {
45 for (local_id, module_data) in def_map.modules() {
46 let mod_def = module_data.origin.definition_source(db);
47 let ast_map = db.ast_id_map(mod_def.file_id);
48 let item_tree = db.item_tree(mod_def.file_id);
49 let root = db.parse_or_expand(mod_def.file_id).unwrap();
50 for item in module_data.scope.declarations() {
51 match item {
52 ModuleDefId::FunctionId(it) => {
53 // Technically blocks can be inside any type (due to arrays and const generics),
54 // and also in const/static initializers. For tests we only really care about
55 // functions though.
56
57 let ast = ast_map.get(item_tree[it.lookup(db).id.value].ast_id).to_node(&root);
58
59 if ast.syntax().text_range().contains(position.offset) {
60 // Cursor inside function, descend into its body's DefMap.
61 // Note that we don't handle block *expressions* inside function bodies.
62 let ast_map = db.ast_id_map(position.file_id.into());
63 let ast_id = ast_map.ast_id(&ast.body().unwrap());
64 let block = BlockLoc {
65 ast_id: InFile::new(position.file_id.into(), ast_id),
66 module: def_map.module_id(local_id),
67 };
68 let block_id = db.intern_block(block);
69 return Some(db.block_def_map(block_id));
70 }
71 }
72 _ => continue,
73 }
74 }
75 }
32 76
33 db.block_def_map(module.krate, InFile::new(position.file_id.into(), block_id)) 77 None
34} 78}
35 79
36fn check(ra_fixture: &str, expect: Expect) { 80fn check(ra_fixture: &str, expect: Expect) {
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs
index 01d6326a7..470ca593e 100644
--- a/crates/hir_def/src/nameres/tests/block.rs
+++ b/crates/hir_def/src/nameres/tests/block.rs
@@ -95,3 +95,29 @@ fn outer() {
95 "#]], 95 "#]],
96 ); 96 );
97} 97}
98
99#[test]
100fn super_imports() {
101 check_at(
102 r#"
103mod module {
104 fn f() {
105 use super::Struct;
106 $0
107 }
108}
109
110struct Struct {}
111"#,
112 expect![[r#"
113 block scope
114 Struct: t
115 crate
116 Struct: t
117 module: t
118
119 crate::module
120 f: v
121 "#]],
122 );
123}