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        "floorf128",
  94        "Match order not expected"
  95    );
  96    assert_eq!(
  97        matches[3].string_match.string.as_str(),
  98        "floorf16",
  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: "unreachable"
 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: 1.0,
 443                positions: vec![],
 444                string: "unreachable".to_string(),
 445            },
 446            is_snippet: false,
 447            sort_text: Some("80000000"),
 448            sort_key: (2, "unreachable"),
 449        },
 450        SortableMatch {
 451            string_match: StringMatch {
 452                candidate_id: 0,
 453                score: 0.7333333333333333,
 454                positions: vec![],
 455                string: "unreachable!(…)".to_string(),
 456            },
 457            is_snippet: false,
 458            sort_text: Some("7fffffff"),
 459            sort_key: (2, "unreachable!(…)"),
 460        },
 461        SortableMatch {
 462            string_match: StringMatch {
 463                candidate_id: 0,
 464                score: 0.5238095238095237,
 465                positions: vec![],
 466                string: "unreachable_unchecked".to_string(),
 467            },
 468            is_snippet: false,
 469            sort_text: Some("80000000"),
 470            sort_key: (2, "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
 481#[gpui::test]
 482fn test_sort_matches_variable_and_constants_over_function(_cx: &mut TestAppContext) {
 483    // Case 1: "var" as variable
 484    let query: Option<&str> = Some("var");
 485    let mut matches: Vec<SortableMatch<'_>> = vec![
 486        SortableMatch {
 487            string_match: StringMatch {
 488                candidate_id: 0,
 489                score: 1.0,
 490                positions: vec![],
 491                string: "var".to_string(),
 492            },
 493            is_snippet: false,
 494            sort_text: Some("7fffffff"),
 495            sort_key: (3, "var"), // function
 496        },
 497        SortableMatch {
 498            string_match: StringMatch {
 499                candidate_id: 1,
 500                score: 1.0,
 501                positions: vec![],
 502                string: "var".to_string(),
 503            },
 504            is_snippet: false,
 505            sort_text: Some("7fffffff"),
 506            sort_key: (1, "var"), // variable
 507        },
 508    ];
 509    CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
 510    assert_eq!(
 511        matches[0].string_match.candidate_id, 1,
 512        "Match order not expected"
 513    );
 514    assert_eq!(
 515        matches[1].string_match.candidate_id, 0,
 516        "Match order not expected"
 517    );
 518
 519    // Case 2:  "var" as constant
 520    let query: Option<&str> = Some("var");
 521    let mut matches: Vec<SortableMatch<'_>> = vec![
 522        SortableMatch {
 523            string_match: StringMatch {
 524                candidate_id: 0,
 525                score: 1.0,
 526                positions: vec![],
 527                string: "var".to_string(),
 528            },
 529            is_snippet: false,
 530            sort_text: Some("7fffffff"),
 531            sort_key: (3, "var"), // function
 532        },
 533        SortableMatch {
 534            string_match: StringMatch {
 535                candidate_id: 1,
 536                score: 1.0,
 537                positions: vec![],
 538                string: "var".to_string(),
 539            },
 540            is_snippet: false,
 541            sort_text: Some("7fffffff"),
 542            sort_key: (2, "var"), // constant
 543        },
 544    ];
 545    CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
 546    assert_eq!(
 547        matches[0].string_match.candidate_id, 1,
 548        "Match order not expected"
 549    );
 550    assert_eq!(
 551        matches[1].string_match.candidate_id, 0,
 552        "Match order not expected"
 553    );
 554}
 555
 556#[gpui::test]
 557fn test_sort_matches_jsx_event_handler(_cx: &mut TestAppContext) {
 558    // Case 1: "on"
 559    let query: Option<&str> = Some("on");
 560    let mut matches: Vec<SortableMatch<'_>> = vec![
 561        SortableMatch {
 562            string_match: StringMatch {
 563                candidate_id: 0,
 564                score: 0.3333333333333333,
 565                positions: vec![],
 566                string: "onCut?".to_string(),
 567            },
 568            is_snippet: false,
 569            sort_text: Some("12"),
 570            sort_key: (3, "onCut?"),
 571        },
 572        SortableMatch {
 573            string_match: StringMatch {
 574                candidate_id: 0,
 575                score: 0.2857142857142857,
 576                positions: vec![],
 577                string: "onPlay?".to_string(),
 578            },
 579            is_snippet: false,
 580            sort_text: Some("12"),
 581            sort_key: (3, "onPlay?"),
 582        },
 583        SortableMatch {
 584            string_match: StringMatch {
 585                candidate_id: 0,
 586                score: 0.25,
 587                positions: vec![],
 588                string: "color?".to_string(),
 589            },
 590            is_snippet: false,
 591            sort_text: Some("12"),
 592            sort_key: (3, "color?"),
 593        },
 594        SortableMatch {
 595            string_match: StringMatch {
 596                candidate_id: 0,
 597                score: 0.25,
 598                positions: vec![],
 599                string: "defaultValue?".to_string(),
 600            },
 601            is_snippet: false,
 602            sort_text: Some("12"),
 603            sort_key: (3, "defaultValue?"),
 604        },
 605        SortableMatch {
 606            string_match: StringMatch {
 607                candidate_id: 0,
 608                score: 0.25,
 609                positions: vec![],
 610                string: "style?".to_string(),
 611            },
 612            is_snippet: false,
 613            sort_text: Some("12"),
 614            sort_key: (3, "style?"),
 615        },
 616        SortableMatch {
 617            string_match: StringMatch {
 618                candidate_id: 0,
 619                score: 0.20,
 620                positions: vec![],
 621                string: "className?".to_string(),
 622            },
 623            is_snippet: false,
 624            sort_text: Some("12"),
 625            sort_key: (3, "className?"),
 626        },
 627    ];
 628    CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
 629    assert_eq!(
 630        matches[0].string_match.string, "onCut?",
 631        "Match order not expected"
 632    );
 633    assert_eq!(
 634        matches[1].string_match.string, "onPlay?",
 635        "Match order not expected"
 636    );
 637
 638    // Case 2: "ona"
 639    let query: Option<&str> = Some("ona");
 640    let mut matches: Vec<SortableMatch<'_>> = vec![
 641        SortableMatch {
 642            string_match: StringMatch {
 643                candidate_id: 0,
 644                score: 0.375,
 645                positions: vec![],
 646                string: "onAbort?".to_string(),
 647            },
 648            is_snippet: false,
 649            sort_text: Some("12"),
 650            sort_key: (3, "onAbort?"),
 651        },
 652        SortableMatch {
 653            string_match: StringMatch {
 654                candidate_id: 0,
 655                score: 0.2727272727272727,
 656                positions: vec![],
 657                string: "onAuxClick?".to_string(),
 658            },
 659            is_snippet: false,
 660            sort_text: Some("12"),
 661            sort_key: (3, "onAuxClick?"),
 662        },
 663        SortableMatch {
 664            string_match: StringMatch {
 665                candidate_id: 0,
 666                score: 0.23571428571428565,
 667                positions: vec![],
 668                string: "onPlay?".to_string(),
 669            },
 670            is_snippet: false,
 671            sort_text: Some("12"),
 672            sort_key: (3, "onPlay?"),
 673        },
 674        SortableMatch {
 675            string_match: StringMatch {
 676                candidate_id: 0,
 677                score: 0.23571428571428565,
 678                positions: vec![],
 679                string: "onLoad?".to_string(),
 680            },
 681            is_snippet: false,
 682            sort_text: Some("12"),
 683            sort_key: (3, "onLoad?"),
 684        },
 685        SortableMatch {
 686            string_match: StringMatch {
 687                candidate_id: 0,
 688                score: 0.23571428571428565,
 689                positions: vec![],
 690                string: "onDrag?".to_string(),
 691            },
 692            is_snippet: false,
 693            sort_text: Some("12"),
 694            sort_key: (3, "onDrag?"),
 695        },
 696        SortableMatch {
 697            string_match: StringMatch {
 698                candidate_id: 0,
 699                score: 0.22499999999999998,
 700                positions: vec![],
 701                string: "onPause?".to_string(),
 702            },
 703            is_snippet: false,
 704            sort_text: Some("12"),
 705            sort_key: (3, "onPause?"),
 706        },
 707        SortableMatch {
 708            string_match: StringMatch {
 709                candidate_id: 0,
 710                score: 0.22499999999999998,
 711                positions: vec![],
 712                string: "onPaste?".to_string(),
 713            },
 714            is_snippet: false,
 715            sort_text: Some("12"),
 716            sort_key: (3, "onPaste?"),
 717        },
 718        SortableMatch {
 719            string_match: StringMatch {
 720                candidate_id: 0,
 721                score: 0.2,
 722                positions: vec![],
 723                string: "onAnimationEnd?".to_string(),
 724            },
 725            is_snippet: false,
 726            sort_text: Some("12"),
 727            sort_key: (3, "onAnimationEnd?"),
 728        },
 729        SortableMatch {
 730            string_match: StringMatch {
 731                candidate_id: 0,
 732                score: 0.2,
 733                positions: vec![],
 734                string: "onAbortCapture?".to_string(),
 735            },
 736            is_snippet: false,
 737            sort_text: Some("12"),
 738            sort_key: (3, "onAbortCapture?"),
 739        },
 740        SortableMatch {
 741            string_match: StringMatch {
 742                candidate_id: 0,
 743                score: 0.1833333333333333,
 744                positions: vec![],
 745                string: "onChange?".to_string(),
 746            },
 747            is_snippet: false,
 748            sort_text: Some("12"),
 749            sort_key: (3, "onChange?"),
 750        },
 751        SortableMatch {
 752            string_match: StringMatch {
 753                candidate_id: 0,
 754                score: 0.18,
 755                positions: vec![],
 756                string: "onWaiting?".to_string(),
 757            },
 758            is_snippet: false,
 759            sort_text: Some("12"),
 760            sort_key: (3, "onWaiting?"),
 761        },
 762        SortableMatch {
 763            string_match: StringMatch {
 764                candidate_id: 0,
 765                score: 0.18,
 766                positions: vec![],
 767                string: "onCanPlay?".to_string(),
 768            },
 769            is_snippet: false,
 770            sort_text: Some("12"),
 771            sort_key: (3, "onCanPlay?"),
 772        },
 773        SortableMatch {
 774            string_match: StringMatch {
 775                candidate_id: 0,
 776                score: 0.1764705882352941,
 777                positions: vec![],
 778                string: "onAnimationStart?".to_string(),
 779            },
 780            is_snippet: false,
 781            sort_text: Some("12"),
 782            sort_key: (3, "onAnimationStart?"),
 783        },
 784        SortableMatch {
 785            string_match: StringMatch {
 786                candidate_id: 0,
 787                score: 0.16666666666666666,
 788                positions: vec![],
 789                string: "onAuxClickCapture?".to_string(),
 790            },
 791            is_snippet: false,
 792            sort_text: Some("12"),
 793            sort_key: (3, "onAuxClickCapture?"),
 794        },
 795        SortableMatch {
 796            string_match: StringMatch {
 797                candidate_id: 0,
 798                score: 0.16499999999999998,
 799                positions: vec![],
 800                string: "onStalled?".to_string(),
 801            },
 802            is_snippet: false,
 803            sort_text: Some("12"),
 804            sort_key: (3, "onStalled?"),
 805        },
 806        SortableMatch {
 807            string_match: StringMatch {
 808                candidate_id: 0,
 809                score: 0.16499999999999998,
 810                positions: vec![],
 811                string: "onPlaying?".to_string(),
 812            },
 813            is_snippet: false,
 814            sort_text: Some("12"),
 815            sort_key: (3, "onPlaying?"),
 816        },
 817        SortableMatch {
 818            string_match: StringMatch {
 819                candidate_id: 0,
 820                score: 0.16499999999999998,
 821                positions: vec![],
 822                string: "onDragEnd?".to_string(),
 823            },
 824            is_snippet: false,
 825            sort_text: Some("12"),
 826            sort_key: (3, "onDragEnd?"),
 827        },
 828        SortableMatch {
 829            string_match: StringMatch {
 830                candidate_id: 0,
 831                score: 0.15000000000000002,
 832                positions: vec![],
 833                string: "onInvalid?".to_string(),
 834            },
 835            is_snippet: false,
 836            sort_text: Some("12"),
 837            sort_key: (3, "onInvalid?"),
 838        },
 839        SortableMatch {
 840            string_match: StringMatch {
 841                candidate_id: 0,
 842                score: 0.15,
 843                positions: vec![],
 844                string: "onDragOver?".to_string(),
 845            },
 846            is_snippet: false,
 847            sort_text: Some("12"),
 848            sort_key: (3, "onDragOver?"),
 849        },
 850        SortableMatch {
 851            string_match: StringMatch {
 852                candidate_id: 0,
 853                score: 0.15,
 854                positions: vec![],
 855                string: "onDragExit?".to_string(),
 856            },
 857            is_snippet: false,
 858            sort_text: Some("12"),
 859            sort_key: (3, "onDragExit?"),
 860        },
 861        SortableMatch {
 862            string_match: StringMatch {
 863                candidate_id: 0,
 864                score: 0.14285714285714285,
 865                positions: vec![],
 866                string: "onAnimationIteration?".to_string(),
 867            },
 868            is_snippet: false,
 869            sort_text: Some("12"),
 870            sort_key: (3, "onAnimationIteration?"),
 871        },
 872        SortableMatch {
 873            string_match: StringMatch {
 874                candidate_id: 0,
 875                score: 0.13846153846153847,
 876                positions: vec![],
 877                string: "onRateChange?".to_string(),
 878            },
 879            is_snippet: false,
 880            sort_text: Some("12"),
 881            sort_key: (3, "onRateChange?"),
 882        },
 883        SortableMatch {
 884            string_match: StringMatch {
 885                candidate_id: 0,
 886                score: 0.13749999999999996,
 887                positions: vec![],
 888                string: "onLoadStart?".to_string(),
 889            },
 890            is_snippet: false,
 891            sort_text: Some("12"),
 892            sort_key: (3, "onLoadStart?"),
 893        },
 894        SortableMatch {
 895            string_match: StringMatch {
 896                candidate_id: 0,
 897                score: 0.13749999999999996,
 898                positions: vec![],
 899                string: "onDragStart?".to_string(),
 900            },
 901            is_snippet: false,
 902            sort_text: Some("12"),
 903            sort_key: (3, "onDragStart?"),
 904        },
 905        SortableMatch {
 906            string_match: StringMatch {
 907                candidate_id: 0,
 908                score: 0.13749999999999996,
 909                positions: vec![],
 910                string: "onDragLeave?".to_string(),
 911            },
 912            is_snippet: false,
 913            sort_text: Some("12"),
 914            sort_key: (3, "onDragLeave?"),
 915        },
 916        SortableMatch {
 917            string_match: StringMatch {
 918                candidate_id: 0,
 919                score: 0.13749999999999996,
 920                positions: vec![],
 921                string: "onDragEnter?".to_string(),
 922            },
 923            is_snippet: false,
 924            sort_text: Some("12"),
 925            sort_key: (3, "onDragEnter?"),
 926        },
 927        SortableMatch {
 928            string_match: StringMatch {
 929                candidate_id: 0,
 930                score: 0.13636363636363635,
 931                positions: vec![],
 932                string: "onAnimationEndCapture?".to_string(),
 933            },
 934            is_snippet: false,
 935            sort_text: Some("12"),
 936            sort_key: (3, "onAnimationEndCapture?"),
 937        },
 938        SortableMatch {
 939            string_match: StringMatch {
 940                candidate_id: 0,
 941                score: 0.12692307692307692,
 942                positions: vec![],
 943                string: "onLoadedData?".to_string(),
 944            },
 945            is_snippet: false,
 946            sort_text: Some("12"),
 947            sort_key: (3, "onLoadedData?"),
 948        },
 949    ];
 950    CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::default());
 951    assert_eq!(
 952        matches
 953            .iter()
 954            .take(12)
 955            .map(|m| m.string_match.string.as_str())
 956            .collect::<Vec<&str>>(),
 957        vec![
 958            "onAbort?",
 959            "onAbortCapture?",
 960            "onAnimationEnd?",
 961            "onAnimationEndCapture?",
 962            "onAnimationIteration?",
 963            "onAnimationStart?",
 964            "onAuxClick?",
 965            "onAuxClickCapture?",
 966            "onCanPlay?",
 967            "onChange?",
 968            "onDrag?",
 969            "onDragEnd?",
 970        ]
 971    );
 972}
 973
 974#[gpui::test]
 975fn test_sort_matches_for_snippets(_cx: &mut TestAppContext) {
 976    // Case 1: "prin"
 977    let query: Option<&str> = Some("prin");
 978    let mut matches: Vec<SortableMatch<'_>> = vec![
 979        SortableMatch {
 980            string_match: StringMatch {
 981                candidate_id: 0,
 982                score: 0.2,
 983                positions: vec![],
 984                string: "println".to_string(),
 985            },
 986            is_snippet: false,
 987            sort_text: Some("80000000"),
 988            sort_key: (2, "unreachable"),
 989        },
 990        SortableMatch {
 991            string_match: StringMatch {
 992                candidate_id: 0,
 993                score: 0.2,
 994                positions: vec![],
 995                string: "println!(…)".to_string(),
 996            },
 997            is_snippet: true,
 998            sort_text: Some("80000000"),
 999            sort_key: (2, "println!(…)"),
1000        },
1001    ];
1002    CompletionsMenu::sort_matches(&mut matches, query, SnippetSortOrder::Top);
1003    assert_eq!(
1004        matches[0].string_match.string.as_str(),
1005        "println!(…)",
1006        "Match order not expected"
1007    );
1008}