about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-17 01:35:22 +0000
committerGitHub <noreply@github.com>2021-04-17 01:35:22 +0000
commitdf5b6f7d459a367b191d5d540c7363d9e526eadf (patch)
treeffb5f57b1d989cbd94be19eae42ca091b060a4e3
parent52585df24aed2c02c17b89913f5a5365b2e76e75 (diff)
parent9e8feeb94aaa9e215c07bf817b6481a0447aed18 (diff)
downloadrust-df5b6f7d459a367b191d5d540c7363d9e526eadf.tar.gz
rust-df5b6f7d459a367b191d5d540c7363d9e526eadf.zip
Merge #8549
8549: Fix `TestDB::module_at_position` with submodules r=jonas-schievink a=jonas-schievink

Found while looking into https://github.com/rust-analyzer/rust-analyzer/issues/8519

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
-rw-r--r--crates/hir_def/src/find_path.rs23
-rw-r--r--crates/hir_def/src/test_db.rs51
2 files changed, 72 insertions, 2 deletions
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index 41da3bc2d42..2c4bbe585ea 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -955,6 +955,29 @@ fn main() {
     }
 
     #[test]
+    fn from_inside_module() {
+        // This worked correctly, but the test suite logic was broken.
+        cov_mark::check!(submodule_in_testdb);
+        check_found_path(
+            r#"
+mod baz {
+    pub struct Foo {}
+}
+
+mod bar {
+    fn bar() {
+        $0
+    }
+}
+            "#,
+            "crate::baz::Foo",
+            "crate::baz::Foo",
+            "crate::baz::Foo",
+            "crate::baz::Foo",
+        )
+    }
+
+    #[test]
     fn recursive_pub_mod_reexport() {
         cov_mark::check!(recursive_imports);
         check_found_path(
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index dd36106f8d2..8fa703a574e 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -15,7 +15,12 @@ use rustc_hash::FxHashSet;
 use syntax::{algo, ast, AstNode, TextRange, TextSize};
 use test_utils::extract_annotations;
 
-use crate::{db::DefDatabase, nameres::DefMap, src::HasSource, Lookup, ModuleDefId, ModuleId};
+use crate::{
+    db::DefDatabase,
+    nameres::{DefMap, ModuleSource},
+    src::HasSource,
+    LocalModuleId, Lookup, ModuleDefId, ModuleId,
+};
 
 #[salsa::database(
     base_db::SourceDatabaseExtStorage,
@@ -87,10 +92,11 @@ impl TestDB {
     pub(crate) fn module_at_position(&self, position: FilePosition) -> ModuleId {
         let file_module = self.module_for_file(position.file_id);
         let mut def_map = file_module.def_map(self);
+        let module = self.mod_at_position(&def_map, position);
 
         def_map = match self.block_at_position(&def_map, position) {
             Some(it) => it,
-            None => return file_module,
+            None => return def_map.module_id(module),
         };
         loop {
             let new_map = self.block_at_position(&def_map, position);
@@ -106,6 +112,47 @@ impl TestDB {
         }
     }
 
+    /// Finds the smallest/innermost module in `def_map` containing `position`.
+    fn mod_at_position(&self, def_map: &DefMap, position: FilePosition) -> LocalModuleId {
+        let mut size = None;
+        let mut res = def_map.root();
+        for (module, data) in def_map.modules() {
+            let src = data.definition_source(self);
+            if src.file_id != position.file_id.into() {
+                continue;
+            }
+
+            let range = match src.value {
+                ModuleSource::SourceFile(it) => it.syntax().text_range(),
+                ModuleSource::Module(it) => it.syntax().text_range(),
+                ModuleSource::BlockExpr(it) => it.syntax().text_range(),
+            };
+
+            if !range.contains(position.offset) {
+                continue;
+            }
+
+            let new_size = match size {
+                None => range.len(),
+                Some(size) => {
+                    if range.len() < size {
+                        range.len()
+                    } else {
+                        size
+                    }
+                }
+            };
+
+            if size != Some(new_size) {
+                cov_mark::hit!(submodule_in_testdb);
+                size = Some(new_size);
+                res = module;
+            }
+        }
+
+        res
+    }
+
     fn block_at_position(&self, def_map: &DefMap, position: FilePosition) -> Option<Arc<DefMap>> {
         // Find the smallest (innermost) function in `def_map` containing the cursor.
         let mut size = None;