mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 17:58:17 +00:00
feat: infer types of show rule transformers (#1045)
* feat: infer types of show rule transformers * test: add test for show rules * feat: more selector cases * test: update snapshot
This commit is contained in:
parent
458695b3a0
commit
5db1cf984a
8 changed files with 119 additions and 4 deletions
|
@ -1,5 +1,7 @@
|
|||
//! Type checking on source file
|
||||
|
||||
use typst::foundations::{Element, Type};
|
||||
|
||||
use super::*;
|
||||
use crate::analysis::ParamAttrs;
|
||||
use crate::docs::{SignatureDocsT, TypelessParamDocs, UntypedDefDocs};
|
||||
|
@ -434,13 +436,66 @@ impl TypeChecker<'_> {
|
|||
}
|
||||
|
||||
fn check_show(&mut self, show: &Interned<ShowExpr>) -> Ty {
|
||||
let _selector = show.selector.as_ref().map(|sel| self.check(sel));
|
||||
// todo: infer it type by selector
|
||||
let _transform = self.check(&show.edit);
|
||||
let selector = show.selector.as_ref().map(|sel| self.check(sel));
|
||||
let transform = self.check(&show.edit);
|
||||
|
||||
self.constraint_show(selector, transform);
|
||||
Ty::Builtin(BuiltinTy::None)
|
||||
}
|
||||
|
||||
fn constraint_show(&mut self, selector: Option<Ty>, transform: Ty) -> Option<()> {
|
||||
crate::log_debug_ct!("show on {selector:?}, transform {transform:?}");
|
||||
|
||||
let selected = match selector {
|
||||
Some(selector) => Self::content_by_selector(selector)?,
|
||||
None => Ty::Builtin(BuiltinTy::Content),
|
||||
};
|
||||
|
||||
let show_fact = Ty::Func(SigTy::unary(selected, Ty::Any));
|
||||
crate::log_debug_ct!("check show_fact type {show_fact:?} value: {transform:?}");
|
||||
self.constrain(&transform, &show_fact);
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn content_by_selector(selector: Ty) -> Option<Ty> {
|
||||
crate::log_debug_ct!("check selector {selector:?}");
|
||||
|
||||
Some(match selector {
|
||||
Ty::With(with) => return Self::content_by_selector(with.sig.as_ref().clone()),
|
||||
Ty::Builtin(BuiltinTy::Type(ty)) => {
|
||||
if ty == Type::of::<typst::foundations::Regex>() {
|
||||
Ty::Builtin(BuiltinTy::Element(Element::of::<typst::text::TextElem>()))
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Ty::Builtin(BuiltinTy::Element(..)) => selector,
|
||||
Ty::Value(ins_ty) => match &ins_ty.val {
|
||||
Value::Str(..) => {
|
||||
Ty::Builtin(BuiltinTy::Element(Element::of::<typst::text::TextElem>()))
|
||||
}
|
||||
Value::Content(c) => Ty::Builtin(BuiltinTy::Element(c.elem())),
|
||||
Value::Func(f) => {
|
||||
if let Some(elem) = f.element() {
|
||||
Ty::Builtin(BuiltinTy::Element(elem))
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Value::Dyn(value) => {
|
||||
if value.ty() == Type::of::<typst::foundations::Regex>() {
|
||||
Ty::Builtin(BuiltinTy::Element(Element::of::<typst::text::TextElem>()))
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
},
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
// todo: merge with func call, and regard difference (may be here)
|
||||
fn check_set(&mut self, set: &Interned<SetExpr>) -> Ty {
|
||||
let callee = self.check(&set.target);
|
||||
|
|
|
@ -15,7 +15,7 @@ snapshot_kind: text
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "052",
|
||||
"sortText": "053",
|
||||
"textEdit": {
|
||||
"newText": "raw(${1:})",
|
||||
"range": {
|
||||
|
|
5
crates/tinymist-query/src/fixtures/type_check/show.typ
Normal file
5
crates/tinymist-query/src/fixtures/type_check/show.typ
Normal file
|
@ -0,0 +1,5 @@
|
|||
/// contains: text
|
||||
|
||||
#show regex(":\S+:"): it => it./* range 0..1 */
|
||||
|
||||
:test:
|
|
@ -0,0 +1,5 @@
|
|||
/// contains: text
|
||||
|
||||
#show raw: it => it./* range 0..1 */
|
||||
|
||||
:test:
|
|
@ -0,0 +1,5 @@
|
|||
/// contains: text
|
||||
|
||||
#show raw.where(block: false): it => it./* range 0..1 */
|
||||
|
||||
:test:
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/analysis.rs
|
||||
expression: result
|
||||
input_file: crates/tinymist-query/src/fixtures/type_check/show.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
"" = (Any) => Any.it
|
||||
"it" = Element(text)
|
||||
=====
|
||||
26..31 -> Type(regex)
|
||||
26..40 -> Type(regex)
|
||||
42..44 -> @it
|
||||
42..51 -> @
|
||||
48..50 -> @it
|
||||
48..51 -> @v"it".it
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/analysis.rs
|
||||
expression: result
|
||||
input_file: crates/tinymist-query/src/fixtures/type_check/show_raw.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
"" = (Any) => Any.it
|
||||
"it" = Element(raw)
|
||||
=====
|
||||
26..29 -> Func(raw)
|
||||
31..33 -> @it
|
||||
31..40 -> @
|
||||
37..39 -> @it
|
||||
37..40 -> @v"it".it
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/analysis.rs
|
||||
expression: result
|
||||
input_file: crates/tinymist-query/src/fixtures/type_check/show_raw_where.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
"" = (Any) => Any.it
|
||||
"it" = Element(raw)
|
||||
=====
|
||||
26..29 -> Func(raw)
|
||||
26..35 -> (Func(raw) | Func(raw).where)
|
||||
26..49 -> (Func(raw)).with(..("block": false) => any)
|
||||
51..53 -> @it
|
||||
51..60 -> @
|
||||
57..59 -> @it
|
||||
57..60 -> @v"it".it
|
Loading…
Add table
Add a link
Reference in a new issue