test_trycatch.vim (52802B)
1 " Test try-catch-finally exception handling 2 " Most of this was formerly in test49. 3 4 source check.vim 5 source shared.vim 6 source vim9.vim 7 8 "------------------------------------------------------------------------------- 9 " Test environment {{{1 10 "------------------------------------------------------------------------------- 11 12 com! XpathINIT let g:Xpath = '' 13 com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . <args> 14 15 " Test 25: Executing :finally clauses on normal control flow {{{1 16 " 17 " Control flow in a :try conditional should always fall through to its 18 " :finally clause. A :finally clause of a :try conditional inside an 19 " inactive conditional should never be executed. 20 "------------------------------------------------------------------------------- 21 22 func T25_F() 23 let loops = 3 24 while loops > 0 25 Xpath 'a' . loops 26 if loops >= 2 27 try 28 Xpath 'b' . loops 29 if loops == 2 30 try 31 Xpath 'c' . loops 32 finally 33 Xpath 'd' . loops 34 endtry 35 endif 36 finally 37 Xpath 'e' . loops 38 if loops == 2 39 try 40 Xpath 'f' . loops 41 final 42 Xpath 'g' . loops 43 endtry 44 endif 45 endtry 46 endif 47 Xpath 'h' . loops 48 let loops = loops - 1 49 endwhile 50 Xpath 'i' 51 endfunc 52 53 " Also try using "fina" and "final" and "finall" as abbreviations. 54 func T25_G() 55 if 1 56 try 57 Xpath 'A' 58 call T25_F() 59 Xpath 'B' 60 fina 61 Xpath 'C' 62 endtry 63 else 64 try 65 Xpath 'D' 66 finall 67 Xpath 'E' 68 endtry 69 endif 70 endfunc 71 72 func Test_finally() 73 XpathINIT 74 call T25_G() 75 call assert_equal('Aa3b3e3h3a2b2c2d2e2f2g2h2a1h1iBC', g:Xpath) 76 endfunc 77 78 79 "------------------------------------------------------------------------------- 80 " Test 26: Executing :finally clauses after :continue or :break {{{1 81 " 82 " For a :continue or :break dynamically enclosed in a :try/:endtry 83 " region inside the next surrounding :while/:endwhile, if the 84 " :continue/:break is before the :finally, the :finally clause is 85 " executed first. If the :continue/:break is after the :finally, the 86 " :finally clause is broken (like an :if/:endif region). 87 "------------------------------------------------------------------------------- 88 89 func T26_F() 90 try 91 let loops = 3 92 while loops > 0 93 try 94 try 95 if loops == 2 96 Xpath 'a' . loops 97 let loops = loops - 1 98 continue 99 elseif loops == 1 100 Xpath 'b' . loops 101 break 102 finish 103 endif 104 Xpath 'c' . loops 105 endtry 106 finally 107 Xpath 'd' . loops 108 endtry 109 Xpath 'e' . loops 110 let loops = loops - 1 111 endwhile 112 Xpath 'f' 113 finally 114 Xpath 'g' 115 let loops = 3 116 while loops > 0 117 try 118 finally 119 try 120 if loops == 2 121 Xpath 'h' . loops 122 let loops = loops - 1 123 continue 124 elseif loops == 1 125 Xpath 'i' . loops 126 break 127 finish 128 endif 129 endtry 130 Xpath 'j' . loops 131 endtry 132 Xpath 'k' . loops 133 let loops = loops - 1 134 endwhile 135 Xpath 'l' 136 endtry 137 Xpath 'm' 138 endfunc 139 140 func Test_finally_after_continue() 141 XpathINIT 142 call T26_F() 143 call assert_equal('c3d3e3a2d1b1d1fgj3k3h2i1lm', g:Xpath) 144 endfunc 145 146 147 "------------------------------------------------------------------------------- 148 " Test 32: Remembering the :return value on :finally {{{1 149 " 150 " If a :finally clause is executed due to a :return specifying 151 " a value, this is the value visible to the caller if not overwritten 152 " by a new :return in the :finally clause. A :return without a value 153 " in the :finally clause overwrites with value 0. 154 "------------------------------------------------------------------------------- 155 156 func T32_F() 157 try 158 Xpath 'a' 159 try 160 Xpath 'b' 161 return "ABCD" 162 Xpath 'c' 163 finally 164 Xpath 'd' 165 endtry 166 Xpath 'e' 167 finally 168 Xpath 'f' 169 endtry 170 Xpath 'g' 171 endfunc 172 173 func T32_G() 174 try 175 Xpath 'h' 176 return 8 177 Xpath 'i' 178 finally 179 Xpath 'j' 180 return 16 + strlen(T32_F()) 181 Xpath 'k' 182 endtry 183 Xpath 'l' 184 endfunc 185 186 func T32_H() 187 try 188 Xpath 'm' 189 return 32 190 Xpath 'n' 191 finally 192 Xpath 'o' 193 return 194 Xpath 'p' 195 endtry 196 Xpath 'q' 197 endfunc 198 199 func T32_I() 200 try 201 Xpath 'r' 202 finally 203 Xpath 's' 204 return T32_G() + T32_H() + 64 205 Xpath 't' 206 endtry 207 Xpath 'u' 208 endfunc 209 210 func Test_finally_return() 211 XpathINIT 212 call assert_equal(84, T32_I()) 213 call assert_equal('rshjabdfmo', g:Xpath) 214 endfunc 215 216 "------------------------------------------------------------------------------- 217 " Test 33: :return under :execute or user command and :finally {{{1 218 " 219 " A :return command may be executed under an ":execute" or from 220 " a user command. Executing of :finally clauses and passing through 221 " the return code works also then. 222 "------------------------------------------------------------------------------- 223 224 func T33_F() 225 try 226 RETURN 10 227 Xpath 'a' 228 finally 229 Xpath 'b' 230 endtry 231 Xpath 'c' 232 endfunc 233 234 func T33_G() 235 try 236 RETURN 20 237 Xpath 'd' 238 finally 239 Xpath 'e' 240 RETURN 30 241 Xpath 'f' 242 endtry 243 Xpath 'g' 244 endfunc 245 246 func T33_H() 247 try 248 execute "try | return 40 | finally | return 50 | endtry" 249 Xpath 'h' 250 finally 251 Xpath 'i' 252 endtry 253 Xpath 'j' 254 endfunc 255 256 func T33_I() 257 try 258 execute "try | return 60 | finally | return 70 | endtry" 259 Xpath 'k' 260 finally 261 Xpath 'l' 262 execute "try | return 80 | finally | return 90 | endtry" 263 Xpath 'm' 264 endtry 265 Xpath 'n' 266 endfunc 267 268 func T33_J() 269 try 270 RETURN 100 271 Xpath 'o' 272 finally 273 Xpath 'p' 274 return 275 Xpath 'q' 276 endtry 277 Xpath 'r' 278 endfunc 279 280 func T33_K() 281 try 282 execute "try | return 110 | finally | return 120 | endtry" 283 Xpath 's' 284 finally 285 Xpath 't' 286 execute "try | return 130 | finally | return | endtry" 287 Xpath 'u' 288 endtry 289 Xpath 'v' 290 endfunc 291 292 func T33_L() 293 try 294 return 295 Xpath 'w' 296 finally 297 Xpath 'x' 298 RETURN 140 299 Xpath 'y' 300 endtry 301 Xpath 'z' 302 endfunc 303 304 func T33_M() 305 try 306 return 307 Xpath 'A' 308 finally 309 Xpath 'B' 310 execute "try | return 150 | finally | return 160 | endtry" 311 Xpath 'C' 312 endtry 313 Xpath 'D' 314 endfunc 315 316 func T33_N() 317 RETURN 170 318 endfunc 319 320 func T33_O() 321 execute "try | return 180 | finally | return 190 | endtry" 322 endfunc 323 324 func Test_finally_cmd_return() 325 command! -nargs=? RETURN 326 \ try | return <args> | finally | return <args> * 2 | endtry 327 XpathINIT 328 call assert_equal(20, T33_F()) 329 call assert_equal(60, T33_G()) 330 call assert_equal(50, T33_H()) 331 call assert_equal(90, T33_I()) 332 call assert_equal(0, T33_J()) 333 call assert_equal(0, T33_K()) 334 call assert_equal(280, T33_L()) 335 call assert_equal(160, T33_M()) 336 call assert_equal(340, T33_N()) 337 call assert_equal(190, T33_O()) 338 call assert_equal('beilptxB', g:Xpath) 339 delcommand RETURN 340 endfunc 341 342 343 "------------------------------------------------------------------------------- 344 " Test 41: Skipped :throw finding next command {{{1 345 " 346 " A :throw in an inactive conditional must not hide a following 347 " command. 348 "------------------------------------------------------------------------------- 349 350 func T41_F() 351 Xpath 'a' 352 if 0 | throw 'never' | endif | Xpath 'b' 353 Xpath 'c' 354 endfunc 355 356 func T41_G() 357 Xpath 'd' 358 while 0 | throw 'never' | endwhile | Xpath 'e' 359 Xpath 'f' 360 endfunc 361 362 func T41_H() 363 Xpath 'g' 364 if 0 | try | throw 'never' | endtry | endif | Xpath 'h' 365 Xpath 'i' 366 endfunc 367 368 func Test_throw_inactive_cond() 369 XpathINIT 370 try 371 Xpath 'j' 372 call T41_F() 373 Xpath 'k' 374 catch /.*/ 375 Xpath 'l' 376 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 377 endtry 378 379 try 380 Xpath 'm' 381 call T41_G() 382 Xpath 'n' 383 catch /.*/ 384 Xpath 'o' 385 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 386 endtry 387 388 try 389 Xpath 'p' 390 call T41_H() 391 Xpath 'q' 392 catch /.*/ 393 Xpath 'r' 394 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 395 endtry 396 397 call assert_equal('jabckmdefnpghiq', g:Xpath) 398 endfunc 399 400 401 "------------------------------------------------------------------------------- 402 " Test 42: Catching number and string exceptions {{{1 403 " 404 " When a number is thrown, it is converted to a string exception. 405 " Numbers and strings may be caught by specifying a regular exception 406 " as argument to the :catch command. 407 "------------------------------------------------------------------------------- 408 409 410 func T42_F() 411 try 412 413 try 414 Xpath 'a' 415 throw 4711 416 Xpath 'b' 417 catch /4711/ 418 Xpath 'c' 419 endtry 420 421 try 422 Xpath 'd' 423 throw 4711 424 Xpath 'e' 425 catch /^4711$/ 426 Xpath 'f' 427 endtry 428 429 try 430 Xpath 'g' 431 throw 4711 432 Xpath 'h' 433 catch /\d/ 434 Xpath 'i' 435 endtry 436 437 try 438 Xpath 'j' 439 throw 4711 440 Xpath 'k' 441 catch /^\d\+$/ 442 Xpath 'l' 443 endtry 444 445 try 446 Xpath 'm' 447 throw "arrgh" 448 Xpath 'n' 449 catch /arrgh/ 450 Xpath 'o' 451 endtry 452 453 try 454 Xpath 'p' 455 throw "arrgh" 456 Xpath 'q' 457 catch /^arrgh$/ 458 Xpath 'r' 459 endtry 460 461 try 462 Xpath 's' 463 throw "arrgh" 464 Xpath 't' 465 catch /\l/ 466 Xpath 'u' 467 endtry 468 469 try 470 Xpath 'v' 471 throw "arrgh" 472 Xpath 'w' 473 catch /^\l\+$/ 474 Xpath 'x' 475 endtry 476 477 try 478 try 479 Xpath 'y' 480 throw "ARRGH" 481 Xpath 'z' 482 catch /^arrgh$/ 483 Xpath 'A' 484 endtry 485 catch /^\carrgh$/ 486 Xpath 'B' 487 endtry 488 489 try 490 Xpath 'C' 491 throw "" 492 Xpath 'D' 493 catch /^$/ 494 Xpath 'E' 495 endtry 496 497 catch /.*/ 498 Xpath 'F' 499 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 500 endtry 501 endfunc 502 503 func Test_catch_number_string() 504 XpathINIT 505 call T42_F() 506 call assert_equal('acdfgijlmoprsuvxyBCE', g:Xpath) 507 endfunc 508 509 510 "------------------------------------------------------------------------------- 511 " Test 43: Selecting the correct :catch clause {{{1 512 " 513 " When an exception is thrown and there are multiple :catch clauses, 514 " the first matching one is taken. 515 "------------------------------------------------------------------------------- 516 517 func T43_F() 518 let loops = 3 519 while loops > 0 520 try 521 if loops == 3 522 Xpath 'a' . loops 523 throw "a" 524 Xpath 'b' . loops 525 elseif loops == 2 526 Xpath 'c' . loops 527 throw "ab" 528 Xpath 'd' . loops 529 elseif loops == 1 530 Xpath 'e' . loops 531 throw "abc" 532 Xpath 'f' . loops 533 endif 534 catch /abc/ 535 Xpath 'g' . loops 536 catch /ab/ 537 Xpath 'h' . loops 538 catch /.*/ 539 Xpath 'i' . loops 540 catch /a/ 541 Xpath 'j' . loops 542 endtry 543 544 let loops = loops - 1 545 endwhile 546 Xpath 'k' 547 endfunc 548 549 func Test_multi_catch() 550 XpathINIT 551 call T43_F() 552 call assert_equal('a3i3c2h2e1g1k', g:Xpath) 553 endfunc 554 555 556 "------------------------------------------------------------------------------- 557 " Test 44: Missing or empty :catch patterns {{{1 558 " 559 " A missing or empty :catch pattern means the same as /.*/, that is, 560 " catches everything. To catch only empty exceptions, /^$/ must be 561 " used. A :catch with missing, empty, or /.*/ argument also works 562 " when followed by another command separated by a bar on the same 563 " line. :catch patterns cannot be specified between ||. But other 564 " pattern separators can be used instead of //. 565 "------------------------------------------------------------------------------- 566 567 func T44_F() 568 try 569 try 570 Xpath 'a' 571 throw "" 572 catch /^$/ 573 Xpath 'b' 574 endtry 575 576 try 577 Xpath 'c' 578 throw "" 579 catch /.*/ 580 Xpath 'd' 581 endtry 582 583 try 584 Xpath 'e' 585 throw "" 586 catch // 587 Xpath 'f' 588 endtry 589 590 try 591 Xpath 'g' 592 throw "" 593 catch 594 Xpath 'h' 595 endtry 596 597 try 598 Xpath 'i' 599 throw "oops" 600 catch /^$/ 601 Xpath 'j' 602 catch /.*/ 603 Xpath 'k' 604 endtry 605 606 try 607 Xpath 'l' 608 throw "arrgh" 609 catch /^$/ 610 Xpath 'm' 611 catch // 612 Xpath 'n' 613 endtry 614 615 try 616 Xpath 'o' 617 throw "brrr" 618 catch /^$/ 619 Xpath 'p' 620 catch 621 Xpath 'q' 622 endtry 623 624 try | Xpath 'r' | throw "x" | catch /.*/ | Xpath 's' | endtry 625 626 try | Xpath 't' | throw "y" | catch // | Xpath 'u' | endtry 627 628 while 1 629 try 630 let caught = 0 631 let v:errmsg = "" 632 " Extra try level: if ":catch" without arguments below raises 633 " a syntax error because it misinterprets the "Xpath" as a pattern, 634 " let it be caught by the ":catch /.*/" below. 635 try 636 try | Xpath 'v' | throw "z" | catch | Xpath 'w' | : 637 endtry 638 endtry 639 catch /.*/ 640 let caught = 1 641 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 642 finally 643 if $VIMNOERRTHROW && v:errmsg != "" 644 call assert_report(v:errmsg) 645 endif 646 if caught || $VIMNOERRTHROW && v:errmsg != "" 647 Xpath 'x' 648 endif 649 break " discard error for $VIMNOERRTHROW 650 endtry 651 endwhile 652 653 let cologne = 4711 654 try 655 try 656 Xpath 'y' 657 throw "throw cologne" 658 " Next lines catches all and throws 4711: 659 catch |throw cologne| 660 Xpath 'z' 661 endtry 662 catch /4711/ 663 Xpath 'A' 664 endtry 665 666 try 667 Xpath 'B' 668 throw "plus" 669 catch +plus+ 670 Xpath 'C' 671 endtry 672 673 Xpath 'D' 674 catch /.*/ 675 Xpath 'E' 676 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 677 endtry 678 endfunc 679 680 func Test_empty_catch() 681 XpathINIT 682 call T44_F() 683 call assert_equal('abcdefghiklnoqrstuvwyABCD', g:Xpath) 684 endfunc 685 686 687 "------------------------------------------------------------------------------- 688 " Test 45: Catching exceptions from nested :try blocks {{{1 689 " 690 " When :try blocks are nested, an exception is caught by the innermost 691 " try conditional that has a matching :catch clause. 692 "------------------------------------------------------------------------------- 693 694 func T45_F() 695 let loops = 3 696 while loops > 0 697 try 698 try 699 try 700 try 701 if loops == 3 702 Xpath 'a' . loops 703 throw "a" 704 Xpath 'b' . loops 705 elseif loops == 2 706 Xpath 'c' . loops 707 throw "ab" 708 Xpath 'd' . loops 709 elseif loops == 1 710 Xpath 'e' . loops 711 throw "abc" 712 Xpath 'f' . loops 713 endif 714 catch /abc/ 715 Xpath 'g' . loops 716 endtry 717 catch /ab/ 718 Xpath 'h' . loops 719 endtry 720 catch /.*/ 721 Xpath 'i' . loops 722 endtry 723 catch /a/ 724 Xpath 'j' . loops 725 endtry 726 727 let loops = loops - 1 728 endwhile 729 Xpath 'k' 730 endfunc 731 732 func Test_catch_from_nested_try() 733 XpathINIT 734 call T45_F() 735 call assert_equal('a3i3c2h2e1g1k', g:Xpath) 736 endfunc 737 738 739 "------------------------------------------------------------------------------- 740 " Test 46: Executing :finally after a :throw in nested :try {{{1 741 " 742 " When an exception is thrown from within nested :try blocks, the 743 " :finally clauses of the non-catching try conditionals should be 744 " executed before the matching :catch of the next surrounding :try 745 " gets the control. If this also has a :finally clause, it is 746 " executed afterwards. 747 "------------------------------------------------------------------------------- 748 749 func T46_F() 750 let sum = 0 751 752 try 753 Xpath 'a' 754 try 755 Xpath 'b' 756 try 757 Xpath 'c' 758 try 759 Xpath 'd' 760 throw "ABC" 761 Xpath 'e' 762 catch /xyz/ 763 Xpath 'f' 764 finally 765 Xpath 'g' 766 if sum != 0 767 Xpath 'h' 768 endif 769 let sum = sum + 1 770 endtry 771 Xpath 'i' 772 catch /123/ 773 Xpath 'j' 774 catch /321/ 775 Xpath 'k' 776 finally 777 Xpath 'l' 778 if sum != 1 779 Xpath 'm' 780 endif 781 let sum = sum + 2 782 endtry 783 Xpath 'n' 784 finally 785 Xpath 'o' 786 if sum != 3 787 Xpath 'p' 788 endif 789 let sum = sum + 4 790 endtry 791 Xpath 'q' 792 catch /ABC/ 793 Xpath 'r' 794 if sum != 7 795 Xpath 's' 796 endif 797 let sum = sum + 8 798 finally 799 Xpath 't' 800 if sum != 15 801 Xpath 'u' 802 endif 803 let sum = sum + 16 804 endtry 805 Xpath 'v' 806 if sum != 31 807 Xpath 'w' 808 endif 809 endfunc 810 811 func Test_finally_after_throw() 812 XpathINIT 813 call T46_F() 814 call assert_equal('abcdglortv', g:Xpath) 815 endfunc 816 817 818 "------------------------------------------------------------------------------- 819 " Test 47: Throwing exceptions from a :catch clause {{{1 820 " 821 " When an exception is thrown from a :catch clause, it should not be 822 " caught by a :catch of the same :try conditional. After executing 823 " the :finally clause (if present), surrounding try conditionals 824 " should be checked for a matching :catch. 825 "------------------------------------------------------------------------------- 826 827 func T47_F() 828 Xpath 'a' 829 try 830 Xpath 'b' 831 try 832 Xpath 'c' 833 try 834 Xpath 'd' 835 throw "x1" 836 Xpath 'e' 837 catch /x1/ 838 Xpath 'f' 839 try 840 Xpath 'g' 841 throw "x2" 842 Xpath 'h' 843 catch /x1/ 844 Xpath 'i' 845 catch /x2/ 846 Xpath 'j' 847 try 848 Xpath 'k' 849 throw "x3" 850 Xpath 'l' 851 catch /x1/ 852 Xpath 'm' 853 catch /x2/ 854 Xpath 'n' 855 finally 856 Xpath 'o' 857 endtry 858 Xpath 'p' 859 catch /x3/ 860 Xpath 'q' 861 endtry 862 Xpath 'r' 863 catch /x1/ 864 Xpath 's' 865 catch /x2/ 866 Xpath 't' 867 catch /x3/ 868 Xpath 'u' 869 finally 870 Xpath 'v' 871 endtry 872 Xpath 'w' 873 catch /x1/ 874 Xpath 'x' 875 catch /x2/ 876 Xpath 'y' 877 catch /x3/ 878 Xpath 'z' 879 endtry 880 Xpath 'A' 881 catch /.*/ 882 Xpath 'B' 883 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 884 endtry 885 Xpath 'C' 886 endfunc 887 888 func Test_throw_from_catch() 889 XpathINIT 890 call T47_F() 891 call assert_equal('abcdfgjkovzAC', g:Xpath) 892 endfunc 893 894 895 "------------------------------------------------------------------------------- 896 " Test 48: Throwing exceptions from a :finally clause {{{1 897 " 898 " When an exception is thrown from a :finally clause, it should not be 899 " caught by a :catch of the same :try conditional. Surrounding try 900 " conditionals should be checked for a matching :catch. A previously 901 " thrown exception is discarded. 902 "------------------------------------------------------------------------------- 903 904 func T48_F() 905 try 906 907 try 908 try 909 Xpath 'a' 910 catch /x1/ 911 Xpath 'b' 912 finally 913 Xpath 'c' 914 throw "x1" 915 Xpath 'd' 916 endtry 917 Xpath 'e' 918 catch /x1/ 919 Xpath 'f' 920 endtry 921 Xpath 'g' 922 923 try 924 try 925 Xpath 'h' 926 throw "x2" 927 Xpath 'i' 928 catch /x2/ 929 Xpath 'j' 930 catch /x3/ 931 Xpath 'k' 932 finally 933 Xpath 'l' 934 throw "x3" 935 Xpath 'm' 936 endtry 937 Xpath 'n' 938 catch /x2/ 939 Xpath 'o' 940 catch /x3/ 941 Xpath 'p' 942 endtry 943 Xpath 'q' 944 945 try 946 try 947 try 948 Xpath 'r' 949 throw "x4" 950 Xpath 's' 951 catch /x5/ 952 Xpath 't' 953 finally 954 Xpath 'u' 955 throw "x5" " discards 'x4' 956 Xpath 'v' 957 endtry 958 Xpath 'w' 959 catch /x4/ 960 Xpath 'x' 961 finally 962 Xpath 'y' 963 endtry 964 Xpath 'z' 965 catch /x5/ 966 Xpath 'A' 967 endtry 968 Xpath 'B' 969 970 catch /.*/ 971 Xpath 'C' 972 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 973 endtry 974 Xpath 'D' 975 endfunc 976 977 func Test_throw_from_finally() 978 XpathINIT 979 call T48_F() 980 call assert_equal('acfghjlpqruyABD', g:Xpath) 981 endfunc 982 983 984 "------------------------------------------------------------------------------- 985 " Test 51: Throwing exceptions across :execute and user commands {{{1 986 " 987 " A :throw command may be executed under an ":execute" or from 988 " a user command. 989 "------------------------------------------------------------------------------- 990 991 func T51_F() 992 command! -nargs=? THROW1 throw <args> | throw 1 993 command! -nargs=? THROW2 try | throw <args> | endtry | throw 2 994 command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry 995 command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry 996 997 try 998 999 try 1000 try 1001 Xpath 'a' 1002 THROW1 "A" 1003 catch /A/ 1004 Xpath 'b' 1005 endtry 1006 catch /1/ 1007 Xpath 'c' 1008 endtry 1009 1010 try 1011 try 1012 Xpath 'd' 1013 THROW2 "B" 1014 catch /B/ 1015 Xpath 'e' 1016 endtry 1017 catch /2/ 1018 Xpath 'f' 1019 endtry 1020 1021 try 1022 try 1023 Xpath 'g' 1024 THROW3 "C" 1025 catch /C/ 1026 Xpath 'h' 1027 endtry 1028 catch /3/ 1029 Xpath 'i' 1030 endtry 1031 1032 try 1033 try 1034 Xpath 'j' 1035 THROW4 "D" 1036 catch /D/ 1037 Xpath 'k' 1038 endtry 1039 catch /4/ 1040 Xpath 'l' 1041 endtry 1042 1043 try 1044 try 1045 Xpath 'm' 1046 execute 'throw "E" | throw 5' 1047 catch /E/ 1048 Xpath 'n' 1049 endtry 1050 catch /5/ 1051 Xpath 'o' 1052 endtry 1053 1054 try 1055 try 1056 Xpath 'p' 1057 execute 'try | throw "F" | endtry | throw 6' 1058 catch /F/ 1059 Xpath 'q' 1060 endtry 1061 catch /6/ 1062 Xpath 'r' 1063 endtry 1064 1065 try 1066 try 1067 Xpath 's' 1068 execute'try | throw 7 | catch /7/ | throw "G" | endtry' 1069 catch /G/ 1070 Xpath 't' 1071 endtry 1072 catch /7/ 1073 Xpath 'u' 1074 endtry 1075 1076 try 1077 try 1078 Xpath 'v' 1079 execute 'try | throw 8 | finally | throw "H" | endtry' 1080 catch /H/ 1081 Xpath 'w' 1082 endtry 1083 catch /8/ 1084 Xpath 'x' 1085 endtry 1086 1087 catch /.*/ 1088 Xpath 'y' 1089 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 1090 endtry 1091 1092 Xpath 'z' 1093 1094 delcommand THROW1 1095 delcommand THROW2 1096 delcommand THROW3 1097 delcommand THROW4 1098 endfunc 1099 1100 func Test_throw_across_commands() 1101 XpathINIT 1102 call T51_F() 1103 call assert_equal('abdeghjkmnpqstvwz', g:Xpath) 1104 endfunc 1105 1106 1107 1108 "------------------------------------------------------------------------------- 1109 " Test 69: :throw across :if, :elseif, :while {{{1 1110 " 1111 " On an :if, :elseif, or :while command, an exception might be thrown 1112 " during evaluation of the expression to test. The exception can be 1113 " caught by the script. 1114 "------------------------------------------------------------------------------- 1115 1116 func T69_throw(x) 1117 Xpath 'x' 1118 throw a:x 1119 endfunc 1120 1121 func Test_throw_ifelsewhile() 1122 XpathINIT 1123 1124 try 1125 try 1126 Xpath 'a' 1127 if 111 == T69_throw("if") + 111 1128 Xpath 'b' 1129 else 1130 Xpath 'c' 1131 endif 1132 Xpath 'd' 1133 catch /^if$/ 1134 Xpath 'e' 1135 catch /.*/ 1136 Xpath 'f' 1137 call assert_report("if: " . v:exception . " in " . v:throwpoint) 1138 endtry 1139 1140 try 1141 Xpath 'g' 1142 if v:false 1143 Xpath 'h' 1144 elseif 222 == T69_throw("elseif") + 222 1145 Xpath 'i' 1146 else 1147 Xpath 'j' 1148 endif 1149 Xpath 'k' 1150 catch /^elseif$/ 1151 Xpath 'l' 1152 catch /.*/ 1153 Xpath 'm' 1154 call assert_report("elseif: " . v:exception . " in " . v:throwpoint) 1155 endtry 1156 1157 try 1158 Xpath 'n' 1159 while 333 == T69_throw("while") + 333 1160 Xpath 'o' 1161 break 1162 endwhile 1163 Xpath 'p' 1164 catch /^while$/ 1165 Xpath 'q' 1166 catch /.*/ 1167 Xpath 'r' 1168 call assert_report("while: " .. v:exception .. " in " .. v:throwpoint) 1169 endtry 1170 catch /^0$/ " default return value 1171 Xpath 's' 1172 call assert_report(v:throwpoint) 1173 catch /.*/ 1174 call assert_report(v:exception .. " in " .. v:throwpoint) 1175 Xpath 't' 1176 endtry 1177 1178 call assert_equal('axegxlnxq', g:Xpath) 1179 endfunc 1180 1181 1182 "------------------------------------------------------------------------------- 1183 " Test 70: :throw across :return or :throw {{{1 1184 " 1185 " On a :return or :throw command, an exception might be thrown during 1186 " evaluation of the expression to return or throw, respectively. The 1187 " exception can be caught by the script. 1188 "------------------------------------------------------------------------------- 1189 1190 let T70_taken = "" 1191 1192 func T70_throw(x, n) 1193 let g:T70_taken = g:T70_taken . "T" . a:n 1194 throw a:x 1195 endfunc 1196 1197 func T70_F(x, y, n) 1198 let g:T70_taken = g:T70_taken . "F" . a:n 1199 return a:x + T70_throw(a:y, a:n) 1200 endfunc 1201 1202 func T70_G(x, y, n) 1203 let g:T70_taken = g:T70_taken . "G" . a:n 1204 throw a:x . T70_throw(a:y, a:n) 1205 return a:x 1206 endfunc 1207 1208 func Test_throwreturn() 1209 XpathINIT 1210 1211 try 1212 try 1213 Xpath 'a' 1214 call T70_F(4711, "return", 1) 1215 Xpath 'b' 1216 catch /^return$/ 1217 Xpath 'c' 1218 catch /.*/ 1219 Xpath 'd' 1220 call assert_report("return: " .. v:exception .. " in " .. v:throwpoint) 1221 endtry 1222 1223 try 1224 Xpath 'e' 1225 let var = T70_F(4712, "return-var", 2) 1226 Xpath 'f' 1227 catch /^return-var$/ 1228 Xpath 'g' 1229 catch /.*/ 1230 Xpath 'h' 1231 call assert_report("return-var: " . v:exception . " in " . v:throwpoint) 1232 finally 1233 unlet! var 1234 endtry 1235 1236 try 1237 Xpath 'i' 1238 throw "except1" . T70_throw("throw1", 3) 1239 Xpath 'j' 1240 catch /^except1/ 1241 Xpath 'k' 1242 catch /^throw1$/ 1243 Xpath 'l' 1244 catch /.*/ 1245 Xpath 'm' 1246 call assert_report("throw1: " .. v:exception .. " in " .. v:throwpoint) 1247 endtry 1248 1249 try 1250 Xpath 'n' 1251 call T70_G("except2", "throw2", 4) 1252 Xpath 'o' 1253 catch /^except2/ 1254 Xpath 'p' 1255 catch /^throw2$/ 1256 Xpath 'q' 1257 catch /.*/ 1258 Xpath 'r' 1259 call assert_report("throw2: " .. v:exception .. " in " .. v:throwpoint) 1260 endtry 1261 1262 try 1263 Xpath 's' 1264 let var = T70_G("except3", "throw3", 5) 1265 Xpath 't' 1266 catch /^except3/ 1267 Xpath 'u' 1268 catch /^throw3$/ 1269 Xpath 'v' 1270 catch /.*/ 1271 Xpath 'w' 1272 call assert_report("throw3: " .. v:exception .. " in " .. v:throwpoint) 1273 finally 1274 unlet! var 1275 endtry 1276 1277 call assert_equal('F1T1F2T2T3G4T4G5T5', g:T70_taken) 1278 Xpath 'x' 1279 catch /^0$/ " default return value 1280 Xpath 'y' 1281 call assert_report(v:throwpoint) 1282 catch /.*/ 1283 Xpath 'z' 1284 call assert_report('Caught' .. v:exception .. ' in ' .. v:throwpoint) 1285 endtry 1286 1287 call assert_equal('acegilnqsvx', g:Xpath) 1288 endfunc 1289 1290 "------------------------------------------------------------------------------- 1291 " Test 71: :throw across :echo variants and :execute {{{1 1292 " 1293 " On an :echo, :echon, :echomsg, :echoerr, or :execute command, an 1294 " exception might be thrown during evaluation of the arguments to 1295 " be displayed or executed as a command, respectively. Any following 1296 " arguments are not evaluated, then. The exception can be caught by 1297 " the script. 1298 "------------------------------------------------------------------------------- 1299 1300 let T71_taken = "" 1301 1302 func T71_throw(x, n) 1303 let g:T71_taken = g:T71_taken . "T" . a:n 1304 throw a:x 1305 endfunc 1306 1307 func T71_F(n) 1308 let g:T71_taken = g:T71_taken . "F" . a:n 1309 return "F" . a:n 1310 endfunc 1311 1312 func Test_throw_echo() 1313 XpathINIT 1314 1315 try 1316 try 1317 Xpath 'a' 1318 echo 'echo ' . T71_throw("echo-except", 1) . T71_F(1) 1319 Xpath 'b' 1320 catch /^echo-except$/ 1321 Xpath 'c' 1322 catch /.*/ 1323 Xpath 'd' 1324 call assert_report("echo: " .. v:exception .. " in " .. v:throwpoint) 1325 endtry 1326 1327 try 1328 Xpath 'e' 1329 echon "echon " . T71_throw("echon-except", 2) . T71_F(2) 1330 Xpath 'f' 1331 catch /^echon-except$/ 1332 Xpath 'g' 1333 catch /.*/ 1334 Xpath 'h' 1335 call assert_report('echon: ' . v:exception . ' in ' . v:throwpoint) 1336 endtry 1337 1338 try 1339 Xpath 'i' 1340 echomsg "echomsg " . T71_throw("echomsg-except", 3) . T71_F(3) 1341 Xpath 'j' 1342 catch /^echomsg-except$/ 1343 Xpath 'k' 1344 catch /.*/ 1345 Xpath 'l' 1346 call assert_report('echomsg: ' . v:exception . ' in ' . v:throwpoint) 1347 endtry 1348 1349 try 1350 Xpath 'm' 1351 echoerr "echoerr " . T71_throw("echoerr-except", 4) . T71_F(4) 1352 Xpath 'n' 1353 catch /^echoerr-except$/ 1354 Xpath 'o' 1355 catch /Vim/ 1356 Xpath 'p' 1357 catch /echoerr/ 1358 Xpath 'q' 1359 catch /.*/ 1360 Xpath 'r' 1361 call assert_report('echoerr: ' . v:exception . ' in ' . v:throwpoint) 1362 endtry 1363 1364 try 1365 Xpath 's' 1366 execute "echo 'execute " . T71_throw("execute-except", 5) . T71_F(5) "'" 1367 Xpath 't' 1368 catch /^execute-except$/ 1369 Xpath 'u' 1370 catch /.*/ 1371 Xpath 'v' 1372 call assert_report('execute: ' . v:exception . ' in ' . v:throwpoint) 1373 endtry 1374 1375 call assert_equal('T1T2T3T4T5', g:T71_taken) 1376 Xpath 'w' 1377 catch /^0$/ " default return value 1378 Xpath 'x' 1379 call assert_report(v:throwpoint) 1380 catch /.*/ 1381 Xpath 'y' 1382 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 1383 endtry 1384 1385 call assert_equal('acegikmosuw', g:Xpath) 1386 endfunc 1387 1388 1389 "------------------------------------------------------------------------------- 1390 " Test 72: :throw across :let or :unlet {{{1 1391 " 1392 " On a :let command, an exception might be thrown during evaluation 1393 " of the expression to assign. On an :let or :unlet command, the 1394 " evaluation of the name of the variable to be assigned or list or 1395 " deleted, respectively, may throw an exception. Any following 1396 " arguments are not evaluated, then. The exception can be caught by 1397 " the script. 1398 "------------------------------------------------------------------------------- 1399 1400 let throwcount = 0 1401 1402 func T72_throw(x) 1403 let g:throwcount = g:throwcount + 1 1404 throw a:x 1405 endfunc 1406 1407 let T72_addpath = '' 1408 1409 func T72_addpath(p) 1410 let g:T72_addpath = g:T72_addpath . a:p 1411 endfunc 1412 1413 func Test_throw_let() 1414 XpathINIT 1415 1416 try 1417 try 1418 let $VAR = 'old_value' 1419 Xpath 'a' 1420 let $VAR = 'let(' . T72_throw('var') . ')' 1421 Xpath 'b' 1422 catch /^var$/ 1423 Xpath 'c' 1424 finally 1425 call assert_equal('old_value', $VAR) 1426 endtry 1427 1428 try 1429 let @a = 'old_value' 1430 Xpath 'd' 1431 let @a = 'let(' . T72_throw('reg') . ')' 1432 Xpath 'e' 1433 catch /^reg$/ 1434 try 1435 Xpath 'f' 1436 let @A = 'let(' . T72_throw('REG') . ')' 1437 Xpath 'g' 1438 catch /^REG$/ 1439 Xpath 'h' 1440 endtry 1441 finally 1442 call assert_equal('old_value', @a) 1443 call assert_equal('old_value', @A) 1444 endtry 1445 1446 try 1447 let saved_gpath = &g:path 1448 let saved_lpath = &l:path 1449 Xpath 'i' 1450 let &path = 'let(' . T72_throw('opt') . ')' 1451 Xpath 'j' 1452 catch /^opt$/ 1453 try 1454 Xpath 'k' 1455 let &g:path = 'let(' . T72_throw('gopt') . ')' 1456 Xpath 'l' 1457 catch /^gopt$/ 1458 try 1459 Xpath 'm' 1460 let &l:path = 'let(' . T72_throw('lopt') . ')' 1461 Xpath 'n' 1462 catch /^lopt$/ 1463 Xpath 'o' 1464 endtry 1465 endtry 1466 finally 1467 call assert_equal(saved_gpath, &g:path) 1468 call assert_equal(saved_lpath, &l:path) 1469 let &g:path = saved_gpath 1470 let &l:path = saved_lpath 1471 endtry 1472 1473 unlet! var1 var2 var3 1474 1475 try 1476 Xpath 'p' 1477 let var1 = 'let(' . T72_throw('var1') . ')' 1478 Xpath 'q' 1479 catch /^var1$/ 1480 Xpath 'r' 1481 finally 1482 call assert_true(!exists('var1')) 1483 endtry 1484 1485 try 1486 let var2 = 'old_value' 1487 Xpath 's' 1488 let var2 = 'let(' . T72_throw('var2'). ')' 1489 Xpath 't' 1490 catch /^var2$/ 1491 Xpath 'u' 1492 finally 1493 call assert_equal('old_value', var2) 1494 endtry 1495 1496 try 1497 Xpath 'v' 1498 let var{T72_throw('var3')} = 4711 1499 Xpath 'w' 1500 catch /^var3$/ 1501 Xpath 'x' 1502 endtry 1503 1504 try 1505 call T72_addpath('T1') 1506 let var{T72_throw('var4')} var{T72_addpath('T2')} | call T72_addpath('T3') 1507 call T72_addpath('T4') 1508 catch /^var4$/ 1509 call T72_addpath('T5') 1510 endtry 1511 1512 try 1513 call T72_addpath('T6') 1514 unlet var{T72_throw('var5')} var{T72_addpath('T7')} 1515 \ | call T72_addpath('T8') 1516 call T72_addpath('T9') 1517 catch /^var5$/ 1518 call T72_addpath('T10') 1519 endtry 1520 1521 call assert_equal('T1T5T6T10', g:T72_addpath) 1522 call assert_equal(11, g:throwcount) 1523 catch /.*/ 1524 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 1525 endtry 1526 1527 call assert_equal('acdfhikmoprsuvx', g:Xpath) 1528 endfunc 1529 1530 1531 "------------------------------------------------------------------------------- 1532 " Test 73: :throw across :function, :delfunction {{{1 1533 " 1534 " The :function and :delfunction commands may cause an expression 1535 " specified in braces to be evaluated. During evaluation, an 1536 " exception might be thrown. The exception can be caught by the 1537 " script. 1538 "------------------------------------------------------------------------------- 1539 1540 let T73_taken = '' 1541 1542 func T73_throw(x, n) 1543 let g:T73_taken = g:T73_taken . 'T' . a:n 1544 throw a:x 1545 endfunc 1546 1547 func T73_expr(x, n) 1548 let g:T73_taken = g:T73_taken . 'E' . a:n 1549 if a:n % 2 == 0 1550 call T73_throw(a:x, a:n) 1551 endif 1552 return 2 - a:n % 2 1553 endfunc 1554 1555 func Test_throw_func() 1556 XpathINIT 1557 1558 try 1559 try 1560 " Define function. 1561 Xpath 'a' 1562 function! F0() 1563 endfunction 1564 Xpath 'b' 1565 function! F{T73_expr('function-def-ok', 1)}() 1566 endfunction 1567 Xpath 'c' 1568 function! F{T73_expr('function-def', 2)}() 1569 endfunction 1570 Xpath 'd' 1571 catch /^function-def-ok$/ 1572 Xpath 'e' 1573 catch /^function-def$/ 1574 Xpath 'f' 1575 catch /.*/ 1576 call assert_report('def: ' . v:exception . ' in ' . v:throwpoint) 1577 endtry 1578 1579 try 1580 " List function. 1581 Xpath 'g' 1582 function F0 1583 Xpath 'h' 1584 function F{T73_expr('function-lst-ok', 3)} 1585 Xpath 'i' 1586 function F{T73_expr('function-lst', 4)} 1587 Xpath 'j' 1588 catch /^function-lst-ok$/ 1589 Xpath 'k' 1590 catch /^function-lst$/ 1591 Xpath 'l' 1592 catch /.*/ 1593 call assert_report('lst: ' . v:exception . ' in ' . v:throwpoint) 1594 endtry 1595 1596 try 1597 " Delete function 1598 Xpath 'm' 1599 delfunction F0 1600 Xpath 'n' 1601 delfunction F{T73_expr('function-del-ok', 5)} 1602 Xpath 'o' 1603 delfunction F{T73_expr('function-del', 6)} 1604 Xpath 'p' 1605 catch /^function-del-ok$/ 1606 Xpath 'q' 1607 catch /^function-del$/ 1608 Xpath 'r' 1609 catch /.*/ 1610 call assert_report('del: ' . v:exception . ' in ' . v:throwpoint) 1611 endtry 1612 call assert_equal('E1E2T2E3E4T4E5E6T6', g:T73_taken) 1613 catch /.*/ 1614 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 1615 endtry 1616 1617 call assert_equal('abcfghilmnor', g:Xpath) 1618 endfunc 1619 1620 1621 "------------------------------------------------------------------------------- 1622 " Test 74: :throw across builtin functions and commands {{{1 1623 " 1624 " Some functions like exists(), searchpair() take expression 1625 " arguments, other functions or commands like substitute() or 1626 " :substitute cause an expression (specified in the regular 1627 " expression) to be evaluated. During evaluation an exception 1628 " might be thrown. The exception can be caught by the script. 1629 "------------------------------------------------------------------------------- 1630 1631 let T74_taken = "" 1632 1633 func T74_throw(x, n) 1634 let g:T74_taken = g:T74_taken . "T" . a:n 1635 throw a:x 1636 endfunc 1637 1638 func T74_expr(x, n) 1639 let g:T74_taken = g:T74_taken . "E" . a:n 1640 call T74_throw(a:x . a:n, a:n) 1641 return "EXPR" 1642 endfunc 1643 1644 func T74_skip(x, n) 1645 let g:T74_taken = g:T74_taken . "S" . a:n . "(" . line(".") 1646 let theline = getline(".") 1647 if theline =~ "skip" 1648 let g:T74_taken = g:T74_taken . "s)" 1649 return 1 1650 elseif theline =~ "throw" 1651 let g:T74_taken = g:T74_taken . "t)" 1652 call T74_throw(a:x . a:n, a:n) 1653 else 1654 let g:T74_taken = g:T74_taken . ")" 1655 return 0 1656 endif 1657 endfunc 1658 1659 func T74_subst(x, n) 1660 let g:T74_taken = g:T74_taken . "U" . a:n . "(" . line(".") 1661 let theline = getline(".") 1662 if theline =~ "not" " T74_subst() should not be called for this line 1663 let g:T74_taken = g:T74_taken . "n)" 1664 call T74_throw(a:x . a:n, a:n) 1665 elseif theline =~ "throw" 1666 let g:T74_taken = g:T74_taken . "t)" 1667 call T74_throw(a:x . a:n, a:n) 1668 else 1669 let g:T74_taken = g:T74_taken . ")" 1670 return "replaced" 1671 endif 1672 endfunc 1673 1674 func Test_throw_builtin_func() 1675 XpathINIT 1676 1677 try 1678 try 1679 Xpath 'a' 1680 let result = exists('*{T74_expr("exists", 1)}') 1681 Xpath 'b' 1682 catch /^exists1$/ 1683 Xpath 'c' 1684 try 1685 let result = exists('{T74_expr("exists", 2)}') 1686 Xpath 'd' 1687 catch /^exists2$/ 1688 Xpath 'e' 1689 catch /.*/ 1690 call assert_report('exists2: ' . v:exception . ' in ' . v:throwpoint) 1691 endtry 1692 catch /.*/ 1693 call assert_report('exists1: ' . v:exception . ' in ' . v:throwpoint) 1694 endtry 1695 1696 try 1697 let file = tempname() 1698 exec "edit" file 1699 call append(0, [ 1700 \ 'begin', 1701 \ 'xx', 1702 \ 'middle 3', 1703 \ 'xx', 1704 \ 'middle 5 skip', 1705 \ 'xx', 1706 \ 'middle 7 throw', 1707 \ 'xx', 1708 \ 'end']) 1709 normal! gg 1710 Xpath 'f' 1711 let result = searchpair("begin", "middle", "end", '', 1712 \ 'T74_skip("searchpair", 3)') 1713 Xpath 'g' 1714 let result = searchpair("begin", "middle", "end", '', 1715 \ 'T74_skip("searchpair", 4)') 1716 Xpath 'h' 1717 let result = searchpair("begin", "middle", "end", '', 1718 \ 'T74_skip("searchpair", 5)') 1719 Xpath 'i' 1720 catch /^searchpair[35]$/ 1721 Xpath 'j' 1722 catch /^searchpair4$/ 1723 Xpath 'k' 1724 catch /.*/ 1725 call assert_report('searchpair: ' . v:exception . ' in ' . v:throwpoint) 1726 finally 1727 bwipeout! 1728 call delete(file) 1729 endtry 1730 1731 try 1732 let file = tempname() 1733 exec "edit" file 1734 call append(0, [ 1735 \ 'subst 1', 1736 \ 'subst 2', 1737 \ 'not', 1738 \ 'subst 4', 1739 \ 'subst throw', 1740 \ 'subst 6']) 1741 normal! gg 1742 Xpath 'l' 1743 1,2substitute/subst/\=T74_subst("substitute", 6)/ 1744 try 1745 Xpath 'm' 1746 try 1747 let v:errmsg = "" 1748 3substitute/subst/\=T74_subst("substitute", 7)/ 1749 finally 1750 if v:errmsg != "" 1751 " If exceptions are not thrown on errors, fake the error 1752 " exception in order to get the same execution path. 1753 throw "faked Vim(substitute)" 1754 endif 1755 endtry 1756 catch /Vim(substitute)/ " Pattern not found ('e' flag missing) 1757 Xpath 'n' 1758 3substitute/subst/\=T74_subst("substitute", 8)/e 1759 Xpath 'o' 1760 endtry 1761 Xpath 'p' 1762 4,6substitute/subst/\=T74_subst("substitute", 9)/ 1763 Xpath 'q' 1764 catch /^substitute[678]/ 1765 Xpath 'r' 1766 catch /^substitute9/ 1767 Xpath 's' 1768 finally 1769 bwipeout! 1770 call delete(file) 1771 endtry 1772 1773 try 1774 Xpath 't' 1775 let var = substitute("sub", "sub", '\=T74_throw("substitute()y", 10)', '') 1776 Xpath 'u' 1777 catch /substitute()y/ 1778 Xpath 'v' 1779 catch /.*/ 1780 call assert_report('substitute()y: ' . v:exception . ' in ' 1781 \ . v:throwpoint) 1782 endtry 1783 1784 try 1785 Xpath 'w' 1786 let var = substitute("not", "sub", '\=T74_throw("substitute()n", 11)', '') 1787 Xpath 'x' 1788 catch /substitute()n/ 1789 Xpath 'y' 1790 catch /.*/ 1791 call assert_report('substitute()n: ' . v:exception . ' in ' 1792 \ . v:throwpoint) 1793 endtry 1794 1795 call assert_equal('E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10', 1796 \ g:T74_taken) 1797 1798 catch /.*/ 1799 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 1800 endtry 1801 1802 call assert_equal('acefgklmnopstvwx', g:Xpath) 1803 endfunc 1804 1805 1806 "------------------------------------------------------------------------------- 1807 " Test 75: Errors in builtin functions. {{{1 1808 " 1809 " On an error in a builtin function called inside a :try/:endtry 1810 " region, the evaluation of the expression calling that function and 1811 " the command containing that expression are abandoned. The error can 1812 " be caught as an exception. 1813 " 1814 " A simple :call of the builtin function is a trivial case. If the 1815 " builtin function is called in the argument list of another function, 1816 " no further arguments are evaluated, and the other function is not 1817 " executed. If the builtin function is called from the argument of 1818 " a :return command, the :return command is not executed. If the 1819 " builtin function is called from the argument of a :throw command, 1820 " the :throw command is not executed. The evaluation of the 1821 " expression calling the builtin function is abandoned. 1822 "------------------------------------------------------------------------------- 1823 1824 func T75_F1(arg1) 1825 Xpath 'a' 1826 endfunc 1827 1828 func T75_F2(arg1, arg2) 1829 Xpath 'b' 1830 endfunc 1831 1832 func T75_G() 1833 Xpath 'c' 1834 endfunc 1835 1836 func T75_H() 1837 Xpath 'd' 1838 endfunc 1839 1840 func T75_R() 1841 while 1 1842 try 1843 let caught = 0 1844 let v:errmsg = "" 1845 Xpath 'e' 1846 return append(1, "s") 1847 catch /E21/ 1848 let caught = 1 1849 catch /.*/ 1850 Xpath 'f' 1851 finally 1852 Xpath 'g' 1853 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21:' 1854 Xpath 'h' 1855 endif 1856 break " discard error for $VIMNOERRTHROW 1857 endtry 1858 endwhile 1859 Xpath 'i' 1860 endfunc 1861 1862 func Test_builtin_func_error() 1863 XpathINIT 1864 1865 try 1866 set noma " let append() fail with "E21" 1867 1868 while 1 1869 try 1870 let caught = 0 1871 let v:errmsg = "" 1872 Xpath 'j' 1873 call append(1, "s") 1874 catch /E21/ 1875 let caught = 1 1876 catch /.*/ 1877 Xpath 'k' 1878 finally 1879 Xpath 'l' 1880 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21:' 1881 Xpath 'm' 1882 endif 1883 break " discard error for $VIMNOERRTHROW 1884 endtry 1885 endwhile 1886 1887 while 1 1888 try 1889 let caught = 0 1890 let v:errmsg = "" 1891 Xpath 'n' 1892 call T75_F1('x' . append(1, "s")) 1893 catch /E21/ 1894 let caught = 1 1895 catch /.*/ 1896 Xpath 'o' 1897 finally 1898 Xpath 'p' 1899 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21:' 1900 Xpath 'q' 1901 endif 1902 break " discard error for $VIMNOERRTHROW 1903 endtry 1904 endwhile 1905 1906 while 1 1907 try 1908 let caught = 0 1909 let v:errmsg = "" 1910 Xpath 'r' 1911 call T75_F2('x' . append(1, "s"), T75_G()) 1912 catch /E21/ 1913 let caught = 1 1914 catch /.*/ 1915 Xpath 's' 1916 finally 1917 Xpath 't' 1918 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21:' 1919 Xpath 'u' 1920 endif 1921 break " discard error for $VIMNOERRTHROW 1922 endtry 1923 endwhile 1924 1925 call T75_R() 1926 1927 while 1 1928 try 1929 let caught = 0 1930 let v:errmsg = "" 1931 Xpath 'v' 1932 throw "T" . append(1, "s") 1933 catch /E21/ 1934 let caught = 1 1935 catch /^T.*/ 1936 Xpath 'w' 1937 catch /.*/ 1938 Xpath 'x' 1939 finally 1940 Xpath 'y' 1941 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21:' 1942 Xpath 'z' 1943 endif 1944 break " discard error for $VIMNOERRTHROW 1945 endtry 1946 endwhile 1947 1948 while 1 1949 try 1950 let caught = 0 1951 let v:errmsg = "" 1952 Xpath 'A' 1953 let x = "a" 1954 let x = x . "b" . append(1, "s") . T75_H() 1955 catch /E21/ 1956 let caught = 1 1957 catch /.*/ 1958 Xpath 'B' 1959 finally 1960 Xpath 'C' 1961 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21:' 1962 Xpath 'D' 1963 endif 1964 call assert_equal('a', x) 1965 break " discard error for $VIMNOERRTHROW 1966 endtry 1967 endwhile 1968 catch /.*/ 1969 call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) 1970 finally 1971 set ma& 1972 endtry 1973 1974 call assert_equal('jlmnpqrtueghivyzACD', g:Xpath) 1975 endfunc 1976 1977 func Test_reload_in_try_catch() 1978 call writefile(['x'], 'Xreload') 1979 set autoread 1980 edit Xreload 1981 tabnew 1982 call writefile(['xx'], 'Xreload') 1983 augroup ReLoad 1984 au FileReadPost Xreload let x = doesnotexist 1985 au BufReadPost Xreload let x = doesnotexist 1986 augroup END 1987 try 1988 edit Xreload 1989 catch 1990 endtry 1991 tabnew 1992 1993 tabclose 1994 tabclose 1995 autocmd! ReLoad 1996 set noautoread 1997 bwipe! Xreload 1998 call delete('Xreload') 1999 endfunc 2000 2001 " Test for errors with :catch, :throw, :finally {{{1 2002 func Test_try_catch_errors() 2003 call assert_fails('throw |', 'E471:') 2004 call assert_fails("throw \n ", 'E471:') 2005 call assert_fails('catch abc', 'E654:') 2006 call assert_fails('try | let i = 1| finally | catch | endtry', 'E604:') 2007 call assert_fails('finally', 'E606:') 2008 call assert_fails('try | finally | finally | endtry', 'E607:') 2009 call assert_fails('try | for i in range(5) | endif | endtry', 'E580:') 2010 call assert_fails('try | while v:true | endtry', 'E170:') 2011 call assert_fails('try | if v:true | endtry', 'E171:') 2012 2013 " this was using a negative index in cstack[] 2014 let lines =<< trim END 2015 try 2016 for 2017 if 2018 endwhile 2019 if 2020 finally 2021 END 2022 call CheckScriptFailure(lines, 'E690:') 2023 2024 let lines =<< trim END 2025 try 2026 for 2027 if 2028 endwhile 2029 if 2030 endtry 2031 END 2032 call CheckScriptFailure(lines, 'E690:') 2033 endfunc 2034 2035 " Test for verbose messages with :try :catch, and :finally {{{1 2036 func Test_try_catch_verbose() 2037 " This test works only when the language is English 2038 CheckEnglish 2039 2040 set verbose=14 2041 2042 " Test for verbose messages displayed when an exception is caught 2043 redir => msg 2044 try 2045 echo i 2046 catch /E121:/ 2047 finally 2048 endtry 2049 redir END 2050 let expected = [ 2051 \ 'Exception thrown: Vim(echo):E121: Undefined variable: i', '', 2052 \ 'Exception caught: Vim(echo):E121: Undefined variable: i', '', 2053 \ 'Exception finished: Vim(echo):E121: Undefined variable: i'] 2054 call assert_equal(expected, split(msg, "\n")) 2055 2056 " Test for verbose messages displayed when an exception is discarded 2057 redir => msg 2058 try 2059 try 2060 throw 'abc' 2061 finally 2062 throw 'xyz' 2063 endtry 2064 catch 2065 endtry 2066 redir END 2067 let expected = [ 2068 \ 'Exception thrown: abc', '', 2069 \ 'Exception made pending: abc', '', 2070 \ 'Exception thrown: xyz', '', 2071 \ 'Exception discarded: abc', '', 2072 \ 'Exception caught: xyz', '', 2073 \ 'Exception finished: xyz'] 2074 call assert_equal(expected, split(msg, "\n")) 2075 2076 " Test for messages displayed when :throw is resumed after :finally 2077 redir => msg 2078 try 2079 try 2080 throw 'abc' 2081 finally 2082 endtry 2083 catch 2084 endtry 2085 redir END 2086 let expected = [ 2087 \ 'Exception thrown: abc', '', 2088 \ 'Exception made pending: abc', '', 2089 \ 'Exception resumed: abc', '', 2090 \ 'Exception caught: abc', '', 2091 \ 'Exception finished: abc'] 2092 call assert_equal(expected, split(msg, "\n")) 2093 2094 " Test for messages displayed when :break is resumed after :finally 2095 redir => msg 2096 for i in range(1) 2097 try 2098 break 2099 finally 2100 endtry 2101 endfor 2102 redir END 2103 let expected = [':break made pending', '', ':break resumed'] 2104 call assert_equal(expected, split(msg, "\n")) 2105 2106 " Test for messages displayed when :continue is resumed after :finally 2107 redir => msg 2108 for i in range(1) 2109 try 2110 continue 2111 finally 2112 endtry 2113 endfor 2114 redir END 2115 let expected = [':continue made pending', '', ':continue resumed'] 2116 call assert_equal(expected, split(msg, "\n")) 2117 2118 " Test for messages displayed when :return is resumed after :finally 2119 func Xtest() 2120 try 2121 return 'vim' 2122 finally 2123 endtry 2124 endfunc 2125 redir => msg 2126 call Xtest() 2127 redir END 2128 let expected = [ 2129 \ 'calling Xtest()', '', 2130 \ ':return vim made pending', '', 2131 \ ':return vim resumed', '', 2132 \ 'Xtest returning ''vim''', '', 2133 \ 'continuing in Test_try_catch_verbose'] 2134 call assert_equal(expected, split(msg, "\n")) 2135 delfunc Xtest 2136 2137 " Test for messages displayed when :finish is resumed after :finally 2138 call writefile(['try', 'finish', 'finally', 'endtry'], 'Xscript') 2139 redir => msg 2140 source Xscript 2141 redir END 2142 let expected = [ 2143 \ ':finish made pending', '', 2144 \ ':finish resumed', '', 2145 \ 'finished sourcing Xscript', 2146 \ 'continuing in Test_try_catch_verbose'] 2147 call assert_equal(expected, split(msg, "\n")[1:]) 2148 call delete('Xscript') 2149 2150 " Test for messages displayed when a pending :continue is discarded by an 2151 " exception in a finally handler 2152 redir => msg 2153 try 2154 for i in range(1) 2155 try 2156 continue 2157 finally 2158 throw 'abc' 2159 endtry 2160 endfor 2161 catch 2162 endtry 2163 redir END 2164 let expected = [ 2165 \ ':continue made pending', '', 2166 \ 'Exception thrown: abc', '', 2167 \ ':continue discarded', '', 2168 \ 'Exception caught: abc', '', 2169 \ 'Exception finished: abc'] 2170 call assert_equal(expected, split(msg, "\n")) 2171 2172 set verbose& 2173 endfunc 2174 2175 " Test for throwing an exception from a BufEnter autocmd {{{1 2176 func Test_BufEnter_exception() 2177 augroup bufenter_exception 2178 au! 2179 autocmd BufEnter Xfile1 throw 'abc' 2180 augroup END 2181 2182 let caught_abc = 0 2183 try 2184 sp Xfile1 2185 catch /^abc/ 2186 let caught_abc = 1 2187 endtry 2188 call assert_equal(1, caught_abc) 2189 call assert_equal(1, winnr('$')) 2190 2191 augroup bufenter_exception 2192 au! 2193 augroup END 2194 augroup! bufenter_exception 2195 %bwipe! 2196 2197 " Test for recursively throwing exceptions in autocmds 2198 augroup bufenter_exception 2199 au! 2200 autocmd BufEnter Xfile1 throw 'bufenter' 2201 autocmd BufLeave Xfile1 throw 'bufleave' 2202 augroup END 2203 2204 let ex_count = 0 2205 try 2206 try 2207 sp Xfile1 2208 catch /^bufenter/ 2209 let ex_count += 1 2210 endtry 2211 catch /^bufleave/ 2212 let ex_count += 10 2213 endtry 2214 call assert_equal(10, ex_count) 2215 call assert_equal(2, winnr('$')) 2216 2217 augroup bufenter_exception 2218 au! 2219 augroup END 2220 augroup! bufenter_exception 2221 %bwipe! 2222 endfunc 2223 2224 " Test for using try/catch when lines are joined by "|" or "\n" {{{1 2225 func Test_try_catch_nextcmd() 2226 func Throw() 2227 throw "Failure" 2228 endfunc 2229 2230 let lines =<< trim END 2231 try 2232 let s:x = Throw() 2233 catch 2234 let g:caught = 1 2235 endtry 2236 END 2237 2238 let g:caught = 0 2239 call execute(lines) 2240 call assert_equal(1, g:caught) 2241 2242 let g:caught = 0 2243 call execute(join(lines, '|')) 2244 call assert_equal(1, g:caught) 2245 2246 let g:caught = 0 2247 call execute(join(lines, "\n")) 2248 call assert_equal(1, g:caught) 2249 2250 unlet g:caught 2251 delfunc Throw 2252 endfunc 2253 2254 " Test for using try/catch in a user command with a failing expression {{{1 2255 func Test_user_command_try_catch() 2256 let lines =<< trim END 2257 function s:throw() abort 2258 throw 'error' 2259 endfunction 2260 2261 command! Execute 2262 \ try 2263 \ | let s:x = s:throw() 2264 \ | catch 2265 \ | let g:caught = 'caught' 2266 \ | endtry 2267 2268 let g:caught = 'no' 2269 Execute 2270 call assert_equal('caught', g:caught) 2271 END 2272 call writefile(lines, 'XtestTryCatch') 2273 source XtestTryCatch 2274 2275 call delete('XtestTryCatch') 2276 unlet g:caught 2277 endfunc 2278 2279 " Test for using throw in a called function with following error {{{1 2280 func Test_user_command_throw_in_function_call() 2281 let lines =<< trim END 2282 function s:get_dict() abort 2283 throw 'my_error' 2284 endfunction 2285 2286 try 2287 call s:get_dict().foo() 2288 catch /my_error/ 2289 let caught = 'yes' 2290 catch 2291 let caught = v:exception 2292 endtry 2293 call assert_equal('yes', caught) 2294 END 2295 call writefile(lines, 'XtestThrow') 2296 source XtestThrow 2297 2298 call delete('XtestThrow') 2299 unlet g:caught 2300 endfunc 2301 2302 " Test that after reporting an uncaught exception there is no error for a 2303 " missing :endif 2304 func Test_after_exception_no_endif_error() 2305 function Throw() 2306 throw "Failure" 2307 endfunction 2308 2309 function Foo() 2310 if 1 2311 call Throw() 2312 endif 2313 endfunction 2314 call assert_fails('call Foo()', ['E605:', 'E605:']) 2315 delfunc Throw 2316 delfunc Foo 2317 endfunc 2318 2319 " Test for using throw in a called function with following endtry {{{1 2320 func Test_user_command_function_call_with_endtry() 2321 let lines =<< trim END 2322 funct s:throw(msg) abort 2323 throw a:msg 2324 endfunc 2325 func s:main() abort 2326 try 2327 try 2328 throw 'err1' 2329 catch 2330 call s:throw('err2') | endtry 2331 catch 2332 let s:caught = 'yes' 2333 endtry 2334 endfunc 2335 2336 call s:main() 2337 call assert_equal('yes', s:caught) 2338 END 2339 call writefile(lines, 'XtestThrow') 2340 source XtestThrow 2341 2342 call delete('XtestThrow') 2343 endfunc 2344 2345 func ThisWillFail() 2346 2347 endfunc 2348 2349 " This was crashing prior to the fix in 8.2.3478. 2350 func Test_error_in_catch_and_finally() 2351 let lines =<< trim END 2352 try 2353 echo x 2354 catch 2355 for l in [] 2356 finally 2357 END 2358 call writefile(lines, 'XtestCatchAndFinally') 2359 try 2360 source XtestCatchAndFinally 2361 catch /E600:/ 2362 endtry 2363 2364 call delete('XtestCatchAndFinally') 2365 endfunc 2366 2367 " This was causing an illegal memory access 2368 func Test_leave_block_in_endtry_not_called() 2369 let lines =<< trim END 2370 " vim9script 2371 " try # 2372 try " 2373 for x in [] 2374 if 2375 endwhile 2376 if 2377 endtry 2378 END 2379 call writefile(lines, 'XtestEndtry') 2380 try 2381 source XtestEndtry 2382 catch /E171:/ 2383 endtry 2384 2385 call delete('XtestEndtry') 2386 endfunc 2387 2388 " Modeline {{{1 2389 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker