code_completion_tests.rs

   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}