Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/lib.rs5
-rw-r--r--crates/ide-completion/src/context.rs10
-rw-r--r--crates/ide/src/hover/render.rs12
-rw-r--r--crates/ide/src/hover/tests.rs26
4 files changed, 46 insertions, 7 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index e2cf5b0789..32b14c383a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -497,10 +497,9 @@ impl Module {
/// Finds a parent module.
pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
- // FIXME: handle block expressions as modules (their parent is in a different DefMap)
let def_map = self.id.def_map(db.upcast());
- let parent_id = def_map[self.id.local_id].parent?;
- Some(Module { id: def_map.module_id(parent_id) })
+ let parent_id = def_map.containing_module(self.id.local_id)?;
+ Some(Module { id: parent_id })
}
/// Finds nearest non-block ancestor `Module` (`self` included).
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 192f1b43fa..e49a9e3b06 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -7,7 +7,8 @@ mod tests;
use std::{iter, ops::ControlFlow};
use hir::{
- HasAttrs, Local, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo,
+ HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type,
+ TypeInfo,
};
use ide_db::{
base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition,
@@ -743,7 +744,12 @@ impl<'a> CompletionContext<'a> {
}
});
- let depth_from_crate_root = iter::successors(module.parent(db), |m| m.parent(db)).count();
+ let depth_from_crate_root = iter::successors(Some(module), |m| m.parent(db))
+ // `BlockExpr` modules are not count as module depth
+ .filter(|m| !matches!(m.definition_source(db).value, ModuleSource::BlockExpr(_)))
+ .count()
+ // exclude `m` itself
+ .saturating_sub(1);
let complete_semicolon = if config.add_semicolon_to_unit {
let inside_closure_ret = token.parent_ancestors().try_for_each(|ancestor| {
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 5a8c9a9f11..01fa316d5f 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -3,7 +3,7 @@ use std::{mem, ops::Not};
use either::Either;
use hir::{
- db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind,
+ db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, AssocItemContainer, CaptureKind,
DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError,
MethodViolationCode, Name, Semantics, Trait, Type, TypeInfo,
};
@@ -813,7 +813,15 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) ->
if matches!(def, Definition::GenericParam(_) | Definition::Local(_) | Definition::Label(_)) {
return None;
}
- def.module(db).map(|module| path(db, module, definition_owner_name(db, def, edition), edition))
+ let container: Option<Definition> =
+ def.as_assoc_item(db).and_then(|assoc| match assoc.container(db) {
+ AssocItemContainer::Trait(trait_) => Some(trait_.into()),
+ AssocItemContainer::Impl(impl_) => impl_.self_ty(db).as_adt().map(|adt| adt.into()),
+ });
+ container
+ .unwrap_or(*def)
+ .module(db)
+ .map(|module| path(db, module, definition_owner_name(db, def, edition), edition))
}
fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup {
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index db2b98090c..e60be577f7 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -8962,3 +8962,29 @@ fn test_hover_function_with_pat_param() {
"#]],
);
}
+
+#[test]
+fn hover_path_inside_block_scope() {
+ check(
+ r#"
+mod m {
+ const _: () = {
+ mod m2 {
+ const C$0: () = ();
+ }
+ };
+}
+"#,
+ expect![[r#"
+ *C*
+
+ ```rust
+ test::m::m2
+ ```
+
+ ```rust
+ const C: () = ()
+ ```
+ "#]],
+ );
+}