1use crate::{
2 code_context_menus::{CompletionsMenu, SortableMatch},
3 editor_settings::SnippetSortOrder,
4};
5use fuzzy::StringMatch;
6use gpui::TestAppContext;
7
8#[gpui::test]
9fn test_sort_matches_local_variable_over_global_variable(_cx: &mut TestAppContext) {
10 // Case 1: "foo"
11 let query: Option<&str> = Some("foo");
12 let mut matches: Vec<SortableMatch<'_>> = vec![
13 SortableMatch {
14 string_match: StringMatch {
15 candidate_id: 0,
16 score: 0.2727272727272727,
17 positions: vec![],
18 string: "foo_bar_baz".to_string(),
19 },
20 is_snippet: false,
21 sort_text: Some("7fffffff"),
22 sort_kind: 2,
23 sort_label: "foo_bar_baz",
24 },
25 SortableMatch {
26 string_match: StringMatch {
27 candidate_id: 0,
28 score: 0.2727272727272727,
29 positions: vec![],
30 string: "foo_bar_qux".to_string(),
31 },
32 is_snippet: false,
33 sort_text: Some("7ffffffe"),
34 sort_kind: 1,
35 sort_label: "foo_bar_qux",
36 },
37 SortableMatch {
38 string_match: StringMatch {
39 candidate_id: 0,
40 score: 0.22499999999999998,
41 positions: vec![],
42 string: "floorf64".to_string(),
43 },
44 is_snippet: false,
45 sort_text: Some("80000000"),
46 sort_kind: 2,
47 sort_label: "floorf64",
48 },
49 SortableMatch {
50 string_match: StringMatch {
51 candidate_id: 0,
52 score: 0.22499999999999998,
53 positions: vec![],
54 string: "floorf32".to_string(),
55 },
56 is_snippet: false,
57 sort_text: Some("80000000"),
58 sort_kind: 2,
59 sort_label: "floorf32",
60 },
61 SortableMatch {
62 string_match: StringMatch {
63 candidate_id: 0,
64 score: 0.22499999999999998,
65 positions: vec![],
66 string: "floorf16".to_string(),
67 },
68 is_snippet: false,
69 sort_text: Some("80000000"),
70 sort_kind: 2,
71 sort_label: "floorf16",
72 },
73 SortableMatch {
74 string_match: StringMatch {
75 candidate_id: 0,
76 score: 0.2,
77 positions: vec![],
78 string: "floorf128".to_string(),
79 },
80 is_snippet: false,
81 sort_text: Some("80000000"),
82 sort_kind: 2,
83 sort_label: "floorf128",
84 },
85 ];
86 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
87 assert_eq!(
88 matches[0].string_match.string.as_str(),
89 "foo_bar_qux",
90 "Match order not expected"
91 );
92 assert_eq!(
93 matches[1].string_match.string.as_str(),
94 "foo_bar_baz",
95 "Match order not expected"
96 );
97 assert_eq!(
98 matches[2].string_match.string.as_str(),
99 "floorf16",
100 "Match order not expected"
101 );
102 assert_eq!(
103 matches[3].string_match.string.as_str(),
104 "floorf32",
105 "Match order not expected"
106 );
107
108 // Case 2: "foobar"
109 let query: Option<&str> = Some("foobar");
110 let mut matches: Vec<SortableMatch<'_>> = vec![
111 SortableMatch {
112 string_match: StringMatch {
113 candidate_id: 0,
114 score: 0.4363636363636364,
115 positions: vec![],
116 string: "foo_bar_baz".to_string(),
117 },
118 is_snippet: false,
119 sort_text: Some("7fffffff"),
120 sort_kind: 2,
121 sort_label: "foo_bar_baz",
122 },
123 SortableMatch {
124 string_match: StringMatch {
125 candidate_id: 0,
126 score: 0.4363636363636364,
127 positions: vec![],
128 string: "foo_bar_qux".to_string(),
129 },
130 is_snippet: false,
131 sort_text: Some("7ffffffe"),
132 sort_kind: 1,
133 sort_label: "foo_bar_qux",
134 },
135 ];
136 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
137 assert_eq!(
138 matches[0].string_match.string.as_str(),
139 "foo_bar_qux",
140 "Match order not expected"
141 );
142 assert_eq!(
143 matches[1].string_match.string.as_str(),
144 "foo_bar_baz",
145 "Match order not expected"
146 );
147}
148
149#[gpui::test]
150fn test_sort_matches_local_variable_over_global_enum(_cx: &mut TestAppContext) {
151 // Case 1: "ele"
152 let query: Option<&str> = Some("ele");
153 let mut matches: Vec<SortableMatch<'_>> = vec![
154 SortableMatch {
155 string_match: StringMatch {
156 candidate_id: 0,
157 score: 0.2727272727272727,
158 positions: vec![],
159 string: "ElementType".to_string(),
160 },
161 is_snippet: false,
162 sort_text: Some("7fffffff"),
163 sort_kind: 2,
164 sort_label: "ElementType",
165 },
166 SortableMatch {
167 string_match: StringMatch {
168 candidate_id: 0,
169 score: 0.25,
170 positions: vec![],
171 string: "element_type".to_string(),
172 },
173 is_snippet: false,
174 sort_text: Some("7ffffffe"),
175 sort_kind: 1,
176 sort_label: "element_type",
177 },
178 SortableMatch {
179 string_match: StringMatch {
180 candidate_id: 0,
181 score: 0.16363636363636364,
182 positions: vec![],
183 string: "simd_select".to_string(),
184 },
185 is_snippet: false,
186 sort_text: Some("80000000"),
187 sort_kind: 2,
188 sort_label: "simd_select",
189 },
190 SortableMatch {
191 string_match: StringMatch {
192 candidate_id: 0,
193 score: 0.16,
194 positions: vec![],
195 string: "while let".to_string(),
196 },
197 is_snippet: false,
198 sort_text: Some("7fffffff"),
199 sort_kind: 0,
200 sort_label: "while let",
201 },
202 ];
203 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
204 assert_eq!(
205 matches[0].string_match.string.as_str(),
206 "element_type",
207 "Match order not expected"
208 );
209 assert_eq!(
210 matches[1].string_match.string.as_str(),
211 "ElementType",
212 "Match order not expected"
213 );
214
215 // Case 2: "eleme"
216 let query: Option<&str> = Some("eleme");
217 let mut matches: Vec<SortableMatch<'_>> = vec![
218 SortableMatch {
219 string_match: StringMatch {
220 candidate_id: 0,
221 score: 0.4545454545454546,
222 positions: vec![],
223 string: "ElementType".to_string(),
224 },
225 is_snippet: false,
226 sort_text: Some("7fffffff"),
227 sort_kind: 2,
228 sort_label: "ElementType",
229 },
230 SortableMatch {
231 string_match: StringMatch {
232 candidate_id: 0,
233 score: 0.41666666666666663,
234 positions: vec![],
235 string: "element_type".to_string(),
236 },
237 is_snippet: false,
238 sort_text: Some("7ffffffe"),
239 sort_kind: 1,
240 sort_label: "element_type",
241 },
242 SortableMatch {
243 string_match: StringMatch {
244 candidate_id: 0,
245 score: 0.04714285714285713,
246 positions: vec![],
247 string: "REPLACEMENT_CHARACTER".to_string(),
248 },
249 is_snippet: false,
250 sort_text: Some("80000000"),
251 sort_kind: 2,
252 sort_label: "REPLACEMENT_CHARACTER",
253 },
254 ];
255 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
256 assert_eq!(
257 matches[0].string_match.string.as_str(),
258 "element_type",
259 "Match order not expected"
260 );
261 assert_eq!(
262 matches[1].string_match.string.as_str(),
263 "ElementType",
264 "Match order not expected"
265 );
266
267 // Case 3: "Elem"
268 let query: Option<&str> = Some("Elem");
269 let mut matches: Vec<SortableMatch<'_>> = vec![
270 SortableMatch {
271 string_match: StringMatch {
272 candidate_id: 0,
273 score: 0.36363636363636365,
274 positions: vec![],
275 string: "ElementType".to_string(),
276 },
277 is_snippet: false,
278 sort_text: Some("7fffffff"),
279 sort_kind: 2,
280 sort_label: "ElementType",
281 },
282 SortableMatch {
283 string_match: StringMatch {
284 candidate_id: 0,
285 score: 0.0003333333333333333,
286 positions: vec![],
287 string: "element_type".to_string(),
288 },
289 is_snippet: false,
290 sort_text: Some("7ffffffe"),
291 sort_kind: 1,
292 sort_label: "element_type",
293 },
294 ];
295 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
296 assert_eq!(
297 matches[0].string_match.string.as_str(),
298 "ElementType",
299 "Match order not expected"
300 );
301 assert_eq!(
302 matches[1].string_match.string.as_str(),
303 "element_type",
304 "Match order not expected"
305 );
306}
307
308#[gpui::test]
309fn test_sort_matches_for_unreachable(_cx: &mut TestAppContext) {
310 // Case 1: "unre"
311 let query: Option<&str> = Some("unre");
312 let mut matches: Vec<SortableMatch<'_>> = vec![
313 SortableMatch {
314 string_match: StringMatch {
315 candidate_id: 0,
316 score: 0.36363636363636365,
317 positions: vec![],
318 string: "unreachable".to_string(),
319 },
320 is_snippet: false,
321 sort_text: Some("80000000"),
322 sort_kind: 2,
323 sort_label: "unreachable",
324 },
325 SortableMatch {
326 string_match: StringMatch {
327 candidate_id: 0,
328 score: 0.26666666666666666,
329 positions: vec![],
330 string: "unreachable!(…)".to_string(),
331 },
332 is_snippet: true,
333 sort_text: Some("7fffffff"),
334 sort_kind: 2,
335 sort_label: "unreachable!(…)",
336 },
337 SortableMatch {
338 string_match: StringMatch {
339 candidate_id: 0,
340 score: 0.24615384615384617,
341 positions: vec![],
342 string: "unchecked_rem".to_string(),
343 },
344 is_snippet: false,
345 sort_text: Some("80000000"),
346 sort_kind: 2,
347 sort_label: "unchecked_rem",
348 },
349 SortableMatch {
350 string_match: StringMatch {
351 candidate_id: 0,
352 score: 0.19047619047619047,
353 positions: vec![],
354 string: "unreachable_unchecked".to_string(),
355 },
356 is_snippet: false,
357 sort_text: Some("80000000"),
358 sort_kind: 2,
359 sort_label: "unreachable_unchecked",
360 },
361 ];
362 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
363 assert_eq!(
364 matches[0].string_match.string.as_str(),
365 "unreachable!(…)",
366 "Match order not expected"
367 );
368
369 // Case 2: "unrea"
370 let query: Option<&str> = Some("unrea");
371 let mut matches: Vec<SortableMatch<'_>> = vec![
372 SortableMatch {
373 string_match: StringMatch {
374 candidate_id: 0,
375 score: 0.4545454545454546,
376 positions: vec![],
377 string: "unreachable".to_string(),
378 },
379 is_snippet: true,
380 sort_text: Some("80000000"),
381 sort_kind: 3,
382 sort_label: "unreachable",
383 },
384 SortableMatch {
385 string_match: StringMatch {
386 candidate_id: 0,
387 score: 0.3333333333333333,
388 positions: vec![],
389 string: "unreachable!(…)".to_string(),
390 },
391 is_snippet: true,
392 sort_text: Some("7fffffff"),
393 sort_kind: 3,
394 sort_label: "unreachable!(…)",
395 },
396 SortableMatch {
397 string_match: StringMatch {
398 candidate_id: 0,
399 score: 0.23809523809523808,
400 positions: vec![],
401 string: "unreachable_unchecked".to_string(),
402 },
403 is_snippet: true,
404 sort_text: Some("80000000"),
405 sort_kind: 3,
406 sort_label: "unreachable_unchecked",
407 },
408 ];
409 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
410 assert_eq!(
411 matches[0].string_match.string.as_str(),
412 "unreachable!(…)",
413 "Match order not expected"
414 );
415
416 // Case 3: "unreach"
417 let query: Option<&str> = Some("unreach");
418 let mut matches: Vec<SortableMatch<'_>> = vec![
419 SortableMatch {
420 string_match: StringMatch {
421 candidate_id: 0,
422 score: 0.6363636363636364,
423 positions: vec![],
424 string: "unreachable".to_string(),
425 },
426 is_snippet: false,
427 sort_text: Some("80000000"),
428 sort_kind: 2,
429 sort_label: "unreachable",
430 },
431 SortableMatch {
432 string_match: StringMatch {
433 candidate_id: 0,
434 score: 0.4666666666666667,
435 positions: vec![],
436 string: "unreachable!(…)".to_string(),
437 },
438 is_snippet: true,
439 sort_text: Some("7fffffff"),
440 sort_kind: 2,
441 sort_label: "unreachable!(…)",
442 },
443 SortableMatch {
444 string_match: StringMatch {
445 candidate_id: 0,
446 score: 0.3333333333333333,
447 positions: vec![],
448 string: "unreachable_unchecked".to_string(),
449 },
450 is_snippet: false,
451 sort_text: Some("80000000"),
452 sort_kind: 2,
453 sort_label: "unreachable_unchecked",
454 },
455 ];
456 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
457 assert_eq!(
458 matches[0].string_match.string.as_str(),
459 "unreachable!(…)",
460 "Match order not expected"
461 );
462
463 // Case 4: "unreachabl"
464 let query: Option<&str> = Some("unreachable");
465 let mut matches: Vec<SortableMatch<'_>> = vec![
466 SortableMatch {
467 string_match: StringMatch {
468 candidate_id: 0,
469 score: 0.9090909090909092,
470 positions: vec![],
471 string: "unreachable".to_string(),
472 },
473 is_snippet: false,
474 sort_text: Some("80000000"),
475 sort_kind: 3,
476 sort_label: "unreachable",
477 },
478 SortableMatch {
479 string_match: StringMatch {
480 candidate_id: 0,
481 score: 0.6666666666666666,
482 positions: vec![],
483 string: "unreachable!(…)".to_string(),
484 },
485 is_snippet: false,
486 sort_text: Some("7fffffff"),
487 sort_kind: 3,
488 sort_label: "unreachable!(…)",
489 },
490 SortableMatch {
491 string_match: StringMatch {
492 candidate_id: 0,
493 score: 0.47619047619047616,
494 positions: vec![],
495 string: "unreachable_unchecked".to_string(),
496 },
497 is_snippet: false,
498 sort_text: Some("80000000"),
499 sort_kind: 3,
500 sort_label: "unreachable_unchecked",
501 },
502 ];
503 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
504 assert_eq!(
505 matches[0].string_match.string.as_str(),
506 "unreachable!(…)",
507 "Match order not expected"
508 );
509
510 // Case 5: "unreachable"
511 let query: Option<&str> = Some("unreachable");
512 let mut matches: Vec<SortableMatch<'_>> = vec![
513 SortableMatch {
514 string_match: StringMatch {
515 candidate_id: 0,
516 score: 1.0,
517 positions: vec![],
518 string: "unreachable".to_string(),
519 },
520 is_snippet: false,
521 sort_text: Some("80000000"),
522 sort_kind: 2,
523 sort_label: "unreachable",
524 },
525 SortableMatch {
526 string_match: StringMatch {
527 candidate_id: 0,
528 score: 0.7333333333333333,
529 positions: vec![],
530 string: "unreachable!(…)".to_string(),
531 },
532 is_snippet: false,
533 sort_text: Some("7fffffff"),
534 sort_kind: 2,
535 sort_label: "unreachable!(…)",
536 },
537 SortableMatch {
538 string_match: StringMatch {
539 candidate_id: 0,
540 score: 0.5238095238095237,
541 positions: vec![],
542 string: "unreachable_unchecked".to_string(),
543 },
544 is_snippet: false,
545 sort_text: Some("80000000"),
546 sort_kind: 2,
547 sort_label: "unreachable_unchecked",
548 },
549 ];
550 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
551 assert_eq!(
552 matches[0].string_match.string.as_str(),
553 "unreachable!(…)",
554 "LSP should take over even when fuzzy perfect matches"
555 );
556}
557
558#[gpui::test]
559fn test_sort_matches_variable_and_constants_over_function(_cx: &mut TestAppContext) {
560 // Case 1: "var" as variable
561 let query: Option<&str> = Some("var");
562 let mut matches: Vec<SortableMatch<'_>> = vec![
563 SortableMatch {
564 string_match: StringMatch {
565 candidate_id: 0,
566 score: 1.0,
567 positions: vec![],
568 string: "var".to_string(),
569 },
570 is_snippet: false,
571 sort_text: Some("7fffffff"),
572 sort_kind: 3,
573 sort_label: "var", // function
574 },
575 SortableMatch {
576 string_match: StringMatch {
577 candidate_id: 1,
578 score: 1.0,
579 positions: vec![],
580 string: "var".to_string(),
581 },
582 is_snippet: false,
583 sort_text: Some("7fffffff"),
584 sort_kind: 1,
585 sort_label: "var", // variable
586 },
587 ];
588 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
589 assert_eq!(
590 matches[0].string_match.candidate_id, 1,
591 "Match order not expected"
592 );
593 assert_eq!(
594 matches[1].string_match.candidate_id, 0,
595 "Match order not expected"
596 );
597
598 // Case 2: "var" as constant
599 let query: Option<&str> = Some("var");
600 let mut matches: Vec<SortableMatch<'_>> = vec![
601 SortableMatch {
602 string_match: StringMatch {
603 candidate_id: 0,
604 score: 1.0,
605 positions: vec![],
606 string: "var".to_string(),
607 },
608 is_snippet: false,
609 sort_text: Some("7fffffff"),
610 sort_kind: 3,
611 sort_label: "var", // function
612 },
613 SortableMatch {
614 string_match: StringMatch {
615 candidate_id: 1,
616 score: 1.0,
617 positions: vec![],
618 string: "var".to_string(),
619 },
620 is_snippet: false,
621 sort_text: Some("7fffffff"),
622 sort_kind: 2,
623 sort_label: "var", // constant
624 },
625 ];
626 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
627 assert_eq!(
628 matches[0].string_match.candidate_id, 1,
629 "Match order not expected"
630 );
631 assert_eq!(
632 matches[1].string_match.candidate_id, 0,
633 "Match order not expected"
634 );
635}
636
637#[gpui::test]
638fn test_sort_matches_for_jsx_event_handler(_cx: &mut TestAppContext) {
639 // Case 1: "on"
640 let query: Option<&str> = Some("on");
641 let mut matches: Vec<SortableMatch<'_>> = vec![
642 SortableMatch {
643 string_match: StringMatch {
644 candidate_id: 0,
645 score: 0.3333333333333333,
646 positions: vec![],
647 string: "onCut?".to_string(),
648 },
649 is_snippet: false,
650 sort_text: Some("12"),
651 sort_kind: 3,
652 sort_label: "onCut?",
653 },
654 SortableMatch {
655 string_match: StringMatch {
656 candidate_id: 0,
657 score: 0.2857142857142857,
658 positions: vec![],
659 string: "onPlay?".to_string(),
660 },
661 is_snippet: false,
662 sort_text: Some("12"),
663 sort_kind: 3,
664 sort_label: "onPlay?",
665 },
666 SortableMatch {
667 string_match: StringMatch {
668 candidate_id: 0,
669 score: 0.25,
670 positions: vec![],
671 string: "color?".to_string(),
672 },
673 is_snippet: false,
674 sort_text: Some("12"),
675 sort_kind: 3,
676 sort_label: "color?",
677 },
678 SortableMatch {
679 string_match: StringMatch {
680 candidate_id: 0,
681 score: 0.25,
682 positions: vec![],
683 string: "defaultValue?".to_string(),
684 },
685 is_snippet: false,
686 sort_text: Some("12"),
687 sort_kind: 3,
688 sort_label: "defaultValue?",
689 },
690 SortableMatch {
691 string_match: StringMatch {
692 candidate_id: 0,
693 score: 0.25,
694 positions: vec![],
695 string: "style?".to_string(),
696 },
697 is_snippet: false,
698 sort_text: Some("12"),
699 sort_kind: 3,
700 sort_label: "style?",
701 },
702 SortableMatch {
703 string_match: StringMatch {
704 candidate_id: 0,
705 score: 0.20,
706 positions: vec![],
707 string: "className?".to_string(),
708 },
709 is_snippet: false,
710 sort_text: Some("12"),
711 sort_kind: 3,
712 sort_label: "className?",
713 },
714 ];
715 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
716 assert_eq!(
717 matches[0].string_match.string, "onCut?",
718 "Match order not expected"
719 );
720 assert_eq!(
721 matches[1].string_match.string, "onPlay?",
722 "Match order not expected"
723 );
724
725 // Case 2: "ona"
726 let query: Option<&str> = Some("ona");
727 let mut matches: Vec<SortableMatch<'_>> = vec![
728 SortableMatch {
729 string_match: StringMatch {
730 candidate_id: 0,
731 score: 0.375,
732 positions: vec![],
733 string: "onAbort?".to_string(),
734 },
735 is_snippet: false,
736 sort_text: Some("12"),
737 sort_kind: 3,
738 sort_label: "onAbort?",
739 },
740 SortableMatch {
741 string_match: StringMatch {
742 candidate_id: 0,
743 score: 0.2727272727272727,
744 positions: vec![],
745 string: "onAuxClick?".to_string(),
746 },
747 is_snippet: false,
748 sort_text: Some("12"),
749 sort_kind: 3,
750 sort_label: "onAuxClick?",
751 },
752 SortableMatch {
753 string_match: StringMatch {
754 candidate_id: 0,
755 score: 0.23571428571428565,
756 positions: vec![],
757 string: "onPlay?".to_string(),
758 },
759 is_snippet: false,
760 sort_text: Some("12"),
761 sort_kind: 3,
762 sort_label: "onPlay?",
763 },
764 SortableMatch {
765 string_match: StringMatch {
766 candidate_id: 0,
767 score: 0.23571428571428565,
768 positions: vec![],
769 string: "onLoad?".to_string(),
770 },
771 is_snippet: false,
772 sort_text: Some("12"),
773 sort_kind: 3,
774 sort_label: "onLoad?",
775 },
776 SortableMatch {
777 string_match: StringMatch {
778 candidate_id: 0,
779 score: 0.23571428571428565,
780 positions: vec![],
781 string: "onDrag?".to_string(),
782 },
783 is_snippet: false,
784 sort_text: Some("12"),
785 sort_kind: 3,
786 sort_label: "onDrag?",
787 },
788 SortableMatch {
789 string_match: StringMatch {
790 candidate_id: 0,
791 score: 0.22499999999999998,
792 positions: vec![],
793 string: "onPause?".to_string(),
794 },
795 is_snippet: false,
796 sort_text: Some("12"),
797 sort_kind: 3,
798 sort_label: "onPause?",
799 },
800 SortableMatch {
801 string_match: StringMatch {
802 candidate_id: 0,
803 score: 0.22499999999999998,
804 positions: vec![],
805 string: "onPaste?".to_string(),
806 },
807 is_snippet: false,
808 sort_text: Some("12"),
809 sort_kind: 3,
810 sort_label: "onPaste?",
811 },
812 SortableMatch {
813 string_match: StringMatch {
814 candidate_id: 0,
815 score: 0.2,
816 positions: vec![],
817 string: "onAnimationEnd?".to_string(),
818 },
819 is_snippet: false,
820 sort_text: Some("12"),
821 sort_kind: 3,
822 sort_label: "onAnimationEnd?",
823 },
824 SortableMatch {
825 string_match: StringMatch {
826 candidate_id: 0,
827 score: 0.2,
828 positions: vec![],
829 string: "onAbortCapture?".to_string(),
830 },
831 is_snippet: false,
832 sort_text: Some("12"),
833 sort_kind: 3,
834 sort_label: "onAbortCapture?",
835 },
836 SortableMatch {
837 string_match: StringMatch {
838 candidate_id: 0,
839 score: 0.1833333333333333,
840 positions: vec![],
841 string: "onChange?".to_string(),
842 },
843 is_snippet: false,
844 sort_text: Some("12"),
845 sort_kind: 3,
846 sort_label: "onChange?",
847 },
848 SortableMatch {
849 string_match: StringMatch {
850 candidate_id: 0,
851 score: 0.18,
852 positions: vec![],
853 string: "onWaiting?".to_string(),
854 },
855 is_snippet: false,
856 sort_text: Some("12"),
857 sort_kind: 3,
858 sort_label: "onWaiting?",
859 },
860 SortableMatch {
861 string_match: StringMatch {
862 candidate_id: 0,
863 score: 0.18,
864 positions: vec![],
865 string: "onCanPlay?".to_string(),
866 },
867 is_snippet: false,
868 sort_text: Some("12"),
869 sort_kind: 3,
870 sort_label: "onCanPlay?",
871 },
872 SortableMatch {
873 string_match: StringMatch {
874 candidate_id: 0,
875 score: 0.1764705882352941,
876 positions: vec![],
877 string: "onAnimationStart?".to_string(),
878 },
879 is_snippet: false,
880 sort_text: Some("12"),
881 sort_kind: 3,
882 sort_label: "onAnimationStart?",
883 },
884 SortableMatch {
885 string_match: StringMatch {
886 candidate_id: 0,
887 score: 0.16666666666666666,
888 positions: vec![],
889 string: "onAuxClickCapture?".to_string(),
890 },
891 is_snippet: false,
892 sort_text: Some("12"),
893 sort_kind: 3,
894 sort_label: "onAuxClickCapture?",
895 },
896 SortableMatch {
897 string_match: StringMatch {
898 candidate_id: 0,
899 score: 0.16499999999999998,
900 positions: vec![],
901 string: "onStalled?".to_string(),
902 },
903 is_snippet: false,
904 sort_text: Some("12"),
905 sort_kind: 3,
906 sort_label: "onStalled?",
907 },
908 SortableMatch {
909 string_match: StringMatch {
910 candidate_id: 0,
911 score: 0.16499999999999998,
912 positions: vec![],
913 string: "onPlaying?".to_string(),
914 },
915 is_snippet: false,
916 sort_text: Some("12"),
917 sort_kind: 3,
918 sort_label: "onPlaying?",
919 },
920 SortableMatch {
921 string_match: StringMatch {
922 candidate_id: 0,
923 score: 0.16499999999999998,
924 positions: vec![],
925 string: "onDragEnd?".to_string(),
926 },
927 is_snippet: false,
928 sort_text: Some("12"),
929 sort_kind: 3,
930 sort_label: "onDragEnd?",
931 },
932 SortableMatch {
933 string_match: StringMatch {
934 candidate_id: 0,
935 score: 0.15000000000000002,
936 positions: vec![],
937 string: "onInvalid?".to_string(),
938 },
939 is_snippet: false,
940 sort_text: Some("12"),
941 sort_kind: 3,
942 sort_label: "onInvalid?",
943 },
944 SortableMatch {
945 string_match: StringMatch {
946 candidate_id: 0,
947 score: 0.15,
948 positions: vec![],
949 string: "onDragOver?".to_string(),
950 },
951 is_snippet: false,
952 sort_text: Some("12"),
953 sort_kind: 3,
954 sort_label: "onDragOver?",
955 },
956 SortableMatch {
957 string_match: StringMatch {
958 candidate_id: 0,
959 score: 0.15,
960 positions: vec![],
961 string: "onDragExit?".to_string(),
962 },
963 is_snippet: false,
964 sort_text: Some("12"),
965 sort_kind: 3,
966 sort_label: "onDragExit?",
967 },
968 SortableMatch {
969 string_match: StringMatch {
970 candidate_id: 0,
971 score: 0.14285714285714285,
972 positions: vec![],
973 string: "onAnimationIteration?".to_string(),
974 },
975 is_snippet: false,
976 sort_text: Some("12"),
977 sort_kind: 3,
978 sort_label: "onAnimationIteration?",
979 },
980 SortableMatch {
981 string_match: StringMatch {
982 candidate_id: 0,
983 score: 0.13846153846153847,
984 positions: vec![],
985 string: "onRateChange?".to_string(),
986 },
987 is_snippet: false,
988 sort_text: Some("12"),
989 sort_kind: 3,
990 sort_label: "onRateChange?",
991 },
992 SortableMatch {
993 string_match: StringMatch {
994 candidate_id: 0,
995 score: 0.13749999999999996,
996 positions: vec![],
997 string: "onLoadStart?".to_string(),
998 },
999 is_snippet: false,
1000 sort_text: Some("12"),
1001 sort_kind: 3,
1002 sort_label: "onLoadStart?",
1003 },
1004 SortableMatch {
1005 string_match: StringMatch {
1006 candidate_id: 0,
1007 score: 0.13749999999999996,
1008 positions: vec![],
1009 string: "onDragStart?".to_string(),
1010 },
1011 is_snippet: false,
1012 sort_text: Some("12"),
1013 sort_kind: 3,
1014 sort_label: "onDragStart?",
1015 },
1016 SortableMatch {
1017 string_match: StringMatch {
1018 candidate_id: 0,
1019 score: 0.13749999999999996,
1020 positions: vec![],
1021 string: "onDragLeave?".to_string(),
1022 },
1023 is_snippet: false,
1024 sort_text: Some("12"),
1025 sort_kind: 3,
1026 sort_label: "onDragLeave?",
1027 },
1028 SortableMatch {
1029 string_match: StringMatch {
1030 candidate_id: 0,
1031 score: 0.13749999999999996,
1032 positions: vec![],
1033 string: "onDragEnter?".to_string(),
1034 },
1035 is_snippet: false,
1036 sort_text: Some("12"),
1037 sort_kind: 3,
1038 sort_label: "onDragEnter?",
1039 },
1040 SortableMatch {
1041 string_match: StringMatch {
1042 candidate_id: 0,
1043 score: 0.13636363636363635,
1044 positions: vec![],
1045 string: "onAnimationEndCapture?".to_string(),
1046 },
1047 is_snippet: false,
1048 sort_text: Some("12"),
1049 sort_kind: 3,
1050 sort_label: "onAnimationEndCapture?",
1051 },
1052 SortableMatch {
1053 string_match: StringMatch {
1054 candidate_id: 0,
1055 score: 0.12692307692307692,
1056 positions: vec![],
1057 string: "onLoadedData?".to_string(),
1058 },
1059 is_snippet: false,
1060 sort_text: Some("12"),
1061 sort_kind: 3,
1062 sort_label: "onLoadedData?",
1063 },
1064 ];
1065 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
1066 assert_eq!(
1067 matches
1068 .iter()
1069 .take(12)
1070 .map(|m| m.string_match.string.as_str())
1071 .collect::<Vec<&str>>(),
1072 vec![
1073 "onAbort?",
1074 "onAuxClick?",
1075 "onAbortCapture?",
1076 "onAnimationEnd?",
1077 "onAnimationStart?",
1078 "onAuxClickCapture?",
1079 "onAnimationIteration?",
1080 "onAnimationEndCapture?",
1081 "onDrag?",
1082 "onLoad?",
1083 "onPlay?",
1084 "onPaste?",
1085 ]
1086 );
1087}
1088
1089#[gpui::test]
1090fn test_sort_matches_for_snippets(_cx: &mut TestAppContext) {
1091 // Case 1: "prin"
1092 let query: Option<&str> = Some("prin");
1093 let mut matches: Vec<SortableMatch<'_>> = vec![
1094 SortableMatch {
1095 string_match: StringMatch {
1096 candidate_id: 0,
1097 score: 0.2,
1098 positions: vec![],
1099 string: "println".to_string(),
1100 },
1101 is_snippet: false,
1102 sort_text: Some("80000000"),
1103 sort_kind: 2,
1104 sort_label: "println",
1105 },
1106 SortableMatch {
1107 string_match: StringMatch {
1108 candidate_id: 0,
1109 score: 0.2,
1110 positions: vec![],
1111 string: "println!(…)".to_string(),
1112 },
1113 is_snippet: true,
1114 sort_text: Some("80000000"),
1115 sort_kind: 2,
1116 sort_label: "println!(…)",
1117 },
1118 ];
1119 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1120 assert_eq!(
1121 matches[0].string_match.string.as_str(),
1122 "println!(…)",
1123 "Match order not expected"
1124 );
1125}
1126
1127#[gpui::test]
1128fn test_sort_matches_for_exact_match(_cx: &mut TestAppContext) {
1129 // Case 1: "set_text"
1130 let query: Option<&str> = Some("set_text");
1131 let mut matches: Vec<SortableMatch<'_>> = vec![
1132 SortableMatch {
1133 string_match: StringMatch {
1134 candidate_id: 0,
1135 score: 1.0,
1136 positions: vec![],
1137 string: "set_text".to_string(),
1138 },
1139 is_snippet: false,
1140 sort_text: Some("7fffffff"),
1141 sort_kind: 3,
1142 sort_label: "set_text",
1143 },
1144 SortableMatch {
1145 string_match: StringMatch {
1146 candidate_id: 0,
1147 score: 0.32000000000000006,
1148 positions: vec![],
1149 string: "set_placeholder_text".to_string(),
1150 },
1151 is_snippet: false,
1152 sort_text: Some("7fffffff"),
1153 sort_kind: 3,
1154 sort_label: "set_placeholder_text",
1155 },
1156 SortableMatch {
1157 string_match: StringMatch {
1158 candidate_id: 0,
1159 score: 0.32,
1160 positions: vec![],
1161 string: "set_text_style_refinement".to_string(),
1162 },
1163 is_snippet: false,
1164 sort_text: Some("7fffffff"),
1165 sort_kind: 3,
1166 sort_label: "set_text_style_refinement",
1167 },
1168 SortableMatch {
1169 string_match: StringMatch {
1170 candidate_id: 0,
1171 score: 0.16666666666666666,
1172 positions: vec![],
1173 string: "set_context_menu_options".to_string(),
1174 },
1175 is_snippet: false,
1176 sort_text: Some("7fffffff"),
1177 sort_kind: 3,
1178 sort_label: "set_context_menu_options",
1179 },
1180 SortableMatch {
1181 string_match: StringMatch {
1182 candidate_id: 0,
1183 score: 0.08695652173913043,
1184 positions: vec![],
1185 string: "select_to_next_word_end".to_string(),
1186 },
1187 is_snippet: false,
1188 sort_text: Some("7fffffff"),
1189 sort_kind: 3,
1190 sort_label: "select_to_next_word_end",
1191 },
1192 SortableMatch {
1193 string_match: StringMatch {
1194 candidate_id: 0,
1195 score: 0.07692307692307693,
1196 positions: vec![],
1197 string: "select_to_next_subword_end".to_string(),
1198 },
1199 is_snippet: false,
1200 sort_text: Some("7fffffff"),
1201 sort_kind: 3,
1202 sort_label: "select_to_next_subword_end",
1203 },
1204 SortableMatch {
1205 string_match: StringMatch {
1206 candidate_id: 0,
1207 score: 0.06956521739130435,
1208 positions: vec![],
1209 string: "set_custom_context_menu".to_string(),
1210 },
1211 is_snippet: false,
1212 sort_text: Some("7fffffff"),
1213 sort_kind: 3,
1214 sort_label: "set_custom_context_menu",
1215 },
1216 SortableMatch {
1217 string_match: StringMatch {
1218 candidate_id: 0,
1219 score: 0.06,
1220 positions: vec![],
1221 string: "select_to_end_of_excerpt".to_string(),
1222 },
1223 is_snippet: false,
1224 sort_text: Some("7fffffff"),
1225 sort_kind: 3,
1226 sort_label: "select_to_end_of_excerpt",
1227 },
1228 SortableMatch {
1229 string_match: StringMatch {
1230 candidate_id: 0,
1231 score: 0.055384615384615386,
1232 positions: vec![],
1233 string: "select_to_start_of_excerpt".to_string(),
1234 },
1235 is_snippet: false,
1236 sort_text: Some("7fffffff"),
1237 sort_kind: 3,
1238 sort_label: "select_to_start_of_excerpt",
1239 },
1240 SortableMatch {
1241 string_match: StringMatch {
1242 candidate_id: 0,
1243 score: 0.0464516129032258,
1244 positions: vec![],
1245 string: "select_to_start_of_next_excerpt".to_string(),
1246 },
1247 is_snippet: false,
1248 sort_text: Some("7fffffff"),
1249 sort_kind: 3,
1250 sort_label: "select_to_start_of_next_excerpt",
1251 },
1252 SortableMatch {
1253 string_match: StringMatch {
1254 candidate_id: 0,
1255 score: 0.04363636363636363,
1256 positions: vec![],
1257 string: "select_to_end_of_previous_excerpt".to_string(),
1258 },
1259 is_snippet: false,
1260 sort_text: Some("7fffffff"),
1261 sort_kind: 3,
1262 sort_label: "select_to_end_of_previous_excerpt",
1263 },
1264 ];
1265 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1266 assert_eq!(
1267 matches
1268 .iter()
1269 .map(|m| m.string_match.string.as_str())
1270 .collect::<Vec<&str>>(),
1271 vec![
1272 "set_text",
1273 "set_text_style_refinement",
1274 "set_placeholder_text",
1275 "set_context_menu_options",
1276 "set_custom_context_menu",
1277 "select_to_next_word_end",
1278 "select_to_next_subword_end",
1279 "select_to_end_of_excerpt",
1280 "select_to_start_of_excerpt",
1281 "select_to_start_of_next_excerpt",
1282 "select_to_end_of_previous_excerpt",
1283 ]
1284 );
1285}
1286
1287#[gpui::test]
1288fn test_sort_matches_for_prefix_matches(_cx: &mut TestAppContext) {
1289 // Case 1: "set"
1290 let query: Option<&str> = Some("set");
1291 let mut matches: Vec<SortableMatch<'_>> = vec![
1292 SortableMatch {
1293 string_match: StringMatch {
1294 candidate_id: 0,
1295 score: 0.12631578947368421,
1296 positions: vec![],
1297 string: "select_to_beginning".to_string(),
1298 },
1299 is_snippet: false,
1300 sort_text: Some("7fffffff"),
1301 sort_kind: 3,
1302 sort_label: "select_to_beginning",
1303 },
1304 SortableMatch {
1305 string_match: StringMatch {
1306 candidate_id: 0,
1307 score: 0.15000000000000002,
1308 positions: vec![],
1309 string: "set_collapse_matches".to_string(),
1310 },
1311 is_snippet: false,
1312 sort_text: Some("7fffffff"),
1313 sort_kind: 3,
1314 sort_label: "set_collapse_matches",
1315 },
1316 SortableMatch {
1317 string_match: StringMatch {
1318 candidate_id: 0,
1319 score: 0.21428571428571427,
1320 positions: vec![],
1321 string: "set_autoindent".to_string(),
1322 },
1323 is_snippet: false,
1324 sort_text: Some("7fffffff"),
1325 sort_kind: 3,
1326 sort_label: "set_autoindent",
1327 },
1328 SortableMatch {
1329 string_match: StringMatch {
1330 candidate_id: 0,
1331 score: 0.11538461538461539,
1332 positions: vec![],
1333 string: "set_all_diagnostics_active".to_string(),
1334 },
1335 is_snippet: false,
1336 sort_text: Some("7fffffff"),
1337 sort_kind: 3,
1338 sort_label: "set_all_diagnostics_active",
1339 },
1340 SortableMatch {
1341 string_match: StringMatch {
1342 candidate_id: 0,
1343 score: 0.1142857142857143,
1344 positions: vec![],
1345 string: "select_to_end_of_line".to_string(),
1346 },
1347 is_snippet: false,
1348 sort_text: Some("7fffffff"),
1349 sort_kind: 3,
1350 sort_label: "select_to_end_of_line",
1351 },
1352 SortableMatch {
1353 string_match: StringMatch {
1354 candidate_id: 0,
1355 score: 0.15000000000000002,
1356 positions: vec![],
1357 string: "select_all".to_string(),
1358 },
1359 is_snippet: false,
1360 sort_text: Some("7fffffff"),
1361 sort_kind: 3,
1362 sort_label: "select_all",
1363 },
1364 SortableMatch {
1365 string_match: StringMatch {
1366 candidate_id: 0,
1367 score: 0.13636363636363635,
1368 positions: vec![],
1369 string: "select_line".to_string(),
1370 },
1371 is_snippet: false,
1372 sort_text: Some("7fffffff"),
1373 sort_kind: 3,
1374 sort_label: "select_line",
1375 },
1376 SortableMatch {
1377 string_match: StringMatch {
1378 candidate_id: 0,
1379 score: 0.13636363636363635,
1380 positions: vec![],
1381 string: "select_left".to_string(),
1382 },
1383 is_snippet: false,
1384 sort_text: Some("7fffffff"),
1385 sort_kind: 3,
1386 sort_label: "select_left",
1387 },
1388 SortableMatch {
1389 string_match: StringMatch {
1390 candidate_id: 0,
1391 score: 0.13636363636363635,
1392 positions: vec![],
1393 string: "select_down".to_string(),
1394 },
1395 is_snippet: false,
1396 sort_text: Some("7fffffff"),
1397 sort_kind: 3,
1398 sort_label: "select_down",
1399 },
1400 ];
1401 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1402 assert_eq!(
1403 matches
1404 .iter()
1405 .map(|m| m.string_match.string.as_str())
1406 .collect::<Vec<&str>>(),
1407 vec![
1408 "set_autoindent",
1409 "set_collapse_matches",
1410 "set_all_diagnostics_active",
1411 "select_all",
1412 "select_down",
1413 "select_left",
1414 "select_line",
1415 "select_to_beginning",
1416 "select_to_end_of_line",
1417 ]
1418 );
1419}
1420
1421#[gpui::test]
1422fn test_sort_matches_for_await(_cx: &mut TestAppContext) {
1423 // Case 1: "awa"
1424 let query: Option<&str> = Some("awa");
1425 let mut matches: Vec<SortableMatch<'_>> = vec![
1426 SortableMatch {
1427 string_match: StringMatch {
1428 candidate_id: 0,
1429 score: 0.6000000000000001,
1430 positions: vec![],
1431 string: "await".to_string(),
1432 },
1433 is_snippet: false,
1434 sort_text: Some("7fffffff"),
1435 sort_kind: 0,
1436 sort_label: "await",
1437 },
1438 SortableMatch {
1439 string_match: StringMatch {
1440 candidate_id: 35,
1441 score: 0.375,
1442 positions: vec![],
1443 string: "await.ne".to_string(),
1444 },
1445 is_snippet: false,
1446 sort_text: Some("80000010"),
1447 sort_kind: 3,
1448 sort_label: "await.ne",
1449 },
1450 SortableMatch {
1451 string_match: StringMatch {
1452 candidate_id: 34,
1453 score: 0.375,
1454 positions: vec![],
1455 string: "await.eq".to_string(),
1456 },
1457 is_snippet: false,
1458 sort_text: Some("80000010"),
1459 sort_kind: 3,
1460 sort_label: "await.eq",
1461 },
1462 SortableMatch {
1463 string_match: StringMatch {
1464 candidate_id: 18,
1465 score: 0.375,
1466 positions: vec![],
1467 string: "await.or".to_string(),
1468 },
1469 is_snippet: false,
1470 sort_text: Some("7ffffff8"),
1471 sort_kind: 3,
1472 sort_label: "await.or",
1473 },
1474 SortableMatch {
1475 string_match: StringMatch {
1476 candidate_id: 21,
1477 score: 0.3333333333333333,
1478 positions: vec![],
1479 string: "await.zip".to_string(),
1480 },
1481 is_snippet: false,
1482 sort_text: Some("80000006"),
1483 sort_kind: 3,
1484 sort_label: "await.zip",
1485 },
1486 SortableMatch {
1487 string_match: StringMatch {
1488 candidate_id: 20,
1489 score: 0.3333333333333333,
1490 positions: vec![],
1491 string: "await.xor".to_string(),
1492 },
1493 is_snippet: false,
1494 sort_text: Some("7ffffff8"),
1495 sort_kind: 3,
1496 sort_label: "await.xor",
1497 },
1498 SortableMatch {
1499 string_match: StringMatch {
1500 candidate_id: 15,
1501 score: 0.3333333333333333,
1502 positions: vec![],
1503 string: "await.and".to_string(),
1504 },
1505 is_snippet: false,
1506 sort_text: Some("80000006"),
1507 sort_kind: 3,
1508 sort_label: "await.and",
1509 },
1510 SortableMatch {
1511 string_match: StringMatch {
1512 candidate_id: 9,
1513 score: 0.3333333333333333,
1514 positions: vec![],
1515 string: "await.map".to_string(),
1516 },
1517 is_snippet: false,
1518 sort_text: Some("80000006"),
1519 sort_kind: 3,
1520 sort_label: "await.map",
1521 },
1522 SortableMatch {
1523 string_match: StringMatch {
1524 candidate_id: 47,
1525 score: 0.30000000000000004,
1526 positions: vec![],
1527 string: "await.take".to_string(),
1528 },
1529 is_snippet: false,
1530 sort_text: Some("7ffffff8"),
1531 sort_kind: 3,
1532 sort_label: "await.take",
1533 },
1534 ];
1535 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1536 assert_eq!(
1537 matches
1538 .iter()
1539 .map(|m| m.string_match.string.as_str())
1540 .collect::<Vec<&str>>(),
1541 vec![
1542 "await",
1543 "await.or",
1544 "await.eq",
1545 "await.ne",
1546 "await.xor",
1547 "await.take",
1548 "await.and",
1549 "await.map",
1550 "await.zip"
1551 ]
1552 );
1553 // Case 2: "await"
1554 let query: Option<&str> = Some("await");
1555 let mut matches: Vec<SortableMatch<'_>> = vec![
1556 SortableMatch {
1557 string_match: StringMatch {
1558 candidate_id: 0,
1559 score: 1.0,
1560 positions: vec![],
1561 string: "await".to_string(),
1562 },
1563 is_snippet: false,
1564 sort_text: Some("7fffffff"),
1565 sort_kind: 0,
1566 sort_label: "await",
1567 },
1568 SortableMatch {
1569 string_match: StringMatch {
1570 candidate_id: 35,
1571 score: 0.625,
1572 positions: vec![],
1573 string: "await.ne".to_string(),
1574 },
1575 is_snippet: false,
1576 sort_text: Some("80000010"),
1577 sort_kind: 3,
1578 sort_label: "await.ne",
1579 },
1580 SortableMatch {
1581 string_match: StringMatch {
1582 candidate_id: 34,
1583 score: 0.625,
1584 positions: vec![],
1585 string: "await.eq".to_string(),
1586 },
1587 is_snippet: false,
1588 sort_text: Some("80000010"),
1589 sort_kind: 3,
1590 sort_label: "await.eq",
1591 },
1592 SortableMatch {
1593 string_match: StringMatch {
1594 candidate_id: 18,
1595 score: 0.625,
1596 positions: vec![],
1597 string: "await.or".to_string(),
1598 },
1599 is_snippet: false,
1600 sort_text: Some("7ffffff8"),
1601 sort_kind: 3,
1602 sort_label: "await.or",
1603 },
1604 SortableMatch {
1605 string_match: StringMatch {
1606 candidate_id: 21,
1607 score: 0.5555555555555556,
1608 positions: vec![],
1609 string: "await.zip".to_string(),
1610 },
1611 is_snippet: false,
1612 sort_text: Some("80000006"),
1613 sort_kind: 3,
1614 sort_label: "await.zip",
1615 },
1616 SortableMatch {
1617 string_match: StringMatch {
1618 candidate_id: 20,
1619 score: 0.5555555555555556,
1620 positions: vec![],
1621 string: "await.xor".to_string(),
1622 },
1623 is_snippet: false,
1624 sort_text: Some("7ffffff8"),
1625 sort_kind: 3,
1626 sort_label: "await.xor",
1627 },
1628 SortableMatch {
1629 string_match: StringMatch {
1630 candidate_id: 15,
1631 score: 0.5555555555555556,
1632 positions: vec![],
1633 string: "await.and".to_string(),
1634 },
1635 is_snippet: false,
1636 sort_text: Some("80000006"),
1637 sort_kind: 3,
1638 sort_label: "await.and",
1639 },
1640 SortableMatch {
1641 string_match: StringMatch {
1642 candidate_id: 9,
1643 score: 0.5555555555555556,
1644 positions: vec![],
1645 string: "await.map".to_string(),
1646 },
1647 is_snippet: false,
1648 sort_text: Some("80000006"),
1649 sort_kind: 3,
1650 sort_label: "await.map",
1651 },
1652 SortableMatch {
1653 string_match: StringMatch {
1654 candidate_id: 47,
1655 score: 0.5,
1656 positions: vec![],
1657 string: "await.take".to_string(),
1658 },
1659 is_snippet: false,
1660 sort_text: Some("7ffffff8"),
1661 sort_kind: 3,
1662 sort_label: "await.take",
1663 },
1664 ];
1665 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1666 assert_eq!(
1667 matches
1668 .iter()
1669 .map(|m| m.string_match.string.as_str())
1670 .collect::<Vec<&str>>(),
1671 vec![
1672 "await",
1673 "await.or",
1674 "await.eq",
1675 "await.ne",
1676 "await.xor",
1677 "await.take",
1678 "await.and",
1679 "await.map",
1680 "await.zip"
1681 ]
1682 );
1683}
1684
1685#[gpui::test]
1686fn test_sort_matches_for_python_init(_cx: &mut TestAppContext) {
1687 // Case 1: "__in"
1688 let query: Option<&str> = Some("__in");
1689 let mut matches: Vec<SortableMatch<'_>> = vec![
1690 SortableMatch {
1691 string_match: StringMatch {
1692 candidate_id: 211,
1693 score: 0.5,
1694 positions: vec![],
1695 string: "__init__".to_string(),
1696 },
1697 is_snippet: false,
1698 sort_text: Some("05.0003.__init__"),
1699 sort_kind: 3,
1700 sort_label: "__init__",
1701 },
1702 SortableMatch {
1703 string_match: StringMatch {
1704 candidate_id: 0,
1705 score: 0.5,
1706 positions: vec![],
1707 string: "__init__".to_string(),
1708 },
1709 is_snippet: false,
1710 sort_text: Some("05.0003"),
1711 sort_kind: 3,
1712 sort_label: "__init__",
1713 },
1714 SortableMatch {
1715 string_match: StringMatch {
1716 candidate_id: 215,
1717 score: 0.23529411764705882,
1718 positions: vec![],
1719 string: "__instancecheck__".to_string(),
1720 },
1721 is_snippet: false,
1722 sort_text: Some("05.0005.__instancecheck__"),
1723 sort_kind: 3,
1724 sort_label: "__instancecheck__",
1725 },
1726 SortableMatch {
1727 string_match: StringMatch {
1728 candidate_id: 213,
1729 score: 0.23529411764705882,
1730 positions: vec![],
1731 string: "__init_subclass__".to_string(),
1732 },
1733 is_snippet: false,
1734 sort_text: Some("05.0004.__init_subclass__"),
1735 sort_kind: 3,
1736 sort_label: "__init_subclass__",
1737 },
1738 SortableMatch {
1739 string_match: StringMatch {
1740 candidate_id: 4,
1741 score: 0.23529411764705882,
1742 positions: vec![],
1743 string: "__instancecheck__".to_string(),
1744 },
1745 is_snippet: false,
1746 sort_text: Some("05.0005"),
1747 sort_kind: 3,
1748 sort_label: "__instancecheck__",
1749 },
1750 SortableMatch {
1751 string_match: StringMatch {
1752 candidate_id: 2,
1753 score: 0.23529411764705882,
1754 positions: vec![],
1755 string: "__init_subclass__".to_string(),
1756 },
1757 is_snippet: false,
1758 sort_text: Some("05.0004"),
1759 sort_kind: 3,
1760 sort_label: "__init_subclass__",
1761 },
1762 ];
1763 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1764 assert_eq!(
1765 matches
1766 .iter()
1767 .map(|m| m.string_match.string.as_str())
1768 .collect::<Vec<&str>>(),
1769 vec![
1770 "__init__",
1771 "__init__",
1772 "__init_subclass__",
1773 "__init_subclass__",
1774 "__instancecheck__",
1775 "__instancecheck__",
1776 ]
1777 );
1778 // Case 2: "__ini"
1779 let query: Option<&str> = Some("__ini");
1780 let mut matches: Vec<SortableMatch<'_>> = vec![
1781 SortableMatch {
1782 string_match: StringMatch {
1783 candidate_id: 9,
1784 score: 0.625,
1785 positions: vec![],
1786 string: "__init__".to_string(),
1787 },
1788 is_snippet: false,
1789 sort_text: Some("05.0004.__init__"),
1790 sort_kind: 3,
1791 sort_label: "__init__",
1792 },
1793 SortableMatch {
1794 string_match: StringMatch {
1795 candidate_id: 0,
1796 score: 0.625,
1797 positions: vec![],
1798 string: "__init__".to_string(),
1799 },
1800 is_snippet: false,
1801 sort_text: Some("05.0004"),
1802 sort_kind: 3,
1803 sort_label: "__init__",
1804 },
1805 SortableMatch {
1806 string_match: StringMatch {
1807 candidate_id: 10,
1808 score: 0.29411764705882354,
1809 positions: vec![],
1810 string: "__init_subclass__".to_string(),
1811 },
1812 is_snippet: false,
1813 sort_text: Some("05.0003.__init_subclass__"),
1814 sort_kind: 3,
1815 sort_label: "__init_subclass__",
1816 },
1817 SortableMatch {
1818 string_match: StringMatch {
1819 candidate_id: 1,
1820 score: 0.29411764705882354,
1821 positions: vec![],
1822 string: "__init_subclass__".to_string(),
1823 },
1824 is_snippet: false,
1825 sort_text: Some("05.0003"),
1826 sort_kind: 3,
1827 sort_label: "__init_subclass__",
1828 },
1829 ];
1830 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1831 assert_eq!(
1832 matches
1833 .iter()
1834 .map(|m| m.string_match.string.as_str())
1835 .collect::<Vec<&str>>(),
1836 vec![
1837 "__init__",
1838 "__init__",
1839 "__init_subclass__",
1840 "__init_subclass__",
1841 ]
1842 );
1843 // Case 3: "__init"
1844 let query: Option<&str> = Some("__init");
1845 let mut matches: Vec<SortableMatch<'_>> = vec![
1846 SortableMatch {
1847 string_match: StringMatch {
1848 candidate_id: 7,
1849 score: 0.75,
1850 positions: vec![],
1851 string: "__init__".to_string(),
1852 },
1853 is_snippet: false,
1854 sort_text: Some("05.0000.__init__"),
1855 sort_kind: 3,
1856 sort_label: "__init__",
1857 },
1858 SortableMatch {
1859 string_match: StringMatch {
1860 candidate_id: 0,
1861 score: 0.75,
1862 positions: vec![],
1863 string: "__init__".to_string(),
1864 },
1865 is_snippet: false,
1866 sort_text: Some("05.0000"),
1867 sort_kind: 3,
1868 sort_label: "__init__",
1869 },
1870 SortableMatch {
1871 string_match: StringMatch {
1872 candidate_id: 8,
1873 score: 0.3529411764705882,
1874 positions: vec![],
1875 string: "__init_subclass__".to_string(),
1876 },
1877 is_snippet: false,
1878 sort_text: Some("05.0001.__init_subclass__"),
1879 sort_kind: 3,
1880 sort_label: "__init_subclass__",
1881 },
1882 SortableMatch {
1883 string_match: StringMatch {
1884 candidate_id: 1,
1885 score: 0.3529411764705882,
1886 positions: vec![],
1887 string: "__init_subclass__".to_string(),
1888 },
1889 is_snippet: false,
1890 sort_text: Some("05.0001"),
1891 sort_kind: 3,
1892 sort_label: "__init_subclass__",
1893 },
1894 ];
1895 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1896 assert_eq!(
1897 matches
1898 .iter()
1899 .map(|m| m.string_match.string.as_str())
1900 .collect::<Vec<&str>>(),
1901 vec![
1902 "__init__",
1903 "__init__",
1904 "__init_subclass__",
1905 "__init_subclass__",
1906 ]
1907 );
1908 // Case 4: "__init_"
1909 let query: Option<&str> = Some("__init_");
1910 let mut matches: Vec<SortableMatch<'_>> = vec![
1911 SortableMatch {
1912 string_match: StringMatch {
1913 candidate_id: 4,
1914 score: 0.875,
1915 positions: vec![],
1916 string: "__init__".to_string(),
1917 },
1918 is_snippet: false,
1919 sort_text: Some("11.9999.__init__"),
1920 sort_kind: 3,
1921 sort_label: "__init__",
1922 },
1923 SortableMatch {
1924 string_match: StringMatch {
1925 candidate_id: 0,
1926 score: 0.875,
1927 positions: vec![],
1928 string: "__init__".to_string(),
1929 },
1930 is_snippet: false,
1931 sort_text: Some("11.9999"),
1932 sort_kind: 3,
1933 sort_label: "__init__",
1934 },
1935 SortableMatch {
1936 string_match: StringMatch {
1937 candidate_id: 5,
1938 score: 0.4117647058823529,
1939 positions: vec![],
1940 string: "__init_subclass__".to_string(),
1941 },
1942 is_snippet: false,
1943 sort_text: Some("05.0000.__init_subclass__"),
1944 sort_kind: 3,
1945 sort_label: "__init_subclass__",
1946 },
1947 SortableMatch {
1948 string_match: StringMatch {
1949 candidate_id: 1,
1950 score: 0.4117647058823529,
1951 positions: vec![],
1952 string: "__init_subclass__".to_string(),
1953 },
1954 is_snippet: false,
1955 sort_text: Some("05.0000"),
1956 sort_kind: 3,
1957 sort_label: "__init_subclass__",
1958 },
1959 ];
1960 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1961 assert_eq!(
1962 matches
1963 .iter()
1964 .map(|m| m.string_match.string.as_str())
1965 .collect::<Vec<&str>>(),
1966 vec![
1967 "__init__",
1968 "__init__",
1969 "__init_subclass__",
1970 "__init_subclass__",
1971 ]
1972 );
1973}
1974
1975#[gpui::test]
1976fn test_sort_matches_for_rust_into(_cx: &mut TestAppContext) {
1977 // Case 1: "int"
1978 let query: Option<&str> = Some("int");
1979 let mut matches: Vec<SortableMatch<'_>> = vec![
1980 SortableMatch {
1981 string_match: StringMatch {
1982 candidate_id: 67,
1983 score: 0.75,
1984 positions: vec![],
1985 string: "into".to_string(),
1986 },
1987 is_snippet: false,
1988 sort_text: Some("80000004"),
1989 sort_kind: 3,
1990 sort_label: "into",
1991 },
1992 SortableMatch {
1993 string_match: StringMatch {
1994 candidate_id: 68,
1995 score: 0.30000000000000004,
1996 positions: vec![],
1997 string: "try_into".to_string(),
1998 },
1999 is_snippet: false,
2000 sort_text: Some("80000004"),
2001 sort_kind: 3,
2002 sort_label: "try_into",
2003 },
2004 SortableMatch {
2005 string_match: StringMatch {
2006 candidate_id: 108,
2007 score: 0.2571428571428571,
2008 positions: vec![],
2009 string: "println".to_string(),
2010 },
2011 is_snippet: true,
2012 sort_text: Some("80000004"),
2013 sort_kind: 3,
2014 sort_label: "println",
2015 },
2016 SortableMatch {
2017 string_match: StringMatch {
2018 candidate_id: 73,
2019 score: 0.24,
2020 positions: vec![],
2021 string: "clone_into".to_string(),
2022 },
2023 is_snippet: false,
2024 sort_text: Some("80000004"),
2025 sort_kind: 3,
2026 sort_label: "clone_into",
2027 },
2028 SortableMatch {
2029 string_match: StringMatch {
2030 candidate_id: 1,
2031 score: 0.23076923076923078,
2032 positions: vec![],
2033 string: "into_searcher".to_string(),
2034 },
2035 is_snippet: false,
2036 sort_text: Some("80000000"),
2037 sort_kind: 3,
2038 sort_label: "into_searcher",
2039 },
2040 SortableMatch {
2041 string_match: StringMatch {
2042 candidate_id: 109,
2043 score: 0.22499999999999998,
2044 positions: vec![],
2045 string: "eprintln".to_string(),
2046 },
2047 is_snippet: true,
2048 sort_text: Some("80000004"),
2049 sort_kind: 3,
2050 sort_label: "eprintln",
2051 },
2052 ];
2053 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
2054 assert_eq!(
2055 matches[0].string_match.string.as_str(),
2056 "into",
2057 "Match order not expected"
2058 );
2059 // Case 2: "into"
2060 let query: Option<&str> = Some("into");
2061 let mut matches: Vec<SortableMatch<'_>> = vec![
2062 SortableMatch {
2063 string_match: StringMatch {
2064 candidate_id: 65,
2065 score: 1.0,
2066 positions: vec![],
2067 string: "into".to_string(),
2068 },
2069 is_snippet: false,
2070 sort_text: Some("80000004"),
2071 sort_kind: 3,
2072 sort_label: "into",
2073 },
2074 SortableMatch {
2075 string_match: StringMatch {
2076 candidate_id: 66,
2077 score: 0.4,
2078 positions: vec![],
2079 string: "try_into".to_string(),
2080 },
2081 is_snippet: false,
2082 sort_text: Some("80000004"),
2083 sort_kind: 3,
2084 sort_label: "try_into",
2085 },
2086 SortableMatch {
2087 string_match: StringMatch {
2088 candidate_id: 71,
2089 score: 0.32,
2090 positions: vec![],
2091 string: "clone_into".to_string(),
2092 },
2093 is_snippet: false,
2094 sort_text: Some("80000004"),
2095 sort_kind: 3,
2096 sort_label: "clone_into",
2097 },
2098 SortableMatch {
2099 string_match: StringMatch {
2100 candidate_id: 0,
2101 score: 0.3076923076923077,
2102 positions: vec![],
2103 string: "into_searcher".to_string(),
2104 },
2105 is_snippet: false,
2106 sort_text: Some("80000000"),
2107 sort_kind: 3,
2108 sort_label: "into_searcher",
2109 },
2110 SortableMatch {
2111 string_match: StringMatch {
2112 candidate_id: 27,
2113 score: 0.09,
2114 positions: vec![],
2115 string: "split_terminator".to_string(),
2116 },
2117 is_snippet: false,
2118 sort_text: Some("7fffffff"),
2119 sort_kind: 3,
2120 sort_label: "split_terminator",
2121 },
2122 SortableMatch {
2123 string_match: StringMatch {
2124 candidate_id: 28,
2125 score: 0.08470588235294117,
2126 positions: vec![],
2127 string: "rsplit_terminator".to_string(),
2128 },
2129 is_snippet: false,
2130 sort_text: Some("7fffffff"),
2131 sort_kind: 3,
2132 sort_label: "rsplit_terminator",
2133 },
2134 ];
2135 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
2136 assert_eq!(
2137 matches[0].string_match.string.as_str(),
2138 "into",
2139 "Match order not expected"
2140 );
2141}
2142
2143#[gpui::test]
2144fn test_sort_matches_for_variable_over_function(_cx: &mut TestAppContext) {
2145 // Case 1: "serial"
2146 let query: Option<&str> = Some("serial");
2147 let mut matches: Vec<SortableMatch<'_>> = vec![
2148 SortableMatch {
2149 string_match: StringMatch {
2150 candidate_id: 33,
2151 score: 0.6666666666666666,
2152 positions: vec![],
2153 string: "serialize".to_string(),
2154 },
2155 is_snippet: false,
2156 sort_text: Some("80000000"),
2157 sort_kind: 3,
2158 sort_label: "serialize",
2159 },
2160 SortableMatch {
2161 string_match: StringMatch {
2162 candidate_id: 32,
2163 score: 0.6666666666666666,
2164 positions: vec![],
2165 string: "serialize".to_string(),
2166 },
2167 is_snippet: false,
2168 sort_text: Some("80000000"),
2169 sort_kind: 3,
2170 sort_label: "serialize",
2171 },
2172 SortableMatch {
2173 string_match: StringMatch {
2174 candidate_id: 103,
2175 score: 0.3529411764705882,
2176 positions: vec![],
2177 string: "serialization_key".to_string(),
2178 },
2179 is_snippet: false,
2180 sort_text: Some("7ffffffe"),
2181 sort_kind: 1,
2182 sort_label: "serialization_key",
2183 },
2184 SortableMatch {
2185 string_match: StringMatch {
2186 candidate_id: 18,
2187 score: 0.3529411764705882,
2188 positions: vec![],
2189 string: "serialize_version".to_string(),
2190 },
2191 is_snippet: false,
2192 sort_text: Some("80000000"),
2193 sort_kind: 3,
2194 sort_label: "serialize_version",
2195 },
2196 SortableMatch {
2197 string_match: StringMatch {
2198 candidate_id: 65,
2199 score: 0.32727272727272727,
2200 positions: vec![],
2201 string: "deserialize".to_string(),
2202 },
2203 is_snippet: false,
2204 sort_text: Some("80000000"),
2205 sort_kind: 3,
2206 sort_label: "deserialize",
2207 },
2208 ];
2209 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
2210 assert_eq!(
2211 matches
2212 .iter()
2213 .map(|m| m.string_match.string.as_str())
2214 .collect::<Vec<&str>>(),
2215 vec![
2216 "serialization_key",
2217 "serialize",
2218 "serialize",
2219 "serialize_version",
2220 "deserialize"
2221 ]
2222 );
2223}
2224
2225#[gpui::test]
2226fn test_sort_matches_for_local_methods_over_library(_cx: &mut TestAppContext) {
2227 // Case 1: "setis"
2228 let query: Option<&str> = Some("setis");
2229 let mut matches: Vec<SortableMatch<'_>> = vec![
2230 SortableMatch {
2231 string_match: StringMatch {
2232 candidate_id: 1200,
2233 score: 0.5555555555555556,
2234 positions: vec![],
2235 string: "setISODay".to_string(),
2236 },
2237 is_snippet: false,
2238 sort_text: Some("16"),
2239 sort_kind: 1,
2240 sort_label: "setISODay",
2241 },
2242 SortableMatch {
2243 string_match: StringMatch {
2244 candidate_id: 1216,
2245 score: 0.5,
2246 positions: vec![],
2247 string: "setISOWeek".to_string(),
2248 },
2249 is_snippet: false,
2250 sort_text: Some("16"),
2251 sort_kind: 1,
2252 sort_label: "setISOWeek",
2253 },
2254 SortableMatch {
2255 string_match: StringMatch {
2256 candidate_id: 1232,
2257 score: 0.3571428571428571,
2258 positions: vec![],
2259 string: "setISOWeekYear".to_string(),
2260 },
2261 is_snippet: false,
2262 sort_text: Some("16"),
2263 sort_kind: 1,
2264 sort_label: "setISOWeekYear",
2265 },
2266 SortableMatch {
2267 string_match: StringMatch {
2268 candidate_id: 1217,
2269 score: 0.3571428571428571,
2270 positions: vec![],
2271 string: "setISOWeekYear".to_string(),
2272 },
2273 is_snippet: false,
2274 sort_text: Some("16"),
2275 sort_kind: 3,
2276 sort_label: "setISOWeekYear",
2277 },
2278 SortableMatch {
2279 string_match: StringMatch {
2280 candidate_id: 53,
2281 score: 0.3333333333333333,
2282 positions: vec![],
2283 string: "setIsRefreshing".to_string(),
2284 },
2285 is_snippet: false,
2286 sort_text: Some("11"),
2287 sort_kind: 1,
2288 sort_label: "setIsRefreshing",
2289 },
2290 SortableMatch {
2291 string_match: StringMatch {
2292 candidate_id: 1180,
2293 score: 0.2571428571428571,
2294 positions: vec![],
2295 string: "setFips".to_string(),
2296 },
2297 is_snippet: false,
2298 sort_text: Some("16"),
2299 sort_kind: 3,
2300 sort_label: "setFips",
2301 },
2302 ];
2303 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
2304 assert_eq!(
2305 matches
2306 .iter()
2307 .map(|m| m.string_match.string.as_str())
2308 .collect::<Vec<&str>>(),
2309 vec![
2310 "setIsRefreshing",
2311 "setISODay",
2312 "setISOWeek",
2313 "setISOWeekYear",
2314 "setISOWeekYear",
2315 "setFips"
2316 ]
2317 );
2318}
2319
2320#[gpui::test]
2321fn test_sort_matches_for_priotize_not_exact_match(_cx: &mut TestAppContext) {
2322 // Case 1: "item"
2323 let query: Option<&str> = Some("item");
2324 let mut matches: Vec<SortableMatch<'_>> = vec![
2325 SortableMatch {
2326 string_match: StringMatch {
2327 candidate_id: 1115,
2328 score: 1.0,
2329 positions: vec![],
2330 string: "Item".to_string(),
2331 },
2332 is_snippet: false,
2333 sort_text: Some("16"),
2334 sort_kind: 3,
2335 sort_label: "Item",
2336 },
2337 SortableMatch {
2338 string_match: StringMatch {
2339 candidate_id: 1108,
2340 score: 1.0,
2341 positions: vec![],
2342 string: "Item".to_string(),
2343 },
2344 is_snippet: false,
2345 sort_text: Some("16"),
2346 sort_kind: 1,
2347 sort_label: "Item",
2348 },
2349 SortableMatch {
2350 string_match: StringMatch {
2351 candidate_id: 26,
2352 score: 0.8,
2353 positions: vec![],
2354 string: "items".to_string(),
2355 },
2356 is_snippet: false,
2357 sort_text: Some("11"),
2358 sort_kind: 1,
2359 sort_label: "items",
2360 },
2361 SortableMatch {
2362 string_match: StringMatch {
2363 candidate_id: 1138,
2364 score: 0.5,
2365 positions: vec![],
2366 string: "ItemText".to_string(),
2367 },
2368 is_snippet: false,
2369 sort_text: Some("16"),
2370 sort_kind: 3,
2371 sort_label: "ItemText",
2372 },
2373 ];
2374 CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
2375 assert_eq!(
2376 matches
2377 .iter()
2378 .map(|m| m.string_match.string.as_str())
2379 .collect::<Vec<&str>>(),
2380 vec!["items", "Item", "Item", "ItemText"]
2381 );
2382}