feat: check field of literals (#1619)

* feat: check field of literals

* test: add more tests

* test: update snapshot
This commit is contained in:
Myriad-Dreamin 2025-04-06 20:33:26 +08:00 committed by GitHub
parent 7f5bb5dc45
commit e3f41f81ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 100 additions and 18 deletions

View file

@ -0,0 +1,4 @@
#text("A").text
#([A]./* ident after */text);

View file

@ -0,0 +1,2 @@
#("a"./* ident after */clusters());

View file

@ -0,0 +1,2 @@
#(()./* ident after */len());

View file

@ -0,0 +1,9 @@
---
source: crates/tinymist-query/src/hover.rs
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
input_file: crates/tinymist-query/src/fixtures/hover/content_field.typ
---
{
"contents": "### Sampled Values\n```typc\n\"A\"\n```",
"range": "2:23:2:27"
}

View file

@ -0,0 +1,9 @@
---
source: crates/tinymist-query/src/hover.rs
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
input_file: crates/tinymist-query/src/fixtures/hover/literal_method.typ
---
{
"contents": "```typc\nlet clusters(\n self: str,\n) = array;\n```\n\n---\n\nReturns the grapheme clusters of the string as an array of substrings.\n\n# Positional Parameters\n\n## self\n\n```typc\ntype: str\n```\n\n\n\n---\n\n[Open docs](https://typst.app/docs/reference/foundations/str/#definitions-clusters)",
"range": "0:23:0:31"
}

View file

@ -0,0 +1,9 @@
---
source: crates/tinymist-query/src/hover.rs
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
input_file: crates/tinymist-query/src/fixtures/hover/literal_method2.typ
---
{
"contents": "```typc\nlet len(\n self: array,\n) = int;\n```\n\n---\n\nThe number of values in the array.\n\n# Positional Parameters\n\n## self\n\n```typc\ntype: array\n```\n\n\n\n---\n\n[Open docs](https://typst.app/docs/reference/foundations/array/#definitions-len)",
"range": "0:22:0:25"
}

View file

@ -10,5 +10,5 @@ input_file: crates/tinymist-query/src/fixtures/type_check/tuple_at.typ
9..18 -> (1, 2, 3, )
25..26 -> @b
29..30 -> @a
29..33 -> @v"a".at
29..36 -> 2
29..33 -> (Func(at) | (Func(at) | @v"a".at))
29..36 -> (Any | 2)

View file

@ -7,7 +7,7 @@ input_file: crates/tinymist-query/src/fixtures/type_check/tuple_map.typ
"f" = ((Type(bytes) | Type(decimal) | Type(float) | Type(int) | Type(label) | Type(str) | Type(type) | Type(version))) => Type(str)
"" = ((Type(bytes) | Type(decimal) | Type(float) | Type(int) | Type(label) | Type(str) | Type(type) | Type(version))) => Type(str)
"x" = Type(int)
"b" = (Type(str), )
"b" = (Type(array) | ((Type(array) | Type(str)), ))
=====
5..6 -> @a
9..13 -> (1, )
@ -19,6 +19,6 @@ input_file: crates/tinymist-query/src/fixtures/type_check/tuple_map.typ
33..34 -> @x
42..43 -> @b
46..47 -> @a
46..51 -> @v"a".map
46..54 -> (Type(str), )
46..51 -> (Func(map) | (Func(map) | @v"a".map))
46..54 -> (Type(array) | ((Type(array) | Type(str)), ))
52..53 -> @f

View file

@ -60,7 +60,9 @@ impl Iface<'_> {
crate::log_debug_ct!("iface shape: {self:?}");
match self {
Iface::Array(..) | Iface::Tuple(..) => None,
Iface::Array(..) | Iface::Tuple(..) => {
select_scope(Some(Type::of::<typst::foundations::Array>().scope()), key)
}
Iface::Dict(dict) => dict.field_by_name(key).cloned(),
Iface::Content { val, .. } => select_scope(Some(val.scope()), key),
// todo: distinguish TypeType and Type
@ -123,23 +125,14 @@ impl BoundChecker for IfaceCheckDriver<'_> {
impl IfaceCheckDriver<'_> {
fn array_as_iface(&self) -> bool {
// matches!(
// self.ctx.sig_kind,
// SigSurfaceKind::DictIface | SigSurfaceKind::ArrayOrDict
// )
true
}
fn dict_as_iface(&self) -> bool {
// matches!(
// self.ctx.sig_kind,
// SigSurfaceKind::DictIface | SigSurfaceKind::ArrayOrDict
// )
true
}
fn value_as_iface(&self) -> bool {
// matches!(self.ctx.sig_kind, SigSurfaceKind::Func)
true
}
@ -171,8 +164,8 @@ impl IfaceCheckDriver<'_> {
self.checker
.check(Iface::Dict(&FLOW_TEXT_FONT_DICT), &mut self.ctx, pol);
}
// // todo: deduplicate checking early
Ty::Value(ins_ty) => {
// todo: deduplicate checking early
if self.value_as_iface() {
match &ins_ty.val {
Value::Module(val) => {
@ -191,7 +184,41 @@ impl IfaceCheckDriver<'_> {
self.checker
.check(Iface::Func { val: func, at }, &mut self.ctx, pol);
}
_ => {}
Value::None
| Value::Auto
| Value::Bool(_)
| Value::Int(_)
| Value::Float(_)
| Value::Length(..)
| Value::Angle(..)
| Value::Ratio(..)
| Value::Relative(..)
| Value::Fraction(..)
| Value::Color(..)
| Value::Gradient(..)
| Value::Tiling(..)
| Value::Symbol(..)
| Value::Version(..)
| Value::Str(..)
| Value::Bytes(..)
| Value::Label(..)
| Value::Datetime(..)
| Value::Decimal(..)
| Value::Duration(..)
| Value::Content(..)
| Value::Styles(..)
| Value::Array(..)
| Value::Args(..)
| Value::Dyn(..) => {
self.checker.check(
Iface::Type {
val: &ins_ty.val.ty(),
at,
},
&mut self.ctx,
pol,
);
}
}
}
}
@ -226,7 +253,7 @@ impl IfaceCheckDriver<'_> {
.check(Iface::Module { val: m.fid, at }, &mut self.ctx, pol);
}
}
// Ty::Func(sig) if self.value_as_iface() => {
// Ty::Func(..) if self.value_as_iface() => {
// self.checker.check(Iface::Type(sig), &mut self.ctx, pol);
// }
// Ty::Array(sig) if self.array_as_sig() => {
@ -247,6 +274,26 @@ impl IfaceCheckDriver<'_> {
// self.check_dict_signature(sig, pol, self.checker);
self.checker.check(Iface::Array(sig), &mut self.ctx, pol);
}
Ty::Dict(..) => {
self.checker.check(
Iface::Type {
val: &Type::of::<typst::foundations::Dict>(),
at,
},
&mut self.ctx,
pol,
);
}
Ty::Tuple(..) | Ty::Array(..) => {
self.checker.check(
Iface::Type {
val: &Type::of::<typst::foundations::Array>(),
at,
},
&mut self.ctx,
pol,
);
}
Ty::Var(..) => at.bounds(pol, self),
_ if at.has_bounds() => at.bounds(pol, self),
_ => {}