diff --git a/crates/tinymist-query/src/analysis/signature.rs b/crates/tinymist-query/src/analysis/signature.rs index b6cbb9d7..23ef593f 100644 --- a/crates/tinymist-query/src/analysis/signature.rs +++ b/crates/tinymist-query/src/analysis/signature.rs @@ -32,10 +32,8 @@ pub struct ParamSpec { pub name: Interned, /// Documentation for the parameter. pub docs: Cow<'static, str>, - /// Describe what values this parameter accepts. - pub input: CastInfo, /// Inferred type of the parameter. - pub(crate) base_type: Option, + pub(crate) base_type: Ty, /// The parameter's default name as type. pub type_repr: Option, /// The parameter's default name as value. @@ -60,7 +58,6 @@ impl ParamSpec { Arc::new(Self { name: p.name.into(), docs: Cow::Borrowed(p.docs), - input: p.input.clone(), base_type: Ty::from_param_site(f, p), type_repr: Some(eco_format!("{}", TypeExpr(&p.input))), expr: None, @@ -324,7 +321,7 @@ fn analyze_dyn_signature_inner(func: Func) -> Arc { Repr::With(..) => unreachable!(), Repr::Closure(c) => (analyze_closure_signature(c.clone()), None), Repr::Element(..) | Repr::Native(..) => { - let ret_ty = func.returns().and_then(|r| Ty::from_return_site(&func, r)); + let ret_ty = func.returns().map(|r| Ty::from_return_site(&func, r)); let params = func.params().unwrap(); ( params @@ -374,16 +371,16 @@ fn analyze_dyn_signature_inner(func: Func) -> Arc { let mut named_vec: Vec<(Interned, Ty)> = named .iter() - .map(|e| (e.0.clone(), e.1.base_type.clone().unwrap_or(Ty::Any))) + .map(|e| (e.0.clone(), e.1.base_type.clone())) .collect::>(); named_vec.sort_by(|a, b| a.0.cmp(&b.0)); let sig_ty = SigTy::new( - pos.iter().map(|e| e.base_type.clone().unwrap_or(Ty::Any)), + pos.iter().map(|e| e.base_type.clone()), named_vec, rest.as_ref() - .map(|e| e.base_type.clone().unwrap_or(Ty::Any)), + .map(|e| e.base_type.clone()), ret_ty.clone(), ); Arc::new(PrimarySignature { @@ -415,8 +412,7 @@ fn analyze_closure_signature(c: Arc>) -> Vec> { params.push(Arc::new(ParamSpec { name: name.as_str().into(), - input: CastInfo::Any, - base_type: None, + base_type: Ty::Any, type_repr: None, expr: None, default: None, @@ -432,8 +428,7 @@ fn analyze_closure_signature(c: Arc>) -> Vec> { let expr = unwrap_expr(n.expr()).to_untyped().clone().into_text(); params.push(Arc::new(ParamSpec { name: n.name().into(), - input: CastInfo::Any, - base_type: None, + base_type: Ty::Any, type_repr: Some(expr.clone()), expr: Some(expr.clone()), default: None, @@ -448,8 +443,7 @@ fn analyze_closure_signature(c: Arc>) -> Vec> { let ident = n.sink_ident().map(|e| e.as_str()); params.push(Arc::new(ParamSpec { name: ident.unwrap_or_default().into(), - input: CastInfo::Any, - base_type: None, + base_type: Ty::Any, type_repr: None, expr: None, default: None, diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin.typ.snap index d5695de3..0c2b94ae 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin.typ.snap @@ -3,4 +3,4 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/builtin.typ --- -1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "angle", docs: "The angle whose sine to calculate.", input: Union([Type(Type(integer)), Type(Type(float)), Type(Type(angle))]), base_type: Some((Type(integer) | Type(float) | Type(angle))), type_repr: Some("int | float | angle"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "angle", docs: "The angle whose sine to calculate.", base_type: (Type(integer) | Type(float) | Type(angle)), type_repr: Some("int | float | angle"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly.typ.snap index c5e31fc0..71867af6 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly.typ.snap @@ -3,6 +3,6 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/builtin_poly.typ --- -255 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "red", docs: "The red component.", input: Union([Type(Type(integer)), Type(Type(ratio))]), base_type: Some((Type(integer) | Type(ratio))), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } -255 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "green", docs: "The green component.", input: Union([Type(Type(integer)), Type(Type(ratio))]), base_type: Some((Type(integer) | Type(ratio))), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } -255 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "blue", docs: "The blue component.", input: Union([Type(Type(integer)), Type(Type(ratio))]), base_type: Some((Type(integer) | Type(ratio))), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +255 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "red", docs: "The red component.", base_type: (Type(integer) | Type(ratio)), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +255 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "green", docs: "The green component.", base_type: (Type(integer) | Type(ratio)), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +255 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "blue", docs: "The blue component.", base_type: (Type(integer) | Type(ratio)), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly2.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly2.typ.snap index 5cf645a6..294b7cfc 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly2.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@builtin_poly2.typ.snap @@ -3,4 +3,4 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/builtin_poly2.typ --- -"#fff" -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "red", docs: "The red component.", input: Union([Type(Type(integer)), Type(Type(ratio))]), base_type: Some((Type(integer) | Type(ratio))), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +"#fff" -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "red", docs: "The red component.", base_type: (Type(integer) | Type(ratio)), type_repr: Some("int | ratio"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user.typ.snap index 8ad470a2..fbd6be23 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user.typ.snap @@ -3,5 +3,5 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/user.typ --- -1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "x", docs: "", input: Any, base_type: None, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } -1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "y", docs: "", input: Any, base_type: None, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "x", docs: "", base_type: Any, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "y", docs: "", base_type: Any, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap index 95566cc8..ee9ecb4e 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap @@ -3,5 +3,5 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/user_named.typ --- -y: 1 -> CallParamInfo { kind: Named, is_content_block: false, param: ParamSpec { name: "y", docs: "Default value: none", input: Any, base_type: None, type_repr: Some("none"), expr: Some("none"), default: None, positional: false, named: true, variadic: false, settable: true } } -1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "x", docs: "", input: Any, base_type: None, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +y: 1 -> CallParamInfo { kind: Named, is_content_block: false, param: ParamSpec { name: "y", docs: "Default value: none", base_type: Any, type_repr: Some("none"), expr: Some("none"), default: None, positional: false, named: true, variadic: false, settable: true } } +1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "x", docs: "", base_type: Any, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with.typ.snap index 6f0f10b2..a81d94ea 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with.typ.snap @@ -3,4 +3,4 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/user_named_with.typ --- -1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "x", docs: "", input: Any, base_type: None, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "x", docs: "", base_type: Any, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with2.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with2.typ.snap index 8968f10d..db90414e 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with2.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named_with2.typ.snap @@ -3,4 +3,4 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/user_named_with2.typ --- -y: 1 -> CallParamInfo { kind: Named, is_content_block: false, param: ParamSpec { name: "y", docs: "Default value: none", input: Any, base_type: None, type_repr: Some("none"), expr: Some("none"), default: None, positional: false, named: true, variadic: false, settable: true } } +y: 1 -> CallParamInfo { kind: Named, is_content_block: false, param: ParamSpec { name: "y", docs: "Default value: none", base_type: Any, type_repr: Some("none"), expr: Some("none"), default: None, positional: false, named: true, variadic: false, settable: true } } diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_with.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_with.typ.snap index 4db097dd..370580b7 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_with.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_with.typ.snap @@ -3,4 +3,4 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/user_with.typ --- -1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "y", docs: "", input: Any, base_type: None, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } +1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "y", docs: "", base_type: Any, type_repr: None, expr: None, default: None, positional: true, named: false, variadic: false, settable: false } } diff --git a/crates/tinymist-query/src/signature_help.rs b/crates/tinymist-query/src/signature_help.rs index 20ebee9c..bcebd622 100644 --- a/crates/tinymist-query/src/signature_help.rs +++ b/crates/tinymist-query/src/signature_help.rs @@ -2,7 +2,7 @@ use once_cell::sync::OnceCell; use crate::{ adt::interner::Interned, - analysis::{analyze_dyn_signature, find_definition, Ty}, + analysis::{analyze_dyn_signature, find_definition, }, prelude::*, syntax::{get_check_target, get_deref_target, CheckTarget, ParamTarget}, DocTooltip, LspParamInfo, SemanticRequest, @@ -121,8 +121,7 @@ impl SemanticRequest for SignatureHelpRequest { label.push_str(&format!( "{}: {}", param.name, - ty.or_else(|| param.base_type.as_ref()) - .unwrap_or(&Ty::Any) + ty.unwrap_or(¶m.base_type) .describe() .as_deref() .unwrap_or("any") diff --git a/crates/tinymist-query/src/ty/builtin.rs b/crates/tinymist-query/src/ty/builtin.rs index 096b9521..f89ba6ff 100644 --- a/crates/tinymist-query/src/ty/builtin.rs +++ b/crates/tinymist-query/src/ty/builtin.rs @@ -99,31 +99,31 @@ impl Ty { } } - pub(crate) fn from_param_site(f: &Func, p: &ParamInfo) -> Option { + pub(crate) fn from_param_site(f: &Func, p: &ParamInfo) -> Ty { use typst::foundations::func::Repr; match f.inner() { Repr::Element(..) | Repr::Native(..) => { if let Some(ty) = param_mapping(f, p) { - return Some(ty); + return ty; } } Repr::Closure(_) => {} Repr::With(w) => return Ty::from_param_site(&w.0, p), }; - Some(Self::from_cast_info(&p.input)) + Self::from_cast_info(&p.input) } - pub(crate) fn from_return_site(f: &Func, c: &'_ CastInfo) -> Option { + pub(crate) fn from_return_site(f: &Func, c: &'_ CastInfo) -> Self { use typst::foundations::func::Repr; match f.inner() { - Repr::Element(e) => return Some(Ty::Builtin(BuiltinTy::Element(*e))), + Repr::Element(e) => return Ty::Builtin(BuiltinTy::Element(*e)), Repr::Closure(_) => {} Repr::With(w) => return Ty::from_return_site(&w.0, c), Repr::Native(_) => {} }; - Some(Self::from_cast_info(c)) + Self::from_cast_info(c) } } diff --git a/crates/tinymist-query/src/upstream/complete.rs b/crates/tinymist-query/src/upstream/complete.rs index 9c7cc46c..f8cc81d6 100644 --- a/crates/tinymist-query/src/upstream/complete.rs +++ b/crates/tinymist-query/src/upstream/complete.rs @@ -6,14 +6,12 @@ use ecow::{eco_format, EcoString}; use if_chain::if_chain; use serde::{Deserialize, Serialize}; use typst::foundations::{ - fields_on, format_str, mutable_methods_on, repr, AutoValue, CastInfo, Func, Label, NoneValue, - Repr, StyleChain, Styles, Type, Value, + fields_on, format_str, mutable_methods_on, repr, Repr, StyleChain, Styles, Value, }; use typst::model::Document; use typst::syntax::ast::AstNode; use typst::syntax::{ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind}; use typst::text::RawElem; -use typst::visualize::Color; use unscanny::Scanner; use super::{plain_docs_sentence, summarize_font_family}; @@ -1173,6 +1171,11 @@ impl<'a, 'w> CompletionContext<'a, 'w> { label_detail: Option, docs: Option<&str>, ) { + // Prevent duplicate completions from appearing. + if !self.seen_casts.insert(typst::util::hash128(value)) { + return; + } + let at = label.as_deref().is_some_and(|field| !is_ident(field)); let label = label.unwrap_or_else(|| value.repr()); @@ -1218,91 +1221,6 @@ impl<'a, 'w> CompletionContext<'a, 'w> { ..Completion::default() }); } - - /// Add completions for a castable. - fn cast_completions(&mut self, cast: &CastInfo) { - // Prevent duplicate completions from appearing. - if !self.seen_casts.insert(typst::util::hash128(cast)) { - return; - } - - match cast { - CastInfo::Any => {} - CastInfo::Value(value, docs) => { - self.value_completion(None, value, true, Some(docs)); - } - CastInfo::Type(ty) => { - if *ty == Type::of::() { - self.snippet_completion("none", "none", "Nothing.") - } else if *ty == Type::of::() { - self.snippet_completion("auto", "auto", "A smart default."); - } else if *ty == Type::of::() { - self.snippet_completion("false", "false", "No / Disabled."); - self.snippet_completion("true", "true", "Yes / Enabled."); - } else if *ty == Type::of::() { - self.snippet_completion("luma()", "luma(${v})", "A custom grayscale color."); - self.snippet_completion( - "rgb()", - "rgb(${r}, ${g}, ${b}, ${a})", - "A custom RGBA color.", - ); - self.snippet_completion( - "cmyk()", - "cmyk(${c}, ${m}, ${y}, ${k})", - "A custom CMYK color.", - ); - self.snippet_completion( - "oklab()", - "oklab(${l}, ${a}, ${b}, ${alpha})", - "A custom Oklab color.", - ); - self.snippet_completion( - "oklch()", - "oklch(${l}, ${chroma}, ${hue}, ${alpha})", - "A custom Oklch color.", - ); - self.snippet_completion( - "color.linear-rgb()", - "color.linear-rgb(${r}, ${g}, ${b}, ${a})", - "A custom linear RGBA color.", - ); - self.snippet_completion( - "color.hsv()", - "color.hsv(${h}, ${s}, ${v}, ${a})", - "A custom HSVA color.", - ); - self.snippet_completion( - "color.hsl()", - "color.hsl(${h}, ${s}, ${l}, ${a})", - "A custom HSLA color.", - ); - self.scope_completions(false, |value| value.ty() == *ty); - } else if *ty == Type::of::