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>
This commit is contained in:
commit
df5b6f7d45
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user