feat: remove cast completion (#348)

* feat: remove cast completion

* fix: update snapshot
This commit is contained in:
Myriad-Dreamin 2024-06-27 15:42:40 +08:00 committed by GitHub
parent 00ec24e18f
commit a3724bc87f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 77 additions and 181 deletions

View file

@ -32,10 +32,8 @@ pub struct ParamSpec {
pub name: Interned<str>,
/// 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<Ty>,
pub(crate) base_type: Ty,
/// The parameter's default name as type.
pub type_repr: Option<EcoString>,
/// 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<PrimarySignature> {
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<PrimarySignature> {
let mut named_vec: Vec<(Interned<str>, 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::<Vec<_>>();
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<LazyHash<Closure>>) -> Vec<Arc<ParamSpec>> {
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<LazyHash<Closure>>) -> Vec<Arc<ParamSpec>> {
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<LazyHash<Closure>>) -> Vec<Arc<ParamSpec>> {
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,

View file

@ -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 } }

View file

@ -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 } }

View file

@ -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 } }

View file

@ -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 } }

View file

@ -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 } }

View file

@ -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 } }

View file

@ -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 } }

View file

@ -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 } }

View file

@ -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(&param.base_type)
.describe()
.as_deref()
.unwrap_or("any")

View file

@ -99,31 +99,31 @@ impl Ty {
}
}
pub(crate) fn from_param_site(f: &Func, p: &ParamInfo) -> Option<Ty> {
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<Self> {
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)
}
}

View file

@ -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<EcoString>,
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::<NoneValue>() {
self.snippet_completion("none", "none", "Nothing.")
} else if *ty == Type::of::<AutoValue>() {
self.snippet_completion("auto", "auto", "A smart default.");
} else if *ty == Type::of::<bool>() {
self.snippet_completion("false", "false", "No / Disabled.");
self.snippet_completion("true", "true", "Yes / Enabled.");
} else if *ty == Type::of::<Color>() {
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::<Label>() {
self.label_completions()
} else if *ty == Type::of::<Func>() {
self.snippet_completion(
"function",
"(${params}) => ${output}",
"A custom function.",
);
} else {
self.completions.push(Completion {
kind: CompletionKind::Syntax,
label: ty.long_name().into(),
apply: Some(eco_format!("${{{ty}}}")),
detail: Some(eco_format!("A value of type {ty}.")),
..Completion::default()
});
self.scope_completions(false, |value| value.ty() == *ty);
}
}
CastInfo::Union(union) => {
for info in union {
self.cast_completions(info);
}
}
}
}
}
/// Slices a smaller string at character boundaries safely.

View file

