tinymist_query/analysis/completion/
func.rs1use super::*;
4
5impl CompletionPair<'_, '_, '_> {
6 pub fn func_completion(
7 &mut self,
8 mode: InterpretMode,
9 fn_feat: FnCompletionFeat,
10 name: EcoString,
11 label_details: Option<EcoString>,
12 detail: Option<EcoString>,
13 parens: bool,
14 ) {
15 let base = Completion {
16 kind: CompletionKind::Func,
17 label_details,
18 detail,
19 command: self
20 .worker
21 .ctx
22 .analysis
23 .trigger_on_snippet_with_param_hint(true)
24 .map(From::from),
25 ..Default::default()
26 };
27
28 if matches!(
29 self.cursor.surrounding_syntax,
30 SurroundingSyntax::ShowTransform
31 ) && (fn_feat.min_pos() > 0 || fn_feat.min_named() > 0)
32 {
33 self.push_completion(Completion {
34 label: eco_format!("{name}.with"),
35 apply: Some(eco_format!("{name}.with(${{}})")),
36 ..base.clone()
37 });
38 }
39 if fn_feat.is_element
40 && matches!(self.cursor.surrounding_syntax, SurroundingSyntax::Selector)
41 {
42 self.push_completion(Completion {
43 label: eco_format!("{name}.where"),
44 apply: Some(eco_format!("{name}.where(${{}})")),
45 ..base.clone()
46 });
47 }
48
49 let bad_instantiate = match self.cursor.surrounding_syntax {
50 SurroundingSyntax::Selector => name == "with",
52 SurroundingSyntax::SetRule => !fn_feat.is_element,
53 _ => false,
54 };
55 if !bad_instantiate {
56 let only_parens = !parens
57 || (matches!(self.cursor.surrounding_syntax, SurroundingSyntax::Selector)
58 && fn_feat.is_element);
59 let is_set = matches!(self.cursor.surrounding_syntax, SurroundingSyntax::SetRule);
60
61 if !only_parens && fn_feat.prefer_to_be_scope(is_set) {
62 self.push_completion(Completion {
63 label: name.clone(),
64 ..base.clone()
65 });
66 }
67
68 if only_parens {
69 self.push_completion(Completion {
70 label: name,
71 ..base
72 });
73 } else if (fn_feat.min_pos() < 1 || fn_feat.has_only_self()) && !fn_feat.has_rest {
74 self.push_completion(Completion {
75 apply: Some(eco_format!("{}()${{}}", name)),
76 label: paren_label(&name, &fn_feat, is_set),
77 command: None,
78 ..base
79 });
80 } else {
81 let accept_content_arg = fn_feat.next_arg_is_content && !fn_feat.has_rest;
82 let scope_reject_content = matches!(mode, InterpretMode::Math)
83 || matches!(
84 self.cursor.surrounding_syntax,
85 SurroundingSyntax::Selector | SurroundingSyntax::SetRule
86 );
87 self.push_completion(Completion {
88 apply: Some(eco_format!("{name}(${{}})")),
89 label: paren_label(&name, &fn_feat, is_set),
90 ..base.clone()
91 });
92 if !scope_reject_content && accept_content_arg {
93 self.push_completion(Completion {
94 apply: Some(eco_format!("{name}[${{}}]")),
95 label: eco_format!("{name}.bracket"),
96 ..base
97 });
98 };
99 }
100 }
101
102 fn paren_label(name: &EcoString, fn_feat: &FnCompletionFeat, is_set: bool) -> EcoString {
103 if fn_feat.prefer_to_be_scope(is_set) {
104 eco_format!("{name}.paren")
105 } else {
106 name.clone()
107 }
108 }
109 }
110}