Skip to content

Commit 8da850b

Browse files
committed
Improve hover message for inert attributes
1 parent d174158 commit 8da850b

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

crates/hir/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ pub use {
103103
hir_def::{
104104
adt::StructKind,
105105
attr::{Attr, Attrs, AttrsWithOwner, Documentation},
106+
builtin_attr::AttributeTemplate,
106107
find_path::PrefixKind,
107108
import_map,
108109
item_scope::ItemScope,
@@ -2036,6 +2037,10 @@ impl BuiltinAttr {
20362037
// FIXME: Return a `Name` here
20372038
hir_def::builtin_attr::INERT_ATTRIBUTES[self.0].name
20382039
}
2040+
2041+
pub fn template(&self, _: &dyn HirDatabase) -> AttributeTemplate {
2042+
hir_def::builtin_attr::INERT_ATTRIBUTES[self.0].template
2043+
}
20392044
}
20402045

20412046
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]

crates/hir_def/src/builtin_attr.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ pub struct BuiltinAttribute {
2121

2222
/// A template that the attribute input must match.
2323
/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
24+
#[derive(Clone, Copy)]
2425
pub struct AttributeTemplate {
2526
pub word: bool,
2627
pub list: Option<&'static str>,
2728
pub name_value_str: Option<&'static str>,
2829
}
2930

30-
static BUILTIN_LOOKUP_TABLE: OnceCell<FxHashMap<&'static str, usize>> = OnceCell::new();
31-
3231
pub fn find_builtin_attr_idx(name: &str) -> Option<usize> {
32+
static BUILTIN_LOOKUP_TABLE: OnceCell<FxHashMap<&'static str, usize>> = OnceCell::new();
3333
BUILTIN_LOOKUP_TABLE
3434
.get_or_init(|| {
3535
INERT_ATTRIBUTES.iter().map(|attr| attr.name).enumerate().map(|(a, b)| (b, a)).collect()
@@ -58,9 +58,11 @@ macro_rules! template {
5858
(Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
5959
template!(@ true, Some($descr1), Some($descr2))
6060
};
61-
(@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate {
62-
word: $word, list: $list, name_value_str: $name_value_str
63-
} };
61+
(@ $word: expr, $list: expr, $name_value_str: expr) => {
62+
AttributeTemplate {
63+
word: $word, list: $list, name_value_str: $name_value_str
64+
}
65+
};
6466
}
6567

6668
macro_rules! ungated {

crates/ide/src/hover/render.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::fmt::Display;
33

44
use either::Either;
5-
use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
5+
use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
66
use ide_db::{
77
base_db::SourceDatabase,
88
defs::Definition,
@@ -370,13 +370,31 @@ pub(super) fn definition(
370370
Definition::GenericParam(it) => label_and_docs(db, it),
371371
Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db))),
372372
// FIXME: We should be able to show more info about these
373-
Definition::BuiltinAttr(it) => return Some(Markup::fenced_block(&it.name(db))),
373+
Definition::BuiltinAttr(it) => return render_builtin_attr(db, it),
374374
Definition::ToolModule(it) => return Some(Markup::fenced_block(&it.name(db))),
375375
};
376376

377377
markup(docs.filter(|_| config.documentation.is_some()).map(Into::into), label, mod_path)
378378
}
379379

380+
fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option<Markup> {
381+
let name = attr.name(db);
382+
let desc = format!("#[{}]", name);
383+
384+
let AttributeTemplate { word, list, name_value_str } = attr.template(db);
385+
let mut docs = "Valid forms are:".to_owned();
386+
if word {
387+
format_to!(docs, "\n - #\\[{}]", name);
388+
}
389+
if let Some(list) = list {
390+
format_to!(docs, "\n - #\\[{}({})]", name, list);
391+
}
392+
if let Some(name_value_str) = name_value_str {
393+
format_to!(docs, "\n - #\\[{} = {}]", name, name_value_str);
394+
}
395+
markup(Some(docs.replace('*', "\\*")), desc, None)
396+
}
397+
380398
fn label_and_docs<D>(db: &RootDatabase, def: D) -> (String, Option<hir::Documentation>)
381399
where
382400
D: HasAttrs + HirDisplay,

crates/ide/src/hover/tests.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4277,3 +4277,46 @@ pub struct Foo;
42774277
"#]],
42784278
);
42794279
}
4280+
4281+
#[test]
4282+
fn hover_inert_attr() {
4283+
check(
4284+
r#"
4285+
#[doc$0 = ""]
4286+
pub struct Foo;
4287+
"#,
4288+
expect![[r##"
4289+
*doc*
4290+
4291+
```rust
4292+
#[doc]
4293+
```
4294+
4295+
---
4296+
4297+
Valid forms are:
4298+
4299+
* \#\[doc(hidden|inline|...)\]
4300+
* \#\[doc = string\]
4301+
"##]],
4302+
);
4303+
check(
4304+
r#"
4305+
#[allow$0()]
4306+
pub struct Foo;
4307+
"#,
4308+
expect![[r##"
4309+
*allow*
4310+
4311+
```rust
4312+
#[allow]
4313+
```
4314+
4315+
---
4316+
4317+
Valid forms are:
4318+
4319+
* \#\[allow(lint1, lint2, ..., /\*opt\*/ reason = "...")\]
4320+
"##]],
4321+
);
4322+
}

0 commit comments

Comments
 (0)