Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit aafa40c

Browse files
bors[bot]danii
andauthored
11369: feat: Add type hint for keyword expression hovers r=Veykril a=danii Adds the return type of keywords to tool-tips where it makes sense. This applies to: `if`, `else`, `match`, `loop`, `unsafe` and `await`. Thanks to `@Veykril` for sharing the idea of putting return type highlighting on other keywords! ![image](https://user-images.githubusercontent.com/39541871/151611737-12325c23-a1f9-4fca-ae48-279b374bdcdf.png) Closes rust-lang#11359 Co-authored-by: Daniel Conley <[email protected]>
2 parents 014d3ef + 768804f commit aafa40c

File tree

1 file changed

+67
-9
lines changed

1 file changed

+67
-9
lines changed

crates/ide/src/hover/render.rs

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,22 +239,18 @@ pub(super) fn keyword(
239239
}
240240
let parent = token.parent()?;
241241
let famous_defs = FamousDefs(sema, sema.scope(&parent).krate());
242-
let keyword_mod = if token.kind() == T![fn] && ast::FnPtrType::cast(parent).is_some() {
243-
// treat fn keyword inside function pointer type as primitive
244-
format!("prim_{}", token.text())
245-
} else {
246-
// std exposes {}_keyword modules with docstrings on the root to document keywords
247-
format!("{}_keyword", token.text())
248-
};
242+
243+
let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent);
244+
249245
let doc_owner = find_std_module(&famous_defs, &keyword_mod)?;
250246
let docs = doc_owner.attrs(sema.db).docs()?;
251247
let markup = process_markup(
252248
sema.db,
253249
Definition::Module(doc_owner),
254-
&markup(Some(docs.into()), token.text().into(), None)?,
250+
&markup(Some(docs.into()), description, None)?,
255251
config,
256252
);
257-
Some(HoverResult { markup, actions: Default::default() })
253+
Some(HoverResult { markup, actions })
258254
}
259255

260256
pub(super) fn try_for_lint(attr: &ast::Attr, token: &SyntaxToken) -> Option<HoverResult> {
@@ -500,3 +496,65 @@ fn local(db: &RootDatabase, it: hir::Local) -> Option<Markup> {
500496
};
501497
markup(None, desc, None)
502498
}
499+
500+
struct KeywordHint {
501+
description: String,
502+
keyword_mod: String,
503+
actions: Vec<HoverAction>,
504+
}
505+
506+
impl KeywordHint {
507+
fn new(description: String, keyword_mod: String) -> Self {
508+
Self { description, keyword_mod, actions: Vec::default() }
509+
}
510+
}
511+
512+
fn keyword_hints(
513+
sema: &Semantics<RootDatabase>,
514+
token: &SyntaxToken,
515+
parent: syntax::SyntaxNode,
516+
) -> KeywordHint {
517+
match token.kind() {
518+
T![await] | T![loop] | T![match] | T![unsafe] | T![as] | T![try] | T![if] | T![else] => {
519+
let keyword_mod = format!("{}_keyword", token.text());
520+
521+
match ast::Expr::cast(parent).and_then(|site| sema.type_of_expr(&site)) {
522+
// ignore the unit type ()
523+
Some(ty) if !ty.adjusted.as_ref().unwrap_or(&ty.original).is_unit() => {
524+
let mut targets: Vec<hir::ModuleDef> = Vec::new();
525+
let mut push_new_def = |item: hir::ModuleDef| {
526+
if !targets.contains(&item) {
527+
targets.push(item);
528+
}
529+
};
530+
walk_and_push_ty(sema.db, &ty.original, &mut push_new_def);
531+
532+
let ty = ty.adjusted();
533+
let description = format!("{}: {}", token.text(), ty.display(sema.db));
534+
535+
KeywordHint {
536+
description,
537+
keyword_mod,
538+
actions: vec![HoverAction::goto_type_from_targets(sema.db, targets)],
539+
}
540+
}
541+
_ => KeywordHint {
542+
description: token.text().to_string(),
543+
keyword_mod,
544+
actions: Vec::new(),
545+
},
546+
}
547+
}
548+
549+
T![fn] => {
550+
let module = match ast::FnPtrType::cast(parent) {
551+
// treat fn keyword inside function pointer type as primitive
552+
Some(_) => format!("prim_{}", token.text()),
553+
None => format!("{}_keyword", token.text()),
554+
};
555+
KeywordHint::new(token.text().to_string(), module)
556+
}
557+
558+
_ => KeywordHint::new(token.text().to_string(), format!("{}_keyword", token.text())),
559+
}
560+
}

0 commit comments

Comments
 (0)