Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/hover.rs')
-rw-r--r--crates/ide/src/hover.rs97
1 files changed, 64 insertions, 33 deletions
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 4e57484c78..4b7043bd9b 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -20,10 +20,7 @@ use syntax::{
use crate::{
display::{macro_label, TryToNav},
- doc_links::{
- doc_attributes, extract_definitions_from_docs, remove_links, resolve_doc_path_for_def,
- rewrite_links,
- },
+ doc_links::{remove_links, rewrite_links, token_as_doc_comment},
markdown_remove::remove_markdown,
markup::Markup,
runnables::{runnable_fn, runnable_mod},
@@ -114,40 +111,15 @@ pub(crate) fn hover(
_ => 1,
})?;
- let descended = sema.descend_into_macros_many(original_token.clone());
-
- // FIXME handle doc attributes? TokenMap currently doesn't work with comments
- if original_token.kind() == COMMENT {
- let relative_comment_offset = offset - original_token.text_range().start();
- // intra-doc links
+ if let Some(doc_comment) = token_as_doc_comment(&original_token) {
cov_mark::hit!(no_highlight_on_comment_hover);
- return descended.iter().find_map(|t| {
- match t.kind() {
- COMMENT => (),
- TOKEN_TREE => {}
- _ => return None,
- }
- let node = t.parent()?;
- let absolute_comment_offset = t.text_range().start() + relative_comment_offset;
- let (attributes, def) = doc_attributes(sema, &node)?;
- let (docs, doc_mapping) = attributes.docs_with_rangemap(sema.db)?;
- let (idl_range, link, ns) = extract_definitions_from_docs(&docs).into_iter().find_map(
- |(range, link, ns)| {
- let mapped = doc_mapping.map(range)?;
- (mapped.file_id == file_id.into()
- && mapped.value.contains(absolute_comment_offset))
- .then(|| (mapped.value, link, ns))
- },
- )?;
- let def = match resolve_doc_path_for_def(sema.db, def, &link, ns)? {
- Either::Left(it) => Definition::ModuleDef(it),
- Either::Right(it) => Definition::Macro(it),
- };
+ return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
let res = hover_for_definition(sema, file_id, def, &node, config)?;
- Some(RangeInfo::new(idl_range, res))
+ Some(RangeInfo::new(range, res))
});
}
+ let descended = sema.descend_into_macros_many(original_token.clone());
// attributes, require special machinery as they are mere ident tokens
// FIXME: Definition should include known lints and the like instead of having this special case here
@@ -4941,4 +4913,63 @@ fn foo() {
"#]],
);
}
+
+ #[test]
+ fn hover_intra_in_macro() {
+ check(
+ r#"
+macro_rules! foo_macro {
+ ($(#[$attr:meta])* $name:ident) => {
+ $(#[$attr])*
+ pub struct $name;
+ }
+}
+
+foo_macro!(
+ /// Doc comment for [`Foo$0`]
+ Foo
+);
+"#,
+ expect![[r#"
+ *[`Foo`]*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ pub struct Foo
+ ```
+
+ ---
+
+ Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
+ "#]],
+ );
+ }
+
+ #[test]
+ fn hover_intra_in_attr() {
+ check(
+ r#"
+#[doc = "Doc comment for [`Foo$0`]"]
+pub struct Foo;
+"#,
+ expect![[r#"
+ *[`Foo`]*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ pub struct Foo
+ ```
+
+ ---
+
+ Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
+ "#]],
+ );
+ }
}