mirror of
https://github.com/oxalica/nil.git
synced 2025-12-23 09:19:49 +00:00
Show types in hover messages
This commit is contained in:
parent
8e4b0d6764
commit
2cd3354204
2 changed files with 27 additions and 21 deletions
|
|
@ -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;`
|
||||
"#]],
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue