mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 05:45:12 +00:00
Render matched macro arm on hover of macro calls
This commit is contained in:
parent
062e1b9b81
commit
6bfdd38c69
11 changed files with 133 additions and 65 deletions
|
@ -14,7 +14,7 @@ use ide_db::{
|
|||
helpers::pick_best_token,
|
||||
FxIndexSet, RootDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use itertools::{multizip, Itertools};
|
||||
use syntax::{ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxNode, T};
|
||||
|
||||
use crate::{
|
||||
|
@ -149,7 +149,7 @@ fn hover_simple(
|
|||
if let Some(doc_comment) = token_as_doc_comment(&original_token) {
|
||||
cov_mark::hit!(no_highlight_on_comment_hover);
|
||||
return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
|
||||
let res = hover_for_definition(sema, file_id, def, &node, config);
|
||||
let res = hover_for_definition(sema, file_id, def, &node, None, config);
|
||||
Some(RangeInfo::new(range, res))
|
||||
});
|
||||
}
|
||||
|
@ -162,6 +162,7 @@ fn hover_simple(
|
|||
file_id,
|
||||
Definition::from(resolution?),
|
||||
&original_token.parent()?,
|
||||
None,
|
||||
config,
|
||||
);
|
||||
return Some(RangeInfo::new(range, res));
|
||||
|
@ -196,6 +197,29 @@ fn hover_simple(
|
|||
descended()
|
||||
.filter_map(|token| {
|
||||
let node = token.parent()?;
|
||||
|
||||
// special case macro calls, we wanna render the invoked arm index
|
||||
if let Some(name) = ast::NameRef::cast(node.clone()) {
|
||||
if let Some(path_seg) =
|
||||
name.syntax().parent().and_then(ast::PathSegment::cast)
|
||||
{
|
||||
if let Some(macro_call) = path_seg
|
||||
.parent_path()
|
||||
.syntax()
|
||||
.parent()
|
||||
.and_then(ast::MacroCall::cast)
|
||||
{
|
||||
if let Some(macro_) = sema.resolve_macro_call(¯o_call) {
|
||||
return Some(vec![(
|
||||
Definition::Macro(macro_),
|
||||
sema.resolve_macro_call_arm(¯o_call),
|
||||
node,
|
||||
)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match IdentClass::classify_node(sema, &node)? {
|
||||
// It's better for us to fall back to the keyword hover here,
|
||||
// rendering poll is very confusing
|
||||
|
@ -204,20 +228,19 @@ fn hover_simple(
|
|||
IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand {
|
||||
decl,
|
||||
..
|
||||
}) => Some(vec![(Definition::ExternCrateDecl(decl), node)]),
|
||||
}) => Some(vec![(Definition::ExternCrateDecl(decl), None, node)]),
|
||||
|
||||
class => Some(
|
||||
class
|
||||
.definitions()
|
||||
.into_iter()
|
||||
.zip(iter::repeat(node))
|
||||
multizip((class.definitions(), iter::repeat(None), iter::repeat(node)))
|
||||
.collect::<Vec<_>>(),
|
||||
),
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.unique_by(|&(def, _)| def)
|
||||
.map(|(def, node)| hover_for_definition(sema, file_id, def, &node, config))
|
||||
.unique_by(|&(def, _, _)| def)
|
||||
.map(|(def, macro_arm, node)| {
|
||||
hover_for_definition(sema, file_id, def, &node, macro_arm, config)
|
||||
})
|
||||
.reduce(|mut acc: HoverResult, HoverResult { markup, actions }| {
|
||||
acc.actions.extend(actions);
|
||||
acc.markup = Markup::from(format!("{}\n---\n{markup}", acc.markup));
|
||||
|
@ -374,6 +397,7 @@ pub(crate) fn hover_for_definition(
|
|||
file_id: FileId,
|
||||
def: Definition,
|
||||
scope_node: &SyntaxNode,
|
||||
macro_arm: Option<u32>,
|
||||
config: &HoverConfig,
|
||||
) -> HoverResult {
|
||||
let famous_defs = match &def {
|
||||
|
@ -398,7 +422,8 @@ pub(crate) fn hover_for_definition(
|
|||
};
|
||||
let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
|
||||
|
||||
let markup = render::definition(sema.db, def, famous_defs.as_ref(), ¬able_traits, config);
|
||||
let markup =
|
||||
render::definition(sema.db, def, famous_defs.as_ref(), ¬able_traits, macro_arm, config);
|
||||
HoverResult {
|
||||
markup: render::process_markup(sema.db, def, &markup, config),
|
||||
actions: [
|
||||
|
|
|
@ -403,6 +403,7 @@ pub(super) fn definition(
|
|||
def: Definition,
|
||||
famous_defs: Option<&FamousDefs<'_, '_>>,
|
||||
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
|
||||
macro_arm: Option<u32>,
|
||||
config: &HoverConfig,
|
||||
) -> Markup {
|
||||
let mod_path = definition_mod_path(db, &def);
|
||||
|
@ -413,6 +414,13 @@ pub(super) fn definition(
|
|||
Definition::Adt(Adt::Struct(struct_)) => {
|
||||
struct_.display_limited(db, config.max_struct_field_count).to_string()
|
||||
}
|
||||
Definition::Macro(it) => {
|
||||
let mut label = it.display(db).to_string();
|
||||
if let Some(macro_arm) = macro_arm {
|
||||
format_to!(label, " // matched arm #{}", macro_arm);
|
||||
}
|
||||
label
|
||||
}
|
||||
_ => def.label(db),
|
||||
};
|
||||
let docs = def.docs(db, famous_defs);
|
||||
|
|
|
@ -1560,21 +1560,21 @@ fn y() {
|
|||
fn test_hover_macro_invocation() {
|
||||
check(
|
||||
r#"
|
||||
macro_rules! foo { () => {} }
|
||||
macro_rules! foo { (a) => {}; () => {} }
|
||||
|
||||
fn f() { fo$0o!(); }
|
||||
"#,
|
||||
expect![[r#"
|
||||
*foo*
|
||||
*foo*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
macro_rules! foo
|
||||
```
|
||||
"#]],
|
||||
```rust
|
||||
macro_rules! foo // matched arm #1
|
||||
```
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1590,22 +1590,22 @@ macro foo() {}
|
|||
fn f() { fo$0o!(); }
|
||||
"#,
|
||||
expect![[r#"
|
||||
*foo*
|
||||
*foo*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
macro foo
|
||||
```
|
||||
```rust
|
||||
macro foo // matched arm #0
|
||||
```
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
foo bar
|
||||
foo bar
|
||||
|
||||
foo bar baz
|
||||
"#]],
|
||||
foo bar baz
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,14 @@ impl StaticIndex<'_> {
|
|||
} else {
|
||||
let it = self.tokens.insert(TokenStaticData {
|
||||
documentation: documentation_for_definition(&sema, def, &node),
|
||||
hover: Some(hover_for_definition(&sema, file_id, def, &node, &hover_config)),
|
||||
hover: Some(hover_for_definition(
|
||||
&sema,
|
||||
file_id,
|
||||
def,
|
||||
&node,
|
||||
None,
|
||||
&hover_config,
|
||||
)),
|
||||
definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| {
|
||||
FileRange { file_id: it.file_id, range: it.focus_or_full_range() }
|
||||
}),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue