Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / language-server / src / tests / rename.rs
46 kB 2606 lines
1// SPDX-License-Identifier: Apache-2.0 2// SPDX-FileCopyrightText: 2025 The Gleam contributors 3 4use std::collections::HashMap; 5 6use lsp_types::{ 7 Position, PrepareRenameParams, PrepareRenamePlaceholder, Range, RenameParams, 8 TextDocumentPositionParams, Uri as Url, WorkDoneProgressParams, 9}; 10 11use super::{TestProject, find_position_of, hover}; 12 13/// Returns the rename range and edit to apply if the rename is valid and can be 14/// carried out. 15/// However if the rename produces an error response from the language server, 16/// the error message is returned. 17fn rename( 18 tester: &TestProject<'_>, 19 new_name: &str, 20 position: Position, 21) -> Result<Option<(Range, lsp_types::WorkspaceEdit)>, String> { 22 let prepare_rename_response = tester.at(position, |engine, params, _| { 23 let params = PrepareRenameParams { 24 text_document_position_params: TextDocumentPositionParams { 25 text_document: params.text_document, 26 position, 27 }, 28 work_done_progress_params: WorkDoneProgressParams { 29 work_done_token: None, 30 }, 31 }; 32 engine.prepare_rename(params).result.unwrap() 33 }); 34 35 let range = match prepare_rename_response { 36 Some(lsp_types::PrepareRenameResult::Range(range)) => range, 37 Some(lsp_types::PrepareRenameResult::PrepareRenamePlaceholder( 38 PrepareRenamePlaceholder { range, .. }, 39 )) => range, 40 _ => return Ok(None), 41 }; 42 43 let outcome = tester.at(position, |engine, params, _| { 44 let params = RenameParams { 45 text_document_position_params: TextDocumentPositionParams { 46 text_document: params.text_document, 47 position, 48 }, 49 new_name: new_name.to_string(), 50 work_done_progress_params: WorkDoneProgressParams::default(), 51 }; 52 engine.rename(params).result.unwrap() 53 }); 54 55 match outcome { 56 Ok(Some(edit)) => Ok(Some((range, edit))), 57 Ok(None) => Ok(None), 58 Err(error) => Err(error.message), 59 } 60} 61 62fn apply_rename( 63 tester: &TestProject<'_>, 64 new_name: &str, 65 position: Position, 66) -> (Range, HashMap<String, String>) { 67 let (range, edit) = rename(tester, new_name, position) 68 .expect("Rename failed") 69 .expect("No rename produced"); 70 let changes = edit.changes.expect("No text edit found"); 71 (range, apply_code_edit(tester, changes)) 72} 73 74fn apply_code_edit( 75 tester: &TestProject<'_>, 76 changes: HashMap<Url, Vec<lsp_types::TextEdit>>, 77) -> HashMap<String, String> { 78 let mut modules = HashMap::new(); 79 for (uri, change) in changes { 80 let module_name = tester.module_name_from_url(&uri).expect("Valid uri"); 81 let module_code = tester.src_from_module_url(&uri).expect("Module exists"); 82 83 _ = modules.insert(module_name, super::apply_code_edit(module_code, change)); 84 } 85 86 modules 87} 88 89macro_rules! assert_rename { 90 ($code:literal, $new_name:literal, $position:expr $(,)?) => { 91 assert_rename!(TestProject::for_source($code), $new_name, $position); 92 }; 93 94 (($module_name:literal, $module_src:literal), $code:literal, $new_name:literal, $position:expr $(,)?) => { 95 assert_rename!( 96 TestProject::for_source($code).add_module($module_name, $module_src), 97 $new_name, 98 $position 99 ); 100 }; 101 102 ($project:expr, $new_name:literal, $position:expr $(,)?) => { 103 let project = $project; 104 let src = project.src; 105 let position = $position.find_position(src); 106 let (range, result) = apply_rename(&project, $new_name, position); 107 108 let mut output = String::from("----- BEFORE RENAME\n"); 109 for (name, src) in project.root_package_modules.iter() { 110 output.push_str(&format!("-- {name}.gleam\n{src}\n\n")); 111 } 112 output.push_str(&format!( 113 "-- app.gleam\n{}\n\n----- AFTER RENAME\n", 114 hover::show_hover(src, range, range.start) 115 )); 116 for (name, src) in project.root_package_modules.iter() { 117 output.push_str(&format!( 118 "-- {name}.gleam\n{}\n\n", 119 result 120 .get(*name) 121 .map(|string| string.as_str()) 122 .unwrap_or(*src) 123 )); 124 } 125 output.push_str(&format!( 126 "-- app.gleam\n{}", 127 result 128 .get("app") 129 .map(|string| string.as_str()) 130 .unwrap_or(src) 131 )); 132 133 insta::assert_snapshot!(insta::internals::AutoName, output, src); 134 }; 135} 136 137macro_rules! assert_no_rename { 138 ($code:literal, $new_name:literal, $position:expr $(,)?) => { 139 let project = TestProject::for_source($code); 140 assert_no_rename!(&project, $new_name, $position); 141 }; 142 143 ($project:expr, $new_name:literal, $position:expr $(,)?) => { 144 let src = $project.src; 145 let position = $position.find_position(src); 146 let result = rename($project, $new_name, position); 147 assert_eq!(result, Ok(None)); 148 }; 149} 150 151macro_rules! assert_rename_error { 152 ($code:literal, $new_name:literal, $position:expr $(,)?) => { 153 let project = TestProject::for_source($code); 154 assert_rename_error!(&project, $new_name, $position); 155 }; 156 157 ($project:expr, $new_name:literal, $position:expr $(,)?) => { 158 let src = $project.src; 159 let position = $position.find_position(src); 160 let error = rename($project, $new_name, position).unwrap_err(); 161 let snapshot = format!("Error response message:\n\n{error}"); 162 insta::assert_snapshot!(insta::internals::AutoName, snapshot, src); 163 }; 164} 165 166#[test] 167fn rename_local_variable() { 168 assert_rename!( 169 " 170pub fn main() { 171 let wibble = 10 172 wibble 173} 174", 175 "wobble", 176 find_position_of("wibble").nth_occurrence(2), 177 ); 178} 179 180#[test] 181fn rename_shadowed_local_variable() { 182 assert_rename!( 183 " 184pub fn main() { 185 let wibble = 10 186 let wibble = wibble / 2 187 wibble 188} 189", 190 "wobble", 191 find_position_of("wibble /"), 192 ); 193} 194 195#[test] 196fn rename_shadowing_local_variable() { 197 assert_rename!( 198 " 199pub fn main() { 200 let wibble = 10 201 let wibble = wibble / 2 202 wibble 203} 204", 205 "wobble", 206 find_position_of("wibble").nth_occurrence(4), 207 ); 208} 209 210#[test] 211fn rename_local_variable_record_access() { 212 assert_rename!( 213 " 214type Wibble { 215 Wibble(wibble: Int) 216} 217 218pub fn main() { 219 let wibble = Wibble(wibble: 1) 220 wibble.wibble 221} 222", 223 "wobble", 224 find_position_of("wibble."), 225 ); 226} 227#[test] 228fn rename_local_variable_guard_clause() { 229 assert_rename!( 230 " 231pub fn main() { 232 let wibble = True 233 case Nil { 234 Nil if wibble -> todo 235 _ -> panic 236 } 237 wibble || False 238} 239", 240 "wobble", 241 find_position_of("wibble ||"), 242 ); 243} 244 245#[test] 246fn rename_local_variable_from_definition() { 247 assert_rename!( 248 " 249pub fn main() { 250 let wibble = 10 251 let wobble = wibble + 1 252 wobble - wibble 253} 254", 255 "some_value", 256 find_position_of("wibble =") 257 ); 258} 259 260#[test] 261fn rename_local_variable_from_definition_nested_pattern() { 262 assert_rename!( 263 " 264pub fn main() { 265 let assert Ok([_, wibble, ..]) = Error(12) 266 wibble 267} 268", 269 "second_element", 270 find_position_of("wibble,") 271 ); 272} 273 274#[test] 275fn rename_local_variable_assignment_pattern() { 276 assert_rename!( 277 " 278pub fn main() { 279 let assert Error(12 as something) = Error(12) 280 something 281} 282", 283 "the_error", 284 find_position_of("something").nth_occurrence(2) 285 ); 286} 287 288#[test] 289fn rename_local_variable_from_definition_assignment_pattern() { 290 assert_rename!( 291 " 292pub fn main() { 293 let assert Error(12 as something) = Error(12) 294 something 295} 296", 297 "the_error", 298 find_position_of("something)") 299 ); 300} 301 302#[test] 303fn rename_local_variable_argument() { 304 assert_rename!( 305 " 306pub fn add(first_number: Int, x: Int) -> Int { 307 x + first_number 308} 309", 310 "second_number", 311 find_position_of("x +") 312 ); 313} 314 315#[test] 316fn rename_local_variable_argument_from_definition() { 317 assert_rename!( 318 " 319pub fn wibble(wibble: Float) { 320 wibble /. 0.3 321} 322", 323 "wobble", 324 find_position_of("wibble:") 325 ); 326} 327 328#[test] 329fn rename_local_variable_label_shorthand() { 330 assert_rename!( 331 " 332type Wibble { 333 Wibble(wibble: Int) 334} 335 336pub fn main() { 337 let Wibble(wibble:) = todo 338 wibble + 1 339} 340", 341 "wobble", 342 find_position_of("wibble +") 343 ); 344} 345 346#[test] 347fn rename_local_variable_label_shorthand_from_definition() { 348 assert_rename!( 349 " 350type Wibble { 351 Wibble(wibble: Int) 352} 353 354pub fn main() { 355 let Wibble(wibble:) = todo 356 wibble + 1 357} 358", 359 "wobble", 360 find_position_of("wibble:)") 361 ); 362} 363 364#[test] 365fn rename_local_variable_from_label_shorthand() { 366 assert_rename!( 367 " 368type Wibble { 369 Wibble(wibble: Int) 370} 371 372pub fn main() { 373 let wibble = todo 374 Wibble(wibble:) 375} 376", 377 "wobble", 378 find_position_of("wibble:)") 379 ); 380} 381 382#[test] 383fn rename_local_variable_in_bit_array_pattern() { 384 assert_rename!( 385 " 386pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { 387 let prefix_size = bit_size(prefix) 388 389 case bits { 390 <<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True 391 _ -> False 392 } 393} 394", 395 "size_of_prefix", 396 find_position_of("prefix_size =") 397 ); 398} 399 400#[test] 401fn rename_local_variable_from_bit_array_pattern() { 402 assert_rename!( 403 " 404pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { 405 let prefix_size = bit_size(prefix) 406 407 case bits { 408 <<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True 409 _ -> False 410 } 411} 412", 413 "size_of_prefix", 414 find_position_of("prefix_size)") 415 ); 416} 417 418#[test] 419fn no_rename_keyword() { 420 assert_no_rename!( 421 " 422pub fn main() {} 423", 424 "wibble", 425 find_position_of("fn"), 426 ); 427} 428 429#[test] 430fn no_rename_invalid_name() { 431 assert_rename_error!( 432 " 433pub fn main() { 434 let wibble = 10 435 wibble 436} 437", 438 "Not_AValid_Name", 439 find_position_of("wibble").nth_occurrence(2) 440 ); 441} 442 443#[test] 444fn rename_function_from_definition() { 445 assert_rename!( 446 ( 447 "mod", 448 " 449import app 450 451fn wibble() { 452 app.something() 453} 454" 455 ), 456 " 457pub fn something() { 458 something() 459} 460 461fn something_else() { 462 something() 463} 464", 465 "some_function", 466 find_position_of("something") 467 ); 468} 469 470#[test] 471fn rename_function_from_reference() { 472 assert_rename!( 473 ( 474 "mod", 475 " 476import app 477 478fn wibble() { 479 app.something() 480} 481" 482 ), 483 " 484pub fn something() { 485 something() 486} 487 488fn something_else() { 489 something() 490} 491", 492 "some_function", 493 find_position_of("something").nth_occurrence(2) 494 ); 495} 496 497#[test] 498fn rename_function_from_qualified_reference() { 499 assert_rename!( 500 ( 501 "mod", 502 " 503pub fn wibble() { 504 wibble() 505} 506" 507 ), 508 " 509import mod 510 511pub fn main() { 512 mod.wibble() 513} 514", 515 "some_function", 516 find_position_of("wibble") 517 ); 518} 519 520#[test] 521fn rename_function_from_unqualified_reference() { 522 assert_rename!( 523 ( 524 "mod", 525 " 526pub fn wibble() { 527 wibble() 528} 529" 530 ), 531 " 532import mod.{wibble} 533 534pub fn main() { 535 wibble() 536 mod.wibble() 537} 538", 539 "some_function", 540 find_position_of("wibble(") 541 ); 542} 543 544#[test] 545fn rename_aliased_function() { 546 assert_rename!( 547 ( 548 "mod", 549 " 550import app.{something as something_else} 551 552fn wibble() { 553 something_else() 554} 555" 556 ), 557 " 558pub fn something() { 559 something() 560} 561 562fn something_else() { 563 something() 564} 565", 566 "some_function", 567 find_position_of("something") 568 ); 569} 570 571#[test] 572fn rename_function_shadowing_module() { 573 let src = " 574import gleam/list 575 576pub fn list() { 577 [] 578} 579 580pub fn main() { 581 list.map(todo, todo) 582} 583 "; 584 585 assert_rename!( 586 TestProject::for_source(src).add_hex_module("gleam/list", "pub fn map(_, _) {}"), 587 "empty_list", 588 find_position_of("list()") 589 ); 590} 591 592#[test] 593fn rename_function_shadowed_by_field_access() { 594 assert_rename!( 595 ( 596 "mod", 597 " 598import app 599 600type App { 601 App(something: Int) 602} 603 604pub fn main() { 605 let app = App(10) 606 app.something 607} 608" 609 ), 610 " 611pub fn something() { 612 todo 613} 614", 615 "function", 616 find_position_of("something") 617 ); 618} 619 620#[test] 621fn no_rename_function_with_invalid_name() { 622 assert_rename_error!( 623 " 624pub fn main() { 625 let wibble = 10 626 wibble 627} 628", 629 "Not_AValid_Name", 630 find_position_of("main") 631 ); 632} 633 634#[test] 635fn no_rename_function_from_other_package() { 636 let src = " 637import wibble 638 639pub fn main() { 640 wibble.wobble() 641} 642"; 643 644 assert_no_rename!( 645 &TestProject::for_source(src).add_hex_module("wibble", "pub fn wobble() { todo }"), 646 "something", 647 find_position_of("wobble") 648 ); 649} 650 651#[test] 652fn rename_constant_from_definition() { 653 assert_rename!( 654 ( 655 "mod", 656 " 657import app 658 659fn wibble() { 660 app.something 661} 662" 663 ), 664 " 665pub const something = 10 666 667pub fn main() { 668 something + { 4 * something } 669} 670", 671 "ten", 672 find_position_of("something") 673 ); 674} 675 676#[test] 677fn rename_constant_from_reference() { 678 assert_rename!( 679 ( 680 "mod", 681 " 682import app 683 684fn wibble() { 685 app.something 686} 687" 688 ), 689 " 690pub const something = 10 691 692pub fn main() { 693 something + { 4 * something } 694} 695", 696 "ten", 697 find_position_of("something").nth_occurrence(2) 698 ); 699} 700 701#[test] 702fn rename_constant_from_qualified_reference() { 703 assert_rename!( 704 ( 705 "mod", 706 " 707pub const something = 10 708 709fn wibble() { 710 something 711} 712" 713 ), 714 " 715import mod 716 717pub fn main() { 718 mod.something 719} 720", 721 "ten", 722 find_position_of("something") 723 ); 724} 725 726#[test] 727fn rename_constant_from_unqualified_reference() { 728 assert_rename!( 729 ( 730 "mod", 731 " 732pub const something = 10 733 734fn wibble() { 735 something 736} 737" 738 ), 739 " 740import mod.{something} 741 742pub fn main() { 743 something + mod.something 744} 745", 746 "ten", 747 find_position_of("something +") 748 ); 749} 750 751#[test] 752fn rename_aliased_constant() { 753 assert_rename!( 754 ( 755 "mod", 756 " 757import app.{something as some_constant} 758 759fn wibble() { 760 some_constant 761} 762" 763 ), 764 " 765pub const something = 10 766 767pub fn main() { 768 something + { 4 * something } 769} 770", 771 "ten", 772 find_position_of("something") 773 ); 774} 775 776#[test] 777fn rename_constant_shadowing_module() { 778 let src = " 779import gleam/list 780 781const list = [] 782 783pub fn main() { 784 list.map(todo, todo) 785} 786 "; 787 788 assert_rename!( 789 TestProject::for_source(src).add_hex_module("gleam/list", "pub fn map(_, _) {}"), 790 "empty_list", 791 find_position_of("list =") 792 ); 793} 794 795#[test] 796fn rename_constant_shadowed_by_field_access() { 797 assert_rename!( 798 ( 799 "mod", 800 " 801import app 802 803type App { 804 App(something: Int) 805} 806 807pub fn main() { 808 let app = App(10) 809 app.something 810} 811" 812 ), 813 " 814pub const something = 10 815", 816 "constant", 817 find_position_of("something") 818 ); 819} 820 821#[test] 822fn no_rename_constant_with_invalid_name() { 823 assert_rename_error!( 824 " 825const value = 10 826", 827 "Ten", 828 find_position_of("value") 829 ); 830} 831 832#[test] 833fn no_rename_constant_from_other_package() { 834 let src = " 835import wibble 836 837pub fn main() { 838 wibble.wobble 839} 840"; 841 842 assert_no_rename!( 843 &TestProject::for_source(src).add_hex_module("wibble", "pub const wobble = 2"), 844 "something", 845 find_position_of("wobble") 846 ); 847} 848 849#[test] 850fn rename_type_variant_from_definition() { 851 assert_rename!( 852 ( 853 "mod", 854 " 855import app 856 857fn wibble() { 858 app.Constructor(4) 859} 860" 861 ), 862 " 863pub type Wibble { 864 Constructor(Int) 865} 866 867pub fn main() { 868 Constructor(10) 869} 870", 871 "Wibble", 872 find_position_of("Constructor(Int") 873 ); 874} 875 876#[test] 877fn rename_type_variant_from_reference() { 878 assert_rename!( 879 ( 880 "mod", 881 " 882import app 883 884fn wibble() { 885 app.Constructor(4) 886} 887" 888 ), 889 " 890pub type Wibble { 891 Constructor(Int) 892} 893 894pub fn main() { 895 Constructor(10) 896} 897", 898 "Wibble", 899 find_position_of("Constructor(10") 900 ); 901} 902 903#[test] 904fn rename_type_variant_from_qualified_reference() { 905 assert_rename!( 906 ( 907 "mod", 908 " 909pub type Wibble { 910 Constructor(Int) 911} 912 913fn wibble() { 914 Constructor(42) 915} 916" 917 ), 918 " 919import mod 920 921pub fn main() { 922 mod.Constructor 923} 924", 925 "Variant", 926 find_position_of("Constructor") 927 ); 928} 929 930#[test] 931fn rename_type_variant_from_unqualified_reference() { 932 assert_rename!( 933 ( 934 "mod", 935 " 936pub type Wibble { 937 Constructor(Int) 938} 939 940fn wibble() { 941 Constructor(81) 942} 943" 944 ), 945 " 946import mod.{Constructor} 947 948pub fn main() { 949 #(Constructor(75), mod.Constructor(57)) 950} 951", 952 "Number", 953 find_position_of("Constructor(75") 954 ); 955} 956 957#[test] 958fn rename_aliased_type_variant() { 959 assert_rename!( 960 ( 961 "mod", 962 " 963import app.{Constructor as ValueConstructor} 964 965fn wibble() { 966 ValueConstructor(172) 967} 968" 969 ), 970 " 971pub type Wibble { 972 Constructor(Int) 973} 974 975pub fn main() { 976 Constructor(42) 977} 978", 979 "MakeAWibble", 980 find_position_of("Constructor") 981 ); 982} 983 984#[test] 985fn no_rename_type_variant_with_invalid_name() { 986 assert_rename_error!( 987 " 988pub type Wibble { 989 Constructor(Int) 990} 991", 992 "name_in_snake_case", 993 find_position_of("Constructor") 994 ); 995} 996 997#[test] 998fn rename_custom_type_variant_pattern() { 999 assert_rename!( 1000 " 1001pub type Type { 1002 X 1003 Y 1004} 1005 1006pub fn main(t) { 1007 case t { 1008 X -> 0 1009 Y -> 0 1010 } 1011} 1012", 1013 "Renamed", 1014 find_position_of("X") 1015 ); 1016} 1017 1018#[test] 1019fn rename_imported_custom_type_variant_pattern() { 1020 assert_rename!( 1021 ( 1022 "other", 1023 " 1024import app 1025 1026pub fn main(t) { 1027 case t { 1028 app.X -> 0 1029 app.Y -> 0 1030 } 1031} 1032" 1033 ), 1034 " 1035pub type Type { 1036 X 1037 Y 1038} 1039", 1040 "Renamed", 1041 find_position_of("X") 1042 ); 1043} 1044 1045#[test] 1046fn rename_imported_unqualified_custom_type_variant_pattern() { 1047 assert_rename!( 1048 ( 1049 "other", 1050 " 1051import app.{X, Y} 1052 1053pub fn main(t) { 1054 case t { 1055 X -> 0 1056 Y -> 0 1057 } 1058} 1059" 1060 ), 1061 " 1062pub type Type { 1063 X 1064 Y 1065} 1066", 1067 "Renamed", 1068 find_position_of("X") 1069 ); 1070} 1071 1072#[test] 1073fn rename_type_variant_pattern_with_arguments() { 1074 assert_rename!( 1075 " 1076pub type Wibble { 1077 Wibble(Int) 1078 Wobble(Float) 1079} 1080 1081fn wibble() { 1082 case Wibble(10) { 1083 Wibble(20) -> todo 1084 Wibble(_) -> panic 1085 } 1086} 1087", 1088 "Variant", 1089 find_position_of("Wibble(10)") 1090 ); 1091} 1092 1093#[test] 1094fn rename_type_variant_from_pattern() { 1095 assert_rename!( 1096 " 1097pub type Type { 1098 X 1099 Y 1100} 1101 1102pub fn main(t) { 1103 case t { 1104 X -> 0 1105 Y -> 0 1106 } 1107} 1108", 1109 "Renamed", 1110 find_position_of("X ->") 1111 ); 1112} 1113 1114#[test] 1115fn no_rename_type_variant_from_other_package() { 1116 let src = " 1117import wibble 1118 1119pub fn main() { 1120 wibble.Wibble(10) 1121} 1122"; 1123 1124 assert_no_rename!( 1125 &TestProject::for_source(src).add_hex_module("wibble", "pub type Wibble { Wibble(Int) }"), 1126 "Constructor", 1127 find_position_of("Wibble") 1128 ); 1129} 1130 1131#[test] 1132fn rename_value_in_nested_module() { 1133 assert_rename!( 1134 ( 1135 "sub/mod", 1136 " 1137pub fn wibble() { 1138 wibble() 1139} 1140" 1141 ), 1142 " 1143import sub/mod 1144 1145pub fn main() { 1146 mod.wibble() 1147} 1148", 1149 "some_function", 1150 find_position_of("wibble") 1151 ); 1152} 1153 1154#[test] 1155fn rename_value_in_aliased_module() { 1156 assert_rename!( 1157 ( 1158 "mod", 1159 " 1160pub fn wibble() { 1161 wibble() 1162} 1163" 1164 ), 1165 " 1166import mod as the_module 1167 1168pub fn main() { 1169 the_module.wibble() 1170} 1171", 1172 "some_function", 1173 find_position_of("wibble") 1174 ); 1175} 1176 1177#[test] 1178fn rename_aliased_value() { 1179 assert_rename!( 1180 ( 1181 "mod", 1182 " 1183import app.{Wibble as Wobble} 1184 1185fn wobble() { 1186 Wobble 1187} 1188" 1189 ), 1190 " 1191pub type Wibble { Wibble } 1192 1193pub fn main() { 1194 Wibble 1195} 1196", 1197 "Wubble", 1198 find_position_of("Wibble }") 1199 ); 1200} 1201 1202#[test] 1203fn rename_type_from_definition() { 1204 assert_rename!( 1205 ( 1206 "mod", 1207 " 1208import app 1209 1210fn wibble() -> app.Wibble { todo } 1211" 1212 ), 1213 " 1214pub type Wibble { Constructor } 1215 1216pub fn main(w: Wibble) -> Wibble { todo } 1217", 1218 "SomeType", 1219 find_position_of("Wibble") 1220 ); 1221} 1222 1223#[test] 1224fn rename_type_from_reference() { 1225 assert_rename!( 1226 ( 1227 "mod", 1228 " 1229import app 1230 1231fn wibble() -> app.Wibble { todo } 1232" 1233 ), 1234 " 1235pub type Wibble { Constructor } 1236 1237pub fn main(w: Wibble) -> Wibble { todo } 1238", 1239 "SomeType", 1240 find_position_of("Wibble").nth_occurrence(2) 1241 ); 1242} 1243 1244#[test] 1245fn rename_type_from_qualified_reference() { 1246 assert_rename!( 1247 ( 1248 "mod", 1249 " 1250pub type Wibble { Constructor } 1251 1252fn wibble(w: Wibble) -> Wibble { todo } 1253" 1254 ), 1255 " 1256import mod 1257 1258pub fn main(w: mod.Wibble) -> mod.Wibble { todo } 1259", 1260 "SomeType", 1261 find_position_of("Wibble") 1262 ); 1263} 1264 1265#[test] 1266fn rename_type_from_unqualified_reference() { 1267 assert_rename!( 1268 ( 1269 "mod", 1270 " 1271pub type Wibble { Constructor } 1272 1273fn wibble(w: Wibble) -> Wibble { todo } 1274" 1275 ), 1276 " 1277import mod.{type Wibble} 1278 1279pub fn main(w: Wibble) -> mod.Wibble { todo } 1280", 1281 "SomeType", 1282 find_position_of("Wibble)") 1283 ); 1284} 1285 1286#[test] 1287fn rename_aliased_type() { 1288 assert_rename!( 1289 ( 1290 "mod", 1291 " 1292import app.{type Wibble as Wobble} 1293 1294fn wibble() -> Wobble { todo } 1295" 1296 ), 1297 " 1298pub type Wibble { Constructor } 1299 1300pub fn main(w: Wibble) -> Wibble { todo } 1301", 1302 "SomeType", 1303 find_position_of("Wibble") 1304 ); 1305} 1306 1307#[test] 1308fn no_rename_type_with_invalid_name() { 1309 assert_rename_error!( 1310 " 1311type Wibble { Wobble } 1312", 1313 "a_type_name", 1314 find_position_of("Wibble") 1315 ); 1316} 1317 1318#[test] 1319fn no_rename_type_from_other_package() { 1320 let src = " 1321import wibble 1322 1323pub fn main() -> wibble.Wibble { todo } 1324"; 1325 1326 assert_no_rename!( 1327 &TestProject::for_source(src).add_hex_module("wibble", "pub type Wibble { Wibble }"), 1328 "SomeType", 1329 find_position_of("Wibble") 1330 ); 1331} 1332 1333// https://github.com/gleam-lang/gleam/issues/4372 1334#[test] 1335fn rename_type_referenced_in_variant_constructor_argument() { 1336 assert_rename!( 1337 ( 1338 "mod", 1339 " 1340import app 1341 1342pub type Wobble { 1343 Wobble(w: app.Wibble) 1344} 1345" 1346 ), 1347 " 1348pub type Wibble { 1349 Wibble 1350} 1351 1352pub fn main() { 1353 let wibble = Wibble 1354} 1355", 1356 "SomeType", 1357 find_position_of("Wibble") 1358 ); 1359} 1360 1361// https://github.com/gleam-lang/gleam/issues/4372 1362#[test] 1363fn rename_type_from_variant_constructor_argument() { 1364 assert_rename!( 1365 ( 1366 "mod", 1367 " 1368pub type Wibble { 1369 Wibble 1370} 1371 1372pub fn main() { 1373 let wibble = Wibble 1374} 1375" 1376 ), 1377 " 1378import mod 1379 1380pub type Wobble { 1381 Wobble(w: mod.Wibble) 1382} 1383", 1384 "SomeType", 1385 find_position_of("Wibble") 1386 ); 1387} 1388 1389// https://github.com/gleam-lang/gleam/issues/4553 1390#[test] 1391fn rename_local_variable_with_label_shorthand() { 1392 assert_rename!( 1393 " 1394pub type Wibble { 1395 Wibble(first: Int, second: Int) 1396} 1397 1398pub fn main() { 1399 let second = 2 1400 Wibble(first: 1, second:) 1401} 1402", 1403 "something", 1404 find_position_of("second =") 1405 ); 1406} 1407 1408// https://github.com/gleam-lang/gleam/issues/4748 1409#[test] 1410fn rename_alternative_pattern() { 1411 assert_rename!( 1412 " 1413pub fn main(x) { 1414 case x { 1415 #(wibble, [wobble]) | #(wobble, [wibble, _]) | #(_, [wibble, wobble, ..]) -> 1416 wibble + wobble 1417 _ -> 0 1418 } 1419} 1420", 1421 "new_name", 1422 find_position_of("wibble") 1423 ); 1424} 1425 1426// https://github.com/gleam-lang/gleam/issues/5091 1427#[test] 1428fn rename_alternative_pattern_aliases() { 1429 assert_rename!( 1430 " 1431pub fn main(x) { 1432 case x { 1433 [] as list | [_] as list -> list 1434 _ -> [] 1435 } 1436} 1437", 1438 "new_name", 1439 find_position_of("list") 1440 ); 1441} 1442 1443#[test] 1444fn rename_alternative_pattern_aliases_from_alternative() { 1445 assert_rename!( 1446 " 1447pub fn main(x) { 1448 case x { 1449 [] as list | [_] as list -> list 1450 _ -> [] 1451 } 1452} 1453", 1454 "new_name", 1455 find_position_of("list").nth_occurrence(2) 1456 ); 1457} 1458 1459#[test] 1460fn rename_alternative_pattern_aliases_from_usage() { 1461 assert_rename!( 1462 " 1463pub fn main(x) { 1464 case x { 1465 [] as list | [_] as list -> list 1466 _ -> [] 1467 } 1468} 1469", 1470 "new_name", 1471 find_position_of("list").nth_occurrence(3) 1472 ); 1473} 1474 1475#[test] 1476fn rename_alternative_pattern_alias_and_variable_1() { 1477 assert_rename!( 1478 " 1479pub fn main(x) { 1480 case x { 1481 [] as list | [_, ..list] -> list 1482 _ -> [] 1483 } 1484} 1485", 1486 "new_name", 1487 find_position_of("list").nth_occurrence(1) 1488 ); 1489} 1490 1491#[test] 1492fn rename_alternative_pattern_alias_and_variable_2() { 1493 assert_rename!( 1494 " 1495pub fn main(x) { 1496 case x { 1497 [] as list | [_, ..list] -> list 1498 _ -> [] 1499 } 1500} 1501", 1502 "new_name", 1503 find_position_of("list").nth_occurrence(2) 1504 ); 1505} 1506 1507#[test] 1508fn rename_alternative_pattern_alias_and_variable_3() { 1509 assert_rename!( 1510 " 1511pub fn main(x) { 1512 case x { 1513 [_, ..list] | [] as list -> list 1514 _ -> [] 1515 } 1516} 1517", 1518 "new_name", 1519 find_position_of("list").nth_occurrence(1) 1520 ); 1521} 1522 1523#[test] 1524fn rename_alternative_pattern_alias_and_variable_4() { 1525 assert_rename!( 1526 " 1527pub fn main(x) { 1528 case x { 1529 [_, ..list] | [] as list -> list 1530 _ -> [] 1531 } 1532} 1533", 1534 "new_name", 1535 find_position_of("list").nth_occurrence(2) 1536 ); 1537} 1538 1539#[test] 1540fn rename_alternative_pattern_from_usage() { 1541 assert_rename!( 1542 " 1543pub fn main(x) { 1544 case x { 1545 #(wibble, [wobble]) | #(wobble, [wibble, _]) | #(_, [wibble, wobble, ..]) -> 1546 wibble + wobble 1547 _ -> 0 1548 } 1549} 1550", 1551 "new_name", 1552 find_position_of("wibble +") 1553 ); 1554} 1555 1556// https://github.com/gleam-lang/gleam/issues/4605 1557#[test] 1558fn rename_prelude_value() { 1559 assert_rename!( 1560 " 1561pub fn main() { 1562 Ok(10) 1563} 1564", 1565 "Success", 1566 find_position_of("Ok") 1567 ); 1568} 1569#[test] 1570fn rename_prelude_type() { 1571 assert_rename!( 1572 " 1573pub fn main() -> Result(Int, Nil) { 1574 Ok(10) 1575} 1576", 1577 "SuccessOrFailure", 1578 find_position_of("Result") 1579 ); 1580} 1581 1582#[test] 1583fn rename_variable_with_alternative_pattern_with_same_name() { 1584 assert_rename!( 1585 " 1586pub fn main(x) { 1587 let some_var = 10 1588 1589 case x { 1590 #(some_var, []) | #(_, [some_var]) -> 1591 some_var 1592 _ -> 0 1593 } 1594 1595 some_var 1596} 1597", 1598 "new_name", 1599 find_position_of("some_var") 1600 ); 1601} 1602 1603#[test] 1604fn rename_prelude_value_with_prelude_already_imported() { 1605 assert_rename!( 1606 " 1607import gleam 1608 1609pub fn main() { 1610 Ok(gleam.Error(10)) 1611} 1612", 1613 "Success", 1614 find_position_of("Ok") 1615 ); 1616} 1617 1618#[test] 1619fn rename_prelude_value_with_prelude_import_with_empty_braces() { 1620 assert_rename!( 1621 " 1622import gleam.{} 1623 1624pub fn main() { 1625 Ok(gleam.Error(10)) 1626} 1627", 1628 "Success", 1629 find_position_of("Ok") 1630 ); 1631} 1632 1633#[test] 1634fn rename_prelude_value_with_other_prelude_value_imported() { 1635 assert_rename!( 1636 " 1637import gleam.{Error} 1638 1639pub fn main() { 1640 Ok(Error(10)) 1641} 1642", 1643 "Success", 1644 find_position_of("Ok") 1645 ); 1646} 1647 1648#[test] 1649fn rename_prelude_type_with_prelude_value_imported_with_trailing_comma() { 1650 assert_rename!( 1651 " 1652import gleam.{Error,} 1653 1654pub fn main() -> Result(Int, Nil) { 1655 Error(10) 1656} 1657", 1658 "OkOrError", 1659 find_position_of("Result") 1660 ); 1661} 1662 1663#[test] 1664fn rename_prelude_value_with_other_module_imported() { 1665 assert_rename!( 1666 ("something", "pub type Something"), 1667 " 1668import something 1669 1670pub fn main() { 1671 Ok(10) 1672} 1673", 1674 "Success", 1675 find_position_of("Ok") 1676 ); 1677} 1678 1679#[test] 1680fn rename_module_access_in_clause_guard() { 1681 assert_rename!( 1682 ( 1683 "wibble", 1684 " 1685import app 1686 1687pub fn main() { 1688 case app.something { 1689 thing if thing == app.something -> True 1690 _ -> False 1691 } 1692} 1693" 1694 ), 1695 " 1696pub const something = 10 1697", 1698 "new_name", 1699 find_position_of("something") 1700 ); 1701} 1702 1703#[test] 1704fn rename_variable_used_in_record_update() { 1705 assert_rename!( 1706 " 1707type Wibble { 1708 Wibble(a: Int, b: Int, c: Int) 1709} 1710 1711fn wibble(wibble: Wibble) { 1712 Wibble(..wibble, c: 1) 1713} 1714", 1715 "value", 1716 find_position_of("wibble:") 1717 ); 1718} 1719 1720//https://github.com/gleam-lang/gleam/issues/4941 1721#[test] 1722fn rename_external_function() { 1723 assert_rename!( 1724 r#" 1725pub fn main() { wibble() } 1726 1727@external(erlang, "a", "a") 1728fn wibble() -> Nil 1729"#, 1730 "new_name", 1731 find_position_of("wibble").nth_occurrence(2) 1732 ); 1733} 1734 1735#[test] 1736fn rename_external_javascript_function_with_pure_gleam_fallback() { 1737 assert_rename!( 1738 r#" 1739pub fn main() { wibble() } 1740 1741@external(javascript, "a", "a") 1742fn wibble() -> Nil { 1743 Nil 1744} 1745"#, 1746 "new_name", 1747 find_position_of("wibble").nth_occurrence(2) 1748 ); 1749} 1750 1751#[test] 1752fn rename_nested_aliased_pattern() { 1753 assert_rename!( 1754 r#" 1755pub fn go(x) { 1756 case x { 1757 [[nested, ..] as wibble, ..] -> todo 1758 _ -> todo 1759 } 1760} 1761 "#, 1762 "new_name", 1763 find_position_of("nested") 1764 ); 1765} 1766 1767#[test] 1768fn rename_module_from_import() { 1769 assert_rename!( 1770 TestProject::for_source("import option") 1771 .add_module("option", "pub type Option(a) { Some(a) None }"), 1772 "opt", 1773 find_position_of("option"), 1774 ); 1775} 1776 1777#[test] 1778fn rename_works_when_error_is_present() { 1779 assert_rename!( 1780 r#" 1781fn wibble() { 1782 "test string" 1783} 1784 1785pub fn main() { 1786 1 + "1" 1787 echo wibble() 1788} 1789 "#, 1790 "wobble", 1791 find_position_of("wibble") 1792 ); 1793} 1794 1795#[test] 1796fn rename_module_from_import_with_alias() { 1797 assert_rename!( 1798 TestProject::for_source("import option as opt") 1799 .add_module("option", "pub type Option(a) { Some(a) None }"), 1800 "o", 1801 find_position_of("opt"), 1802 ); 1803} 1804 1805#[test] 1806fn reanem_module_from_import_with_unqualified_values() { 1807 assert_rename!( 1808 TestProject::for_source("import option . { Some, None }") 1809 .add_module("option", "pub type Option(a) { Some(a) None }"), 1810 "opt", 1811 find_position_of("option"), 1812 ); 1813} 1814 1815#[test] 1816fn rename_module_from_import_with_unqualified_value_and_alias() { 1817 assert_rename!( 1818 TestProject::for_source("import option . {Some, None} as opt") 1819 .add_module("option", "pub type Option(a) { Some(a) None }"), 1820 "o", 1821 find_position_of("opt"), 1822 ); 1823} 1824 1825#[test] 1826fn rename_module_from_import_namespaced() { 1827 assert_rename!( 1828 TestProject::for_source("import std / option ") 1829 .add_module("std/option", "pub type Option(a) { Some(a) None }"), 1830 "opt", 1831 find_position_of("option"), 1832 ); 1833} 1834 1835#[test] 1836fn rename_module_from_import_namespaced_with_alias() { 1837 assert_rename!( 1838 TestProject::for_source("import std / option as opt") 1839 .add_module("std/option", "pub type Option(a) { Some(a) None }"), 1840 "o", 1841 find_position_of("opt"), 1842 ); 1843} 1844 1845#[test] 1846fn rename_module_from_import_namespaced_with_unqualified_values() { 1847 assert_rename!( 1848 TestProject::for_source("import std / option . { Some, None }") 1849 .add_module("std/option", "pub type Option(a) { Some(a) None }"), 1850 "opt", 1851 find_position_of("option"), 1852 ); 1853} 1854 1855#[test] 1856fn rename_module_from_import_namespaced_with_unqualified_value_and_alias() { 1857 assert_rename!( 1858 TestProject::for_source("import std / option . { Some, None } as opt") 1859 .add_module("std/option", "pub type Option(a) { Some(a) None }"), 1860 "o", 1861 find_position_of("opt"), 1862 ); 1863} 1864 1865#[test] 1866fn rename_module_from_import_with_alias_to_original_name() { 1867 assert_rename!( 1868 TestProject::for_source("import option as opt") 1869 .add_module("option", "pub type Option(a) { Some(a) None }"), 1870 "option", 1871 find_position_of("opt"), 1872 ); 1873} 1874 1875#[test] 1876fn rename_module_from_variant_in_expression() { 1877 let src = r#" 1878import option 1879 1880pub fn main() { 1881 echo option . None 1882} 1883"#; 1884 assert_rename!( 1885 TestProject::for_source(src).add_module("option", "pub type Option(a) { Some(a) None }"), 1886 "opt", 1887 find_position_of("option").nth_occurrence(2) 1888 ); 1889} 1890 1891#[test] 1892fn rename_prefix_string_suffix_variable_in_case() { 1893 assert_rename!( 1894 " 1895fn main() -> String { 1896 let wibble = \"1-wibble\" 1897 case wibble { 1898 \"1\" <> rest -> rest 1899 other -> other 1900 } 1901} 1902", 1903 "new_name", 1904 find_position_of("rest").nth_occurrence(1) 1905 ); 1906} 1907 1908#[test] 1909fn rename_module_from_constant_in_expression() { 1910 let src = r#" 1911import maths 1912 1913pub fn main() { 1914 echo maths . pi 1915} 1916"#; 1917 1918 assert_rename!( 1919 TestProject::for_source(src).add_module("maths", "pub const pi = 3.14"), 1920 "m", 1921 find_position_of("maths").nth_occurrence(2), 1922 ); 1923} 1924 1925#[test] 1926fn rename_module_from_variant_in_const() { 1927 let src = r#" 1928import option 1929 1930const x = option .None 1931"#; 1932 1933 assert_rename!( 1934 TestProject::for_source(src).add_module("option", "pub type Option(a) { Some(a) None }"), 1935 "opt", 1936 find_position_of("option").nth_occurrence(2), 1937 ); 1938} 1939 1940#[test] 1941fn rename_module_from_constant_in_const() { 1942 let src = r#" 1943import maths 1944 1945const x = maths . pi 1946"#; 1947 1948 assert_rename!( 1949 TestProject::for_source(src).add_module("maths", "pub const pi = 3.14"), 1950 "m", 1951 find_position_of("maths").nth_occurrence(2), 1952 ); 1953} 1954 1955#[test] 1956fn rename_module_from_variant_in_pattern() { 1957 let src = r#" 1958import option 1959 1960pub fn is_some(option) { 1961 case option { 1962 option. Some(_) -> True 1963 option .None -> False 1964 } 1965} 1966"#; 1967 1968 assert_rename!( 1969 TestProject::for_source(src).add_module("option", "pub type Option(a) { Some(a) None }"), 1970 "opt", 1971 find_position_of("option").nth_occurrence(4), 1972 ); 1973} 1974 1975#[test] 1976fn rename_prefix_string_suffix_variable_in_case_triggered_from_usage() { 1977 assert_rename!( 1978 " 1979fn main() -> String { 1980 let wibble = \"1-wibble\" 1981 case wibble { 1982 \"1\" <> rest -> rest 1983 other -> other 1984 } 1985} 1986", 1987 "new_name", 1988 find_position_of("rest").nth_occurrence(2) 1989 ); 1990} 1991 1992#[test] 1993fn rename_module_from_variant_in_clause_guard() { 1994 let src = r#" 1995import option 1996 1997pub fn count_none(list) { 1998 case list { 1999 [option, ..rest] if option == option . None -> 1 + count_none(rest) 2000 [_, ..rest] -> count_none(rest) 2001 [] -> 0 2002 } 2003} 2004"#; 2005 2006 assert_rename!( 2007 TestProject::for_source(src).add_module("option", "pub type Option(a) { Some(a) None }"), 2008 "opt", 2009 find_position_of("option").nth_occurrence(4), 2010 ); 2011} 2012 2013#[test] 2014fn rename_prefix_string_suffix_variable_with_alternative_definition_in_case() { 2015 assert_rename!( 2016 " 2017fn main() -> String { 2018 let wibble = \"1-wibble\" 2019 case wibble { 2020 \"1\" <> rest | \"2\" <> rest -> rest 2021 other -> other 2022 } 2023} 2024", 2025 "new_name", 2026 find_position_of("rest").nth_occurrence(1), 2027 ); 2028} 2029 2030#[test] 2031fn rename_module_from_constant_in_clause_guard() { 2032 let src = r#" 2033import maths 2034 2035pub fn count_pi(list) { 2036 case list { 2037 [number, ..rest] if number == maths . pi -> 1 + count_pi(rest) 2038 [_, ..rest] -> count_pi(rest) 2039 [] -> 0 2040 } 2041} 2042"#; 2043 2044 assert_rename!( 2045 TestProject::for_source(src).add_module("maths", "pub const pi = 3.14"), 2046 "m", 2047 find_position_of("maths").nth_occurrence(2), 2048 ); 2049} 2050 2051#[test] 2052fn rename_prefix_string_suffix_variable_with_alternative_definition_triggered_from_second_pattern() 2053{ 2054 assert_rename!( 2055 " 2056fn main() -> String { 2057 let wibble = \"1-wibble\" 2058 case wibble { 2059 \"1\" <> rest | \"2\" <> rest -> rest 2060 other -> other 2061 } 2062} 2063", 2064 "new_name", 2065 find_position_of("rest").nth_occurrence(2), 2066 ); 2067} 2068 2069#[test] 2070fn rename_module_from_type_in_custom_type() { 2071 let src = r#" 2072import option 2073 2074type Value(a) { 2075 Value(option.Option(a)) 2076} 2077"#; 2078 2079 assert_rename!( 2080 TestProject::for_source(src).add_module("option", "pub type Option(a) { Some(a) None }"), 2081 "opt", 2082 find_position_of("option").nth_occurrence(2), 2083 ); 2084} 2085 2086#[test] 2087fn rename_module_from_type_in_type_alias() { 2088 let src = r#" 2089import option 2090 2091type Option(a) = 2092 option.Option(a) 2093"#; 2094 2095 assert_rename!( 2096 TestProject::for_source(src).add_module("option", "pub type Option(a) { Some(a) None }"), 2097 "opt", 2098 find_position_of("option").nth_occurrence(2), 2099 ); 2100} 2101 2102#[test] 2103fn rename_module_from_type_in_annotation() { 2104 let src = r#" 2105import option 2106 2107const x: option.Option(Int) = option.Some(1) 2108"#; 2109 2110 assert_rename!( 2111 TestProject::for_source(src).add_module("option", "pub type Option(a) { Some(a) None }"), 2112 "opt", 2113 find_position_of("option").nth_occurrence(2), 2114 ); 2115} 2116 2117#[test] 2118fn rename_module_from_function_call() { 2119 let src = r#" 2120import option 2121 2122pub fn main() { 2123 option.is_some(option.Some(1)) 2124} 2125"#; 2126 2127 let option_module = r#" 2128pub type Option(a) { 2129 Some(a) 2130 None 2131} 2132 2133pub fn is_some(option: Option(a)) -> Bool { 2134 case option { 2135 Some(_) -> True 2136 None -> False 2137 } 2138} 2139"#; 2140 2141 assert_rename!( 2142 TestProject::for_source(src).add_module("option", option_module), 2143 "opt", 2144 find_position_of("option").nth_occurrence(2), 2145 ); 2146} 2147 2148#[test] 2149fn rename_prefix_string_suffix_variable_in_let_assert() { 2150 assert_rename!( 2151 " 2152fn main() -> String { 2153 let assert \"1\" <> rest = \"1-wibble\" 2154 rest 2155} 2156", 2157 "new_name", 2158 find_position_of("rest").nth_occurrence(1) 2159 ); 2160} 2161 2162#[test] 2163fn rename_prefix_string_suffix_variable_in_let_assert_triggered_from_usage() { 2164 assert_rename!( 2165 " 2166fn main() -> String { 2167 let assert \"1\" <> rest = \"1-wibble\" 2168 rest 2169} 2170", 2171 "new_name", 2172 find_position_of("rest").nth_occurrence(2) 2173 ); 2174} 2175 2176#[test] 2177fn rename_prefix_string_alias_in_case() { 2178 assert_rename!( 2179 " 2180fn main() -> String { 2181 let wibble = \"1-wibble\" 2182 case wibble { 2183 \"1\" as digit <> rest -> digit <> rest 2184 other -> other 2185 } 2186} 2187", 2188 "new_name", 2189 find_position_of("digit").nth_occurrence(1) 2190 ); 2191} 2192 2193#[test] 2194fn rename_prefix_string_alias_in_case_triggered_from_usage() { 2195 assert_rename!( 2196 " 2197fn main() -> String { 2198 let wibble = \"1-wibble\" 2199 case wibble { 2200 \"1\" as digit <> rest -> digit <> rest 2201 other -> other 2202 } 2203} 2204", 2205 "new_name", 2206 find_position_of("digit").nth_occurrence(2) 2207 ); 2208} 2209 2210#[test] 2211fn rename_prefix_string_alias_with_alternative_definitions_in_case() { 2212 assert_rename!( 2213 " 2214fn main() -> String { 2215 let wibble = \"1-wibble\" 2216 case wibble { 2217 \"1\" as digit <> rest | \"2\" as digit <> rest -> digit <> rest 2218 other -> other 2219 } 2220} 2221", 2222 "new_name", 2223 find_position_of("digit").nth_occurrence(1) 2224 ); 2225} 2226 2227#[test] 2228fn rename_prefix_string_alias_with_alternative_definitions_triggered_from_second_pattern() { 2229 assert_rename!( 2230 " 2231fn main() -> String { 2232 let wibble = \"1-wibble\" 2233 case wibble { 2234 \"1\" as digit <> rest | \"2\" as digit <> rest -> digit <> rest 2235 other -> other 2236 } 2237} 2238", 2239 "new_name", 2240 find_position_of("digit").nth_occurrence(2) 2241 ); 2242} 2243 2244#[test] 2245fn rename_prefix_string_alias_in_let_assert() { 2246 assert_rename!( 2247 " 2248fn main() -> String { 2249 let assert \"1\" as digit <> rest = \"1-wibble\" 2250 digit 2251} 2252", 2253 "new_name", 2254 find_position_of("digit").nth_occurrence(1) 2255 ); 2256} 2257 2258#[test] 2259fn rename_prefix_string_alias_in_let_assert_triggered_from_usage() { 2260 assert_rename!( 2261 " 2262fn main() -> String { 2263 let assert \"1\" as digit <> rest = \"1-wibble\" 2264 digit 2265} 2266", 2267 "new_name", 2268 find_position_of("digit").nth_occurrence(2) 2269 ); 2270} 2271 2272#[test] 2273fn rename_prefix_string_suffix_variable_nested_in_tuple() { 2274 assert_rename!( 2275 " 2276fn main() { 2277 case #(\"1-wibble\", 0) { 2278 #(\"1\" <> rest, _) -> rest 2279 _ -> \"\" 2280 } 2281} 2282", 2283 "new_name", 2284 find_position_of("rest").nth_occurrence(1) 2285 ); 2286} 2287 2288#[test] 2289fn rename_prefix_string_alias_used_in_guard() { 2290 assert_rename!( 2291 " 2292fn main() { 2293 case \"1-wibble\" { 2294 \"1\" as digit <> _rest if digit == \"1\" -> digit 2295 _ -> \"\" 2296 } 2297} 2298", 2299 "new_name", 2300 find_position_of("digit").nth_occurrence(1) 2301 ); 2302} 2303 2304#[test] 2305fn rename_prefix_string_suffix_used_in_guard() { 2306 assert_rename!( 2307 " 2308fn main() { 2309 case \"1-wibble\" { 2310 \"1\" <> rest if rest == \"-wibble\" -> rest 2311 _ -> \"\" 2312 } 2313} 2314", 2315 "new_name", 2316 find_position_of("rest").nth_occurrence(1) 2317 ); 2318} 2319 2320#[test] 2321fn rename_prefix_string_suffix_shadowing_outer_variable() { 2322 assert_rename!( 2323 " 2324fn main() { 2325 let rest = \"outer\" 2326 case \"1-wibble\" { 2327 \"1\" <> rest -> rest 2328 _ -> rest 2329 } 2330} 2331", 2332 "new_name", 2333 find_position_of("rest").nth_occurrence(2) 2334 ); 2335} 2336 2337#[test] 2338fn rename_prefix_string_alias_and_suffix_complex_guard() { 2339 assert_rename!( 2340 " 2341fn main() { 2342 case \"1-wibble\" { 2343 \"1\" as digit <> rest if digit == \"1\" && rest == \"-wibble\" -> #(digit, rest) 2344 _ -> #(\"\", \"\") 2345 } 2346} 2347", 2348 "new_name", 2349 find_position_of("digit").nth_occurrence(1) 2350 ); 2351} 2352 2353#[test] 2354fn rename_module_from_alias_use() { 2355 let src = r#" 2356import maths as m 2357 2358pub fn main() { 2359 echo m .pi 2360} 2361"#; 2362 2363 assert_rename!( 2364 TestProject::for_source(src).add_module("maths", "pub const pi = 3.14"), 2365 "mth", 2366 find_position_of("m").nth_occurrence(5) 2367 ); 2368} 2369 2370#[test] 2371fn rename_local_variable_from_guard() { 2372 assert_rename!( 2373 " 2374pub fn main() { 2375 let wibble = True 2376 let wobble = False 2377 case wibble { 2378 True if wobble -> !wibble 2379 False if !wobble -> wibble 2380 _ -> wobble 2381 } 2382} 2383", 2384 "something_else", 2385 find_position_of("wobble").nth_occurrence(2).under_char('o') 2386 ); 2387} 2388 2389#[test] 2390fn alias_imported_module_from_guard() { 2391 assert_rename!( 2392 ("mod", "pub const wibble = 10"), 2393 " 2394import mod 2395 2396pub fn main() { 2397 let wibble = True 2398 case wibble { 2399 True if mod.wibble < 5 -> !wibble 2400 False if mod.wibble != 10 -> wibble 2401 _ -> mod.wibble + 1 2402 } 2403} 2404", 2405 "module", 2406 find_position_of("mod.wibble").under_char('m') 2407 ); 2408} 2409 2410#[test] 2411fn rename_module_select_from_guard() { 2412 assert_rename!( 2413 ("mod", "pub const wibble = 10"), 2414 " 2415import mod 2416 2417pub fn main() { 2418 let wibble = True 2419 case wibble { 2420 True if mod.wibble < 5 -> !wibble 2421 False if mod.wibble != 10 -> wibble 2422 _ -> mod.wibble + 1 2423 } 2424} 2425", 2426 "ten", 2427 find_position_of("mod.wibble").under_char('w') 2428 ); 2429} 2430 2431#[test] 2432fn rename_type_variable_in_function() { 2433 assert_rename!( 2434 " 2435pub fn first(a: wibble, b: wobble) -> wibble { 2436 a 2437} 2438", 2439 "value", 2440 find_position_of("wibble") 2441 ); 2442} 2443 2444#[test] 2445fn rename_type_variable_in_function_from_return() { 2446 assert_rename!( 2447 " 2448pub fn first(a: wibble, b: wobble) -> wibble { 2449 a 2450} 2451", 2452 "value", 2453 find_position_of("-> wibble").under_char('l') 2454 ); 2455} 2456 2457#[test] 2458fn rename_type_variable_in_function_body_not_used_in_head() { 2459 assert_rename!( 2460 " 2461pub fn something() { 2462 let x: Result(a, b) = todo 2463 let y: a = case x { 2464 Ok(a) -> a 2465 Error(_) -> panic 2466 } 2467} 2468", 2469 "ok", 2470 find_position_of(": a").under_char('a') 2471 ); 2472} 2473 2474#[test] 2475fn rename_type_variable_in_function_used_in_body() { 2476 assert_rename!( 2477 " 2478pub fn first(a: wibble, b: wobble) -> wibble { 2479 let x: wibble = a 2480 let f = fn(a: wibble) -> wibble { a } 2481 f(x) 2482} 2483", 2484 "value", 2485 find_position_of("wibble") 2486 ); 2487} 2488 2489#[test] 2490fn rename_type_variable_in_function_from_body() { 2491 assert_rename!( 2492 " 2493pub fn first(a: wibble, b: wobble) -> wibble { 2494 let x: wibble = a 2495 let f = fn(a: wibble) -> wibble { a } 2496 f(x) 2497} 2498", 2499 "value", 2500 find_position_of("x: wibble").under_char('i') 2501 ); 2502} 2503 2504#[test] 2505fn type_variable_in_separate_function_is_not_renamed() { 2506 assert_rename!( 2507 " 2508pub fn first(a: wibble, b: wobble) -> wibble { 2509 a 2510} 2511 2512pub fn an_unrelated_function(a: wibble, b: wibble) -> wibble { 2513 a 2514} 2515", 2516 "value", 2517 find_position_of("wibble") 2518 ); 2519} 2520 2521#[test] 2522fn rename_type_variable_in_constant() { 2523 assert_rename!( 2524 " 2525pub const empty: List(#(anything, anything)) = [] 2526", 2527 "a", 2528 find_position_of("anything") 2529 ); 2530} 2531 2532#[test] 2533fn rename_type_variable_in_type_alias() { 2534 assert_rename!( 2535 " 2536pub type Option(a) { 2537 Some(a) 2538 None 2539} 2540 2541pub type Maybe(some_type) = 2542 Option(some_type) 2543", 2544 "something", 2545 find_position_of("Option(some_type").under_char('_') 2546 ); 2547} 2548 2549#[test] 2550fn rename_type_variable_in_type_alias_from_head() { 2551 assert_rename!( 2552 " 2553pub type Option(a) { 2554 Some(a) 2555 None 2556} 2557 2558pub type Maybe(some_type) = 2559 Option(some_type) 2560", 2561 "something", 2562 find_position_of("some_type") 2563 ); 2564} 2565 2566#[test] 2567fn rename_type_variable_in_custom_type_from_head() { 2568 assert_rename!( 2569 " 2570pub type Option(anything) { 2571 Some(anything) 2572 None 2573} 2574", 2575 "something", 2576 find_position_of("anything") 2577 ); 2578} 2579 2580#[test] 2581fn rename_type_variable_in_custom_type_from_constructor() { 2582 assert_rename!( 2583 " 2584pub type Option(anything) { 2585 Some(anything) 2586 None 2587} 2588", 2589 "something", 2590 find_position_of("Some(anything").under_char('i') 2591 ); 2592} 2593 2594#[test] 2595fn invalid_type_variable_name() { 2596 assert_rename_error!( 2597 " 2598pub type Option(anything) { 2599 Some(anything) 2600 None 2601} 2602", 2603 "SomeType", 2604 find_position_of("anything") 2605 ); 2606}