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.rs | 118 |
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(¯o_call) { + && let Some(macro_) = sema.resolve_macro_call(¯o_call) { break 'a vec![( (Definition::Macro(macro_), None), sema.resolve_macro_call_arm(¯o_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, ¬able_traits, subst_types, edition), + goto_type_action_for_def(sema, def, ¬able_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( |