@ -2,6 +2,7 @@ use std::collections::BTreeMap;
use ecow::{eco_format, EcoString};
use lsp_types::{CompletionItem, CompletionTextEdit, InsertTextFormat, TextEdit};
use once_cell::sync::OnceCell;
use reflexo::path::{unix_slash, PathClean};
use typst::foundations::{AutoValue, Func, Label, NoneValue, Repr, Type, Value};
use typst::layout::{Dir, Length};
@ -608,16 +609,14 @@ pub fn param_completions<'a>(
doc = Some(plain_docs_sentence(&pos.docs));
if pos.positional
&& type_completion(ctx, pos.base_type.as_ref(), doc.as_deref()).is_none()
{
ctx.cast_completions(&pos.input);
if pos.positional {
type_completion(ctx, &pos.base_type, doc.as_deref());
}
}
}
if let Some(leaf_type) = leaf_type {
type_completion(ctx, Some(&leaf_type), doc.as_deref());
type_completion(ctx, &leaf_type, doc.as_deref());
}
for (name, param) in &primary_sig.named {
@ -629,18 +628,21 @@ pub fn param_completions<'a>(
continue;
}
let _d = OnceCell::new();
let docs = || Some(_d.get_or_init(|| plain_docs_sentence(&param.docs)).clone());
if param.named {
let compl = Completion {
kind: CompletionKind::Field,
label: param.name.as_ref().into(),
apply: Some(eco_format!("{}: ${{}}", param.name)),
detail: Some(plain_docs_sentence(&param.docs)),
detail: docs(),
label_detail: None,
command: Some("tinymist.triggerNamedCompletion"),
..Completion::default()
};
match param.base_type {
Some(Ty::Builtin(BuiltinTy::TextSize)) => {
Ty::Builtin(BuiltinTy::TextSize) => {
for size_template in &[
"10.5pt", "12pt", "9pt", "14pt", "8pt", "16pt", "18pt", "20pt", "22pt",
"24pt", "28pt",
@ -653,7 +655,7 @@ pub fn param_completions<'a>(
});
}
}
Some(Ty::Builtin(BuiltinTy::Dir)) => {
Ty::Builtin(BuiltinTy::Dir) => {
for dir_template in &["ltr", "rtl", "ttb", "btt"] {
let compl = compl.clone();
ctx.completions.push(Completion {
@ -668,15 +670,8 @@ pub fn param_completions<'a>(
ctx.completions.push(compl);
}
if param.positional
&& type_completion(
ctx,
param.base_type.as_ref(),
Some(&plain_docs_sentence(&param.docs)),
)
.is_none()
{
ctx.cast_completions(&param.input);
if param.positional {
type_completion(ctx, &param.base_type, docs().as_deref());
}
}
@ -688,19 +683,17 @@ pub fn param_completions<'a>(
fn type_completion(
ctx: &mut CompletionContext<'_, '_>,
infer_type: Option<&Ty>,
infer_type: &Ty,
docs: Option<&str>,
) -> Option<()> {
// Prevent duplicate completions from appearing.
if let Some(infer_type) = infer_type {
if !ctx.seen_types.insert(infer_type.clone()) {
return Some(());
}
if !ctx.seen_types.insert(infer_type.clone()) {
return Some(());
}
log::debug!("type_completion: {:?}", infer_type);
match infer_type? {
match infer_type {
Ty::Any => return None,
Ty::Tuple(..) | Ty::Array(..) => {
ctx.snippet_completion("()", "(${})", "An array.");
@ -752,8 +745,8 @@ fn type_completion(
BuiltinTy::Stroke => {
ctx.snippet_completion("stroke()", "stroke(${})", "Stroke type.");
ctx.snippet_completion("()", "(${})", "Stroke dictionary.");
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Color)), docs);
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Length)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Color), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Length), docs);
}
BuiltinTy::Color => {
ctx.snippet_completion("luma()", "luma(${v})", "A custom grayscale color.");
@ -831,19 +824,19 @@ fn type_completion(
}
BuiltinTy::Margin => {
ctx.snippet_completion("()", "(${})", "Margin dictionary.");
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Length)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Length), docs);
}
BuiltinTy::Inset => {
ctx.snippet_completion("()", "(${})", "Inset dictionary.");
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Length)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Length), docs);
}
BuiltinTy::Outset => {
ctx.snippet_completion("()", "(${})", "Outset dictionary.");
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Length)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Length), docs);
}
BuiltinTy::Radius => {
ctx.snippet_completion("()", "(${})", "Radius dictionary.");
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Length)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Length), docs);
}
BuiltinTy::Length => {
ctx.snippet_completion("pt", "${1}pt", "Point length unit.");
@ -853,21 +846,23 @@ fn type_completion(
ctx.snippet_completion("em", "${1}em", "Em length unit.");
let length_ty = Type::of::<Length>();
ctx.strict_scope_completions(false, |value| value.ty() == length_ty);
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Auto)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Auto), docs);
}
BuiltinTy::Float => {
ctx.snippet_completion("exponential notation", "${1}e${0}", "Exponential notation");
}
BuiltinTy::Type(ty) => {
if *ty == Type::of::<NoneValue>() {
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::None)), docs);
let docs = docs.or(Some("Nothing."));
type_completion(ctx, &Ty::Builtin(BuiltinTy::None), docs);
} else if *ty == Type::of::<AutoValue>() {
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Auto)), docs);
let docs = docs.or(Some("A smart default."));
type_completion(ctx, &Ty::Builtin(BuiltinTy::Auto), docs);
} else if *ty == Type::of::<bool>() {
ctx.snippet_completion("false", "false", "No / Disabled.");
ctx.snippet_completion("true", "true", "Yes / Enabled.");
} else if *ty == Type::of::<Color>() {
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Color)), None);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Color), docs);
} else if *ty == Type::of::<Label>() {
ctx.label_completions()
} else if *ty == Type::of::<Func>() {
@ -897,15 +892,15 @@ fn type_completion(
Ty::Select(_) => return None,
Ty::Union(u) => {
for info in u.as_ref() {
type_completion(ctx, Some(info), docs);
type_completion(ctx, info, docs);
}
}
Ty::Let(e) => {
for ut in e.ubs.iter() {
type_completion(ctx, Some(ut), docs);
type_completion(ctx, ut, docs);
}
for lt in e.lbs.iter() {
type_completion(ctx, Some(lt), docs);
type_completion(ctx, lt, docs);
}
}
Ty::Var(_) => return None,
@ -915,17 +910,12 @@ fn type_completion(
Ty::Value(v) => {
let docs = v.syntax.as_ref().map(|s| s.doc.as_ref()).or(docs);
// Prevent duplicate completions from appearing.
if !ctx.seen_casts.insert(typst::util::hash128(&v.val)) {
return Some(());
}
if let Value::Type(ty) = &v.val {
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Type(*ty))), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Type(*ty)), docs);
} else if v.val.ty() == Type::of::<NoneValue>() {
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::None)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::None), docs);
} else if v.val.ty() == Type::of::<AutoValue>() {
type_completion(ctx, Some(&Ty::Builtin(BuiltinTy::Auto)), docs);
type_completion(ctx, &Ty::Builtin(BuiltinTy::Auto), docs);
} else {
ctx.value_completion(None, &v.val, true, docs);
}
@ -949,7 +939,7 @@ pub fn named_param_value_completions<'a>(
else {
// static analysis
if let Some(ty) = ty {
type_completion(ctx, Some(ty), None);
type_completion(ctx, ty, None);
}
return;
@ -987,13 +977,18 @@ pub fn named_param_value_completions<'a>(
// static analysis
if let Some(ty) = ty {
type_completion(ctx, Some(ty), doc.as_deref());
type_completion(ctx, ty, doc.as_deref());
}
let mut completed = false;
if let Some(type_sig) = leaf_type {
log::debug!("named_param_completion by type: {:?}", param);
type_completion(ctx, Some(&type_sig), doc.as_deref());
type_completion(ctx, &type_sig, doc.as_deref());
completed = true;
}
if !matches!(param.base_type, Ty::Any) {
type_completion(ctx, &param.base_type, doc.as_deref());
completed = true;
}
@ -1009,16 +1004,6 @@ pub fn named_param_value_completions<'a>(
}
}
if type_completion(
ctx,
param.base_type.as_ref(),
Some(&plain_docs_sentence(&param.docs)),
)
.is_none()
{
ctx.cast_completions(&param.input);
}
sort_and_explicit_code_completion(ctx);
if ctx.before.ends_with(':') {
ctx.enrich(" ", "");
@ -1063,7 +1048,7 @@ pub(crate) fn complete_type(ctx: &mut CompletionContext) -> Option<()> {
log::debug!("complete_type: ty {:?} -> {:#?}", ctx.leaf, ty);
// log::debug!("complete_type: before {:?}", ctx.before.chars().last());
type_completion(ctx, Some(&ty), None);
type_completion(ctx, &ty, None);
if ctx.before.ends_with(',') || ctx.before.ends_with(':') {
ctx.enrich(" ", "");
}