Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/hover.rs')
-rw-r--r--crates/ide/src/hover.rs118
1 files changed, 80 insertions, 38 deletions
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index e4d6279759..e1d18b0c41 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -11,29 +11,32 @@ use hir::{
db::DefDatabase,
};
use ide_db::{
- FileRange, FxIndexSet, Ranker, RootDatabase,
+ FileRange, FxIndexSet, MiniCore, Ranker, RootDatabase,
defs::{Definition, IdentClass, NameRefClass, OperatorClass},
famous_defs::FamousDefs,
helpers::pick_best_token,
+ ra_fixture::UpmapFromRaFixture,
};
use itertools::{Itertools, multizip};
-use span::Edition;
+use macros::UpmapFromRaFixture;
+use span::{Edition, TextRange};
use syntax::{
- AstNode,
+ AstNode, AstToken,
SyntaxKind::{self, *},
SyntaxNode, T, ast,
};
use crate::{
- FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, TryToNav,
+ Analysis, FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, TryToNav,
doc_links::token_as_doc_comment,
markdown_remove::remove_markdown,
markup::Markup,
navigation_target::UpmappingResult,
runnables::{runnable_fn, runnable_mod},
};
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct HoverConfig {
+
+#[derive(Clone, Debug)]
+pub struct HoverConfig<'a> {
pub links_in_hover: bool,
pub memory_layout: Option<MemoryLayoutHoverConfig>,
pub documentation: bool,
@@ -44,6 +47,7 @@ pub struct HoverConfig {
pub max_enum_variants_count: Option<usize>,
pub max_subst_ty_len: SubstTyLen,
pub show_drop_glue: bool,
+ pub minicore: MiniCore<'a>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -75,7 +79,7 @@ pub enum HoverDocFormat {
PlainText,
}
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq, UpmapFromRaFixture)]
pub enum HoverAction {
Runnable(Runnable),
Implementation(FilePosition),
@@ -85,10 +89,11 @@ pub enum HoverAction {
impl HoverAction {
fn goto_type_from_targets(
- db: &RootDatabase,
+ sema: &Semantics<'_, RootDatabase>,
targets: Vec<hir::ModuleDef>,
edition: Edition,
) -> Option<Self> {
+ let db = sema.db;
let targets = targets
.into_iter()
.filter_map(|it| {
@@ -99,7 +104,7 @@ impl HoverAction {
it.name(db).map(|name| name.display(db, edition).to_string()),
edition,
),
- nav: it.try_to_nav(db)?.call_site(),
+ nav: it.try_to_nav(sema)?.call_site(),
})
})
.collect::<Vec<_>>();
@@ -107,14 +112,14 @@ impl HoverAction {
}
}
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash, UpmapFromRaFixture)]
pub struct HoverGotoTypeData {
pub mod_path: String,
pub nav: NavigationTarget,
}
/// Contains the results when hovering over an item
-#[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, UpmapFromRaFixture)]
pub struct HoverResult {
pub markup: Markup,
pub actions: Vec<HoverAction>,
@@ -129,7 +134,7 @@ pub struct HoverResult {
pub(crate) fn hover(
db: &RootDatabase,
frange @ FileRange { file_id, range }: FileRange,
- config: &HoverConfig,
+ config: &HoverConfig<'_>,
) -> Option<RangeInfo<HoverResult>> {
let sema = &hir::Semantics::new(db);
let file = sema.parse_guess_edition(file_id).syntax().clone();
@@ -160,7 +165,7 @@ fn hover_offset(
sema: &Semantics<'_, RootDatabase>,
FilePosition { file_id, offset }: FilePosition,
file: SyntaxNode,
- config: &HoverConfig,
+ config: &HoverConfig<'_>,
edition: Edition,
display_target: DisplayTarget,
) -> Option<RangeInfo<HoverResult>> {
@@ -218,6 +223,21 @@ fn hover_offset(
return Some(RangeInfo::new(range, res));
}
+ if let Some(literal) = ast::String::cast(original_token.clone())
+ && let Some((analysis, fixture_analysis)) =
+ Analysis::from_ra_fixture(sema, literal.clone(), &literal, config.minicore)
+ {
+ let (virtual_file_id, virtual_offset) = fixture_analysis.map_offset_down(offset)?;
+ return analysis
+ .hover(
+ config,
+ FileRange { file_id: virtual_file_id, range: TextRange::empty(virtual_offset) },
+ )
+ .ok()??
+ .upmap_from_ra_fixture(&fixture_analysis, virtual_file_id, file_id)
+ .ok();
+ }
+
// prefer descending the same token kind in attribute expansions, in normal macros text
// equivalency is more important
let mut descended = sema.descend_into_macros(original_token.clone());
@@ -244,17 +264,15 @@ fn hover_offset(
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) =
+ if let Some(name) = ast::NameRef::cast(node.clone())
+ && let Some(path_seg) =
name.syntax().parent().and_then(ast::PathSegment::cast)
- {
- if let Some(macro_call) = path_seg
+ && let Some(macro_call) = path_seg
.parent_path()
.syntax()
.parent()
.and_then(ast::MacroCall::cast)
- {
- if let Some(macro_) = sema.resolve_macro_call(&macro_call) {
+ && let Some(macro_) = sema.resolve_macro_call(&macro_call) {
break 'a vec![(
(Definition::Macro(macro_), None),
sema.resolve_macro_call_arm(&macro_call),
@@ -262,9 +280,6 @@ fn hover_offset(
node,
)];
}
- }
- }
- }
match IdentClass::classify_node(sema, &node)? {
// It's better for us to fall back to the keyword hover here,
@@ -387,9 +402,9 @@ fn hover_offset(
fn hover_ranged(
sema: &Semantics<'_, RootDatabase>,
- FileRange { range, .. }: FileRange,
+ FileRange { file_id, range }: FileRange,
file: SyntaxNode,
- config: &HoverConfig,
+ config: &HoverConfig<'_>,
edition: Edition,
display_target: DisplayTarget,
) -> Option<RangeInfo<HoverResult>> {
@@ -408,6 +423,20 @@ fn hover_ranged(
{
render::deref_expr(sema, config, prefix_expr, edition, display_target)
}
+ Either::Left(ast::Expr::Literal(literal)) => {
+ if let Some(literal) = ast::String::cast(literal.token())
+ && let Some((analysis, fixture_analysis)) =
+ Analysis::from_ra_fixture(sema, literal.clone(), &literal, config.minicore)
+ {
+ let (virtual_file_id, virtual_range) = fixture_analysis.map_range_down(range)?;
+ return analysis
+ .hover(config, FileRange { file_id: virtual_file_id, range: virtual_range })
+ .ok()??
+ .upmap_from_ra_fixture(&fixture_analysis, virtual_file_id, file_id)
+ .ok();
+ }
+ None
+ }
_ => None,
};
let res =
@@ -430,7 +459,7 @@ pub(crate) fn hover_for_definition(
scope_node: &SyntaxNode,
macro_arm: Option<u32>,
render_extras: bool,
- config: &HoverConfig,
+ config: &HoverConfig<'_>,
edition: Edition,
display_target: DisplayTarget,
) -> HoverResult {
@@ -444,7 +473,7 @@ pub(crate) fn hover_for_definition(
Definition::Local(it) => Some(it.ty(db)),
Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)),
Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)),
- Definition::Field(field) => Some(field.ty(db)),
+ Definition::Field(field) => Some(field.ty(db).to_type(db)),
Definition::TupleField(it) => Some(it.ty(db)),
Definition::Function(it) => Some(it.ty(db)),
Definition::Adt(it) => Some(it.ty(db)),
@@ -472,10 +501,10 @@ pub(crate) fn hover_for_definition(
HoverResult {
markup: render::process_markup(sema.db, def, &markup, range_map, config),
actions: [
- show_fn_references_action(sema.db, def),
- show_implementations_action(sema.db, def),
+ show_fn_references_action(sema, def),
+ show_implementations_action(sema, def),
runnable_action(sema, def, file_id),
- goto_type_action_for_def(sema.db, def, &notable_traits, subst_types, edition),
+ goto_type_action_for_def(sema, def, &notable_traits, subst_types, edition),
]
.into_iter()
.flatten()
@@ -487,6 +516,12 @@ fn notable_traits<'db>(
db: &'db RootDatabase,
ty: &hir::Type<'db>,
) -> Vec<(hir::Trait, Vec<(Option<hir::Type<'db>>, hir::Name)>)> {
+ if ty.is_unknown() {
+ // The trait solver returns "yes" to the question whether the error type
+ // impls any trait, and we don't want to show it as having any notable trait.
+ return Vec::new();
+ }
+
db.notable_traits_in_deps(ty.krate(db).into())
.iter()
.flat_map(|it| &**it)
@@ -510,7 +545,10 @@ fn notable_traits<'db>(
.collect::<Vec<_>>()
}
-fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
+fn show_implementations_action(
+ sema: &Semantics<'_, RootDatabase>,
+ def: Definition,
+) -> Option<HoverAction> {
fn to_action(nav_target: NavigationTarget) -> HoverAction {
HoverAction::Implementation(FilePosition {
file_id: nav_target.file_id,
@@ -520,19 +558,22 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
let adt = match def {
Definition::Trait(it) => {
- return it.try_to_nav(db).map(UpmappingResult::call_site).map(to_action);
+ return it.try_to_nav(sema).map(UpmappingResult::call_site).map(to_action);
}
Definition::Adt(it) => Some(it),
- Definition::SelfType(it) => it.self_ty(db).as_adt(),
+ Definition::SelfType(it) => it.self_ty(sema.db).as_adt(),
_ => None,
}?;
- adt.try_to_nav(db).map(UpmappingResult::call_site).map(to_action)
+ adt.try_to_nav(sema).map(UpmappingResult::call_site).map(to_action)
}
-fn show_fn_references_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
+fn show_fn_references_action(
+ sema: &Semantics<'_, RootDatabase>,
+ def: Definition,
+) -> Option<HoverAction> {
match def {
Definition::Function(it) => {
- it.try_to_nav(db).map(UpmappingResult::call_site).map(|nav_target| {
+ it.try_to_nav(sema).map(UpmappingResult::call_site).map(|nav_target| {
HoverAction::Reference(FilePosition {
file_id: nav_target.file_id,
offset: nav_target.focus_or_full_range().start(),
@@ -565,12 +606,13 @@ fn runnable_action(
}
fn goto_type_action_for_def(
- db: &RootDatabase,
+ sema: &Semantics<'_, RootDatabase>,
def: Definition,
notable_traits: &[(hir::Trait, Vec<(Option<hir::Type<'_>>, hir::Name)>)],
subst_types: Option<Vec<(hir::Symbol, hir::Type<'_>)>>,
edition: Edition,
) -> Option<HoverAction> {
+ let db = sema.db;
let mut targets: Vec<hir::ModuleDef> = Vec::new();
let mut push_new_def = |item: hir::ModuleDef| {
if !targets.contains(&item) {
@@ -593,7 +635,7 @@ fn goto_type_action_for_def(
let ty = match def {
Definition::Local(it) => Some(it.ty(db)),
- Definition::Field(field) => Some(field.ty(db)),
+ Definition::Field(field) => Some(field.ty(db).to_type(db)),
Definition::TupleField(field) => Some(field.ty(db)),
Definition::Const(it) => Some(it.ty(db)),
Definition::Static(it) => Some(it.ty(db)),
@@ -617,7 +659,7 @@ fn goto_type_action_for_def(
}
}
- HoverAction::goto_type_from_targets(db, targets, edition)
+ HoverAction::goto_type_from_targets(sema, targets, edition)
}
fn walk_and_push_ty(