Skip to content

Commit

Permalink
Tweak type formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
oxalica committed Nov 7, 2022
1 parent e8659c2 commit f43380d
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 34 deletions.
93 changes: 75 additions & 18 deletions crates/ide/src/ty/fmt.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
//! TODO: Limit type length.
use super::{InferenceResult, Ty, TyKind};
use std::fmt;

const MAX_FIELD_CNT: usize = 8;

#[derive(Clone, Copy)]
pub struct TyDisplay<'a> {
ty: Ty,
infer: &'a InferenceResult,
depth: usize,
in_param: bool,
}

impl<'a> TyDisplay<'a> {
pub fn new(ty: Ty, infer: &'a InferenceResult) -> Self {
Self { ty, infer }
}

fn with(self, ty: Ty) -> Self {
Self::new(ty, self.infer)
pub fn new(ty: Ty, infer: &'a InferenceResult, depth: usize) -> Self {
Self {
ty,
infer,
depth,
in_param: false,
}
}
}

Expand All @@ -27,21 +31,74 @@ impl fmt::Display for TyDisplay<'_> {
TyKind::Float => "float".fmt(f),
TyKind::String => "string".fmt(f),
TyKind::Path => "path".fmt(f),
&TyKind::List(elem) => write!(f, "[{}]", self.with(elem)),
&TyKind::Lambda(a, b) => write!(f, "{} -> {}", self.with(a), self.with(b)),
&TyKind::List(ty) => {
if self.depth == 0 {
"[…]".fmt(f)
} else {
let elem = Self {
ty,
infer: self.infer,
depth: self.depth - 1,
in_param: false,
};
write!(f, "[{}]", elem)
}
}
&TyKind::Lambda(param, ret) => {
if self.in_param {
"(".fmt(f)?;
}
if self.depth == 0 {
"… → …".fmt(f)?;
} else {
let param = Self {
ty: param,
infer: self.infer,
// Show full lambda type.
depth: self.depth,
in_param: true,
};
let ret = Self {
ty: ret,
infer: self.infer,
// Show full lambda type.
depth: self.depth,
in_param: false,
};
write!(f, "{} → {}", param, ret)?;
}
if self.in_param {
")".fmt(f)?;
}
Ok(())
}
TyKind::Attrset(set) => {
write!(f, "{{")?;
let mut first = true;
for (name, ty) in set.iter() {
if first {
first = false;
if self.depth == 0 {
"{ … }".fmt(f)
} else {
"{".fmt(f)?;
let mut first = true;
for (name, ty) in set.iter().take(MAX_FIELD_CNT) {
if first {
first = false;
} else {
",".fmt(f)?;
}
// FIXME: Escape field names.
let value = Self {
ty,
infer: self.infer,
depth: self.depth - 1,
in_param: false,
};
write!(f, " {}: {}", name, value)?;
}
if set.len() > MAX_FIELD_CNT {
", … }".fmt(f)
} else {
write!(f, ",")?;
" }".fmt(f)
}
// FIXME: Escape field names.
write!(f, " {}: {}", name, self.with(ty))?;
}
write!(f, " }}")
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion crates/ide/src/ty/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ impl TyKind {
pub struct Attrset(BTreeMap<SmolStr, Ty>);

impl Attrset {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}

pub fn len(&self) -> usize {
self.0.len()
}

pub fn get(&self, field: &str) -> Option<Ty> {
self.0.get(field).copied()
}
Expand Down Expand Up @@ -85,7 +93,11 @@ impl InferenceResult {
}

pub fn display_ty(&self, ty: Ty) -> TyDisplay<'_> {
TyDisplay::new(ty, self)
TyDisplay::new(ty, self, 2)
}

pub fn debug_ty(&self, ty: Ty) -> TyDisplay<'_> {
TyDisplay::new(ty, self, usize::MAX)
}
}

Expand Down
24 changes: 9 additions & 15 deletions crates/ide/src/ty/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn check(src: &str, expect: Expect) {
let module = db.module(file);
let infer = db.infer(file);
let ty = infer.ty_for_expr(module.entry_expr());
let got = infer.display_ty(ty).to_string();
let got = infer.debug_ty(ty).to_string();
expect.assert_eq(&got);
}

Expand All @@ -17,16 +17,10 @@ fn check_all(src: &str, expect: Expect) {
let infer = db.infer(file);
let got = module
.names()
.map(|(i, name)| {
format!(
"{}: {}\n",
name.text,
infer.display_ty(infer.ty_for_name(i))
)
})
.map(|(i, name)| format!("{}: {}\n", name.text, infer.debug_ty(infer.ty_for_name(i))))
.chain([format!(
": {}\n",
infer.display_ty(infer.ty_for_expr(module.entry_expr()))
infer.debug_ty(infer.ty_for_expr(module.entry_expr()))
)])
.collect::<String>();
expect.assert_eq(&got);
Expand Down Expand Up @@ -116,32 +110,32 @@ fn if_then_else() {

#[test]
fn lambda() {
check("a: a", expect!["? -> ?"]);
check("a: a", expect!["? ?"]);
check("(a: a) 1", expect!["int"]);

check("{ }: 1", expect!["{ } -> int"]);
check("{ }: 1", expect!["{ } int"]);
check_all(
"{ a ? b, b ? 42 }@c: b",
expect![[r#"
c: { a: int, b: int }
a: int
b: int
: { a: int, b: int } -> int
: { a: int, b: int } int
"#]],
);
}

#[test]
fn select() {
check("a: a.b.c", expect!["{ b: { c: ? } } -> ?"]);
check("a: a.b.c or 42", expect!["{ b: { c: int } } -> int"]);
check("a: a.b.c", expect!["{ b: { c: ? } } ?"]);
check("a: a.b.c or 42", expect!["{ b: { c: int } } int"]);

check_all(
"a: b: a.${b}",
expect![[r#"
a: { }
b: string
: { } -> string -> ?
: { } string ?
"#]],
);
}

0 comments on commit f43380d

Please sign in to comment.