Improve hover message for inert attributes

This commit is contained in:
Lukas Wirth 2021-12-03 20:28:15 +01:00
parent d174158abc
commit 8da850b6d5
4 changed files with 75 additions and 7 deletions

View file

@ -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)]

View file

@ -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 {

View file

@ -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,

View file

@ -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 = "...")\]
"##]],
);
}