⬆️ rust-analyzer

Merge commit '368e0bb32f'
This commit is contained in:
arcnmx 2023-01-09 10:36:22 -08:00
parent b3ef934ccb
commit 25242fe93f
395 changed files with 14569 additions and 5755 deletions

View file

@ -107,7 +107,7 @@ fn find_path_inner(
}
// - if the item is in the prelude, return the name from there
if let Some(value) = find_in_prelude(db, &crate_root.def_map(db), item, from) {
if let value @ Some(_) = find_in_prelude(db, &crate_root.def_map(db), &def_map, item, from) {
return value;
}
@ -176,7 +176,7 @@ fn find_path_for_module(
// - if relative paths are fine, check if we are searching for a parent
if prefixed.filter(PrefixKind::is_absolute).is_none() {
if let modpath @ Some(_) = find_self_super(&def_map, module_id, from) {
if let modpath @ Some(_) = find_self_super(def_map, module_id, from) {
return modpath;
}
}
@ -205,7 +205,8 @@ fn find_path_for_module(
}
}
if let Some(value) = find_in_prelude(db, &root_def_map, ItemInNs::Types(module_id.into()), from)
if let value @ Some(_) =
find_in_prelude(db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from)
{
return value;
}
@ -234,23 +235,41 @@ fn find_in_scope(
})
}
/// Returns single-segment path (i.e. without any prefix) if `item` is found in prelude and its
/// name doesn't clash in current scope.
fn find_in_prelude(
db: &dyn DefDatabase,
root_def_map: &DefMap,
local_def_map: &DefMap,
item: ItemInNs,
from: ModuleId,
) -> Option<Option<ModPath>> {
if let Some(prelude_module) = root_def_map.prelude() {
// Preludes in block DefMaps are ignored, only the crate DefMap is searched
let prelude_def_map = prelude_module.def_map(db);
let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
if let Some((name, vis)) = prelude_scope.name_of(item) {
if vis.is_visible_from(db, from) {
return Some(Some(ModPath::from_segments(PathKind::Plain, Some(name.clone()))));
}
}
) -> Option<ModPath> {
let prelude_module = root_def_map.prelude()?;
// Preludes in block DefMaps are ignored, only the crate DefMap is searched
let prelude_def_map = prelude_module.def_map(db);
let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
let (name, vis) = prelude_scope.name_of(item)?;
if !vis.is_visible_from(db, from) {
return None;
}
// Check if the name is in current scope and it points to the same def.
let found_and_same_def =
local_def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
let per_ns = def_map[local_id].scope.get(name);
let same_def = match item {
ItemInNs::Types(it) => per_ns.take_types()? == it,
ItemInNs::Values(it) => per_ns.take_values()? == it,
ItemInNs::Macros(it) => per_ns.take_macros()? == it,
};
Some(same_def)
});
if found_and_same_def.unwrap_or(true) {
Some(ModPath::from_segments(PathKind::Plain, Some(name.clone())))
} else {
None
}
None
}
fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option<ModPath> {
@ -512,7 +531,7 @@ mod tests {
fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKind>) {
let (db, pos) = TestDB::with_position(ra_fixture);
let module = db.module_at_position(pos);
let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path));
let parsed_path_file = syntax::SourceFile::parse(&format!("use {path};"));
let ast_path =
parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
let mod_path = ModPath::from_src(&db, ast_path, &Hygiene::new_unhygienic()).unwrap();
@ -531,7 +550,7 @@ mod tests {
let found_path =
find_path_inner(&db, ItemInNs::Types(resolved), module, prefix_kind, false);
assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind);
assert_eq!(found_path, Some(mod_path), "{prefix_kind:?}");
}
fn check_found_path(
@ -808,6 +827,48 @@ pub mod prelude {
);
}
#[test]
fn shadowed_prelude() {
check_found_path(
r#"
//- /main.rs crate:main deps:std
struct S;
$0
//- /std.rs crate:std
pub mod prelude {
pub mod rust_2018 {
pub struct S;
}
}
"#,
"std::prelude::rust_2018::S",
"std::prelude::rust_2018::S",
"std::prelude::rust_2018::S",
"std::prelude::rust_2018::S",
);
}
#[test]
fn imported_prelude() {
check_found_path(
r#"
//- /main.rs crate:main deps:std
use S;
$0
//- /std.rs crate:std
pub mod prelude {
pub mod rust_2018 {
pub struct S;
}
}
"#,
"S",
"S",
"S",
"S",
);
}
#[test]
fn enum_variant_from_prelude() {
let code = r#"