aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres/tests.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-01-25 18:24:04 +0000
committerGitHub <[email protected]>2021-01-25 18:24:04 +0000
commita37091d2d0175b0999d6383d48f538cdbf0267a0 (patch)
tree06981374f0c397b45e31b74c97ed337853fe59d2 /crates/hir_def/src/nameres/tests.rs
parent2c735ed734be9b9041921478e0049fffd7160f78 (diff)
parent08253d5473348e2f3061e0c8d84c62de537a5821 (diff)
Merge #7431
7431: Handle `super` paths inside blocks correctly r=jonas-schievink a=jonas-schievink We now intern `BlockLoc` and use `BlockId` to refer to block expressions. This is needed to keep `ModuleId` simple, since it would otherwise have to store an arbitrarily long chain of blocks and couldn't be `Copy`. The `DefMap` hierarchy is now created as the caller descends into an item body. This is necessary to link the correct module as the block's parent, which is important for correct name resolution. As a result, we can now resolve `super` paths inside block expressions by climbing the `DefMap` chain. bors r+ Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_def/src/nameres/tests.rs')
-rw-r--r--crates/hir_def/src/nameres/tests.rs62
1 files changed, 53 insertions, 9 deletions
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) {