mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 07:04:49 +00:00
Infallible definition hovers
This commit is contained in:
parent
2223b4fa71
commit
a822291a02
5 changed files with 135 additions and 38 deletions
|
@ -213,8 +213,8 @@ impl Definition {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn label(&self, db: &RootDatabase) -> Option<String> {
|
pub fn label(&self, db: &RootDatabase) -> String {
|
||||||
let label = match *self {
|
match *self {
|
||||||
Definition::Macro(it) => it.display(db).to_string(),
|
Definition::Macro(it) => it.display(db).to_string(),
|
||||||
Definition::Field(it) => it.display(db).to_string(),
|
Definition::Field(it) => it.display(db).to_string(),
|
||||||
Definition::TupleField(it) => it.display(db).to_string(),
|
Definition::TupleField(it) => it.display(db).to_string(),
|
||||||
|
@ -241,7 +241,11 @@ impl Definition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Definition::SelfType(impl_def) => {
|
Definition::SelfType(impl_def) => {
|
||||||
impl_def.self_ty(db).as_adt().and_then(|adt| Definition::Adt(adt).label(db))?
|
let self_ty = &impl_def.self_ty(db);
|
||||||
|
match self_ty.as_adt() {
|
||||||
|
Some(it) => it.display(db).to_string(),
|
||||||
|
None => self_ty.display(db).to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Definition::GenericParam(it) => it.display(db).to_string(),
|
Definition::GenericParam(it) => it.display(db).to_string(),
|
||||||
Definition::Label(it) => it.name(db).display(db).to_string(),
|
Definition::Label(it) => it.name(db).display(db).to_string(),
|
||||||
|
@ -249,8 +253,7 @@ impl Definition {
|
||||||
Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db)),
|
Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db)),
|
||||||
Definition::ToolModule(it) => it.name(db).to_string(),
|
Definition::ToolModule(it) => it.name(db).to_string(),
|
||||||
Definition::DeriveHelper(it) => format!("derive_helper {}", it.name(db).display(db)),
|
Definition::DeriveHelper(it) => format!("derive_helper {}", it.name(db).display(db)),
|
||||||
};
|
}
|
||||||
Some(label)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ fn hover_simple(
|
||||||
if let Some(doc_comment) = token_as_doc_comment(&original_token) {
|
if let Some(doc_comment) = token_as_doc_comment(&original_token) {
|
||||||
cov_mark::hit!(no_highlight_on_comment_hover);
|
cov_mark::hit!(no_highlight_on_comment_hover);
|
||||||
return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
|
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, config);
|
||||||
Some(RangeInfo::new(range, res))
|
Some(RangeInfo::new(range, res))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ fn hover_simple(
|
||||||
Definition::from(resolution?),
|
Definition::from(resolution?),
|
||||||
&original_token.parent()?,
|
&original_token.parent()?,
|
||||||
config,
|
config,
|
||||||
)?;
|
);
|
||||||
return Some(RangeInfo::new(range, res));
|
return Some(RangeInfo::new(range, res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ fn hover_simple(
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.unique_by(|&(def, _)| def)
|
.unique_by(|&(def, _)| def)
|
||||||
.filter_map(|(def, node)| hover_for_definition(sema, file_id, def, &node, config))
|
.map(|(def, node)| hover_for_definition(sema, file_id, def, &node, config))
|
||||||
.reduce(|mut acc: HoverResult, HoverResult { markup, actions }| {
|
.reduce(|mut acc: HoverResult, HoverResult { markup, actions }| {
|
||||||
acc.actions.extend(actions);
|
acc.actions.extend(actions);
|
||||||
acc.markup = Markup::from(format!("{}\n---\n{markup}", acc.markup));
|
acc.markup = Markup::from(format!("{}\n---\n{markup}", acc.markup));
|
||||||
|
@ -373,9 +373,9 @@ pub(crate) fn hover_for_definition(
|
||||||
def: Definition,
|
def: Definition,
|
||||||
scope_node: &SyntaxNode,
|
scope_node: &SyntaxNode,
|
||||||
config: &HoverConfig,
|
config: &HoverConfig,
|
||||||
) -> Option<HoverResult> {
|
) -> HoverResult {
|
||||||
let famous_defs = match &def {
|
let famous_defs = match &def {
|
||||||
Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(scope_node)?.krate())),
|
Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -396,20 +396,19 @@ pub(crate) fn hover_for_definition(
|
||||||
};
|
};
|
||||||
let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
|
let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
|
||||||
|
|
||||||
render::definition(sema.db, def, famous_defs.as_ref(), ¬able_traits, config).map(|markup| {
|
let markup = render::definition(sema.db, def, famous_defs.as_ref(), ¬able_traits, config);
|
||||||
HoverResult {
|
HoverResult {
|
||||||
markup: render::process_markup(sema.db, def, &markup, config),
|
markup: render::process_markup(sema.db, def, &markup, config),
|
||||||
actions: [
|
actions: [
|
||||||
show_implementations_action(sema.db, def),
|
show_implementations_action(sema.db, def),
|
||||||
show_fn_references_action(sema.db, def),
|
show_fn_references_action(sema.db, def),
|
||||||
runnable_action(sema, def, file_id),
|
runnable_action(sema, def, file_id),
|
||||||
goto_type_action_for_def(sema.db, def, ¬able_traits),
|
goto_type_action_for_def(sema.db, def, ¬able_traits),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn notable_traits(
|
fn notable_traits(
|
||||||
|
|
|
@ -264,7 +264,7 @@ pub(super) fn keyword(
|
||||||
let markup = process_markup(
|
let markup = process_markup(
|
||||||
sema.db,
|
sema.db,
|
||||||
Definition::Module(doc_owner),
|
Definition::Module(doc_owner),
|
||||||
&markup(Some(docs.into()), description, None)?,
|
&markup(Some(docs.into()), description, None),
|
||||||
config,
|
config,
|
||||||
);
|
);
|
||||||
Some(HoverResult { markup, actions })
|
Some(HoverResult { markup, actions })
|
||||||
|
@ -396,11 +396,11 @@ pub(super) fn definition(
|
||||||
famous_defs: Option<&FamousDefs<'_, '_>>,
|
famous_defs: Option<&FamousDefs<'_, '_>>,
|
||||||
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
|
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
|
||||||
config: &HoverConfig,
|
config: &HoverConfig,
|
||||||
) -> Option<Markup> {
|
) -> Markup {
|
||||||
let mod_path = definition_mod_path(db, &def);
|
let mod_path = definition_mod_path(db, &def);
|
||||||
let label = def.label(db)?;
|
let label = def.label(db);
|
||||||
let docs = def.docs(db, famous_defs);
|
let docs = def.docs(db, famous_defs);
|
||||||
let value = match def {
|
let value = (|| match def {
|
||||||
Definition::Variant(it) => {
|
Definition::Variant(it) => {
|
||||||
if !it.parent_enum(db).is_data_carrying(db) {
|
if !it.parent_enum(db).is_data_carrying(db) {
|
||||||
match it.eval(db) {
|
match it.eval(db) {
|
||||||
|
@ -436,7 +436,7 @@ pub(super) fn definition(
|
||||||
Some(body.to_string())
|
Some(body.to_string())
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
})();
|
||||||
|
|
||||||
let layout_info = match def {
|
let layout_info = match def {
|
||||||
Definition::Field(it) => render_memory_layout(
|
Definition::Field(it) => render_memory_layout(
|
||||||
|
@ -683,7 +683,7 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
|
||||||
def.module(db).map(|module| path(db, module, definition_owner_name(db, def)))
|
def.module(db).map(|module| path(db, module, definition_owner_name(db, def)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Option<Markup> {
|
fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
if let Some(mod_path) = mod_path {
|
if let Some(mod_path) = mod_path {
|
||||||
|
@ -696,7 +696,7 @@ fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Optio
|
||||||
if let Some(doc) = docs {
|
if let Some(doc) = docs {
|
||||||
format_to!(buf, "\n___\n\n{}", doc);
|
format_to!(buf, "\n___\n\n{}", doc);
|
||||||
}
|
}
|
||||||
Some(buf.into())
|
buf.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> {
|
fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> {
|
||||||
|
|
|
@ -1279,11 +1279,11 @@ impl Thing {
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
enum Thing { A }
|
enum Thing { A }
|
||||||
impl Thing {
|
impl Thing {
|
||||||
pub fn thing(a: Self$0) {}
|
pub fn thing(a: Self$0) {}
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
*Self*
|
*Self*
|
||||||
|
|
||||||
|
@ -1298,6 +1298,42 @@ impl Thing {
|
||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
impl usize {
|
||||||
|
pub fn thing(a: Self$0) {}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*Self*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
usize
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
impl fn() -> usize {
|
||||||
|
pub fn thing(a: Self$0) {}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*Self*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn() -> usize
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -7201,6 +7237,65 @@ impl Iterator for S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extern_items() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
extern "C" {
|
||||||
|
static STATIC$0: ();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*STATIC*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
static STATIC: ()
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
extern "C" {
|
||||||
|
fn fun$0();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*fun*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
unsafe fn fun()
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
extern "C" {
|
||||||
|
type Ty$0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*Ty*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// size = 0, align = 1
|
||||||
|
type Ty
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn notable_ranged() {
|
fn notable_ranged() {
|
||||||
check_hover_range(
|
check_hover_range(
|
||||||
|
|
|
@ -186,7 +186,7 @@ impl StaticIndex<'_> {
|
||||||
} else {
|
} else {
|
||||||
let it = self.tokens.insert(TokenStaticData {
|
let it = self.tokens.insert(TokenStaticData {
|
||||||
documentation: documentation_for_definition(&sema, def, &node),
|
documentation: documentation_for_definition(&sema, def, &node),
|
||||||
hover: hover_for_definition(&sema, file_id, def, &node, &hover_config),
|
hover: Some(hover_for_definition(&sema, file_id, def, &node, &hover_config)),
|
||||||
definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| {
|
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() }
|
FileRange { file_id: it.file_id, range: it.focus_or_full_range() }
|
||||||
}),
|
}),
|
||||||
|
@ -196,7 +196,7 @@ impl StaticIndex<'_> {
|
||||||
enclosing_moniker: current_crate
|
enclosing_moniker: current_crate
|
||||||
.zip(def.enclosing_definition(self.db))
|
.zip(def.enclosing_definition(self.db))
|
||||||
.and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)),
|
.and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)),
|
||||||
signature: def.label(self.db),
|
signature: Some(def.label(self.db)),
|
||||||
kind: def_to_kind(self.db, def),
|
kind: def_to_kind(self.db, def),
|
||||||
});
|
});
|
||||||
self.def_map.insert(def, it);
|
self.def_map.insert(def, it);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue