mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 14:51:48 +00:00
Improve hover message for inert attributes
This commit is contained in:
parent
d174158abc
commit
8da850b6d5
4 changed files with 75 additions and 7 deletions
|
@ -103,6 +103,7 @@ pub use {
|
|||
hir_def::{
|
||||
adt::StructKind,
|
||||
attr::{Attr, Attrs, AttrsWithOwner, Documentation},
|
||||
builtin_attr::AttributeTemplate,
|
||||
find_path::PrefixKind,
|
||||
import_map,
|
||||
item_scope::ItemScope,
|
||||
|
@ -2036,6 +2037,10 @@ impl BuiltinAttr {
|
|||
// FIXME: Return a `Name` here
|
||||
hir_def::builtin_attr::INERT_ATTRIBUTES[self.0].name
|
||||
}
|
||||
|
||||
pub fn template(&self, _: &dyn HirDatabase) -> AttributeTemplate {
|
||||
hir_def::builtin_attr::INERT_ATTRIBUTES[self.0].template
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -21,15 +21,15 @@ pub struct BuiltinAttribute {
|
|||
|
||||
/// A template that the attribute input must match.
|
||||
/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct AttributeTemplate {
|
||||
pub word: bool,
|
||||
pub list: Option<&'static str>,
|
||||
pub name_value_str: Option<&'static str>,
|
||||
}
|
||||
|
||||
static BUILTIN_LOOKUP_TABLE: OnceCell<FxHashMap<&'static str, usize>> = OnceCell::new();
|
||||
|
||||
pub fn find_builtin_attr_idx(name: &str) -> Option<usize> {
|
||||
static BUILTIN_LOOKUP_TABLE: OnceCell<FxHashMap<&'static str, usize>> = OnceCell::new();
|
||||
BUILTIN_LOOKUP_TABLE
|
||||
.get_or_init(|| {
|
||||
INERT_ATTRIBUTES.iter().map(|attr| attr.name).enumerate().map(|(a, b)| (b, a)).collect()
|
||||
|
@ -58,9 +58,11 @@ macro_rules! template {
|
|||
(Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
|
||||
template!(@ true, Some($descr1), Some($descr2))
|
||||
};
|
||||
(@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate {
|
||||
(@ $word: expr, $list: expr, $name_value_str: expr) => {
|
||||
AttributeTemplate {
|
||||
word: $word, list: $list, name_value_str: $name_value_str
|
||||
} };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ungated {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use either::Either;
|
||||
use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
|
||||
use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
|
||||
use ide_db::{
|
||||
base_db::SourceDatabase,
|
||||
defs::Definition,
|
||||
|
@ -370,13 +370,31 @@ pub(super) fn definition(
|
|||
Definition::GenericParam(it) => label_and_docs(db, it),
|
||||
Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db))),
|
||||
// FIXME: We should be able to show more info about these
|
||||
Definition::BuiltinAttr(it) => return Some(Markup::fenced_block(&it.name(db))),
|
||||
Definition::BuiltinAttr(it) => return render_builtin_attr(db, it),
|
||||
Definition::ToolModule(it) => return Some(Markup::fenced_block(&it.name(db))),
|
||||
};
|
||||
|
||||
markup(docs.filter(|_| config.documentation.is_some()).map(Into::into), label, mod_path)
|
||||
}
|
||||
|
||||
fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option<Markup> {
|
||||
let name = attr.name(db);
|
||||
let desc = format!("#[{}]", name);
|
||||
|
||||
let AttributeTemplate { word, list, name_value_str } = attr.template(db);
|
||||
let mut docs = "Valid forms are:".to_owned();
|
||||
if word {
|
||||
format_to!(docs, "\n - #\\[{}]", name);
|
||||
}
|
||||
if let Some(list) = list {
|
||||
format_to!(docs, "\n - #\\[{}({})]", name, list);
|
||||
}
|
||||
if let Some(name_value_str) = name_value_str {
|
||||
format_to!(docs, "\n - #\\[{} = {}]", name, name_value_str);
|
||||
}
|
||||
markup(Some(docs.replace('*', "\\*")), desc, None)
|
||||
}
|
||||
|
||||
fn label_and_docs<D>(db: &RootDatabase, def: D) -> (String, Option<hir::Documentation>)
|
||||
where
|
||||
D: HasAttrs + HirDisplay,
|
||||
|
|
|
@ -4277,3 +4277,46 @@ pub struct Foo;
|
|||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_inert_attr() {
|
||||
check(
|
||||
r#"
|
||||
#[doc$0 = ""]
|
||||
pub struct Foo;
|
||||
"#,
|
||||
expect![[r##"
|
||||
*doc*
|
||||
|
||||
```rust
|
||||
#[doc]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Valid forms are:
|
||||
|
||||
* \#\[doc(hidden|inline|...)\]
|
||||
* \#\[doc = string\]
|
||||
"##]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
#[allow$0()]
|
||||
pub struct Foo;
|
||||
"#,
|
||||
expect![[r##"
|
||||
*allow*
|
||||
|
||||
```rust
|
||||
#[allow]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Valid forms are:
|
||||
|
||||
* \#\[allow(lint1, lint2, ..., /\*opt\*/ reason = "...")\]
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue