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