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.rs154
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(&notable_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, &notable_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, &notable_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(),
}