Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/attrs.rs11
-rw-r--r--crates/hir-def/src/attrs/docs.rs68
-rw-r--r--crates/ide/src/hover/tests.rs54
3 files changed, 43 insertions, 90 deletions
diff --git a/crates/hir-def/src/attrs.rs b/crates/hir-def/src/attrs.rs
index 3dbbafdd51..aa7dad8bf1 100644
--- a/crates/hir-def/src/attrs.rs
+++ b/crates/hir-def/src/attrs.rs
@@ -965,20 +965,13 @@ impl AttrFlags {
pub fn docs(db: &dyn DefDatabase, owner: AttrDefId) -> Option<Box<Docs>> {
let (source, outer_mod_decl, _extra_crate_attrs, krate) = attrs_source(db, owner);
let inner_attrs_node = source.value.inner_attributes_node();
- let parent = if outer_mod_decl.is_some()
- && let AttrDefId::ModuleId(module_id) = owner
- {
- module_id.containing_module(db)
- } else {
- None
- };
// Note: we don't have to pass down `_extra_crate_attrs` here, since `extract_docs`
// does not handle crate-level attributes related to docs.
// See: https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html#at-the-crate-level
self::docs::extract_docs(
db,
krate,
- &|| (parent.map(|it| it.resolver(db)), resolver_for_attr_def_id(db, owner)),
+ &|| resolver_for_attr_def_id(db, owner),
&|| krate.cfg_options(db),
source,
outer_mod_decl,
@@ -1001,7 +994,7 @@ impl AttrFlags {
self::docs::extract_docs(
db,
krate,
- &|| (None, variant.resolver(db)),
+ &|| variant.resolver(db),
&|| cfg_options,
field,
None,
diff --git a/crates/hir-def/src/attrs/docs.rs b/crates/hir-def/src/attrs/docs.rs
index 16e813bc5f..a0665dfecd 100644
--- a/crates/hir-def/src/attrs/docs.rs
+++ b/crates/hir-def/src/attrs/docs.rs
@@ -418,10 +418,10 @@ fn extend_with_attrs<'a, 'db>(
indent: &mut usize,
get_cfg_options: &dyn Fn() -> &'a CfgOptions,
cfg_options: &mut Option<&'a CfgOptions>,
- make_resolver: &dyn Fn() -> Option<Resolver<'db>>,
+ make_resolver: &dyn Fn() -> Resolver<'db>,
) {
// Lazily initialised when we first encounter a `#[doc = macro!()]`.
- let mut expander: Option<Option<(DocMacroExpander<'db>, DocExprSourceCtx<'db>)>> = None;
+ let mut expander: Option<(DocMacroExpander<'db>, DocExprSourceCtx<'db>)> = None;
// FIXME: `#[cfg_attr(..., doc = macro!())]` skips macro expansion because
// `top_attr` points to the `cfg_attr` node, not the inner `doc = macro!()`.
@@ -457,32 +457,31 @@ fn extend_with_attrs<'a, 'db>(
top_attr.as_simple_call().is_some_and(|(name, _)| name == "cfg_attr");
if !is_from_cfg_attr
&& let Some(expr) = top_attr.expr()
- && let Some((exp, ctx)) = expander
- .get_or_insert_with(|| {
- make_resolver().map(|resolver| {
- let def_map = resolver.top_level_def_map();
- let recursion_limit = def_map.recursion_limit() as usize;
- (
- DocMacroExpander {
- db,
- krate,
- recursion_depth: 0,
- recursion_limit,
- },
- DocExprSourceCtx {
- resolver,
- file_id,
- ast_id_map: db.ast_id_map(file_id),
- span_map: db.span_map(file_id),
- },
- )
- })
- })
- .as_mut()
- && let Some(expanded) =
- expand_doc_expr_via_macro_pipeline(exp, ctx, expr)
{
- result.extend_with_unmapped_doc_str(&expanded, indent);
+ let (exp, ctx) = expander.get_or_insert_with(|| {
+ let resolver = make_resolver();
+ let def_map = resolver.top_level_def_map();
+ let recursion_limit = def_map.recursion_limit() as usize;
+ (
+ DocMacroExpander {
+ db,
+ krate,
+ recursion_depth: 0,
+ recursion_limit,
+ },
+ DocExprSourceCtx {
+ resolver,
+ file_id,
+ ast_id_map: db.ast_id_map(file_id),
+ span_map: db.span_map(file_id),
+ },
+ )
+ });
+ if let Some(expanded) =
+ expand_doc_expr_via_macro_pipeline(exp, ctx, expr)
+ {
+ result.extend_with_unmapped_doc_str(&expanded, indent);
+ }
}
}
_ => {}
@@ -496,10 +495,7 @@ fn extend_with_attrs<'a, 'db>(
pub(crate) fn extract_docs<'a, 'db>(
db: &'db dyn DefDatabase,
krate: Crate,
- // Returns (outer_resolver, inline_resolver).
- // `outer_resolver` is `Some` only for outlined modules (`mod foo;`) where outer docs
- // should be resolved in the parent module's scope.
- resolvers: &dyn Fn() -> (Option<Resolver<'db>>, Resolver<'db>),
+ resolver: &dyn Fn() -> Resolver<'db>,
get_cfg_options: &dyn Fn() -> &'a CfgOptions,
source: InFile<ast::AnyHasAttrs>,
outer_mod_decl: Option<InFile<ast::Module>>,
@@ -519,8 +515,7 @@ pub(crate) fn extract_docs<'a, 'db>(
if let Some(outer_mod_decl) = outer_mod_decl {
let mut indent = usize::MAX;
- // For outer docs (the `mod foo;` declaration), use the parent module's resolver
- // so that macros are resolved in the parent's scope.
+ // For outer docs (the `mod foo;` declaration), use the module's own resolver.
extend_with_attrs(
&mut result,
db,
@@ -531,7 +526,7 @@ pub(crate) fn extract_docs<'a, 'db>(
&mut indent,
get_cfg_options,
&mut cfg_options,
- &|| resolvers().0,
+ resolver,
);
result.remove_indent(indent, 0);
result.outline_mod = Some((outer_mod_decl.file_id, result.docs_source_map.len()));
@@ -539,7 +534,6 @@ pub(crate) fn extract_docs<'a, 'db>(
let inline_source_map_start = result.docs_source_map.len();
let mut indent = usize::MAX;
- let inline_resolver = &|| Some(resolvers().1);
// For inline docs, use the item's own resolver.
extend_with_attrs(
&mut result,
@@ -551,7 +545,7 @@ pub(crate) fn extract_docs<'a, 'db>(
&mut indent,
get_cfg_options,
&mut cfg_options,
- inline_resolver,
+ resolver,
);
if let Some(inner_attrs_node) = &inner_attrs_node {
result.inline_inner_docs_start = Some(TextSize::of(&result.docs));
@@ -565,7 +559,7 @@ pub(crate) fn extract_docs<'a, 'db>(
&mut indent,
get_cfg_options,
&mut cfg_options,
- inline_resolver,
+ resolver,
);
}
result.remove_indent(indent, inline_source_map_start);
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 2ca43096dd..882aa041ce 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -11660,18 +11660,21 @@ struct Bar {
}
#[test]
-fn test_hover_doc_attr_macro_on_outlined_mod_resolves_from_parent() {
- // Outer doc-macro on `mod foo;` should resolve from the parent module,
- // and combine with inner `//!` docs from the module file.
+fn test_hover_doc_attr_macro_on_outlined_mod() {
+ // Outer doc-macro on `mod foo;` resolves from inside the module's scope
+ // (matching rustc behavior), and combines with inner `//!` docs from the module file.
check(
r#"
//- /main.rs
-macro_rules! doc_str {
- () => { "expanded from parent" };
+mod mac {
+ macro_rules! doc_str {
+ () => { "expanded from macro" };
+ }
+ pub(crate) use doc_str;
}
/// plain outer doc
-#[doc = doc_str!()]
+#[doc = super::mac::doc_str!()]
mod foo$0;
//- /foo.rs
@@ -11692,45 +11695,8 @@ pub struct Bar;
---
plain outer doc
- expanded from parent
+ expanded from macro
inner module docs
"#]],
);
}
-
-#[test]
-fn test_hover_doc_attr_inner_doc_macro() {
- // Inner doc attribute with macro expansion (`#![doc = macro!()]`)
- check(
- r#"
-macro_rules! doc_str {
- () => { "inner doc from macro" };
-}
-
-/// outer doc
-///
-mod foo$0 {
- #![doc = doc_str!()]
-
- pub struct Bar;
-}
-"#,
- expect![[r#"
- *foo*
-
- ```rust
- ra_test_fixture
- ```
-
- ```rust
- mod foo
- ```
-
- ---
-
- outer doc
-
- inner doc from macro
- "#]],
- );
-}