To: vim_dev@googlegroups.com Subject: Patch 8.1.2246 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2246 Problem: Some tests are still in old style. Solution: Change a few tests to new style. (Yegappan Lakshmanan) Files: src/testdir/Make_all.mak, src/testdir/test49.ok, src/testdir/test49.vim, src/testdir/test_trycatch.vim, src/testdir/test_vimscript.vim *** ../vim-8.1.2245/src/testdir/Make_all.mak 2019-10-16 19:27:23.613959056 +0200 --- src/testdir/Make_all.mak 2019-11-03 16:09:05.317249724 +0100 *************** *** 267,272 **** --- 267,273 ---- test_textprop \ test_timers \ test_true_false \ + test_trycatch \ test_undo \ test_unlet \ test_user_func \ *************** *** 433,438 **** --- 434,440 ---- test_textformat.res \ test_textobjects.res \ test_textprop.res \ + test_trycatch.res \ test_undo.res \ test_user_func.res \ test_usercommands.res \ *** ../vim-8.1.2245/src/testdir/test49.ok 2016-01-02 19:36:45.000000000 +0100 --- src/testdir/test49.ok 2019-11-03 16:09:05.317249724 +0100 *************** *** 1,6 **** Results of test49.vim: - *** Test 16: OK (8722) - *** Test 17: OK (285127993) *** Test 18: OK (67224583) *** Test 19: OK (69275973) *** Test 20: OK (1874575085) --- 1,4 ---- *************** *** 8,23 **** *** Test 22: OK (4161) *** Test 23: OK (49) *** Test 24: OK (41) - *** Test 25: OK (260177811) - *** Test 26: OK (1681500476) *** Test 27: OK (1996459) *** Test 28: OK (1996459) *** Test 29: OK (170428555) *** Test 30: OK (190905173) *** Test 31: OK (190905173) - *** Test 32: OK (354833067) - --- Test 33: sum = 178275600 (ok) - *** Test 33: OK (1216907538) *** Test 34: OK (2146584868) *** Test 35: OK (2146584868) *** Test 36: OK (1071644672) --- 6,16 ---- *************** *** 25,41 **** *** Test 38: OK (357908480) *** Test 39: OK (357908480) *** Test 40: OK (357908480) - *** Test 41: OK (3076095) - *** Test 42: OK (1505155949) - *** Test 43: OK (1157763329) - *** Test 44: OK (1031761407) - *** Test 45: OK (1157763329) - *** Test 46: OK (739407) - *** Test 47: OK (371213935) - *** Test 48: OK (756255461) *** Test 49: OK (179000669) *** Test 50: OK (363550045) - *** Test 51: OK (40744667) *** Test 52: OK (1247112011) *** Test 53: OK (131071) *** Test 54: OK (2047) --- 18,25 ---- *************** *** 53,65 **** *** Test 66: OK (5464) *** Test 67: OK (212514423) *** Test 68: OK (212514423) - *** Test 69: OK (8995471) - *** Test 70: OK (69544277) - *** Test 71: OK (34886997) - *** Test 72: OK (1789569365) - *** Test 73: OK (9032615) - *** Test 74: OK (224907669) - *** Test 75: OK (2000403408) *** Test 76: OK (1610087935) *** Test 77: OK (1388671) *** Test 78: OK (134217728) --- 37,42 ---- *************** *** 72,82 **** *** Test 85: OK (198689) --- Test 86: No Crash for vimgrep on BufUnload *** Test 86: OK (0) - --- Test 87: 3 - --- Test 87: 5 - --- Test 87: abcdefghijk - --- Test 87: Successfully executed funcref Add2 - *** Test 87: OK (0) --- Test 88: All tests were run with throwing exceptions on error. The $VIMNOERRTHROW control is not configured. --- Test 88: All tests were run with throwing exceptions on interrupt. --- 49,54 ---- *** ../vim-8.1.2245/src/testdir/test49.vim 2019-10-10 13:30:09.485605298 +0200 --- src/testdir/test49.vim 2019-11-03 16:09:05.321249714 +0100 *************** *** 1,6 **** " Vim script language tests " Author: Servatius Brandt ! " Last Change: 2019 Oct 08 "------------------------------------------------------------------------------- " Test environment {{{1 --- 1,6 ---- " Vim script language tests " Author: Servatius Brandt ! " Last Change: 2019 Nov 03 "------------------------------------------------------------------------------- " Test environment {{{1 *************** *** 608,803 **** " END_OF_TEST_ENVIRONMENT - do not change or remove this line. ! " Tests 1 to 15 were moved to test_vimscript.vim ! let Xtest = 16 ! ! "------------------------------------------------------------------------------- ! " Test 16: Double :else or :elseif after :else {{{1 ! " ! " Multiple :elses or an :elseif after an :else are forbidden. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! function! F() abort ! if 0 ! Xpath 1 " X: 0 ! else ! Xpath 2 " X: 2 ! else " aborts function ! Xpath 4 " X: 0 ! endif ! endfunction ! ! function! G() abort ! if 0 ! Xpath 8 " X: 0 ! else ! Xpath 16 " X: 16 ! elseif 1 " aborts function ! Xpath 32 " X: 0 ! else ! Xpath 64 " X: 0 ! endif ! endfunction ! ! function! H() abort ! if 0 ! Xpath 128 " X: 0 ! elseif 0 ! Xpath 256 " X: 0 ! else ! Xpath 512 " X: 512 ! else " aborts function ! Xpath 1024 " X: 0 ! endif ! endfunction ! ! function! I() abort ! if 0 ! Xpath 2048 " X: 0 ! elseif 0 ! Xpath 4096 " X: 0 ! else ! Xpath 8192 " X: 8192 ! elseif 1 " aborts function ! Xpath 16384 " X: 0 ! else ! Xpath 32768 " X: 0 ! endif ! endfunction ! ! call F() ! call G() ! call H() ! call I() ! ! delfunction F ! delfunction G ! delfunction H ! delfunction I ! ! Xcheck 8722 ! ! ! "------------------------------------------------------------------------------- ! " Test 17: Nesting of unmatched :if or :endif inside a :while {{{1 ! " ! " The :while/:endwhile takes precedence in nesting over an unclosed ! " :if or an unopened :endif. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! function! MSG(enr, emsg) ! let english = v:lang == "C" || v:lang =~ '^[Ee]n' ! if a:enr == "" ! Xout "TODO: Add message number for:" a:emsg ! let v:errmsg = ":" . v:errmsg ! endif ! let match = 1 ! if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) ! let match = 0 ! if v:errmsg == "" ! Xout "Message missing." ! else ! let v:errmsg = escape(v:errmsg, '"') ! Xout "Unexpected message:" v:errmsg ! endif ! endif ! return match ! endfunction ! ! let messages = "" ! ! " While loops inside a function are continued on error. ! function! F() ! let v:errmsg = "" ! XloopINIT 1 16 ! let loops = 3 ! while loops > 0 ! let loops = loops - 1 " 2: 1: 0: ! Xloop 1 " X: 1 + 1*16 + 1*16*16 ! if (loops == 1) ! Xloop 2 " X: 2*16 ! XloopNEXT ! continue ! elseif (loops == 0) ! Xloop 4 " X: 4*16*16 ! break ! elseif 1 ! Xloop 8 " X: 8 ! XloopNEXT ! " endif missing! ! endwhile " :endwhile after :if 1 ! Xpath 4096 " X: 16*16*16 ! if MSG('E171', "Missing :endif") ! let g:messages = g:messages . "A" ! endif ! ! let v:errmsg = "" ! XloopINIT! 8192 4 ! let loops = 2 ! while loops > 0 " 2: 1: ! XloopNEXT ! let loops = loops - 1 ! Xloop 1 " X: 8192 + 8192*4 ! if 0 ! Xloop 2 " X: 0 ! " endif missing ! endwhile " :endwhile after :if 0 ! Xpath 131072 " X: 8192*4*4 ! if MSG('E171', "Missing :endif") ! let g:messages = g:messages . "B" ! endif ! ! let v:errmsg = "" ! XloopINIT 262144 4 ! let loops = 2 ! while loops > 0 " 2: 1: ! let loops = loops - 1 ! Xloop 1 " X: 262144 + 262144 * 4 ! " if missing! ! endif " :endif without :if in while ! Xloop 2 " X: 524288 + 524288 * 4 ! XloopNEXT ! endwhile ! Xpath 4194304 " X: 262144*4*4 ! if MSG('E580', ":endif without :if") ! let g:messages = g:messages . "C" ! endif ! endfunction ! ! call F() ! ! " Error continuation outside a function is at the outermost :endwhile or :endif. ! let v:errmsg = "" ! XloopINIT! 8388608 4 ! let loops = 2 ! while loops > 0 " 2: 1: ! XloopNEXT ! let loops = loops - 1 ! Xloop 1 " X: 8388608 + 0 * 4 ! if 0 ! Xloop 2 " X: 0 ! " endif missing! Following :endwhile fails. ! endwhile | Xpath 134217728 " X: 0 ! Xpath 268435456 " X: 2*8388608*4*4 ! if MSG('E171', "Missing :endif") ! let messages = g:messages . "D" ! endif ! ! if messages != "ABCD" ! Xpath 536870912 " X: 0 ! Xout "messages is" messages "instead of ABCD" ! endif ! ! unlet loops messages ! delfunction F ! delfunction MSG ! ! Xcheck 285127993 ! "------------------------------------------------------------------------------- " Test 18: Interrupt (Ctrl-C pressed) {{{1 --- 608,615 ---- " END_OF_TEST_ENVIRONMENT - do not change or remove this line. ! " Tests 1 to 17 were moved to test_vimscript.vim ! let Xtest = 18 "------------------------------------------------------------------------------- " Test 18: Interrupt (Ctrl-C pressed) {{{1 *************** *** 1313,1452 **** Xcheck 41 ! ! "------------------------------------------------------------------------------- ! " Test 25: Executing :finally clauses on normal control flow {{{1 ! " ! " Control flow in a :try conditional should always fall through to its ! " :finally clause. A :finally clause of a :try conditional inside an ! " inactive conditional should never be executed. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! function! F() ! let loops = 3 ! XloopINIT 1 256 ! while loops > 0 " 3: 2: 1: ! Xloop 1 " X: 1 + 1*256 + 1*256*256 ! if loops >= 2 ! try ! Xloop 2 " X: 2 + 2*256 ! if loops == 2 ! try ! Xloop 4 " X: 4*256 ! finally ! Xloop 8 " X: 8*256 ! endtry ! endif ! finally ! Xloop 16 " X: 16 + 16*256 ! if loops == 2 ! try ! Xloop 32 " X: 32*256 ! finally ! Xloop 64 " X: 64*256 ! endtry ! endif ! endtry ! endif ! Xloop 128 " X: 128 + 128*256 + 128*256*256 ! let loops = loops - 1 ! XloopNEXT ! endwhile ! Xpath 16777216 " X: 16777216 ! endfunction ! ! if 1 ! try ! Xpath 33554432 " X: 33554432 ! call F() ! Xpath 67108864 " X: 67108864 ! finally ! Xpath 134217728 " X: 134217728 ! endtry ! else ! try ! Xpath 268435456 " X: 0 ! finally ! Xpath 536870912 " X: 0 ! endtry ! endif ! ! delfunction F ! ! Xcheck 260177811 ! ! ! "------------------------------------------------------------------------------- ! " Test 26: Executing :finally clauses after :continue or :break {{{1 ! " ! " For a :continue or :break dynamically enclosed in a :try/:endtry ! " region inside the next surrounding :while/:endwhile, if the ! " :continue/:break is before the :finally, the :finally clause is ! " executed first. If the :continue/:break is after the :finally, the ! " :finally clause is broken (like an :if/:endif region). ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! try ! let loops = 3 ! XloopINIT! 1 32 ! while loops > 0 ! XloopNEXT ! try ! try ! if loops == 2 " 3: 2: 1: ! Xloop 1 " X: 1*32 ! let loops = loops - 1 ! continue ! elseif loops == 1 ! Xloop 2 " X: 2*32*32 ! break ! finish ! endif ! Xloop 4 " X: 4 ! endtry ! finally ! Xloop 8 " X: 8 + 8*32 + 8*32*32 ! endtry ! Xloop 16 " X: 16 ! let loops = loops - 1 ! endwhile ! Xpath 32768 " X: 32768 ! finally ! Xpath 65536 " X: 65536 ! let loops = 3 ! XloopINIT 131072 16 ! while loops > 0 ! try ! finally ! try ! if loops == 2 ! Xloop 1 " X: 131072*16 ! let loops = loops - 1 ! XloopNEXT ! continue ! elseif loops == 1 ! Xloop 2 " X: 131072*2*16*16 ! break ! finish ! endif ! endtry ! Xloop 4 " X: 131072*4 ! endtry ! Xloop 8 " X: 131072*8 ! let loops = loops - 1 ! XloopNEXT ! endwhile ! Xpath 536870912 " X: 536870912 ! endtry ! Xpath 1073741824 " X: 1073741824 ! ! unlet loops ! ! Xcheck 1681500476 "------------------------------------------------------------------------------- --- 1125,1132 ---- Xcheck 41 ! " Tests 25 and 26 were moved to test_trycatch.vim ! let Xtest = 27 "------------------------------------------------------------------------------- *************** *** 1783,2034 **** Xcheck 190905173 ! ! "------------------------------------------------------------------------------- ! " Test 32: Remembering the :return value on :finally {{{1 ! " ! " If a :finally clause is executed due to a :return specifying ! " a value, this is the value visible to the caller if not overwritten ! " by a new :return in the :finally clause. A :return without a value ! " in the :finally clause overwrites with value 0. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! function! F() ! try ! Xpath 1 " X: 1 ! try ! Xpath 2 " X: 2 ! return "ABCD" ! Xpath 4 " X: 0 ! finally ! Xpath 8 " X: 8 ! endtry ! Xpath 16 " X: 0 ! finally ! Xpath 32 " X: 32 ! endtry ! Xpath 64 " X: 0 ! endfunction ! ! function! G() ! try ! Xpath 128 " X: 128 ! return 8 ! Xpath 256 " X: 0 ! finally ! Xpath 512 " X: 512 ! return 16 + strlen(F()) ! Xpath 1024 " X: 0 ! endtry ! Xpath 2048 " X: 0 ! endfunction ! ! function! H() ! try ! Xpath 4096 " X: 4096 ! return 32 ! Xpath 8192 " X: 0 ! finally ! Xpath 16384 " X: 16384 ! return ! Xpath 32768 " X: 0 ! endtry ! Xpath 65536 " X: 0 ! endfunction ! ! function! I() ! try ! Xpath 131072 " X: 131072 ! finally ! Xpath 262144 " X: 262144 ! return G() + H() + 64 ! Xpath 524288 " X: 0 ! endtry ! Xpath 1048576 " X: 0 ! endfunction ! ! let retcode = I() ! Xpath 2097152 " X: 2097152 ! ! if retcode < 0 ! Xpath 4194304 " X: 0 ! endif ! if retcode % 4 ! Xpath 8388608 " X: 0 ! endif ! if (retcode/4) % 2 ! Xpath 16777216 " X: 16777216 ! endif ! if (retcode/8) % 2 ! Xpath 33554432 " X: 0 ! endif ! if (retcode/16) % 2 ! Xpath 67108864 " X: 67108864 ! endif ! if (retcode/32) % 2 ! Xpath 134217728 " X: 0 ! endif ! if (retcode/64) % 2 ! Xpath 268435456 " X: 268435456 ! endif ! if retcode/128 ! Xpath 536870912 " X: 0 ! endif ! ! unlet retcode ! delfunction F ! delfunction G ! delfunction H ! delfunction I ! ! Xcheck 354833067 ! ! ! "------------------------------------------------------------------------------- ! " Test 33: :return under :execute or user command and :finally {{{1 ! " ! " A :return command may be executed under an ":execute" or from ! " a user command. Executing of :finally clauses and passing through ! " the return code works also then. ! "------------------------------------------------------------------------------- ! XpathINIT ! ! command! -nargs=? RETURN ! \ try | return | finally | return * 2 | endtry ! ! function! F() ! try ! RETURN 8 ! Xpath 1 " X: 0 ! finally ! Xpath 2 " X: 2 ! endtry ! Xpath 4 " X: 0 ! endfunction ! ! function! G() ! try ! RETURN 32 ! Xpath 8 " X: 0 ! finally ! Xpath 16 " X: 16 ! RETURN 128 ! Xpath 32 " X: 0 ! endtry ! Xpath 64 " X: 0 ! endfunction ! ! function! H() ! try ! execute "try | return 512 | finally | return 1024 | endtry" ! Xpath 128 " X: 0 ! finally ! Xpath 256 " X: 256 ! endtry ! Xpath 512 " X: 0 ! endfunction ! ! function! I() ! try ! execute "try | return 2048 | finally | return 4096 | endtry" ! Xpath 1024 " X: 0 ! finally ! Xpath 2048 " X: 2048 ! execute "try | return 8192 | finally | return 16384 | endtry" ! Xpath 4096 " X: 0 ! endtry ! Xpath 8192 " X: 0 ! endfunction ! ! function! J() ! try ! RETURN 32768 ! Xpath 16384 " X: 0 ! finally ! Xpath 32768 " X: 32768 ! return ! Xpath 65536 " X: 0 ! endtry ! Xpath 131072 " X: 0 ! endfunction ! ! function! K() ! try ! execute "try | return 131072 | finally | return 262144 | endtry" ! Xpath 262144 " X: 0 ! finally ! Xpath 524288 " X: 524288 ! execute "try | return 524288 | finally | return | endtry" ! Xpath 1048576 " X: 0 ! endtry ! Xpath 2097152 " X: 0 ! endfunction ! ! function! L() ! try ! return ! Xpath 4194304 " X: 0 ! finally ! Xpath 8388608 " X: 8388608 ! RETURN 1048576 ! Xpath 16777216 " X: 0 ! endtry ! Xpath 33554432 " X: 0 ! endfunction ! ! function! M() ! try ! return ! Xpath 67108864 " X: 0 ! finally ! Xpath 134217728 " X: 134217728 ! execute "try | return 4194304 | finally | return 8388608 | endtry" ! Xpath 268435456 " X: 0 ! endtry ! Xpath 536870912 " X: 0 ! endfunction ! ! function! N() ! RETURN 16777216 ! endfunction ! ! function! O() ! execute "try | return 67108864 | finally | return 134217728 | endtry" ! endfunction ! ! let sum = F() + G() + H() + I() + J() + K() + L() + M() ! let expected = 16 + 256 + 1024 + 16384 + 0 + 0 + 2097152 + 8388608 ! let sum = sum + N() + O() ! let expected = expected + 33554432 + 134217728 ! ! if sum == expected ! Xout "sum = " . sum . " (ok)" ! else ! Xout "sum = " . sum . ", expected: " . expected ! endif ! ! Xpath 1073741824 " X: 1073741824 ! ! if sum != expected ! " The Xpath command does not accept 2^31 (negative); add explicitly: ! let Xpath = Xpath + 2147483648 " X: 0 ! endif ! ! unlet sum expected ! delfunction F ! delfunction G ! delfunction H ! delfunction I ! delfunction J ! delfunction K ! delfunction L ! delfunction M ! delfunction N ! delfunction O ! ! Xcheck 1216907538 "------------------------------------------------------------------------------- --- 1463,1470 ---- Xcheck 190905173 ! " Tests 32 and 33 were moved to test_trycatch.vim ! let Xtest = 34 "------------------------------------------------------------------------------- *************** *** 2654,3296 **** Xcheck 357908480 ! ! "------------------------------------------------------------------------------- ! " Test 41: Skipped :throw finding next command {{{1 ! " ! " A :throw in an inactive conditional must not hide a following ! " command. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! function! F() ! Xpath 1 " X: 1 ! if 0 | throw "never" | endif | Xpath 2 " X: 2 ! Xpath 4 " X: 4 ! endfunction ! ! function! G() ! Xpath 8 " X: 8 ! while 0 | throw "never" | endwhile | Xpath 16 " X: 16 ! Xpath 32 " X: 32 ! endfunction ! ! function H() ! Xpath 64 " X: 64 ! if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128 ! Xpath 256 " X: 256 ! endfunction ! ! Xpath 512 " X: 512 ! ! try ! Xpath 1024 " X: 1024 ! call F() ! Xpath 2048 " X: 2048 ! catch /.*/ ! Xpath 4096 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xpath 8192 " X: 8192 ! ! try ! Xpath 16384 " X: 16384 ! call G() ! Xpath 32768 " X: 32768 ! catch /.*/ ! Xpath 65536 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xpath 131072 " X: 131072 ! ! try ! Xpath 262144 " X: 262144 ! call H() ! Xpath 524288 " X: 524288 ! catch /.*/ ! Xpath 1048576 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xpath 2097152 " X: 2097152 ! ! delfunction F ! delfunction G ! delfunction H ! ! Xcheck 3076095 ! ! ! "------------------------------------------------------------------------------- ! " Test 42: Catching number and string exceptions {{{1 ! " ! " When a number is thrown, it is converted to a string exception. ! " Numbers and strings may be caught by specifying a regular exception ! " as argument to the :catch command. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! try ! ! try ! Xpath 1 " X: 1 ! throw 4711 ! Xpath 2 " X: 0 ! catch /4711/ ! Xpath 4 " X: 4 ! endtry ! ! try ! Xpath 8 " X: 8 ! throw 4711 ! Xpath 16 " X: 0 ! catch /^4711$/ ! Xpath 32 " X: 32 ! endtry ! ! try ! Xpath 64 " X: 64 ! throw 4711 ! Xpath 128 " X: 0 ! catch /\d/ ! Xpath 256 " X: 256 ! endtry ! ! try ! Xpath 512 " X: 512 ! throw 4711 ! Xpath 1024 " X: 0 ! catch /^\d\+$/ ! Xpath 2048 " X: 2048 ! endtry ! ! try ! Xpath 4096 " X: 4096 ! throw "arrgh" ! Xpath 8192 " X: 0 ! catch /arrgh/ ! Xpath 16384 " X: 16384 ! endtry ! ! try ! Xpath 32768 " X: 32768 ! throw "arrgh" ! Xpath 65536 " X: 0 ! catch /^arrgh$/ ! Xpath 131072 " X: 131072 ! endtry ! ! try ! Xpath 262144 " X: 262144 ! throw "arrgh" ! Xpath 524288 " X: 0 ! catch /\l/ ! Xpath 1048576 " X: 1048576 ! endtry ! ! try ! Xpath 2097152 " X: 2097152 ! throw "arrgh" ! Xpath 4194304 " X: 0 ! catch /^\l\+$/ ! Xpath 8388608 " X: 8388608 ! endtry ! ! try ! try ! Xpath 16777216 " X: 16777216 ! throw "ARRGH" ! Xpath 33554432 " X: 0 ! catch /^arrgh$/ ! Xpath 67108864 " X: 0 ! endtry ! catch /^\carrgh$/ ! Xpath 134217728 " X: 134217728 ! endtry ! ! try ! Xpath 268435456 " X: 268435456 ! throw "" ! Xpath 536870912 " X: 0 ! catch /^$/ ! Xpath 1073741824 " X: 1073741824 ! endtry ! ! catch /.*/ ! " The Xpath command does not accept 2^31 (negative); add explicitly: ! let Xpath = Xpath + 2147483648 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xcheck 1505155949 ! ! ! "------------------------------------------------------------------------------- ! " Test 43: Selecting the correct :catch clause {{{1 ! " ! " When an exception is thrown and there are multiple :catch clauses, ! " the first matching one is taken. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! XloopINIT 1 1024 ! let loops = 3 ! while loops > 0 ! try ! if loops == 3 ! Xloop 1 " X: 1 ! throw "a" ! Xloop 2 " X: 0 ! elseif loops == 2 ! Xloop 4 " X: 4*1024 ! throw "ab" ! Xloop 8 " X: 0 ! elseif loops == 1 ! Xloop 16 " X: 16*1024*1024 ! throw "abc" ! Xloop 32 " X: 0 ! endif ! catch /abc/ ! Xloop 64 " X: 64*1024*1024 ! catch /ab/ ! Xloop 128 " X: 128*1024 ! catch /.*/ ! Xloop 256 " X: 256 ! catch /a/ ! Xloop 512 " X: 0 ! endtry ! ! let loops = loops - 1 ! XloopNEXT ! endwhile ! Xpath 1073741824 " X: 1073741824 ! ! unlet loops ! ! Xcheck 1157763329 ! ! ! "------------------------------------------------------------------------------- ! " Test 44: Missing or empty :catch patterns {{{1 ! " ! " A missing or empty :catch pattern means the same as /.*/, that is, ! " catches everything. To catch only empty exceptions, /^$/ must be ! " used. A :catch with missing, empty, or /.*/ argument also works ! " when followed by another command separated by a bar on the same ! " line. :catch patterns cannot be specified between ||. But other ! " pattern separators can be used instead of //. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! try ! try ! Xpath 1 " X: 1 ! throw "" ! catch /^$/ ! Xpath 2 " X: 2 ! endtry ! ! try ! Xpath 4 " X: 4 ! throw "" ! catch /.*/ ! Xpath 8 " X: 8 ! endtry ! ! try ! Xpath 16 " X: 16 ! throw "" ! catch // ! Xpath 32 " X: 32 ! endtry ! ! try ! Xpath 64 " X: 64 ! throw "" ! catch ! Xpath 128 " X: 128 ! endtry ! ! try ! Xpath 256 " X: 256 ! throw "oops" ! catch /^$/ ! Xpath 512 " X: 0 ! catch /.*/ ! Xpath 1024 " X: 1024 ! endtry ! ! try ! Xpath 2048 " X: 2048 ! throw "arrgh" ! catch /^$/ ! Xpath 4096 " X: 0 ! catch // ! Xpath 8192 " X: 8192 ! endtry ! ! try ! Xpath 16384 " X: 16384 ! throw "brrr" ! catch /^$/ ! Xpath 32768 " X: 0 ! catch ! Xpath 65536 " X: 65536 ! endtry ! ! try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry ! " X: 131072 + 262144 ! ! try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry ! " X: 524288 + 1048576 ! ! while 1 ! try ! let caught = 0 ! let v:errmsg = "" ! " Extra try level: if ":catch" without arguments below raises ! " a syntax error because it misinterprets the "Xpath" as a pattern, ! " let it be caught by the ":catch /.*/" below. ! try ! try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | : ! endtry " X: 2097152 + 4194304 ! endtry ! catch /.*/ ! let caught = 1 ! Xout v:exception "in" v:throwpoint ! finally ! if $VIMNOERRTHROW && v:errmsg != "" ! Xout v:errmsg ! endif ! if caught || $VIMNOERRTHROW && v:errmsg != "" ! Xpath 8388608 " X: 0 ! endif ! break " discard error for $VIMNOERRTHROW ! endtry ! endwhile ! ! let cologne = 4711 ! try ! try ! Xpath 16777216 " X: 16777216 ! throw "throw cologne" ! " Next lines catches all and throws 4711: ! catch |throw cologne| ! Xpath 33554432 " X: 0 ! endtry ! catch /4711/ ! Xpath 67108864 " X: 67108864 ! endtry ! ! try ! Xpath 134217728 " X: 134217728 ! throw "plus" ! catch +plus+ ! Xpath 268435456 " X: 268435456 ! endtry ! ! Xpath 536870912 " X: 536870912 ! catch /.*/ ! Xpath 1073741824 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! unlet! caught cologne ! ! Xcheck 1031761407 ! ! ! "------------------------------------------------------------------------------- ! " Test 45: Catching exceptions from nested :try blocks {{{1 ! " ! " When :try blocks are nested, an exception is caught by the innermost ! " try conditional that has a matching :catch clause. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! XloopINIT 1 1024 ! let loops = 3 ! while loops > 0 ! try ! try ! try ! try ! if loops == 3 ! Xloop 1 " X: 1 ! throw "a" ! Xloop 2 " X: 0 ! elseif loops == 2 ! Xloop 4 " X: 4*1024 ! throw "ab" ! Xloop 8 " X: 0 ! elseif loops == 1 ! Xloop 16 " X: 16*1024*1024 ! throw "abc" ! Xloop 32 " X: 0 ! endif ! catch /abc/ ! Xloop 64 " X: 64*1024*1024 ! endtry ! catch /ab/ ! Xloop 128 " X: 128*1024 ! endtry ! catch /.*/ ! Xloop 256 " X: 256 ! endtry ! catch /a/ ! Xloop 512 " X: 0 ! endtry ! ! let loops = loops - 1 ! XloopNEXT ! endwhile ! Xpath 1073741824 " X: 1073741824 ! ! unlet loops ! ! Xcheck 1157763329 ! ! ! "------------------------------------------------------------------------------- ! " Test 46: Executing :finally after a :throw in nested :try {{{1 ! " ! " When an exception is thrown from within nested :try blocks, the ! " :finally clauses of the non-catching try conditionals should be ! " executed before the matching :catch of the next surrounding :try ! " gets the control. If this also has a :finally clause, it is ! " executed afterwards. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! let sum = 0 ! ! try ! Xpath 1 " X: 1 ! try ! Xpath 2 " X: 2 ! try ! Xpath 4 " X: 4 ! try ! Xpath 8 " X: 8 ! throw "ABC" ! Xpath 16 " X: 0 ! catch /xyz/ ! Xpath 32 " X: 0 ! finally ! Xpath 64 " X: 64 ! if sum != 0 ! Xpath 128 " X: 0 ! endif ! let sum = sum + 1 ! endtry ! Xpath 256 " X: 0 ! catch /123/ ! Xpath 512 " X: 0 ! catch /321/ ! Xpath 1024 " X: 0 ! finally ! Xpath 2048 " X: 2048 ! if sum != 1 ! Xpath 4096 " X: 0 ! endif ! let sum = sum + 2 ! endtry ! Xpath 8192 " X: 0 ! finally ! Xpath 16384 " X: 16384 ! if sum != 3 ! Xpath 32768 " X: 0 ! endif ! let sum = sum + 4 ! endtry ! Xpath 65536 " X: 0 ! catch /ABC/ ! Xpath 131072 " X: 131072 ! if sum != 7 ! Xpath 262144 " X: 0 ! endif ! let sum = sum + 8 ! finally ! Xpath 524288 " X: 524288 ! if sum != 15 ! Xpath 1048576 " X: 0 ! endif ! let sum = sum + 16 ! endtry ! Xpath 65536 " X: 65536 ! if sum != 31 ! Xpath 131072 " X: 0 ! endif ! ! unlet sum ! ! Xcheck 739407 ! ! ! "------------------------------------------------------------------------------- ! " Test 47: Throwing exceptions from a :catch clause {{{1 ! " ! " When an exception is thrown from a :catch clause, it should not be ! " caught by a :catch of the same :try conditional. After executing ! " the :finally clause (if present), surrounding try conditionals ! " should be checked for a matching :catch. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! Xpath 1 " X: 1 ! try ! Xpath 2 " X: 2 ! try ! Xpath 4 " X: 4 ! try ! Xpath 8 " X: 8 ! throw "x1" ! Xpath 16 " X: 0 ! catch /x1/ ! Xpath 32 " X: 32 ! try ! Xpath 64 " X: 64 ! throw "x2" ! Xpath 128 " X: 0 ! catch /x1/ ! Xpath 256 " X: 0 ! catch /x2/ ! Xpath 512 " X: 512 ! try ! Xpath 1024 " X: 1024 ! throw "x3" ! Xpath 2048 " X: 0 ! catch /x1/ ! Xpath 4096 " X: 0 ! catch /x2/ ! Xpath 8192 " X: 0 ! finally ! Xpath 16384 " X: 16384 ! endtry ! Xpath 32768 " X: 0 ! catch /x3/ ! Xpath 65536 " X: 0 ! endtry ! Xpath 131072 " X: 0 ! catch /x1/ ! Xpath 262144 " X: 0 ! catch /x2/ ! Xpath 524288 " X: 0 ! catch /x3/ ! Xpath 1048576 " X: 0 ! finally ! Xpath 2097152 " X: 2097152 ! endtry ! Xpath 4194304 " X: 0 ! catch /x1/ ! Xpath 8388608 " X: 0 ! catch /x2/ ! Xpath 16777216 " X: 0 ! catch /x3/ ! Xpath 33554432 " X: 33554432 ! endtry ! Xpath 67108864 " X: 67108864 ! catch /.*/ ! Xpath 134217728 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! Xpath 268435456 " X: 268435456 ! ! Xcheck 371213935 ! ! ! "------------------------------------------------------------------------------- ! " Test 48: Throwing exceptions from a :finally clause {{{1 ! " ! " When an exception is thrown from a :finally clause, it should not be ! " caught by a :catch of the same :try conditional. Surrounding try ! " conditionals should be checked for a matching :catch. A previously ! " thrown exception is discarded. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! try ! ! try ! try ! Xpath 1 " X: 1 ! catch /x1/ ! Xpath 2 " X: 0 ! finally ! Xpath 4 " X: 4 ! throw "x1" ! Xpath 8 " X: 0 ! endtry ! Xpath 16 " X: 0 ! catch /x1/ ! Xpath 32 " X: 32 ! endtry ! Xpath 64 " X: 64 ! ! try ! try ! Xpath 128 " X: 128 ! throw "x2" ! Xpath 256 " X: 0 ! catch /x2/ ! Xpath 512 " X: 512 ! catch /x3/ ! Xpath 1024 " X: 0 ! finally ! Xpath 2048 " X: 2048 ! throw "x3" ! Xpath 4096 " X: 0 ! endtry ! Xpath 8192 " X: 0 ! catch /x2/ ! Xpath 16384 " X: 0 ! catch /x3/ ! Xpath 32768 " X: 32768 ! endtry ! Xpath 65536 " X: 65536 ! ! try ! try ! try ! Xpath 131072 " X: 131072 ! throw "x4" ! Xpath 262144 " X: 0 ! catch /x5/ ! Xpath 524288 " X: 0 ! finally ! Xpath 1048576 " X: 1048576 ! throw "x5" " discards "x4" ! Xpath 2097152 " X: 0 ! endtry ! Xpath 4194304 " X: 0 ! catch /x4/ ! Xpath 8388608 " X: 0 ! finally ! Xpath 16777216 " X: 16777216 ! endtry ! Xpath 33554432 " X: 0 ! catch /x5/ ! Xpath 67108864 " X: 67108864 ! endtry ! Xpath 134217728 " X: 134217728 ! ! catch /.*/ ! Xpath 268435456 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! Xpath 536870912 " X: 536870912 ! ! Xcheck 756255461 "------------------------------------------------------------------------------- --- 2090,2097 ---- Xcheck 357908480 ! " Tests 41 to 48 were moved to test_trycatch.vim ! let Xtest = 49 "------------------------------------------------------------------------------- *************** *** 3443,3566 **** Xcheck 363550045 ! ! "------------------------------------------------------------------------------- ! " Test 51: Throwing exceptions across :execute and user commands {{{1 ! " ! " A :throw command may be executed under an ":execute" or from ! " a user command. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! command! -nargs=? THROW1 throw | throw 1 ! command! -nargs=? THROW2 try | throw | endtry | throw 2 ! command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw | endtry ! command! -nargs=? THROW4 try | throw 4 | finally | throw | endtry ! ! try ! ! try ! try ! Xpath 1 " X: 1 ! THROW1 "A" ! catch /A/ ! Xpath 2 " X: 2 ! endtry ! catch /1/ ! Xpath 4 " X: 0 ! endtry ! ! try ! try ! Xpath 8 " X: 8 ! THROW2 "B" ! catch /B/ ! Xpath 16 " X: 16 ! endtry ! catch /2/ ! Xpath 32 " X: 0 ! endtry ! ! try ! try ! Xpath 64 " X: 64 ! THROW3 "C" ! catch /C/ ! Xpath 128 " X: 128 ! endtry ! catch /3/ ! Xpath 256 " X: 0 ! endtry ! ! try ! try ! Xpath 512 " X: 512 ! THROW4 "D" ! catch /D/ ! Xpath 1024 " X: 1024 ! endtry ! catch /4/ ! Xpath 2048 " X: 0 ! endtry ! ! try ! try ! Xpath 4096 " X: 4096 ! execute 'throw "E" | throw 5' ! catch /E/ ! Xpath 8192 " X: 8192 ! endtry ! catch /5/ ! Xpath 16384 " X: 0 ! endtry ! ! try ! try ! Xpath 32768 " X: 32768 ! execute 'try | throw "F" | endtry | throw 6' ! catch /F/ ! Xpath 65536 " X: 65536 ! endtry ! catch /6/ ! Xpath 131072 " X: 0 ! endtry ! ! try ! try ! Xpath 262144 " X: 262144 ! execute'try | throw 7 | catch /7/ | throw "G" | endtry' ! catch /G/ ! Xpath 524288 " X: 524288 ! endtry ! catch /7/ ! Xpath 1048576 " X: 0 ! endtry ! ! try ! try ! Xpath 2097152 " X: 2097152 ! execute 'try | throw 8 | finally | throw "H" | endtry' ! catch /H/ ! Xpath 4194304 " X: 4194304 ! endtry ! catch /8/ ! Xpath 8388608 " X: 0 ! endtry ! ! catch /.*/ ! Xpath 16777216 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xpath 33554432 " X: 33554432 ! ! delcommand THROW1 ! delcommand THROW2 ! delcommand THROW3 ! delcommand THROW4 ! ! Xcheck 40744667 "------------------------------------------------------------------------------- --- 2244,2251 ---- Xcheck 363550045 ! " Test 51 was moved to test_trycatch.vim ! let Xtest = 52 "------------------------------------------------------------------------------- *************** *** 6227,7180 **** Xcheck 212514423 ! ! "------------------------------------------------------------------------------- ! " Test 69: :throw across :if, :elseif, :while {{{1 ! " ! " On an :if, :elseif, or :while command, an exception might be thrown ! " during evaluation of the expression to test. The exception can be ! " caught by the script. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! XloopINIT! 1 2 ! ! function! THROW(x) ! XloopNEXT ! Xloop 1 " X: 1 + 2 + 4 ! throw a:x ! endfunction ! ! try ! ! try ! Xpath 8 " X: 8 ! if 4711 == THROW("if") + 111 ! Xpath 16 " X: 0 ! else ! Xpath 32 " X: 0 ! endif ! Xpath 64 " X: 0 ! catch /^if$/ ! Xpath 128 " X: 128 ! catch /.*/ ! Xpath 256 " X: 0 ! Xout "if:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 512 " X: 512 ! if 4711 == 4 + 7 + 1 + 1 ! Xpath 1024 " X: 0 ! elseif 4711 == THROW("elseif") + 222 ! Xpath 2048 " X: 0 ! else ! Xpath 4096 " X: 0 ! endif ! Xpath 8192 " X: 0 ! catch /^elseif$/ ! Xpath 16384 " X: 16384 ! catch /.*/ ! Xpath 32768 " X: 0 ! Xout "elseif:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 65536 " X: 65536 ! while 4711 == THROW("while") + 4711 ! Xpath 131072 " X: 0 ! break ! endwhile ! Xpath 262144 " X: 0 ! catch /^while$/ ! Xpath 524288 " X: 524288 ! catch /.*/ ! Xpath 1048576 " X: 0 ! Xout "while:" v:exception "in" v:throwpoint ! endtry ! ! catch /^0$/ " default return value ! Xpath 2097152 " X: 0 ! Xout v:throwpoint ! catch /.*/ ! Xout v:exception "in" v:throwpoint ! Xpath 4194304 " X: 0 ! endtry ! ! Xpath 8388608 " X: 8388608 ! ! delfunction THROW ! ! Xcheck 8995471 ! ! ! "------------------------------------------------------------------------------- ! " Test 70: :throw across :return or :throw {{{1 ! " ! " On a :return or :throw command, an exception might be thrown during ! " evaluation of the expression to return or throw, respectively. The ! " exception can be caught by the script. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! let taken = "" ! ! function! THROW(x, n) ! let g:taken = g:taken . "T" . a:n ! throw a:x ! endfunction ! ! function! F(x, y, n) ! let g:taken = g:taken . "F" . a:n ! return a:x + THROW(a:y, a:n) ! endfunction ! ! function! G(x, y, n) ! let g:taken = g:taken . "G" . a:n ! throw a:x . THROW(a:y, a:n) ! return a:x ! endfunction ! ! try ! try ! Xpath 1 " X: 1 ! call F(4711, "return", 1) ! Xpath 2 " X: 0 ! catch /^return$/ ! Xpath 4 " X: 4 ! catch /.*/ ! Xpath 8 " X: 0 ! Xout "return:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 16 " X: 16 ! let var = F(4712, "return-var", 2) ! Xpath 32 " X: 0 ! catch /^return-var$/ ! Xpath 64 " X: 64 ! catch /.*/ ! Xpath 128 " X: 0 ! Xout "return-var:" v:exception "in" v:throwpoint ! finally ! unlet! var ! endtry ! ! try ! Xpath 256 " X: 256 ! throw "except1" . THROW("throw1", 3) ! Xpath 512 " X: 0 ! catch /^except1/ ! Xpath 1024 " X: 0 ! catch /^throw1$/ ! Xpath 2048 " X: 2048 ! catch /.*/ ! Xpath 4096 " X: 0 ! Xout "throw1:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 8192 " X: 8192 ! call G("except2", "throw2", 4) ! Xpath 16384 " X: 0 ! catch /^except2/ ! Xpath 32768 " X: 0 ! catch /^throw2$/ ! Xpath 65536 " X: 65536 ! catch /.*/ ! Xpath 131072 " X: 0 ! Xout "throw2:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 262144 " X: 262144 ! let var = G("except3", "throw3", 5) ! Xpath 524288 " X: 0 ! catch /^except3/ ! Xpath 1048576 " X: 0 ! catch /^throw3$/ ! Xpath 2097152 " X: 2097152 ! catch /.*/ ! Xpath 4194304 " X: 0 ! Xout "throw3:" v:exception "in" v:throwpoint ! finally ! unlet! var ! endtry ! ! let expected = "F1T1F2T2T3G4T4G5T5" ! if taken != expected ! Xpath 8388608 " X: 0 ! Xout "'taken' is" taken "instead of" expected ! endif ! ! catch /^0$/ " default return value ! Xpath 16777216 " X: 0 ! Xout v:throwpoint ! catch /.*/ ! Xpath 33554432 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xpath 67108864 " X: 67108864 ! ! unlet taken expected ! delfunction THROW ! delfunction F ! delfunction G ! ! Xcheck 69544277 ! ! ! "------------------------------------------------------------------------------- ! " Test 71: :throw across :echo variants and :execute {{{1 ! " ! " On an :echo, :echon, :echomsg, :echoerr, or :execute command, an ! " exception might be thrown during evaluation of the arguments to ! " be displayed or executed as a command, respectively. Any following ! " arguments are not evaluated, then. The exception can be caught by ! " the script. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! let taken = "" ! ! function! THROW(x, n) ! let g:taken = g:taken . "T" . a:n ! throw a:x ! endfunction ! ! function! F(n) ! let g:taken = g:taken . "F" . a:n ! return "F" . a:n ! endfunction ! ! try ! try ! Xpath 1 " X: 1 ! echo "echo" . THROW("echo-except", 1) F(1) ! Xpath 2 " X: 0 ! catch /^echo-except$/ ! Xpath 4 " X: 4 ! catch /.*/ ! Xpath 8 " X: 0 ! Xout "echo:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 16 " X: 16 ! echon "echon" . THROW("echon-except", 2) F(2) ! Xpath 32 " X: 0 ! catch /^echon-except$/ ! Xpath 64 " X: 64 ! catch /.*/ ! Xpath 128 " X: 0 ! Xout "echon:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 256 " X: 256 ! echomsg "echomsg" . THROW("echomsg-except", 3) F(3) ! Xpath 512 " X: 0 ! catch /^echomsg-except$/ ! Xpath 1024 " X: 1024 ! catch /.*/ ! Xpath 2048 " X: 0 ! Xout "echomsg:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 4096 " X: 4096 ! echoerr "echoerr" . THROW("echoerr-except", 4) F(4) ! Xpath 8192 " X: 0 ! catch /^echoerr-except$/ ! Xpath 16384 " X: 16384 ! catch /Vim/ ! Xpath 32768 " X: 0 ! catch /echoerr/ ! Xpath 65536 " X: 0 ! catch /.*/ ! Xpath 131072 " X: 0 ! Xout "echoerr:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 262144 " X: 262144 ! execute "echo 'execute" . THROW("execute-except", 5) F(5) "'" ! Xpath 524288 " X: 0 ! catch /^execute-except$/ ! Xpath 1048576 " X: 1048576 ! catch /.*/ ! Xpath 2097152 " X: 0 ! Xout "execute:" v:exception "in" v:throwpoint ! endtry ! ! let expected = "T1T2T3T4T5" ! if taken != expected ! Xpath 4194304 " X: 0 ! Xout "'taken' is" taken "instead of" expected ! endif ! ! catch /^0$/ " default return value ! Xpath 8388608 " X: 0 ! Xout v:throwpoint ! catch /.*/ ! Xpath 16777216 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xpath 33554432 " X: 33554432 ! ! unlet taken expected ! delfunction THROW ! delfunction F ! ! Xcheck 34886997 ! ! ! "------------------------------------------------------------------------------- ! " Test 72: :throw across :let or :unlet {{{1 ! " ! " On a :let command, an exception might be thrown during evaluation ! " of the expression to assign. On an :let or :unlet command, the ! " evaluation of the name of the variable to be assigned or list or ! " deleted, respectively, may throw an exception. Any following ! " arguments are not evaluated, then. The exception can be caught by ! " the script. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! let throwcount = 0 ! ! function! THROW(x) ! let g:throwcount = g:throwcount + 1 ! throw a:x ! endfunction ! ! try ! try ! let $VAR = "old_value" ! Xpath 1 " X: 1 ! let $VAR = "let(" . THROW("var") . ")" ! Xpath 2 " X: 0 ! catch /^var$/ ! Xpath 4 " X: 4 ! finally ! if $VAR != "old_value" ! Xpath 8 " X: 0 ! endif ! endtry ! ! try ! let @a = "old_value" ! Xpath 16 " X: 16 ! let @a = "let(" . THROW("reg") . ")" ! Xpath 32 " X: 0 ! catch /^reg$/ ! try ! Xpath 64 " X: 64 ! let @A = "let(" . THROW("REG") . ")" ! Xpath 128 " X: 0 ! catch /^REG$/ ! Xpath 256 " X: 256 ! endtry ! finally ! if @a != "old_value" ! Xpath 512 " X: 0 ! endif ! if @A != "old_value" ! Xpath 1024 " X: 0 ! endif ! endtry ! ! try ! let saved_gpath = &g:path ! let saved_lpath = &l:path ! Xpath 2048 " X: 2048 ! let &path = "let(" . THROW("opt") . ")" ! Xpath 4096 " X: 0 ! catch /^opt$/ ! try ! Xpath 8192 " X: 8192 ! let &g:path = "let(" . THROW("gopt") . ")" ! Xpath 16384 " X: 0 ! catch /^gopt$/ ! try ! Xpath 32768 " X: 32768 ! let &l:path = "let(" . THROW("lopt") . ")" ! Xpath 65536 " X: 0 ! catch /^lopt$/ ! Xpath 131072 " X: 131072 ! endtry ! endtry ! finally ! if &g:path != saved_gpath || &l:path != saved_lpath ! Xpath 262144 " X: 0 ! endif ! let &g:path = saved_gpath ! let &l:path = saved_lpath ! endtry ! ! unlet! var1 var2 var3 ! ! try ! Xpath 524288 " X: 524288 ! let var1 = "let(" . THROW("var1") . ")" ! Xpath 1048576 " X: 0 ! catch /^var1$/ ! Xpath 2097152 " X: 2097152 ! finally ! if exists("var1") ! Xpath 4194304 " X: 0 ! endif ! endtry ! ! try ! let var2 = "old_value" ! Xpath 8388608 " X: 8388608 ! let var2 = "let(" . THROW("var2"). ")" ! Xpath 16777216 " X: 0 ! catch /^var2$/ ! Xpath 33554432 " X: 33554432 ! finally ! if var2 != "old_value" ! Xpath 67108864 " X: 0 ! endif ! endtry ! ! try ! Xpath 134217728 " X: 134217728 ! let var{THROW("var3")} = 4711 ! Xpath 268435456 " X: 0 ! catch /^var3$/ ! Xpath 536870912 " X: 536870912 ! endtry ! ! let addpath = "" ! ! function ADDPATH(p) ! let g:addpath = g:addpath . a:p ! endfunction ! ! try ! call ADDPATH("T1") ! let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3") ! call ADDPATH("T4") ! catch /^var4$/ ! call ADDPATH("T5") ! endtry ! ! try ! call ADDPATH("T6") ! unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8") ! call ADDPATH("T9") ! catch /^var5$/ ! call ADDPATH("T10") ! endtry ! ! if addpath != "T1T5T6T10" || throwcount != 11 ! throw "addpath: " . addpath . ", throwcount: " . throwcount ! endif ! ! Xpath 1073741824 " X: 1073741824 ! ! catch /.*/ ! " The Xpath command does not accept 2^31 (negative); add explicitly: ! let Xpath = Xpath + 2147483648 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! unlet! var1 var2 var3 addpath throwcount ! delfunction THROW ! ! Xcheck 1789569365 ! ! ! "------------------------------------------------------------------------------- ! " Test 73: :throw across :function, :delfunction {{{1 ! " ! " The :function and :delfunction commands may cause an expression ! " specified in braces to be evaluated. During evaluation, an ! " exception might be thrown. The exception can be caught by the ! " script. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! let taken = "" ! ! function! THROW(x, n) ! let g:taken = g:taken . "T" . a:n ! throw a:x ! endfunction ! ! function! EXPR(x, n) ! let g:taken = g:taken . "E" . a:n ! if a:n % 2 == 0 ! call THROW(a:x, a:n) ! endif ! return 2 - a:n % 2 ! endfunction ! ! try ! try ! " Define function. ! Xpath 1 " X: 1 ! function! F0() ! endfunction ! Xpath 2 " X: 2 ! function! F{EXPR("function-def-ok", 1)}() ! endfunction ! Xpath 4 " X: 4 ! function! F{EXPR("function-def", 2)}() ! endfunction ! Xpath 8 " X: 0 ! catch /^function-def-ok$/ ! Xpath 16 " X: 0 ! catch /^function-def$/ ! Xpath 32 " X: 32 ! catch /.*/ ! Xpath 64 " X: 0 ! Xout "def:" v:exception "in" v:throwpoint ! endtry ! ! try ! " List function. ! Xpath 128 " X: 128 ! function F0 ! Xpath 256 " X: 256 ! function F{EXPR("function-lst-ok", 3)} ! Xpath 512 " X: 512 ! function F{EXPR("function-lst", 4)} ! Xpath 1024 " X: 0 ! catch /^function-lst-ok$/ ! Xpath 2048 " X: 0 ! catch /^function-lst$/ ! Xpath 4096 " X: 4096 ! catch /.*/ ! Xpath 8192 " X: 0 ! Xout "lst:" v:exception "in" v:throwpoint ! endtry ! ! try ! " Delete function ! Xpath 16384 " X: 16384 ! delfunction F0 ! Xpath 32768 " X: 32768 ! delfunction F{EXPR("function-del-ok", 5)} ! Xpath 65536 " X: 65536 ! delfunction F{EXPR("function-del", 6)} ! Xpath 131072 " X: 0 ! catch /^function-del-ok$/ ! Xpath 262144 " X: 0 ! catch /^function-del$/ ! Xpath 524288 " X: 524288 ! catch /.*/ ! Xpath 1048576 " X: 0 ! Xout "del:" v:exception "in" v:throwpoint ! endtry ! ! let expected = "E1E2T2E3E4T4E5E6T6" ! if taken != expected ! Xpath 2097152 " X: 0 ! Xout "'taken' is" taken "instead of" expected ! endif ! ! catch /.*/ ! Xpath 4194304 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! Xpath 8388608 " X: 8388608 ! ! unlet taken expected ! delfunction THROW ! delfunction EXPR ! ! Xcheck 9032615 ! ! ! "------------------------------------------------------------------------------- ! " Test 74: :throw across builtin functions and commands {{{1 ! " ! " Some functions like exists(), searchpair() take expression ! " arguments, other functions or commands like substitute() or ! " :substitute cause an expression (specified in the regular ! " expression) to be evaluated. During evaluation an exception ! " might be thrown. The exception can be caught by the script. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! let taken = "" ! ! function! THROW(x, n) ! let g:taken = g:taken . "T" . a:n ! throw a:x ! endfunction ! ! function! EXPR(x, n) ! let g:taken = g:taken . "E" . a:n ! call THROW(a:x . a:n, a:n) ! return "EXPR" ! endfunction ! ! function! SKIP(x, n) ! let g:taken = g:taken . "S" . a:n . "(" . line(".") ! let theline = getline(".") ! if theline =~ "skip" ! let g:taken = g:taken . "s)" ! return 1 ! elseif theline =~ "throw" ! let g:taken = g:taken . "t)" ! call THROW(a:x . a:n, a:n) ! else ! let g:taken = g:taken . ")" ! return 0 ! endif ! endfunction ! ! function! SUBST(x, n) ! let g:taken = g:taken . "U" . a:n . "(" . line(".") ! let theline = getline(".") ! if theline =~ "not" " SUBST() should not be called for this line ! let g:taken = g:taken . "n)" ! call THROW(a:x . a:n, a:n) ! elseif theline =~ "throw" ! let g:taken = g:taken . "t)" ! call THROW(a:x . a:n, a:n) ! else ! let g:taken = g:taken . ")" ! return "replaced" ! endif ! endfunction ! ! try ! try ! Xpath 1 " X: 1 ! let result = exists('*{EXPR("exists", 1)}') ! Xpath 2 " X: 0 ! catch /^exists1$/ ! Xpath 4 " X: 4 ! try ! let result = exists('{EXPR("exists", 2)}') ! Xpath 8 " X: 0 ! catch /^exists2$/ ! Xpath 16 " X: 16 ! catch /.*/ ! Xpath 32 " X: 0 ! Xout "exists2:" v:exception "in" v:throwpoint ! endtry ! catch /.*/ ! Xpath 64 " X: 0 ! Xout "exists1:" v:exception "in" v:throwpoint ! endtry ! ! try ! let file = tempname() ! exec "edit" file ! insert ! begin ! xx ! middle 3 ! xx ! middle 5 skip ! xx ! middle 7 throw ! xx ! end ! . ! normal! gg ! Xpath 128 " X: 128 ! let result = ! \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)') ! Xpath 256 " X: 256 ! let result = ! \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)') ! Xpath 512 " X: 0 ! let result = ! \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)') ! Xpath 1024 " X: 0 ! catch /^searchpair[35]$/ ! Xpath 2048 " X: 0 ! catch /^searchpair4$/ ! Xpath 4096 " X: 4096 ! catch /.*/ ! Xpath 8192 " X: 0 ! Xout "searchpair:" v:exception "in" v:throwpoint ! finally ! bwipeout! ! call delete(file) ! endtry ! ! try ! let file = tempname() ! exec "edit" file ! insert ! subst 1 ! subst 2 ! not ! subst 4 ! subst throw ! subst 6 ! . ! normal! gg ! Xpath 16384 " X: 16384 ! 1,2substitute/subst/\=SUBST("substitute", 6)/ ! try ! Xpath 32768 " X: 32768 ! try ! let v:errmsg = "" ! 3substitute/subst/\=SUBST("substitute", 7)/ ! finally ! if v:errmsg != "" ! " If exceptions are not thrown on errors, fake the error ! " exception in order to get the same execution path. ! throw "faked Vim(substitute)" ! endif ! endtry ! catch /Vim(substitute)/ " Pattern not found ('e' flag missing) ! Xpath 65536 " X: 65536 ! 3substitute/subst/\=SUBST("substitute", 8)/e ! Xpath 131072 " X: 131072 ! endtry ! Xpath 262144 " X: 262144 ! 4,6substitute/subst/\=SUBST("substitute", 9)/ ! Xpath 524288 " X: 0 ! catch /^substitute[678]/ ! Xpath 1048576 " X: 0 ! catch /^substitute9/ ! Xpath 2097152 " X: 2097152 ! finally ! bwipeout! ! call delete(file) ! endtry ! ! try ! Xpath 4194304 " X: 4194304 ! let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '') ! Xpath 8388608 " X: 0 ! catch /substitute()y/ ! Xpath 16777216 " X: 16777216 ! catch /.*/ ! Xpath 33554432 " X: 0 ! Xout "substitute()y:" v:exception "in" v:throwpoint ! endtry ! ! try ! Xpath 67108864 " X: 67108864 ! let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '') ! Xpath 134217728 " X: 134217728 ! catch /substitute()n/ ! Xpath 268435456 " X: 0 ! catch /.*/ ! Xpath 536870912 " X: 0 ! Xout "substitute()n:" v:exception "in" v:throwpoint ! endtry ! ! let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10" ! if taken != expected ! Xpath 1073741824 " X: 0 ! Xout "'taken' is" taken "instead of" expected ! endif ! ! catch /.*/ ! " The Xpath command does not accept 2^31 (negative); add explicitly: ! let Xpath = Xpath + 2147483648 " X: 0 ! Xout v:exception "in" v:throwpoint ! endtry ! ! unlet result var taken expected ! delfunction THROW ! delfunction EXPR ! delfunction SKIP ! delfunction SUBST ! ! Xcheck 224907669 ! ! ! "------------------------------------------------------------------------------- ! " Test 75: Errors in builtin functions. {{{1 ! " ! " On an error in a builtin function called inside a :try/:endtry ! " region, the evaluation of the expression calling that function and ! " the command containing that expression are abandoned. The error can ! " be caught as an exception. ! " ! " A simple :call of the builtin function is a trivial case. If the ! " builtin function is called in the argument list of another function, ! " no further arguments are evaluated, and the other function is not ! " executed. If the builtin function is called from the argument of ! " a :return command, the :return command is not executed. If the ! " builtin function is called from the argument of a :throw command, ! " the :throw command is not executed. The evaluation of the ! " expression calling the builtin function is abandoned. ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! function! F1(arg1) ! Xpath 1 " X: 0 ! endfunction ! ! function! F2(arg1, arg2) ! Xpath 2 " X: 0 ! endfunction ! ! function! G() ! Xpath 4 " X: 0 ! endfunction ! ! function! H() ! Xpath 8 " X: 0 ! endfunction ! ! function! R() ! while 1 ! try ! let caught = 0 ! let v:errmsg = "" ! Xpath 16 " X: 16 ! return append(1, "s") ! catch /E21/ ! let caught = 1 ! catch /.*/ ! Xpath 32 " X: 0 ! finally ! Xpath 64 " X: 64 ! if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' ! Xpath 128 " X: 128 ! endif ! break " discard error for $VIMNOERRTHROW ! endtry ! endwhile ! Xpath 256 " X: 256 ! endfunction ! ! try ! set noma " let append() fail with "E21" ! ! while 1 ! try ! let caught = 0 ! let v:errmsg = "" ! Xpath 512 " X: 512 ! call append(1, "s") ! catch /E21/ ! let caught = 1 ! catch /.*/ ! Xpath 1024 " X: 0 ! finally ! Xpath 2048 " X: 2048 ! if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' ! Xpath 4096 " X: 4096 ! endif ! break " discard error for $VIMNOERRTHROW ! endtry ! endwhile ! ! while 1 ! try ! let caught = 0 ! let v:errmsg = "" ! Xpath 8192 " X: 8192 ! call F1('x' . append(1, "s")) ! catch /E21/ ! let caught = 1 ! catch /.*/ ! Xpath 16384 " X: 0 ! finally ! Xpath 32768 " X: 32768 ! if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' ! Xpath 65536 " X: 65536 ! endif ! break " discard error for $VIMNOERRTHROW ! endtry ! endwhile ! ! while 1 ! try ! let caught = 0 ! let v:errmsg = "" ! Xpath 131072 " X: 131072 ! call F2('x' . append(1, "s"), G()) ! catch /E21/ ! let caught = 1 ! catch /.*/ ! Xpath 262144 " X: 0 ! finally ! Xpath 524288 " X: 524288 ! if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' ! Xpath 1048576 " X: 1048576 ! endif ! break " discard error for $VIMNOERRTHROW ! endtry ! endwhile ! ! call R() ! ! while 1 ! try ! let caught = 0 ! let v:errmsg = "" ! Xpath 2097152 " X: 2097152 ! throw "T" . append(1, "s") ! catch /E21/ ! let caught = 1 ! catch /^T.*/ ! Xpath 4194304 " X: 0 ! catch /.*/ ! Xpath 8388608 " X: 0 ! finally ! Xpath 16777216 " X: 16777216 ! if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' ! Xpath 33554432 " X: 33554432 ! endif ! break " discard error for $VIMNOERRTHROW ! endtry ! endwhile ! ! while 1 ! try ! let caught = 0 ! let v:errmsg = "" ! Xpath 67108864 " X: 67108864 ! let x = "a" ! let x = x . "b" . append(1, "s") . H() ! catch /E21/ ! let caught = 1 ! catch /.*/ ! Xpath 134217728 " X: 0 ! finally ! Xpath 268435456 " X: 268435456 ! if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' ! Xpath 536870912 " X: 536870912 ! endif ! if x == "a" ! Xpath 1073741824 " X: 1073741824 ! endif ! break " discard error for $VIMNOERRTHROW ! endtry ! endwhile ! catch /.*/ ! " The Xpath command does not accept 2^31 (negative); add explicitly: ! let Xpath = Xpath + 2147483648 " X: 0 ! Xout v:exception "in" v:throwpoint ! finally ! set ma& ! endtry ! ! unlet! caught x ! delfunction F1 ! delfunction F2 ! delfunction G ! delfunction H ! delfunction R ! ! Xcheck 2000403408 "------------------------------------------------------------------------------- --- 4912,4919 ---- Xcheck 212514423 ! " Tests 69 to 75 were moved to test_trycatch.vim ! let Xtest = 76 "------------------------------------------------------------------------------- *************** *** 8780,8815 **** Xout "No Crash for vimgrep on BufUnload" Xcheck 0 ! "------------------------------------------------------------------------------- ! " Test 87 using (expr) ? funcref : funcref {{{1 ! " ! " Vim needs to correctly parse the funcref and even when it does ! " not execute the funcref, it needs to consume the trailing () ! "------------------------------------------------------------------------------- ! ! XpathINIT ! ! func Add2(x1, x2) ! return a:x1 + a:x2 ! endfu ! ! func GetStr() ! return "abcdefghijklmnopqrstuvwxyp" ! endfu - echo function('Add2')(2,3) - - Xout 1 ? function('Add2')(1,2) : function('Add2')(2,3) - Xout 0 ? function('Add2')(1,2) : function('Add2')(2,3) - " Make sure, GetStr() still works. - Xout GetStr()[0:10] - - - delfunction GetStr - delfunction Add2 - Xout "Successfully executed funcref Add2" - - Xcheck 0 "------------------------------------------------------------------------------- " Test 88: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1 --- 6519,6527 ---- Xout "No Crash for vimgrep on BufUnload" Xcheck 0 ! " Test 87 was moved to test_vimscript.vim ! let Xtest = 88 "------------------------------------------------------------------------------- " Test 88: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1 *** ../vim-8.1.2245/src/testdir/test_trycatch.vim 2019-11-03 16:16:59.339738638 +0100 --- src/testdir/test_trycatch.vim 2019-11-03 16:09:05.321249714 +0100 *************** *** 0 **** --- 1,1977 ---- + " Test try-catch-finally exception handling + " Most of this was formerly in test49. + + source check.vim + source shared.vim + + "------------------------------------------------------------------------------- + " Test environment {{{1 + "------------------------------------------------------------------------------- + + com! XpathINIT let g:Xpath = '' + com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . + + " Test 25: Executing :finally clauses on normal control flow {{{1 + " + " Control flow in a :try conditional should always fall through to its + " :finally clause. A :finally clause of a :try conditional inside an + " inactive conditional should never be executed. + "------------------------------------------------------------------------------- + + func T25_F() + let loops = 3 + while loops > 0 + Xpath 'a' . loops + if loops >= 2 + try + Xpath 'b' . loops + if loops == 2 + try + Xpath 'c' . loops + finally + Xpath 'd' . loops + endtry + endif + finally + Xpath 'e' . loops + if loops == 2 + try + Xpath 'f' . loops + finally + Xpath 'g' . loops + endtry + endif + endtry + endif + Xpath 'h' . loops + let loops = loops - 1 + endwhile + Xpath 'i' + endfunc + + func T25_G() + if 1 + try + Xpath 'A' + call T25_F() + Xpath 'B' + finally + Xpath 'C' + endtry + else + try + Xpath 'D' + finally + Xpath 'E' + endtry + endif + endfunc + + func Test_finally() + XpathINIT + call T25_G() + call assert_equal('Aa3b3e3h3a2b2c2d2e2f2g2h2a1h1iBC', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 26: Executing :finally clauses after :continue or :break {{{1 + " + " For a :continue or :break dynamically enclosed in a :try/:endtry + " region inside the next surrounding :while/:endwhile, if the + " :continue/:break is before the :finally, the :finally clause is + " executed first. If the :continue/:break is after the :finally, the + " :finally clause is broken (like an :if/:endif region). + "------------------------------------------------------------------------------- + + func T26_F() + try + let loops = 3 + while loops > 0 + try + try + if loops == 2 + Xpath 'a' . loops + let loops = loops - 1 + continue + elseif loops == 1 + Xpath 'b' . loops + break + finish + endif + Xpath 'c' . loops + endtry + finally + Xpath 'd' . loops + endtry + Xpath 'e' . loops + let loops = loops - 1 + endwhile + Xpath 'f' + finally + Xpath 'g' + let loops = 3 + while loops > 0 + try + finally + try + if loops == 2 + Xpath 'h' . loops + let loops = loops - 1 + continue + elseif loops == 1 + Xpath 'i' . loops + break + finish + endif + endtry + Xpath 'j' . loops + endtry + Xpath 'k' . loops + let loops = loops - 1 + endwhile + Xpath 'l' + endtry + Xpath 'm' + endfunc + + func Test_finally_after_continue() + XpathINIT + call T26_F() + call assert_equal('c3d3e3a2d1b1d1fgj3k3h2i1lm', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 32: Remembering the :return value on :finally {{{1 + " + " If a :finally clause is executed due to a :return specifying + " a value, this is the value visible to the caller if not overwritten + " by a new :return in the :finally clause. A :return without a value + " in the :finally clause overwrites with value 0. + "------------------------------------------------------------------------------- + + func T32_F() + try + Xpath 'a' + try + Xpath 'b' + return "ABCD" + Xpath 'c' + finally + Xpath 'd' + endtry + Xpath 'e' + finally + Xpath 'f' + endtry + Xpath 'g' + endfunc + + func T32_G() + try + Xpath 'h' + return 8 + Xpath 'i' + finally + Xpath 'j' + return 16 + strlen(T32_F()) + Xpath 'k' + endtry + Xpath 'l' + endfunc + + func T32_H() + try + Xpath 'm' + return 32 + Xpath 'n' + finally + Xpath 'o' + return + Xpath 'p' + endtry + Xpath 'q' + endfunc + + func T32_I() + try + Xpath 'r' + finally + Xpath 's' + return T32_G() + T32_H() + 64 + Xpath 't' + endtry + Xpath 'u' + endfunc + + func Test_finally_return() + XpathINIT + call assert_equal(84, T32_I()) + call assert_equal('rshjabdfmo', g:Xpath) + endfunc + + "------------------------------------------------------------------------------- + " Test 33: :return under :execute or user command and :finally {{{1 + " + " A :return command may be executed under an ":execute" or from + " a user command. Executing of :finally clauses and passing through + " the return code works also then. + "------------------------------------------------------------------------------- + + func T33_F() + try + RETURN 10 + Xpath 'a' + finally + Xpath 'b' + endtry + Xpath 'c' + endfunc + + func T33_G() + try + RETURN 20 + Xpath 'd' + finally + Xpath 'e' + RETURN 30 + Xpath 'f' + endtry + Xpath 'g' + endfunc + + func T33_H() + try + execute "try | return 40 | finally | return 50 | endtry" + Xpath 'h' + finally + Xpath 'i' + endtry + Xpath 'j' + endfunc + + func T33_I() + try + execute "try | return 60 | finally | return 70 | endtry" + Xpath 'k' + finally + Xpath 'l' + execute "try | return 80 | finally | return 90 | endtry" + Xpath 'm' + endtry + Xpath 'n' + endfunc + + func T33_J() + try + RETURN 100 + Xpath 'o' + finally + Xpath 'p' + return + Xpath 'q' + endtry + Xpath 'r' + endfunc + + func T33_K() + try + execute "try | return 110 | finally | return 120 | endtry" + Xpath 's' + finally + Xpath 't' + execute "try | return 130 | finally | return | endtry" + Xpath 'u' + endtry + Xpath 'v' + endfunc + + func T33_L() + try + return + Xpath 'w' + finally + Xpath 'x' + RETURN 140 + Xpath 'y' + endtry + Xpath 'z' + endfunc + + func T33_M() + try + return + Xpath 'A' + finally + Xpath 'B' + execute "try | return 150 | finally | return 160 | endtry" + Xpath 'C' + endtry + Xpath 'D' + endfunc + + func T33_N() + RETURN 170 + endfunc + + func T33_O() + execute "try | return 180 | finally | return 190 | endtry" + endfunc + + func Test_finally_cmd_return() + command! -nargs=? RETURN + \ try | return | finally | return * 2 | endtry + XpathINIT + call assert_equal(20, T33_F()) + call assert_equal(60, T33_G()) + call assert_equal(50, T33_H()) + call assert_equal(90, T33_I()) + call assert_equal(0, T33_J()) + call assert_equal(0, T33_K()) + call assert_equal(280, T33_L()) + call assert_equal(160, T33_M()) + call assert_equal(340, T33_N()) + call assert_equal(190, T33_O()) + call assert_equal('beilptxB', g:Xpath) + delcommand RETURN + endfunc + + + "------------------------------------------------------------------------------- + " Test 41: Skipped :throw finding next command {{{1 + " + " A :throw in an inactive conditional must not hide a following + " command. + "------------------------------------------------------------------------------- + + func T41_F() + Xpath 'a' + if 0 | throw 'never' | endif | Xpath 'b' + Xpath 'c' + endfunc + + func T41_G() + Xpath 'd' + while 0 | throw 'never' | endwhile | Xpath 'e' + Xpath 'f' + endfunc + + func T41_H() + Xpath 'g' + if 0 | try | throw 'never' | endtry | endif | Xpath 'h' + Xpath 'i' + endfunc + + func Test_throw_inactive_cond() + XpathINIT + try + Xpath 'j' + call T41_F() + Xpath 'k' + catch /.*/ + Xpath 'l' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + Xpath 'm' + call T41_G() + Xpath 'n' + catch /.*/ + Xpath 'o' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + Xpath 'p' + call T41_H() + Xpath 'q' + catch /.*/ + Xpath 'r' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + call assert_equal('jabckmdefnpghiq', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 42: Catching number and string exceptions {{{1 + " + " When a number is thrown, it is converted to a string exception. + " Numbers and strings may be caught by specifying a regular exception + " as argument to the :catch command. + "------------------------------------------------------------------------------- + + + func T42_F() + try + + try + Xpath 'a' + throw 4711 + Xpath 'b' + catch /4711/ + Xpath 'c' + endtry + + try + Xpath 'd' + throw 4711 + Xpath 'e' + catch /^4711$/ + Xpath 'f' + endtry + + try + Xpath 'g' + throw 4711 + Xpath 'h' + catch /\d/ + Xpath 'i' + endtry + + try + Xpath 'j' + throw 4711 + Xpath 'k' + catch /^\d\+$/ + Xpath 'l' + endtry + + try + Xpath 'm' + throw "arrgh" + Xpath 'n' + catch /arrgh/ + Xpath 'o' + endtry + + try + Xpath 'p' + throw "arrgh" + Xpath 'q' + catch /^arrgh$/ + Xpath 'r' + endtry + + try + Xpath 's' + throw "arrgh" + Xpath 't' + catch /\l/ + Xpath 'u' + endtry + + try + Xpath 'v' + throw "arrgh" + Xpath 'w' + catch /^\l\+$/ + Xpath 'x' + endtry + + try + try + Xpath 'y' + throw "ARRGH" + Xpath 'z' + catch /^arrgh$/ + Xpath 'A' + endtry + catch /^\carrgh$/ + Xpath 'B' + endtry + + try + Xpath 'C' + throw "" + Xpath 'D' + catch /^$/ + Xpath 'E' + endtry + + catch /.*/ + Xpath 'F' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + endfunc + + func Test_catch_number_string() + XpathINIT + call T42_F() + call assert_equal('acdfgijlmoprsuvxyBCE', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 43: Selecting the correct :catch clause {{{1 + " + " When an exception is thrown and there are multiple :catch clauses, + " the first matching one is taken. + "------------------------------------------------------------------------------- + + func T43_F() + let loops = 3 + while loops > 0 + try + if loops == 3 + Xpath 'a' . loops + throw "a" + Xpath 'b' . loops + elseif loops == 2 + Xpath 'c' . loops + throw "ab" + Xpath 'd' . loops + elseif loops == 1 + Xpath 'e' . loops + throw "abc" + Xpath 'f' . loops + endif + catch /abc/ + Xpath 'g' . loops + catch /ab/ + Xpath 'h' . loops + catch /.*/ + Xpath 'i' . loops + catch /a/ + Xpath 'j' . loops + endtry + + let loops = loops - 1 + endwhile + Xpath 'k' + endfunc + + func Test_multi_catch() + XpathINIT + call T43_F() + call assert_equal('a3i3c2h2e1g1k', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 44: Missing or empty :catch patterns {{{1 + " + " A missing or empty :catch pattern means the same as /.*/, that is, + " catches everything. To catch only empty exceptions, /^$/ must be + " used. A :catch with missing, empty, or /.*/ argument also works + " when followed by another command separated by a bar on the same + " line. :catch patterns cannot be specified between ||. But other + " pattern separators can be used instead of //. + "------------------------------------------------------------------------------- + + func T44_F() + try + try + Xpath 'a' + throw "" + catch /^$/ + Xpath 'b' + endtry + + try + Xpath 'c' + throw "" + catch /.*/ + Xpath 'd' + endtry + + try + Xpath 'e' + throw "" + catch // + Xpath 'f' + endtry + + try + Xpath 'g' + throw "" + catch + Xpath 'h' + endtry + + try + Xpath 'i' + throw "oops" + catch /^$/ + Xpath 'j' + catch /.*/ + Xpath 'k' + endtry + + try + Xpath 'l' + throw "arrgh" + catch /^$/ + Xpath 'm' + catch // + Xpath 'n' + endtry + + try + Xpath 'o' + throw "brrr" + catch /^$/ + Xpath 'p' + catch + Xpath 'q' + endtry + + try | Xpath 'r' | throw "x" | catch /.*/ | Xpath 's' | endtry + + try | Xpath 't' | throw "y" | catch // | Xpath 'u' | endtry + + while 1 + try + let caught = 0 + let v:errmsg = "" + " Extra try level: if ":catch" without arguments below raises + " a syntax error because it misinterprets the "Xpath" as a pattern, + " let it be caught by the ":catch /.*/" below. + try + try | Xpath 'v' | throw "z" | catch | Xpath 'w' | : + endtry + endtry + catch /.*/ + let caught = 1 + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + finally + if $VIMNOERRTHROW && v:errmsg != "" + call assert_report(v:errmsg) + endif + if caught || $VIMNOERRTHROW && v:errmsg != "" + Xpath 'x' + endif + break " discard error for $VIMNOERRTHROW + endtry + endwhile + + let cologne = 4711 + try + try + Xpath 'y' + throw "throw cologne" + " Next lines catches all and throws 4711: + catch |throw cologne| + Xpath 'z' + endtry + catch /4711/ + Xpath 'A' + endtry + + try + Xpath 'B' + throw "plus" + catch +plus+ + Xpath 'C' + endtry + + Xpath 'D' + catch /.*/ + Xpath 'E' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + endfunc + + func Test_empty_catch() + XpathINIT + call T44_F() + call assert_equal('abcdefghiklnoqrstuvwyABCD', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 45: Catching exceptions from nested :try blocks {{{1 + " + " When :try blocks are nested, an exception is caught by the innermost + " try conditional that has a matching :catch clause. + "------------------------------------------------------------------------------- + + func T45_F() + let loops = 3 + while loops > 0 + try + try + try + try + if loops == 3 + Xpath 'a' . loops + throw "a" + Xpath 'b' . loops + elseif loops == 2 + Xpath 'c' . loops + throw "ab" + Xpath 'd' . loops + elseif loops == 1 + Xpath 'e' . loops + throw "abc" + Xpath 'f' . loops + endif + catch /abc/ + Xpath 'g' . loops + endtry + catch /ab/ + Xpath 'h' . loops + endtry + catch /.*/ + Xpath 'i' . loops + endtry + catch /a/ + Xpath 'j' . loops + endtry + + let loops = loops - 1 + endwhile + Xpath 'k' + endfunc + + func Test_catch_from_nested_try() + XpathINIT + call T45_F() + call assert_equal('a3i3c2h2e1g1k', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 46: Executing :finally after a :throw in nested :try {{{1 + " + " When an exception is thrown from within nested :try blocks, the + " :finally clauses of the non-catching try conditionals should be + " executed before the matching :catch of the next surrounding :try + " gets the control. If this also has a :finally clause, it is + " executed afterwards. + "------------------------------------------------------------------------------- + + func T46_F() + let sum = 0 + + try + Xpath 'a' + try + Xpath 'b' + try + Xpath 'c' + try + Xpath 'd' + throw "ABC" + Xpath 'e' + catch /xyz/ + Xpath 'f' + finally + Xpath 'g' + if sum != 0 + Xpath 'h' + endif + let sum = sum + 1 + endtry + Xpath 'i' + catch /123/ + Xpath 'j' + catch /321/ + Xpath 'k' + finally + Xpath 'l' + if sum != 1 + Xpath 'm' + endif + let sum = sum + 2 + endtry + Xpath 'n' + finally + Xpath 'o' + if sum != 3 + Xpath 'p' + endif + let sum = sum + 4 + endtry + Xpath 'q' + catch /ABC/ + Xpath 'r' + if sum != 7 + Xpath 's' + endif + let sum = sum + 8 + finally + Xpath 't' + if sum != 15 + Xpath 'u' + endif + let sum = sum + 16 + endtry + Xpath 'v' + if sum != 31 + Xpath 'w' + endif + endfunc + + func Test_finally_after_throw() + XpathINIT + call T46_F() + call assert_equal('abcdglortv', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 47: Throwing exceptions from a :catch clause {{{1 + " + " When an exception is thrown from a :catch clause, it should not be + " caught by a :catch of the same :try conditional. After executing + " the :finally clause (if present), surrounding try conditionals + " should be checked for a matching :catch. + "------------------------------------------------------------------------------- + + func T47_F() + Xpath 'a' + try + Xpath 'b' + try + Xpath 'c' + try + Xpath 'd' + throw "x1" + Xpath 'e' + catch /x1/ + Xpath 'f' + try + Xpath 'g' + throw "x2" + Xpath 'h' + catch /x1/ + Xpath 'i' + catch /x2/ + Xpath 'j' + try + Xpath 'k' + throw "x3" + Xpath 'l' + catch /x1/ + Xpath 'm' + catch /x2/ + Xpath 'n' + finally + Xpath 'o' + endtry + Xpath 'p' + catch /x3/ + Xpath 'q' + endtry + Xpath 'r' + catch /x1/ + Xpath 's' + catch /x2/ + Xpath 't' + catch /x3/ + Xpath 'u' + finally + Xpath 'v' + endtry + Xpath 'w' + catch /x1/ + Xpath 'x' + catch /x2/ + Xpath 'y' + catch /x3/ + Xpath 'z' + endtry + Xpath 'A' + catch /.*/ + Xpath 'B' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + Xpath 'C' + endfunc + + func Test_throw_from_catch() + XpathINIT + call T47_F() + call assert_equal('abcdfgjkovzAC', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 48: Throwing exceptions from a :finally clause {{{1 + " + " When an exception is thrown from a :finally clause, it should not be + " caught by a :catch of the same :try conditional. Surrounding try + " conditionals should be checked for a matching :catch. A previously + " thrown exception is discarded. + "------------------------------------------------------------------------------- + + func T48_F() + try + + try + try + Xpath 'a' + catch /x1/ + Xpath 'b' + finally + Xpath 'c' + throw "x1" + Xpath 'd' + endtry + Xpath 'e' + catch /x1/ + Xpath 'f' + endtry + Xpath 'g' + + try + try + Xpath 'h' + throw "x2" + Xpath 'i' + catch /x2/ + Xpath 'j' + catch /x3/ + Xpath 'k' + finally + Xpath 'l' + throw "x3" + Xpath 'm' + endtry + Xpath 'n' + catch /x2/ + Xpath 'o' + catch /x3/ + Xpath 'p' + endtry + Xpath 'q' + + try + try + try + Xpath 'r' + throw "x4" + Xpath 's' + catch /x5/ + Xpath 't' + finally + Xpath 'u' + throw "x5" " discards 'x4' + Xpath 'v' + endtry + Xpath 'w' + catch /x4/ + Xpath 'x' + finally + Xpath 'y' + endtry + Xpath 'z' + catch /x5/ + Xpath 'A' + endtry + Xpath 'B' + + catch /.*/ + Xpath 'C' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + Xpath 'D' + endfunc + + func Test_throw_from_finally() + XpathINIT + call T48_F() + call assert_equal('acfghjlpqruyABD', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 51: Throwing exceptions across :execute and user commands {{{1 + " + " A :throw command may be executed under an ":execute" or from + " a user command. + "------------------------------------------------------------------------------- + + func T51_F() + command! -nargs=? THROW1 throw | throw 1 + command! -nargs=? THROW2 try | throw | endtry | throw 2 + command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw | endtry + command! -nargs=? THROW4 try | throw 4 | finally | throw | endtry + + try + + try + try + Xpath 'a' + THROW1 "A" + catch /A/ + Xpath 'b' + endtry + catch /1/ + Xpath 'c' + endtry + + try + try + Xpath 'd' + THROW2 "B" + catch /B/ + Xpath 'e' + endtry + catch /2/ + Xpath 'f' + endtry + + try + try + Xpath 'g' + THROW3 "C" + catch /C/ + Xpath 'h' + endtry + catch /3/ + Xpath 'i' + endtry + + try + try + Xpath 'j' + THROW4 "D" + catch /D/ + Xpath 'k' + endtry + catch /4/ + Xpath 'l' + endtry + + try + try + Xpath 'm' + execute 'throw "E" | throw 5' + catch /E/ + Xpath 'n' + endtry + catch /5/ + Xpath 'o' + endtry + + try + try + Xpath 'p' + execute 'try | throw "F" | endtry | throw 6' + catch /F/ + Xpath 'q' + endtry + catch /6/ + Xpath 'r' + endtry + + try + try + Xpath 's' + execute'try | throw 7 | catch /7/ | throw "G" | endtry' + catch /G/ + Xpath 't' + endtry + catch /7/ + Xpath 'u' + endtry + + try + try + Xpath 'v' + execute 'try | throw 8 | finally | throw "H" | endtry' + catch /H/ + Xpath 'w' + endtry + catch /8/ + Xpath 'x' + endtry + + catch /.*/ + Xpath 'y' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + Xpath 'z' + + delcommand THROW1 + delcommand THROW2 + delcommand THROW3 + delcommand THROW4 + endfunc + + func Test_throw_across_commands() + XpathINIT + call T51_F() + call assert_equal('abdeghjkmnpqstvwz', g:Xpath) + endfunc + + + + "------------------------------------------------------------------------------- + " Test 69: :throw across :if, :elseif, :while {{{1 + " + " On an :if, :elseif, or :while command, an exception might be thrown + " during evaluation of the expression to test. The exception can be + " caught by the script. + "------------------------------------------------------------------------------- + + func T69_throw(x) + Xpath 'x' + throw a:x + endfunc + + func Test_throw_ifelsewhile() + XpathINIT + + try + try + Xpath 'a' + if 111 == T69_throw("if") + 111 + Xpath 'b' + else + Xpath 'c' + endif + Xpath 'd' + catch /^if$/ + Xpath 'e' + catch /.*/ + Xpath 'f' + call assert_report("if: " . v:exception . " in " . v:throwpoint) + endtry + + try + Xpath 'g' + if v:false + Xpath 'h' + elseif 222 == T69_throw("elseif") + 222 + Xpath 'i' + else + Xpath 'j' + endif + Xpath 'k' + catch /^elseif$/ + Xpath 'l' + catch /.*/ + Xpath 'm' + call assert_report("elseif: " . v:exception . " in " . v:throwpoint) + endtry + + try + Xpath 'n' + while 333 == T69_throw("while") + 333 + Xpath 'o' + break + endwhile + Xpath 'p' + catch /^while$/ + Xpath 'q' + catch /.*/ + Xpath 'r' + call assert_report("while: " .. v:exception .. " in " .. v:throwpoint) + endtry + catch /^0$/ " default return value + Xpath 's' + call assert_report(v:throwpoint) + catch /.*/ + call assert_report(v:exception .. " in " .. v:throwpoint) + Xpath 't' + endtry + + call assert_equal('axegxlnxq', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 70: :throw across :return or :throw {{{1 + " + " On a :return or :throw command, an exception might be thrown during + " evaluation of the expression to return or throw, respectively. The + " exception can be caught by the script. + "------------------------------------------------------------------------------- + + let T70_taken = "" + + func T70_throw(x, n) + let g:T70_taken = g:T70_taken . "T" . a:n + throw a:x + endfunc + + func T70_F(x, y, n) + let g:T70_taken = g:T70_taken . "F" . a:n + return a:x + T70_throw(a:y, a:n) + endfunc + + func T70_G(x, y, n) + let g:T70_taken = g:T70_taken . "G" . a:n + throw a:x . T70_throw(a:y, a:n) + return a:x + endfunc + + func Test_throwreturn() + XpathINIT + + try + try + Xpath 'a' + call T70_F(4711, "return", 1) + Xpath 'b' + catch /^return$/ + Xpath 'c' + catch /.*/ + Xpath 'd' + call assert_report("return: " .. v:exception .. " in " .. v:throwpoint) + endtry + + try + Xpath 'e' + let var = T70_F(4712, "return-var", 2) + Xpath 'f' + catch /^return-var$/ + Xpath 'g' + catch /.*/ + Xpath 'h' + call assert_report("return-var: " . v:exception . " in " . v:throwpoint) + finally + unlet! var + endtry + + try + Xpath 'i' + throw "except1" . T70_throw("throw1", 3) + Xpath 'j' + catch /^except1/ + Xpath 'k' + catch /^throw1$/ + Xpath 'l' + catch /.*/ + Xpath 'm' + call assert_report("throw1: " .. v:exception .. " in " .. v:throwpoint) + endtry + + try + Xpath 'n' + call T70_G("except2", "throw2", 4) + Xpath 'o' + catch /^except2/ + Xpath 'p' + catch /^throw2$/ + Xpath 'q' + catch /.*/ + Xpath 'r' + call assert_report("throw2: " .. v:exception .. " in " .. v:throwpoint) + endtry + + try + Xpath 's' + let var = T70_G("except3", "throw3", 5) + Xpath 't' + catch /^except3/ + Xpath 'u' + catch /^throw3$/ + Xpath 'v' + catch /.*/ + Xpath 'w' + call assert_report("throw3: " .. v:exception .. " in " .. v:throwpoint) + finally + unlet! var + endtry + + call assert_equal('F1T1F2T2T3G4T4G5T5', g:T70_taken) + Xpath 'x' + catch /^0$/ " default return value + Xpath 'y' + call assert_report(v:throwpoint) + catch /.*/ + Xpath 'z' + call assert_report('Caught' .. v:exception .. ' in ' .. v:throwpoint) + endtry + + call assert_equal('acegilnqsvx', g:Xpath) + endfunc + + "------------------------------------------------------------------------------- + " Test 71: :throw across :echo variants and :execute {{{1 + " + " On an :echo, :echon, :echomsg, :echoerr, or :execute command, an + " exception might be thrown during evaluation of the arguments to + " be displayed or executed as a command, respectively. Any following + " arguments are not evaluated, then. The exception can be caught by + " the script. + "------------------------------------------------------------------------------- + + let T71_taken = "" + + func T71_throw(x, n) + let g:T71_taken = g:T71_taken . "T" . a:n + throw a:x + endfunc + + func T71_F(n) + let g:T71_taken = g:T71_taken . "F" . a:n + return "F" . a:n + endfunc + + func Test_throw_echo() + XpathINIT + + try + try + Xpath 'a' + echo 'echo ' . T71_throw("echo-except", 1) . T71_F(1) + Xpath 'b' + catch /^echo-except$/ + Xpath 'c' + catch /.*/ + Xpath 'd' + call assert_report("echo: " .. v:exception .. " in " .. v:throwpoint) + endtry + + try + Xpath 'e' + echon "echon " . T71_throw("echon-except", 2) . T71_F(2) + Xpath 'f' + catch /^echon-except$/ + Xpath 'g' + catch /.*/ + Xpath 'h' + call assert_report('echon: ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + Xpath 'i' + echomsg "echomsg " . T71_throw("echomsg-except", 3) . T71_F(3) + Xpath 'j' + catch /^echomsg-except$/ + Xpath 'k' + catch /.*/ + Xpath 'l' + call assert_report('echomsg: ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + Xpath 'm' + echoerr "echoerr " . T71_throw("echoerr-except", 4) . T71_F(4) + Xpath 'n' + catch /^echoerr-except$/ + Xpath 'o' + catch /Vim/ + Xpath 'p' + catch /echoerr/ + Xpath 'q' + catch /.*/ + Xpath 'r' + call assert_report('echoerr: ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + Xpath 's' + execute "echo 'execute " . T71_throw("execute-except", 5) . T71_F(5) "'" + Xpath 't' + catch /^execute-except$/ + Xpath 'u' + catch /.*/ + Xpath 'v' + call assert_report('execute: ' . v:exception . ' in ' . v:throwpoint) + endtry + + call assert_equal('T1T2T3T4T5', g:T71_taken) + Xpath 'w' + catch /^0$/ " default return value + Xpath 'x' + call assert_report(v:throwpoint) + catch /.*/ + Xpath 'y' + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + call assert_equal('acegikmosuw', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 72: :throw across :let or :unlet {{{1 + " + " On a :let command, an exception might be thrown during evaluation + " of the expression to assign. On an :let or :unlet command, the + " evaluation of the name of the variable to be assigned or list or + " deleted, respectively, may throw an exception. Any following + " arguments are not evaluated, then. The exception can be caught by + " the script. + "------------------------------------------------------------------------------- + + let throwcount = 0 + + func T72_throw(x) + let g:throwcount = g:throwcount + 1 + throw a:x + endfunc + + let T72_addpath = '' + + func T72_addpath(p) + let g:T72_addpath = g:T72_addpath . a:p + endfunc + + func Test_throw_let() + XpathINIT + + try + try + let $VAR = 'old_value' + Xpath 'a' + let $VAR = 'let(' . T72_throw('var') . ')' + Xpath 'b' + catch /^var$/ + Xpath 'c' + finally + call assert_equal('old_value', $VAR) + endtry + + try + let @a = 'old_value' + Xpath 'd' + let @a = 'let(' . T72_throw('reg') . ')' + Xpath 'e' + catch /^reg$/ + try + Xpath 'f' + let @A = 'let(' . T72_throw('REG') . ')' + Xpath 'g' + catch /^REG$/ + Xpath 'h' + endtry + finally + call assert_equal('old_value', @a) + call assert_equal('old_value', @A) + endtry + + try + let saved_gpath = &g:path + let saved_lpath = &l:path + Xpath 'i' + let &path = 'let(' . T72_throw('opt') . ')' + Xpath 'j' + catch /^opt$/ + try + Xpath 'k' + let &g:path = 'let(' . T72_throw('gopt') . ')' + Xpath 'l' + catch /^gopt$/ + try + Xpath 'm' + let &l:path = 'let(' . T72_throw('lopt') . ')' + Xpath 'n' + catch /^lopt$/ + Xpath 'o' + endtry + endtry + finally + call assert_equal(saved_gpath, &g:path) + call assert_equal(saved_lpath, &l:path) + let &g:path = saved_gpath + let &l:path = saved_lpath + endtry + + unlet! var1 var2 var3 + + try + Xpath 'p' + let var1 = 'let(' . T72_throw('var1') . ')' + Xpath 'q' + catch /^var1$/ + Xpath 'r' + finally + call assert_true(!exists('var1')) + endtry + + try + let var2 = 'old_value' + Xpath 's' + let var2 = 'let(' . T72_throw('var2'). ')' + Xpath 't' + catch /^var2$/ + Xpath 'u' + finally + call assert_equal('old_value', var2) + endtry + + try + Xpath 'v' + let var{T72_throw('var3')} = 4711 + Xpath 'w' + catch /^var3$/ + Xpath 'x' + endtry + + try + call T72_addpath('T1') + let var{T72_throw('var4')} var{T72_addpath('T2')} | call T72_addpath('T3') + call T72_addpath('T4') + catch /^var4$/ + call T72_addpath('T5') + endtry + + try + call T72_addpath('T6') + unlet var{T72_throw('var5')} var{T72_addpath('T7')} + \ | call T72_addpath('T8') + call T72_addpath('T9') + catch /^var5$/ + call T72_addpath('T10') + endtry + + call assert_equal('T1T5T6T10', g:T72_addpath) + call assert_equal(11, g:throwcount) + catch /.*/ + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + call assert_equal('acdfhikmoprsuvx', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 73: :throw across :function, :delfunction {{{1 + " + " The :function and :delfunction commands may cause an expression + " specified in braces to be evaluated. During evaluation, an + " exception might be thrown. The exception can be caught by the + " script. + "------------------------------------------------------------------------------- + + let T73_taken = '' + + func T73_throw(x, n) + let g:T73_taken = g:T73_taken . 'T' . a:n + throw a:x + endfunc + + func T73_expr(x, n) + let g:T73_taken = g:T73_taken . 'E' . a:n + if a:n % 2 == 0 + call T73_throw(a:x, a:n) + endif + return 2 - a:n % 2 + endfunc + + func Test_throw_func() + XpathINIT + + try + try + " Define function. + Xpath 'a' + function! F0() + endfunction + Xpath 'b' + function! F{T73_expr('function-def-ok', 1)}() + endfunction + Xpath 'c' + function! F{T73_expr('function-def', 2)}() + endfunction + Xpath 'd' + catch /^function-def-ok$/ + Xpath 'e' + catch /^function-def$/ + Xpath 'f' + catch /.*/ + call assert_report('def: ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + " List function. + Xpath 'g' + function F0 + Xpath 'h' + function F{T73_expr('function-lst-ok', 3)} + Xpath 'i' + function F{T73_expr('function-lst', 4)} + Xpath 'j' + catch /^function-lst-ok$/ + Xpath 'k' + catch /^function-lst$/ + Xpath 'l' + catch /.*/ + call assert_report('lst: ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + " Delete function + Xpath 'm' + delfunction F0 + Xpath 'n' + delfunction F{T73_expr('function-del-ok', 5)} + Xpath 'o' + delfunction F{T73_expr('function-del', 6)} + Xpath 'p' + catch /^function-del-ok$/ + Xpath 'q' + catch /^function-del$/ + Xpath 'r' + catch /.*/ + call assert_report('del: ' . v:exception . ' in ' . v:throwpoint) + endtry + call assert_equal('E1E2T2E3E4T4E5E6T6', g:T73_taken) + catch /.*/ + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + call assert_equal('abcfghilmnor', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 74: :throw across builtin functions and commands {{{1 + " + " Some functions like exists(), searchpair() take expression + " arguments, other functions or commands like substitute() or + " :substitute cause an expression (specified in the regular + " expression) to be evaluated. During evaluation an exception + " might be thrown. The exception can be caught by the script. + "------------------------------------------------------------------------------- + + let T74_taken = "" + + func T74_throw(x, n) + let g:T74_taken = g:T74_taken . "T" . a:n + throw a:x + endfunc + + func T74_expr(x, n) + let g:T74_taken = g:T74_taken . "E" . a:n + call T74_throw(a:x . a:n, a:n) + return "EXPR" + endfunc + + func T74_skip(x, n) + let g:T74_taken = g:T74_taken . "S" . a:n . "(" . line(".") + let theline = getline(".") + if theline =~ "skip" + let g:T74_taken = g:T74_taken . "s)" + return 1 + elseif theline =~ "throw" + let g:T74_taken = g:T74_taken . "t)" + call T74_throw(a:x . a:n, a:n) + else + let g:T74_taken = g:T74_taken . ")" + return 0 + endif + endfunc + + func T74_subst(x, n) + let g:T74_taken = g:T74_taken . "U" . a:n . "(" . line(".") + let theline = getline(".") + if theline =~ "not" " T74_subst() should not be called for this line + let g:T74_taken = g:T74_taken . "n)" + call T74_throw(a:x . a:n, a:n) + elseif theline =~ "throw" + let g:T74_taken = g:T74_taken . "t)" + call T74_throw(a:x . a:n, a:n) + else + let g:T74_taken = g:T74_taken . ")" + return "replaced" + endif + endfunc + + func Test_throw_builtin_func() + XpathINIT + + try + try + Xpath 'a' + let result = exists('*{T74_expr("exists", 1)}') + Xpath 'b' + catch /^exists1$/ + Xpath 'c' + try + let result = exists('{T74_expr("exists", 2)}') + Xpath 'd' + catch /^exists2$/ + Xpath 'e' + catch /.*/ + call assert_report('exists2: ' . v:exception . ' in ' . v:throwpoint) + endtry + catch /.*/ + call assert_report('exists1: ' . v:exception . ' in ' . v:throwpoint) + endtry + + try + let file = tempname() + exec "edit" file + call append(0, [ + \ 'begin', + \ 'xx', + \ 'middle 3', + \ 'xx', + \ 'middle 5 skip', + \ 'xx', + \ 'middle 7 throw', + \ 'xx', + \ 'end']) + normal! gg + Xpath 'f' + let result = searchpair("begin", "middle", "end", '', + \ 'T74_skip("searchpair", 3)') + Xpath 'g' + let result = searchpair("begin", "middle", "end", '', + \ 'T74_skip("searchpair", 4)') + Xpath 'h' + let result = searchpair("begin", "middle", "end", '', + \ 'T74_skip("searchpair", 5)') + Xpath 'i' + catch /^searchpair[35]$/ + Xpath 'j' + catch /^searchpair4$/ + Xpath 'k' + catch /.*/ + call assert_report('searchpair: ' . v:exception . ' in ' . v:throwpoint) + finally + bwipeout! + call delete(file) + endtry + + try + let file = tempname() + exec "edit" file + call append(0, [ + \ 'subst 1', + \ 'subst 2', + \ 'not', + \ 'subst 4', + \ 'subst throw', + \ 'subst 6']) + normal! gg + Xpath 'l' + 1,2substitute/subst/\=T74_subst("substitute", 6)/ + try + Xpath 'm' + try + let v:errmsg = "" + 3substitute/subst/\=T74_subst("substitute", 7)/ + finally + if v:errmsg != "" + " If exceptions are not thrown on errors, fake the error + " exception in order to get the same execution path. + throw "faked Vim(substitute)" + endif + endtry + catch /Vim(substitute)/ " Pattern not found ('e' flag missing) + Xpath 'n' + 3substitute/subst/\=T74_subst("substitute", 8)/e + Xpath 'o' + endtry + Xpath 'p' + 4,6substitute/subst/\=T74_subst("substitute", 9)/ + Xpath 'q' + catch /^substitute[678]/ + Xpath 'r' + catch /^substitute9/ + Xpath 's' + finally + bwipeout! + call delete(file) + endtry + + try + Xpath 't' + let var = substitute("sub", "sub", '\=T74_throw("substitute()y", 10)', '') + Xpath 'u' + catch /substitute()y/ + Xpath 'v' + catch /.*/ + call assert_report('substitute()y: ' . v:exception . ' in ' + \ . v:throwpoint) + endtry + + try + Xpath 'w' + let var = substitute("not", "sub", '\=T74_throw("substitute()n", 11)', '') + Xpath 'x' + catch /substitute()n/ + Xpath 'y' + catch /.*/ + call assert_report('substitute()n: ' . v:exception . ' in ' + \ . v:throwpoint) + endtry + + call assert_equal('E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10', + \ g:T74_taken) + + catch /.*/ + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + + call assert_equal('acefgklmnopstvwx', g:Xpath) + endfunc + + + "------------------------------------------------------------------------------- + " Test 75: Errors in builtin functions. {{{1 + " + " On an error in a builtin function called inside a :try/:endtry + " region, the evaluation of the expression calling that function and + " the command containing that expression are abandoned. The error can + " be caught as an exception. + " + " A simple :call of the builtin function is a trivial case. If the + " builtin function is called in the argument list of another function, + " no further arguments are evaluated, and the other function is not + " executed. If the builtin function is called from the argument of + " a :return command, the :return command is not executed. If the + " builtin function is called from the argument of a :throw command, + " the :throw command is not executed. The evaluation of the + " expression calling the builtin function is abandoned. + "------------------------------------------------------------------------------- + + func T75_F1(arg1) + Xpath 'a' + endfunc + + func T75_F2(arg1, arg2) + Xpath 'b' + endfunc + + func T75_G() + Xpath 'c' + endfunc + + func T75_H() + Xpath 'd' + endfunc + + func T75_R() + while 1 + try + let caught = 0 + let v:errmsg = "" + Xpath 'e' + return append(1, "s") + catch /E21/ + let caught = 1 + catch /.*/ + Xpath 'f' + finally + Xpath 'g' + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' + Xpath 'h' + endif + break " discard error for $VIMNOERRTHROW + endtry + endwhile + Xpath 'i' + endfunc + + func Test_builtin_func_error() + XpathINIT + + try + set noma " let append() fail with "E21" + + while 1 + try + let caught = 0 + let v:errmsg = "" + Xpath 'j' + call append(1, "s") + catch /E21/ + let caught = 1 + catch /.*/ + Xpath 'k' + finally + Xpath 'l' + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' + Xpath 'm' + endif + break " discard error for $VIMNOERRTHROW + endtry + endwhile + + while 1 + try + let caught = 0 + let v:errmsg = "" + Xpath 'n' + call T75_F1('x' . append(1, "s")) + catch /E21/ + let caught = 1 + catch /.*/ + Xpath 'o' + finally + Xpath 'p' + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' + Xpath 'q' + endif + break " discard error for $VIMNOERRTHROW + endtry + endwhile + + while 1 + try + let caught = 0 + let v:errmsg = "" + Xpath 'r' + call T75_F2('x' . append(1, "s"), T75_G()) + catch /E21/ + let caught = 1 + catch /.*/ + Xpath 's' + finally + Xpath 't' + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' + Xpath 'u' + endif + break " discard error for $VIMNOERRTHROW + endtry + endwhile + + call T75_R() + + while 1 + try + let caught = 0 + let v:errmsg = "" + Xpath 'v' + throw "T" . append(1, "s") + catch /E21/ + let caught = 1 + catch /^T.*/ + Xpath 'w' + catch /.*/ + Xpath 'x' + finally + Xpath 'y' + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' + Xpath 'z' + endif + break " discard error for $VIMNOERRTHROW + endtry + endwhile + + while 1 + try + let caught = 0 + let v:errmsg = "" + Xpath 'A' + let x = "a" + let x = x . "b" . append(1, "s") . T75_H() + catch /E21/ + let caught = 1 + catch /.*/ + Xpath 'B' + finally + Xpath 'C' + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' + Xpath 'D' + endif + call assert_equal('a', x) + break " discard error for $VIMNOERRTHROW + endtry + endwhile + catch /.*/ + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + finally + set ma& + endtry + + call assert_equal('jlmnpqrtueghivyzACD', g:Xpath) + endfunc + + " Modelines {{{1 + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker + "------------------------------------------------------------------------------- *** ../vim-8.1.2245/src/testdir/test_vimscript.vim 2019-09-08 18:58:39.557952948 +0200 --- src/testdir/test_vimscript.vim 2019-11-03 16:09:05.321249714 +0100 *************** *** 923,928 **** --- 923,1122 ---- endfunc "------------------------------------------------------------------------------- + " Test 16: Double :else or :elseif after :else {{{1 + " + " Multiple :elses or an :elseif after an :else are forbidden. + "------------------------------------------------------------------------------- + + func T16_F() abort + if 0 + Xpath 'a' + else + Xpath 'b' + else " aborts function + Xpath 'c' + endif + Xpath 'd' + endfunc + + func T16_G() abort + if 0 + Xpath 'a' + else + Xpath 'b' + elseif 1 " aborts function + Xpath 'c' + else + Xpath 'd' + endif + Xpath 'e' + endfunc + + func T16_H() abort + if 0 + Xpath 'a' + elseif 0 + Xpath 'b' + else + Xpath 'c' + else " aborts function + Xpath 'd' + endif + Xpath 'e' + endfunc + + func T16_I() abort + if 0 + Xpath 'a' + elseif 0 + Xpath 'b' + else + Xpath 'c' + elseif 1 " aborts function + Xpath 'd' + else + Xpath 'e' + endif + Xpath 'f' + endfunc + + func Test_Multi_Else() + XpathINIT + try + call T16_F() + catch /E583:/ + Xpath 'e' + endtry + call assert_equal('be', g:Xpath) + + XpathINIT + try + call T16_G() + catch /E584:/ + Xpath 'f' + endtry + call assert_equal('bf', g:Xpath) + + XpathINIT + try + call T16_H() + catch /E583:/ + Xpath 'f' + endtry + call assert_equal('cf', g:Xpath) + + XpathINIT + try + call T16_I() + catch /E584:/ + Xpath 'g' + endtry + call assert_equal('cg', g:Xpath) + endfunc + + "------------------------------------------------------------------------------- + " Test 17: Nesting of unmatched :if or :endif inside a :while {{{1 + " + " The :while/:endwhile takes precedence in nesting over an unclosed + " :if or an unopened :endif. + "------------------------------------------------------------------------------- + + " While loops inside a function are continued on error. + func T17_F() + let loops = 3 + while loops > 0 + let loops -= 1 + Xpath 'a' . loops + if (loops == 1) + Xpath 'b' . loops + continue + elseif (loops == 0) + Xpath 'c' . loops + break + elseif 1 + Xpath 'd' . loops + " endif missing! + endwhile " :endwhile after :if 1 + Xpath 'e' + endfunc + + func T17_G() + let loops = 2 + while loops > 0 + let loops -= 1 + Xpath 'a' . loops + if 0 + Xpath 'b' . loops + " endif missing + endwhile " :endwhile after :if 0 + endfunc + + func T17_H() + let loops = 2 + while loops > 0 + let loops -= 1 + Xpath 'a' . loops + " if missing! + endif " :endif without :if in while + Xpath 'b' . loops + endwhile + endfunc + + " Error continuation outside a function is at the outermost :endwhile or :endif. + XpathINIT + let v:errmsg = '' + let loops = 2 + while loops > 0 + let loops -= 1 + Xpath 'a' . loops + if 0 + Xpath 'b' . loops + " endif missing! Following :endwhile fails. + endwhile | Xpath 'c' + Xpath 'd' + call assert_match('E171:', v:errmsg) + call assert_equal('a1d', g:Xpath) + + func Test_unmatched_if_in_while() + XpathINIT + call assert_fails('call T17_F()', 'E171:') + call assert_equal('a2d2a1b1a0c0e', g:Xpath) + + XpathINIT + call assert_fails('call T17_G()', 'E171:') + call assert_equal('a1a0', g:Xpath) + + XpathINIT + call assert_fails('call T17_H()', 'E580:') + call assert_equal('a1b1a0b0', g:Xpath) + endfunc + + "------------------------------------------------------------------------------- + "------------------------------------------------------------------------------- + "------------------------------------------------------------------------------- + " Test 87 using (expr) ? funcref : funcref {{{1 + " + " Vim needs to correctly parse the funcref and even when it does + " not execute the funcref, it needs to consume the trailing () + "------------------------------------------------------------------------------- + + func Add2(x1, x2) + return a:x1 + a:x2 + endfu + + func GetStr() + return "abcdefghijklmnopqrstuvwxyp" + endfu + + func Test_funcref_with_condexpr() + call assert_equal(5, function('Add2')(2,3)) + + call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3)) + call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3)) + " Make sure, GetStr() still works. + call assert_equal('abcdefghijk', GetStr()[0:10]) + endfunc + " Test 90: Recognizing {} in variable name. {{{1 "------------------------------------------------------------------------------- *************** *** 1752,1756 **** "------------------------------------------------------------------------------- " Modelines {{{1 ! " vim: ts=8 sw=4 tw=80 fdm=marker "------------------------------------------------------------------------------- --- 1946,1950 ---- "------------------------------------------------------------------------------- " Modelines {{{1 ! " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker "------------------------------------------------------------------------------- *** ../vim-8.1.2245/src/version.c 2019-11-03 15:46:40.618538702 +0100 --- src/version.c 2019-11-03 16:16:41.571799874 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 2246, /**/ -- How To Keep A Healthy Level Of Insanity: 5. Put decaf in the coffee maker for 3 weeks. Once everyone has gotten over their caffeine addictions, switch to espresso. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///