mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-23 04:35:00 +00:00
feat: remove cast completion (#348)
* feat: remove cast completion * fix: update snapshot
This commit is contained in:
parent
00ec24e18f
commit
a3724bc87f
13 changed files with 77 additions and 181 deletions
|
@ -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,
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(¶m.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(¶m.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(¶m.docs)),
|
||||
)
|
||||
.is_none()
|
||||
{
|
||||
ctx.cast_completions(¶m.input);
|
||||
if param.positional {
|
||||
type_completion(ctx, ¶m.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, ¶m.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(¶m.docs)),
|
||||
)
|
||||
.is_none()
|
||||
{
|
||||
ctx.cast_completions(¶m.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(" ", "");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue