Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/hover/render.rs')
| -rw-r--r-- | crates/ide/src/hover/render.rs | 154 |
1 files changed, 92 insertions, 62 deletions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 7091b15b8a..3e41b42be4 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -20,6 +20,7 @@ use rustc_apfloat::{ ieee::{Half as f16, Quad as f128}, Float, }; +use span::Edition; use stdx::format_to; use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxToken, T}; @@ -34,27 +35,30 @@ pub(super) fn type_info_of( sema: &Semantics<'_, RootDatabase>, _config: &HoverConfig, expr_or_pat: &Either<ast::Expr, ast::Pat>, + edition: Edition, ) -> Option<HoverResult> { let ty_info = match expr_or_pat { Either::Left(expr) => sema.type_of_expr(expr)?, Either::Right(pat) => sema.type_of_pat(pat)?, }; - type_info(sema, _config, ty_info) + type_info(sema, _config, ty_info, edition) } pub(super) fn closure_expr( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, c: ast::ClosureExpr, + edition: Edition, ) -> Option<HoverResult> { let TypeInfo { original, .. } = sema.type_of_expr(&c.into())?; - closure_ty(sema, config, &TypeInfo { original, adjusted: None }) + closure_ty(sema, config, &TypeInfo { original, adjusted: None }, edition) } pub(super) fn try_expr( sema: &Semantics<'_, RootDatabase>, _config: &HoverConfig, try_expr: &ast::TryExpr, + edition: Edition, ) -> Option<HoverResult> { let inner_ty = sema.type_of_expr(&try_expr.expr()?)?.original; let mut ancestors = try_expr.syntax().ancestors(); @@ -117,12 +121,12 @@ pub(super) fn try_expr( }; walk_and_push_ty(sema.db, &inner_ty, &mut push_new_def); walk_and_push_ty(sema.db, &body_ty, &mut push_new_def); - if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) { res.actions.push(actions); } - let inner_ty = inner_ty.display(sema.db).to_string(); - let body_ty = body_ty.display(sema.db).to_string(); + let inner_ty = inner_ty.display(sema.db, edition).to_string(); + let body_ty = body_ty.display(sema.db, edition).to_string(); let ty_len_max = inner_ty.len().max(body_ty.len()); let l = "Propagated as: ".len() - " Type: ".len(); @@ -146,6 +150,7 @@ pub(super) fn deref_expr( sema: &Semantics<'_, RootDatabase>, _config: &HoverConfig, deref_expr: &ast::PrefixExpr, + edition: Edition, ) -> Option<HoverResult> { let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original; let TypeInfo { original, adjusted } = @@ -163,9 +168,9 @@ pub(super) fn deref_expr( res.markup = if let Some(adjusted_ty) = adjusted { walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def); - let original = original.display(sema.db).to_string(); - let adjusted = adjusted_ty.display(sema.db).to_string(); - let inner = inner_ty.display(sema.db).to_string(); + let original = original.display(sema.db, edition).to_string(); + let adjusted = adjusted_ty.display(sema.db, edition).to_string(); + let inner = inner_ty.display(sema.db, edition).to_string(); let type_len = "To type: ".len(); let coerced_len = "Coerced to: ".len(); let deref_len = "Dereferenced from: ".len(); @@ -183,8 +188,8 @@ pub(super) fn deref_expr( ) .into() } else { - let original = original.display(sema.db).to_string(); - let inner = inner_ty.display(sema.db).to_string(); + let original = original.display(sema.db, edition).to_string(); + let inner = inner_ty.display(sema.db, edition).to_string(); let type_len = "To type: ".len(); let deref_len = "Dereferenced from: ".len(); let max_len = (original.len() + type_len).max(inner.len() + deref_len); @@ -197,7 +202,7 @@ pub(super) fn deref_expr( ) .into() }; - if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) { res.actions.push(actions); } @@ -208,6 +213,7 @@ pub(super) fn underscore( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, token: &SyntaxToken, + edition: Edition, ) -> Option<HoverResult> { if token.kind() != T![_] { return None; @@ -216,8 +222,8 @@ pub(super) fn underscore( let _it = match_ast! { match parent { ast::InferType(it) => it, - ast::UnderscoreExpr(it) => return type_info_of(sema, config, &Either::Left(ast::Expr::UnderscoreExpr(it))), - ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(it))), + ast::UnderscoreExpr(it) => return type_info_of(sema, config, &Either::Left(ast::Expr::UnderscoreExpr(it)),edition), + ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(it)),edition), _ => return None, } }; @@ -250,16 +256,18 @@ pub(super) fn keyword( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, token: &SyntaxToken, + edition: Edition, ) -> Option<HoverResult> { - if !token.kind().is_keyword() || !config.documentation || !config.keywords { + if !token.kind().is_keyword(edition) || !config.documentation || !config.keywords { return None; } let parent = token.parent()?; let famous_defs = FamousDefs(sema, sema.scope(&parent)?.krate()); - let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent); + let KeywordHint { description, keyword_mod, actions } = + keyword_hints(sema, token, parent, edition); - let doc_owner = find_std_module(&famous_defs, &keyword_mod)?; + let doc_owner = find_std_module(&famous_defs, &keyword_mod, edition)?; let docs = doc_owner.docs(sema.db)?; let markup = process_markup( sema.db, @@ -277,6 +285,7 @@ pub(super) fn struct_rest_pat( sema: &Semantics<'_, RootDatabase>, _config: &HoverConfig, pattern: &ast::RecordPat, + edition: Edition, ) -> HoverResult { let missing_fields = sema.record_pattern_missing_fields(pattern); @@ -298,7 +307,7 @@ pub(super) fn struct_rest_pat( res.markup = { let mut s = String::from(".., "); for (f, _) in &missing_fields { - s += f.display(sema.db).to_string().as_ref(); + s += f.display(sema.db, edition).to_string().as_ref(); s += ", "; } // get rid of trailing comma @@ -306,7 +315,7 @@ pub(super) fn struct_rest_pat( Markup::fenced_block(&s) }; - if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) { res.actions.push(actions); } res @@ -365,7 +374,7 @@ pub(super) fn process_markup( Markup::from(markup) } -fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> { +fn definition_owner_name(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> { match def { Definition::Field(f) => Some(f.parent_def(db).name(db)), Definition::Local(l) => l.parent(db).name(db), @@ -384,17 +393,22 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> } } } - .map(|name| name.display(db).to_string()) + .map(|name| name.display(db, edition).to_string()) } -pub(super) fn path(db: &RootDatabase, module: hir::Module, item_name: Option<String>) -> String { +pub(super) fn path( + db: &RootDatabase, + module: hir::Module, + item_name: Option<String>, + edition: Edition, +) -> String { let crate_name = db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string()); let module_path = module .path_to_root(db) .into_iter() .rev() - .flat_map(|it| it.name(db).map(|name| name.display(db).to_string())); + .flat_map(|it| it.name(db).map(|name| name.display(db, edition).to_string())); crate_name.into_iter().chain(module_path).chain(item_name).join("::") } @@ -405,39 +419,42 @@ pub(super) fn definition( notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], macro_arm: Option<u32>, config: &HoverConfig, + edition: Edition, ) -> Markup { - let mod_path = definition_mod_path(db, &def); + let mod_path = definition_mod_path(db, &def, edition); let label = match def { Definition::Trait(trait_) => { - trait_.display_limited(db, config.max_trait_assoc_items_count).to_string() + trait_.display_limited(db, config.max_trait_assoc_items_count, edition).to_string() } Definition::Adt(adt @ (Adt::Struct(_) | Adt::Union(_))) => { - adt.display_limited(db, config.max_fields_count).to_string() + adt.display_limited(db, config.max_fields_count, edition).to_string() } Definition::Variant(variant) => { - variant.display_limited(db, config.max_fields_count).to_string() + variant.display_limited(db, config.max_fields_count, edition).to_string() } Definition::Adt(adt @ Adt::Enum(_)) => { - adt.display_limited(db, config.max_enum_variants_count).to_string() + adt.display_limited(db, config.max_enum_variants_count, edition).to_string() } Definition::SelfType(impl_def) => { let self_ty = &impl_def.self_ty(db); match self_ty.as_adt() { - Some(adt) => adt.display_limited(db, config.max_fields_count).to_string(), - None => self_ty.display(db).to_string(), + Some(adt) => adt.display_limited(db, config.max_fields_count, edition).to_string(), + None => self_ty.display(db, edition).to_string(), } } Definition::Macro(it) => { - let mut label = it.display(db).to_string(); + let mut label = it.display(db, edition).to_string(); if let Some(macro_arm) = macro_arm { format_to!(label, " // matched arm #{}", macro_arm); } label } - Definition::Function(fn_) => fn_.display_with_container_bounds(db, true).to_string(), - _ => def.label(db), + Definition::Function(fn_) => { + fn_.display_with_container_bounds(db, true, edition).to_string() + } + _ => def.label(db, edition), }; - let docs = def.docs(db, famous_defs); + let docs = def.docs(db, famous_defs, edition); let value = (|| match def { Definition::Variant(it) => { if !it.parent_enum(db).is_data_carrying(db) { @@ -452,7 +469,7 @@ pub(super) fn definition( } } Definition::Const(it) => { - let body = it.render_eval(db); + let body = it.render_eval(db, edition); match body { Ok(it) => Some(it), Err(_) => { @@ -510,7 +527,7 @@ pub(super) fn definition( }; let mut desc = String::new(); - if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits) { + if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits, edition) { desc.push_str(¬able_traits); desc.push('\n'); } @@ -527,7 +544,11 @@ pub(super) fn definition( markup(docs.map(Into::into), desc, mod_path) } -pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option<Markup> { +pub(super) fn literal( + sema: &Semantics<'_, RootDatabase>, + token: SyntaxToken, + edition: Edition, +) -> Option<Markup> { let lit = token.parent().and_then(ast::Literal::cast)?; let ty = if let Some(p) = lit.syntax().parent().and_then(ast::Pat::cast) { sema.type_of_pat(&p)? @@ -574,7 +595,7 @@ pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> _ => return None } }; - let ty = ty.display(sema.db); + let ty = ty.display(sema.db, edition); let mut s = format!("```rust\n{ty}\n```\n___\n\n"); match value { @@ -593,6 +614,7 @@ pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> fn render_notable_trait_comment( db: &RootDatabase, notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], + edition: Edition, ) -> Option<String> { let mut desc = String::new(); let mut needs_impl_header = true; @@ -602,17 +624,17 @@ fn render_notable_trait_comment( } else { ", " }); - format_to!(desc, "{}", trait_.name(db).display(db),); + format_to!(desc, "{}", trait_.name(db).display(db, edition)); if !assoc_types.is_empty() { desc.push('<'); format_to!( desc, "{}", assoc_types.iter().format_with(", ", |(ty, name), f| { - f(&name.display(db))?; + f(&name.display(db, edition))?; f(&" = ")?; match ty { - Some(ty) => f(&ty.display(db)), + Some(ty) => f(&ty.display(db, edition)), None => f(&"?"), } }) @@ -627,8 +649,9 @@ fn type_info( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, ty: TypeInfo, + edition: Edition, ) -> Option<HoverResult> { - if let Some(res) = closure_ty(sema, config, &ty) { + if let Some(res) = closure_ty(sema, config, &ty, edition) { return Some(res); }; let db = sema.db; @@ -654,17 +677,17 @@ fn type_info( } else { ", " }); - format_to!(desc, "{}", trait_.name(db).display(db),); + format_to!(desc, "{}", trait_.name(db).display(db, edition)); if !assoc_types.is_empty() { desc.push('<'); format_to!( desc, "{}", assoc_types.into_iter().format_with(", ", |(ty, name), f| { - f(&name.display(db))?; + f(&name.display(db, edition))?; f(&" = ")?; match ty { - Some(ty) => f(&ty.display(db)), + Some(ty) => f(&ty.display(db, edition)), None => f(&"?"), } }) @@ -678,8 +701,8 @@ fn type_info( desc }; - let original = original.display(db).to_string(); - let adjusted = adjusted_ty.display(db).to_string(); + let original = original.display(db, edition).to_string(); + let adjusted = adjusted_ty.display(db, edition).to_string(); let static_text_diff_len = "Coerced to: ".len() - "Type: ".len(); format!( "```text\nType: {:>apad$}\nCoerced to: {:>opad$}\n{notable}```\n", @@ -690,14 +713,15 @@ fn type_info( ) .into() } else { - let mut desc = match render_notable_trait_comment(db, ¬able_traits(db, &original)) { - Some(desc) => desc + "\n", - None => String::new(), - }; - format_to!(desc, "{}", original.display(db)); + let mut desc = + match render_notable_trait_comment(db, ¬able_traits(db, &original), edition) { + Some(desc) => desc + "\n", + None => String::new(), + }; + format_to!(desc, "{}", original.display(db, edition)); Markup::fenced_block(&desc) }; - if let Some(actions) = HoverAction::goto_type_from_targets(db, targets) { + if let Some(actions) = HoverAction::goto_type_from_targets(db, targets, edition) { res.actions.push(actions); } Some(res) @@ -707,6 +731,7 @@ fn closure_ty( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, TypeInfo { original, adjusted }: &TypeInfo, + edition: Edition, ) -> Option<HoverResult> { let c = original.as_closure()?; let mut captures_rendered = c.captured_items(sema.db) @@ -739,12 +764,12 @@ fn closure_ty( walk_and_push_ty(sema.db, adjusted_ty, &mut push_new_def); format!( "\nCoerced to: {}", - adjusted_ty.display(sema.db).with_closure_style(hir::ClosureStyle::ImplFn) + adjusted_ty.display(sema.db, edition).with_closure_style(hir::ClosureStyle::ImplFn) ) } else { String::new() }; - let mut markup = format!("```rust\n{}", c.display_with_id(sema.db),); + let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition)); if let Some(layout) = render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None) @@ -757,23 +782,23 @@ fn closure_ty( format_to!( markup, "\n{}\n```{adjusted}\n\n## Captures\n{}", - c.display_with_impl(sema.db), + c.display_with_impl(sema.db, edition), captures_rendered, ); let mut res = HoverResult::default(); - if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) { res.actions.push(actions); } res.markup = markup.into(); Some(res) } -fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { +fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> { if matches!(def, Definition::GenericParam(_) | Definition::Local(_) | Definition::Label(_)) { return None; } - 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, edition), edition)) } fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup { @@ -792,12 +817,16 @@ fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Marku buf.into() } -fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> { +fn find_std_module( + famous_defs: &FamousDefs<'_, '_>, + name: &str, + edition: Edition, +) -> Option<hir::Module> { let db = famous_defs.0.db; let std_crate = famous_defs.std()?; let std_root_module = std_crate.root_module(); std_root_module.children(db).find(|module| { - module.name(db).map_or(false, |module| module.display(db).to_string() == name) + module.name(db).map_or(false, |module| module.display(db, edition).to_string() == name) }) } @@ -888,6 +917,7 @@ fn keyword_hints( sema: &Semantics<'_, RootDatabase>, token: &SyntaxToken, parent: syntax::SyntaxNode, + edition: Edition, ) -> KeywordHint { match token.kind() { T![await] | T![loop] | T![match] | T![unsafe] | T![as] | T![try] | T![if] | T![else] => { @@ -905,12 +935,12 @@ fn keyword_hints( walk_and_push_ty(sema.db, &ty.original, &mut push_new_def); let ty = ty.adjusted(); - let description = format!("{}: {}", token.text(), ty.display(sema.db)); + let description = format!("{}: {}", token.text(), ty.display(sema.db, edition)); KeywordHint { description, keyword_mod, - actions: HoverAction::goto_type_from_targets(sema.db, targets) + actions: HoverAction::goto_type_from_targets(sema.db, targets, edition) .into_iter() .collect(), } |