Show types in hover messages

This commit is contained in:
oxalica 2022-11-07 09:34:24 +08:00
parent 8e4b0d6764
commit 2cd3354204
2 changed files with 27 additions and 21 deletions

View file

@ -1,5 +1,5 @@
use crate::def::{AstPtr, Expr, ResolveResult};
use crate::{DefDatabase, FilePos, NameKind};
use crate::{FilePos, NameKind, TyDatabase};
use builtin::ALL_BUILTINS;
use rowan::ast::AstNode;
use rowan::TextRange;
@ -12,10 +12,7 @@ pub struct HoverResult {
pub markup: String,
}
pub(crate) fn hover(
db: &dyn DefDatabase,
FilePos { file_id, pos }: FilePos,
) -> Option<HoverResult> {
pub(crate) fn hover(db: &dyn TyDatabase, FilePos { file_id, pos }: FilePos) -> Option<HoverResult> {
let parse = db.parse(file_id);
let tok = best_token_at_offset(&parse.syntax_node(), pos)?;
let ptr = tok.parent_ancestors().find_map(|node| {
@ -34,6 +31,7 @@ pub(crate) fn hover(
let module = db.module(file_id);
let source_map = db.source_map(file_id);
let nameres = db.name_resolution(file_id);
let infer = db.infer(file_id);
let mut name = None;
@ -42,6 +40,7 @@ pub(crate) fn hover(
None => {}
Some(ResolveResult::Builtin(name)) => {
let b = &ALL_BUILTINS[*name];
// TODO: Types of builtins.
let markup = format!(
"{}\n\n{}",
b.summary,
@ -54,7 +53,8 @@ pub(crate) fn hover(
Expr::Reference(text) => text,
_ => return None,
};
let mut markup = format!("Attribute `{}` from:", text);
let ty = infer.display_ty(infer.ty_for_expr(expr)).to_string();
let mut markup = format!("`with` attribute `{text}`: `{ty}`");
for (&expr, i) in withs.iter().zip(1..) {
let ptr = source_map.node_for_expr(expr)?;
let with_node = ast::With::cast(ptr.to_node(&parse.syntax_node()))?;
@ -72,6 +72,7 @@ pub(crate) fn hover(
}
if let Some(name) = name.or_else(|| source_map.name_for_node(ptr.clone())) {
let ty = infer.display_ty(infer.ty_for_name(name)).to_string();
let text = &module[name].text;
let kind = match module[name].kind {
NameKind::LetIn => "Let binding",
@ -82,7 +83,7 @@ pub(crate) fn hover(
};
return Some(HoverResult {
range,
markup: format!("{kind} `{text}`"),
markup: format!("{kind} `{text}`: `{ty}`"),
});
}
@ -111,33 +112,37 @@ mod tests {
#[test]
fn definition() {
check("let $0a = 1; in a", "a", expect!["Let binding `a`"]);
check("let a.$0a = 1; in a", "a", expect!["Attrset attribute `a`"]);
check("{ $0a = 1; }", "a", expect!["Attrset attribute `a`"]);
check("let $0a = 1; in a", "a", expect!["Let binding `a`: `int`"]);
check(
"let a.$0a = 1; in a",
"a",
expect!["Attrset attribute `a`: `int`"],
);
check("{ $0a = 1; }", "a", expect!["Attrset attribute `a`: `int`"]);
check(
"rec { $0a = 1; }",
"a",
expect!["Rec-attrset attribute `a`"],
expect!["Rec-attrset attribute `a`: `int`"],
);
check("$0a: a", "a", expect!["Parameter `a`"]);
check("{$0a}: a", "a", expect!["Field parameter `a`"]);
check("$0a: a", "a", expect!["Parameter `a`: `?`"]);
check("{$0a}: a", "a", expect!["Field parameter `a`: `?`"]);
}
#[test]
fn reference() {
check("let a = 1; in $0a", "a", expect!["Let binding `a`"]);
check("let a = 1; in $0a", "a", expect!["Let binding `a`: `int`"]);
check(
"let a = 1; in { inherit $0a; }",
"a",
expect!["Let binding `a`"],
expect!["Let binding `a`: `int`"],
);
check(
"let a = 1; in rec { inherit $0a; }",
"a",
expect!["Let binding `a`"],
expect!["Let binding `a`: `int`"],
);
check("a: $0a", "a", expect!["Parameter `a`"]);
check("{a}: $0a", "a", expect!["Field parameter `a`"]);
check("a: $0a", "a", expect!["Parameter `a`: `?`"]);
check("{a}: $0a", "a", expect!["Field parameter `a`: `?`"]);
}
#[test]
@ -146,7 +151,7 @@ mod tests {
"with 1; $0a",
"a",
expect![[r#"
Attribute `a` from:
`with` attribute `a`: `?`
1. `with 1;`
"#]],
);
@ -154,7 +159,7 @@ mod tests {
"with 1; with 2; $0a",
"a",
expect![[r#"
Attribute `a` from:
`with` attribute `a`: `?`
1. `with 2;`
2. `with 1;`
"#]],

View file

@ -10,6 +10,7 @@ mod syntax_highlighting;
use crate::base::SourceDatabaseStorage;
use crate::def::DefDatabaseStorage;
use crate::ty::TyDatabaseStorage;
use crate::{Change, Diagnostic, FileId, FilePos, FileRange, WorkspaceEdit};
use rowan::TextRange;
use salsa::{Database, Durability, ParallelDatabase};
@ -34,7 +35,7 @@ pub use salsa::Cancelled;
pub type Cancellable<T> = Result<T, Cancelled>;
#[salsa::database(SourceDatabaseStorage, DefDatabaseStorage)]
#[salsa::database(SourceDatabaseStorage, DefDatabaseStorage, TyDatabaseStorage)]
#[derive(Default)]
pub struct RootDatabase {
storage: salsa::Storage<Self>,