mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-04 02:08:17 +00:00
feat: type check labels with tolerating syntax error (#975)
* feat: type check labels with tolerating syntax error * fix: naming * fix: use and type
This commit is contained in:
parent
2f882378bc
commit
c430e3d051
5 changed files with 93 additions and 33 deletions
|
@ -189,19 +189,11 @@ impl<'a> PostTypeChecker<'a> {
|
|||
node.kind(),
|
||||
);
|
||||
|
||||
Ty::or(self_ty, contextual_self_ty)
|
||||
Ty::union(self_ty, contextual_self_ty)
|
||||
}
|
||||
|
||||
fn check_context_or(&mut self, context: &LinkedNode, context_ty: Option<Ty>) -> Option<Ty> {
|
||||
let checked_context = self.check(context);
|
||||
if checked_context.is_some() && context_ty.is_some() {
|
||||
let c = checked_context?;
|
||||
let s = context_ty?;
|
||||
|
||||
Some(Ty::from_types([c, s].into_iter()))
|
||||
} else {
|
||||
checked_context.or(context_ty)
|
||||
}
|
||||
fn check_or(&mut self, node: &LinkedNode, ty: Option<Ty>) -> Option<Ty> {
|
||||
Ty::union(self.check(node), ty)
|
||||
}
|
||||
|
||||
fn check_target(&mut self, node: Option<CheckTarget>, context_ty: Option<Ty>) -> Option<Ty> {
|
||||
|
@ -210,14 +202,14 @@ impl<'a> PostTypeChecker<'a> {
|
|||
};
|
||||
crate::log_debug_ct!("post check target: {node:?}");
|
||||
|
||||
match node {
|
||||
match &node {
|
||||
CheckTarget::Param {
|
||||
callee,
|
||||
args: _,
|
||||
target,
|
||||
is_set,
|
||||
} => {
|
||||
let callee = self.check_context_or(&callee, context_ty)?;
|
||||
let callee = self.check_or(callee, context_ty)?;
|
||||
crate::log_debug_ct!(
|
||||
"post check call target: ({callee:?})::{target:?} is_set: {is_set}"
|
||||
);
|
||||
|
@ -226,7 +218,7 @@ impl<'a> PostTypeChecker<'a> {
|
|||
crate::log_debug_ct!("post check call sig: {target:?} {sig:?}");
|
||||
let mut resp = SignatureReceiver::default();
|
||||
|
||||
match &target {
|
||||
match target {
|
||||
ParamTarget::Named(n) => {
|
||||
let ident = n.cast::<ast::Ident>()?.into();
|
||||
let ty = sig.primary().get_named(&ident)?;
|
||||
|
@ -255,7 +247,7 @@ impl<'a> PostTypeChecker<'a> {
|
|||
|
||||
// names
|
||||
for field in sig.primary().named() {
|
||||
if is_set && !field.attrs.settable {
|
||||
if *is_set && !field.attrs.settable {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -268,7 +260,7 @@ impl<'a> PostTypeChecker<'a> {
|
|||
Some(resp.finalize())
|
||||
}
|
||||
CheckTarget::Element { container, target } => {
|
||||
let container_ty = self.check_context_or(&container, context_ty)?;
|
||||
let container_ty = self.check_or(container, context_ty)?;
|
||||
crate::log_debug_ct!("post check element target: ({container_ty:?})::{target:?}");
|
||||
|
||||
let mut resp = SignatureReceiver::default();
|
||||
|
@ -276,8 +268,8 @@ impl<'a> PostTypeChecker<'a> {
|
|||
self.check_element_of(
|
||||
&container_ty,
|
||||
false,
|
||||
&container,
|
||||
&mut check_signature(&mut resp, &target),
|
||||
container,
|
||||
&mut check_signature(&mut resp, target),
|
||||
);
|
||||
|
||||
crate::log_debug_ct!("post check target iterated: {:?}", resp.bounds);
|
||||
|
@ -287,7 +279,7 @@ impl<'a> PostTypeChecker<'a> {
|
|||
container,
|
||||
is_before,
|
||||
} => {
|
||||
let container_ty = self.check_context_or(&container, context_ty)?;
|
||||
let container_ty = self.check_or(container, context_ty)?;
|
||||
crate::log_debug_ct!("post check paren target: {container_ty:?}::{is_before:?}");
|
||||
|
||||
let mut resp = SignatureReceiver::default();
|
||||
|
@ -299,7 +291,7 @@ impl<'a> PostTypeChecker<'a> {
|
|||
self.check_element_of(
|
||||
&container_ty,
|
||||
false,
|
||||
&container,
|
||||
container,
|
||||
&mut check_signature(&mut resp, &target),
|
||||
);
|
||||
|
||||
|
@ -311,11 +303,14 @@ impl<'a> PostTypeChecker<'a> {
|
|||
allow_package: true,
|
||||
}),
|
||||
)),
|
||||
CheckTarget::LabelError(..) => Some(Ty::Builtin(BuiltinTy::Label)),
|
||||
CheckTarget::Label(target) | CheckTarget::Normal(target) => {
|
||||
let ty = self.check_context_or(&target, context_ty)?;
|
||||
crate::log_debug_ct!("post check target normal: {ty:?}");
|
||||
Some(ty)
|
||||
CheckTarget::LabelError(target)
|
||||
| CheckTarget::Label(target)
|
||||
| CheckTarget::Normal(target) => {
|
||||
let label_ty = matches!(node, CheckTarget::LabelError(_))
|
||||
.then_some(Ty::Builtin(BuiltinTy::Label));
|
||||
let ty = self.check_or(target, context_ty);
|
||||
crate::log_debug_ct!("post check target normal: {ty:?} {label_ty:?}");
|
||||
ty.or(label_ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/// path: references.yaml
|
||||
tarry:
|
||||
type: Book
|
||||
title: Harry Potter and the Order of the Phoenix
|
||||
author: Rowling, J. K.
|
||||
volume: 5
|
||||
page-total: 768
|
||||
date: 2003-06-21
|
||||
|
||||
electronic:
|
||||
type: Web
|
||||
title: Ishkur's Guide to Electronic Music
|
||||
serial-number: v2.5
|
||||
author: Ishkur
|
||||
url: http://www.techno.org/electronic-music-guide/
|
||||
|
||||
-----
|
||||
/// path: base.typ
|
||||
|
||||
#set heading(numbering: "1.1")
|
||||
|
||||
= H <test>
|
||||
|
||||
#bibliography("references.yaml")
|
||||
|
||||
-----
|
||||
/// contains: tarry, test
|
||||
/// compile: base.typ
|
||||
|
||||
#cite(<t /* range -2..-1 */)
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/completion.rs
|
||||
description: Completion on t (56..57)
|
||||
expression: "JsonRepr::new_pure(results)"
|
||||
input_file: crates/tinymist-query/src/fixtures/completion/complete_half_label_cite.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
[
|
||||
{
|
||||
"isIncomplete": false,
|
||||
"items": [
|
||||
{
|
||||
"kind": 18,
|
||||
"label": "tarry",
|
||||
"labelDetails": {
|
||||
"description": "Harry Potter and the Order of the Phoenix"
|
||||
},
|
||||
"sortText": "003",
|
||||
"textEdit": {
|
||||
"newText": "tarry>",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 7,
|
||||
"line": 3
|
||||
},
|
||||
"start": {
|
||||
"character": 7,
|
||||
"line": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -561,15 +561,16 @@ pub fn get_check_target_by_context<'a>(
|
|||
context: LinkedNode<'a>,
|
||||
node: LinkedNode<'a>,
|
||||
) -> Option<CheckTarget<'a>> {
|
||||
use DerefTarget::*;
|
||||
let context_deref_target = get_deref_target(context.clone(), node.offset())?;
|
||||
let node_deref_target = get_deref_target(node.clone(), node.offset())?;
|
||||
|
||||
match context_deref_target {
|
||||
DerefTarget::Callee(callee)
|
||||
Callee(callee)
|
||||
if matches!(
|
||||
node_deref_target,
|
||||
DerefTarget::Normal(..) | DerefTarget::Label(..) | DerefTarget::Ref(..)
|
||||
) && !matches!(node_deref_target, DerefTarget::Callee(..)) =>
|
||||
Normal(..) | Label(..) | LabelError(..) | Ref(..)
|
||||
) && !matches!(node_deref_target, Callee(..)) =>
|
||||
{
|
||||
let parent = callee.parent()?;
|
||||
let args = match parent.cast::<ast::Expr>() {
|
||||
|
|
|
@ -144,11 +144,10 @@ impl Ty {
|
|||
matches!(self, Ty::Dict(..))
|
||||
}
|
||||
|
||||
pub(crate) fn or(ty: Option<Ty>, pos: Option<Ty>) -> Option<Ty> {
|
||||
Some(match (ty, pos) {
|
||||
(Some(ty), Some(pos)) => Ty::from_types([ty, pos].into_iter()),
|
||||
(Some(ty), None) => ty,
|
||||
(None, Some(pos)) => pos,
|
||||
pub(crate) fn union(lhs: Option<Ty>, rhs: Option<Ty>) -> Option<Ty> {
|
||||
Some(match (lhs, rhs) {
|
||||
(Some(lhs), Some(rhs)) => Ty::from_types([lhs, rhs].into_iter()),
|
||||
(Some(ty), None) | (None, Some(ty)) => ty,
|
||||
(None, None) => return None,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue