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