From 9e8feeb94aaa9e215c07bf817b6481a0447aed18 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 17 Apr 2021 03:34:05 +0200 Subject: Fix `TestDB::module_at_position` with submodules --- crates/hir_def/src/find_path.rs | 23 +++++++++++++++++++ crates/hir_def/src/test_db.rs | 51 +++++++++++++++++++++++++++++++++++++++-- 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 41da3bc2d..2c4bbe585 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs @@ -954,6 +954,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); diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index dd36106f8..8fa703a57 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> { // Find the smallest (innermost) function in `def_map` containing the cursor. let mut size = None; -- cgit v1.2.3