diff options
Diffstat (limited to 'src/nvim/testdir/test_vimscript.vim')
-rw-r--r-- | src/nvim/testdir/test_vimscript.vim | 7284 |
1 files changed, 0 insertions, 7284 deletions
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim deleted file mode 100644 index b0c4baf7c2..0000000000 --- a/src/nvim/testdir/test_vimscript.vim +++ /dev/null @@ -1,7284 +0,0 @@ -" Test various aspects of the Vim script language. -" Most of this was formerly in test49.vim (developed by Servatius Brandt -" <Servatius.Brandt@fujitsu-siemens.com>) - -source check.vim -source shared.vim -source script_util.vim - -"------------------------------------------------------------------------------- -" Test environment {{{1 -"------------------------------------------------------------------------------- - -" Append a message to the "messages" file -func Xout(text) - split messages - $put =a:text - wq -endfunc - -com! -nargs=1 Xout call Xout(<args>) - -" Create a new instance of Vim and run the commands in 'test' and then 'verify' -" The commands in 'test' are expected to store the test results in the Xtest.out -" file. If the test passes successfully, then Xtest.out should be empty. -func RunInNewVim(test, verify) - let init =<< trim END - set cpo-=C " support line-continuation in sourced script - source script_util.vim - XpathINIT - XloopINIT - END - let cleanup =<< trim END - call writefile(v:errors, 'Xtest.out') - qall - END - call writefile(init, 'Xtest.vim') - call writefile(a:test, 'Xtest.vim', 'a') - call writefile(a:verify, 'Xverify.vim') - call writefile(cleanup, 'Xverify.vim', 'a') - call RunVim([], [], "-S Xtest.vim -S Xverify.vim") - call assert_equal([], readfile('Xtest.out')) - call delete('Xtest.out') - call delete('Xtest.vim') - call delete('Xverify.vim') -endfunc - -"------------------------------------------------------------------------------- -" Test 1: :endwhile in function {{{1 -" -" Detect if a broken loop is (incorrectly) reactivated by the -" :endwhile. Use a :return to prevent an endless loop, and make -" this test first to get a meaningful result on an error before other -" tests will hang. -"------------------------------------------------------------------------------- - -func T1_F() - Xpath 'a' - let first = 1 - while 1 - Xpath 'b' - if first - Xpath 'c' - let first = 0 - break - else - Xpath 'd' - return - endif - endwhile -endfunc - -func T1_G() - Xpath 'h' - let first = 1 - while 1 - Xpath 'i' - if first - Xpath 'j' - let first = 0 - break - else - Xpath 'k' - return - endif - if 1 " unmatched :if - endwhile -endfunc - -func Test_endwhile_function() - XpathINIT - call T1_F() - Xpath 'F' - - try - call T1_G() - catch - " Catch missing :endif - call assert_true(v:exception =~ 'E171') - Xpath 'x' - endtry - Xpath 'G' - - call assert_equal('abcFhijxG', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 2: :endwhile in script {{{1 -" -" Detect if a broken loop is (incorrectly) reactivated by the -" :endwhile. Use a :finish to prevent an endless loop, and place -" this test before others that might hang to get a meaningful result -" on an error. -" -" This test executes the bodies of the functions T1_F and T1_G from -" the previous test as script files (:return replaced by :finish). -"------------------------------------------------------------------------------- - -func Test_endwhile_script() - XpathINIT - ExecAsScript T1_F - Xpath 'F' - call DeleteTheScript() - - try - ExecAsScript T1_G - catch - " Catch missing :endif - call assert_true(v:exception =~ 'E171') - Xpath 'x' - endtry - Xpath 'G' - call DeleteTheScript() - - call assert_equal('abcFhijxG', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 3: :if, :elseif, :while, :continue, :break {{{1 -"------------------------------------------------------------------------------- - -func Test_if_while() - XpathINIT - if 1 - Xpath 'a' - let loops = 3 - while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) - if loops <= 0 - let break_err = 1 - let loops = -1 - else - Xpath 'b' . loops - endif - if (loops == 2) - while loops == 2 " dummy loop - Xpath 'c' . loops - let loops = loops - 1 - continue " stop dummy loop - Xpath 'd' . loops - endwhile - continue " continue main loop - Xpath 'e' . loops - elseif (loops == 1) - let p = 1 - while p " dummy loop - Xpath 'f' . loops - let p = 0 - break " break dummy loop - Xpath 'g' . loops - endwhile - Xpath 'h' . loops - unlet p - break " break main loop - Xpath 'i' . loops - endif - if (loops > 0) - Xpath 'j' . loops - endif - while loops == 3 " dummy loop - let loops = loops - 1 - endwhile " end dummy loop - endwhile " end main loop - Xpath 'k' - else - Xpath 'l' - endif - Xpath 'm' - if exists("break_err") - Xpath 'm' - unlet break_err - endif - - unlet loops - - call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath) -endfunc - -" Check double quote after skipped "elseif" does not give error E15 -func Test_skipped_elseif() - if "foo" ==? "foo" - let result = "first" - elseif "foo" ==? "foo" - let result = "second" - endif - call assert_equal('first', result) -endfunc - -"------------------------------------------------------------------------------- -" Test 4: :return {{{1 -"------------------------------------------------------------------------------- - -func T4_F() - if 1 - Xpath 'a' - let loops = 3 - while loops > 0 " 3: 2: 1: - Xpath 'b' . loops - if (loops == 2) - Xpath 'c' . loops - return - Xpath 'd' . loops - endif - Xpath 'e' . loops - let loops = loops - 1 - endwhile - Xpath 'f' - else - Xpath 'g' - endif -endfunc - -func Test_return() - XpathINIT - call T4_F() - Xpath '4' - - call assert_equal('ab3e3b2c24', g:Xpath) -endfunc - - -"------------------------------------------------------------------------------- -" Test 5: :finish {{{1 -" -" This test executes the body of the function T4_F from the previous -" test as a script file (:return replaced by :finish). -"------------------------------------------------------------------------------- - -func Test_finish() - XpathINIT - ExecAsScript T4_F - Xpath '5' - call DeleteTheScript() - - call assert_equal('ab3e3b2c25', g:Xpath) -endfunc - - - -"------------------------------------------------------------------------------- -" Test 6: Defining functions in :while loops {{{1 -" -" Functions can be defined inside other functions. An inner function -" gets defined when the outer function is executed. Functions may -" also be defined inside while loops. Expressions in braces for -" defining the function name are allowed. -" -" The functions are defined when sourcing the script, only the -" resulting path is checked in the test function. -"------------------------------------------------------------------------------- - -XpathINIT - -" The command CALL collects the argument of all its invocations in "calls" -" when used from a function (that is, when the global variable "calls" needs -" the "g:" prefix). This is to check that the function code is skipped when -" the function is defined. For inner functions, do so only if the outer -" function is not being executed. -" -let calls = "" -com! -nargs=1 CALL - \ if !exists("calls") && !exists("outer") | - \ let g:calls = g:calls . <args> | - \ endif - -let i = 0 -while i < 3 - let i = i + 1 - if i == 1 - Xpath 'a' - function! F1(arg) - CALL a:arg - let outer = 1 - - let j = 0 - while j < 1 - Xpath 'b' - let j = j + 1 - function! G1(arg) - CALL a:arg - endfunction - Xpath 'c' - endwhile - endfunction - Xpath 'd' - - continue - endif - - Xpath 'e' . i - function! F{i}(i, arg) - CALL a:arg - let outer = 1 - - if a:i == 3 - Xpath 'f' - endif - let k = 0 - while k < 3 - Xpath 'g' . k - let k = k + 1 - function! G{a:i}{k}(arg) - CALL a:arg - endfunction - Xpath 'h' . k - endwhile - endfunction - Xpath 'i' - -endwhile - -if exists("*G1") - Xpath 'j' -endif -if exists("*F1") - call F1("F1") - if exists("*G1") - call G1("G1") - endif -endif - -if exists("G21") || exists("G22") || exists("G23") - Xpath 'k' -endif -if exists("*F2") - call F2(2, "F2") - if exists("*G21") - call G21("G21") - endif - if exists("*G22") - call G22("G22") - endif - if exists("*G23") - call G23("G23") - endif -endif - -if exists("G31") || exists("G32") || exists("G33") - Xpath 'l' -endif -if exists("*F3") - call F3(3, "F3") - if exists("*G31") - call G31("G31") - endif - if exists("*G32") - call G32("G32") - endif - if exists("*G33") - call G33("G33") - endif -endif - -Xpath 'm' - -let g:test6_result = g:Xpath -let g:test6_calls = calls - -unlet calls -delfunction F1 -delfunction G1 -delfunction F2 -delfunction G21 -delfunction G22 -delfunction G23 -delfunction G31 -delfunction G32 -delfunction G33 - -func Test_defining_functions() - call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result) - call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls) -endfunc - -"------------------------------------------------------------------------------- -" Test 7: Continuing on errors outside functions {{{1 -" -" On an error outside a function, the script processing continues -" at the line following the outermost :endif or :endwhile. When not -" inside an :if or :while, the script processing continues at the next -" line. -"------------------------------------------------------------------------------- - -XpathINIT - -if 1 - Xpath 'a' - while 1 - Xpath 'b' - asdf - Xpath 'c' - break - endwhile | Xpath 'd' - Xpath 'e' -endif | Xpath 'f' -Xpath 'g' - -while 1 - Xpath 'h' - if 1 - Xpath 'i' - asdf - Xpath 'j' - endif | Xpath 'k' - Xpath 'l' - break -endwhile | Xpath 'm' -Xpath 'n' - -asdf -Xpath 'o' - -asdf | Xpath 'p' -Xpath 'q' - -let g:test7_result = g:Xpath - -func Test_error_in_script() - call assert_equal('abghinoq', g:test7_result) -endfunc - -"------------------------------------------------------------------------------- -" Test 8: Aborting and continuing on errors inside functions {{{1 -" -" On an error inside a function without the "abort" attribute, the -" script processing continues at the next line (unless the error was -" in a :return command). On an error inside a function with the -" "abort" attribute, the function is aborted and the script processing -" continues after the function call; the value -1 is returned then. -"------------------------------------------------------------------------------- - -XpathINIT - -func T8_F() - if 1 - Xpath 'a' - while 1 - Xpath 'b' - asdf - Xpath 'c' - asdf | Xpath 'd' - Xpath 'e' - break - endwhile - Xpath 'f' - endif | Xpath 'g' - Xpath 'h' - - while 1 - Xpath 'i' - if 1 - Xpath 'j' - asdf - Xpath 'k' - asdf | Xpath 'l' - Xpath 'm' - endif - Xpath 'n' - break - endwhile | Xpath 'o' - Xpath 'p' - - return novar " returns (default return value 0) - Xpath 'q' - return 1 " not reached -endfunc - -func T8_G() abort - if 1 - Xpath 'r' - while 1 - Xpath 's' - asdf " returns -1 - Xpath 't' - break - endwhile - Xpath 'v' - endif | Xpath 'w' - Xpath 'x' - - return -4 " not reached -endfunc - -func T8_H() abort - while 1 - Xpath 'A' - if 1 - Xpath 'B' - asdf " returns -1 - Xpath 'C' - endif - Xpath 'D' - break - endwhile | Xpath 'E' - Xpath 'F' - - return -4 " not reached -endfunc - -" Aborted functions (T8_G and T8_H) return -1. -let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H() -Xpath 'X' -let g:test8_result = g:Xpath - -func Test_error_in_function() - call assert_equal(13, g:test8_sum) - call assert_equal('abcefghijkmnoprsABX', g:test8_result) - - delfunction T8_F - delfunction T8_G - delfunction T8_H -endfunc - - -"------------------------------------------------------------------------------- -" Test 9: Continuing after aborted functions {{{1 -" -" When a function with the "abort" attribute is aborted due to an -" error, the next function back in the call hierarchy without an -" "abort" attribute continues; the value -1 is returned then. -"------------------------------------------------------------------------------- - -XpathINIT - -func F() abort - Xpath 'a' - let result = G() " not aborted - Xpath 'b' - if result != 2 - Xpath 'c' - endif - return 1 -endfunc - -func G() " no abort attribute - Xpath 'd' - if H() != -1 " aborted - Xpath 'e' - endif - Xpath 'f' - return 2 -endfunc - -func H() abort - Xpath 'g' - call I() " aborted - Xpath 'h' - return 4 -endfunc - -func I() abort - Xpath 'i' - asdf " error - Xpath 'j' - return 8 -endfunc - -if F() != 1 - Xpath 'k' -endif - -let g:test9_result = g:Xpath - -delfunction F -delfunction G -delfunction H -delfunction I - -func Test_func_abort() - call assert_equal('adgifb', g:test9_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 10: :if, :elseif, :while argument parsing {{{1 -" -" A '"' or '|' in an argument expression must not be mixed up with -" a comment or a next command after a bar. Parsing errors should -" be recognized. -"------------------------------------------------------------------------------- - -XpathINIT - -func 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 = v:errmsg->escape('"') - Xout "Unexpected message:" v:errmsg - endif - endif - return match -endfunc - -if 1 || strlen("\"") | Xpath 'a' - Xpath 'b' -endif -Xpath 'c' - -if 0 -elseif 1 || strlen("\"") | Xpath 'd' - Xpath 'e' -endif -Xpath 'f' - -while 1 || strlen("\"") | Xpath 'g' - Xpath 'h' - break -endwhile -Xpath 'i' - -let v:errmsg = "" -if 1 ||| strlen("\"") | Xpath 'j' - Xpath 'k' -endif -Xpath 'l' -if !MSG('E15', "Invalid expression") - Xpath 'm' -endif - -let v:errmsg = "" -if 0 -elseif 1 ||| strlen("\"") | Xpath 'n' - Xpath 'o' -endif -Xpath 'p' -if !MSG('E15', "Invalid expression") - Xpath 'q' -endif - -let v:errmsg = "" -while 1 ||| strlen("\"") | Xpath 'r' - Xpath 's' - break -endwhile -Xpath 't' -if !MSG('E15', "Invalid expression") - Xpath 'u' -endif - -let g:test10_result = g:Xpath -delfunction MSG - -func Test_expr_parsing() - call assert_equal('abcdefghilpt', g:test10_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 11: :if, :elseif, :while argument evaluation after abort {{{1 -" -" When code is skipped over due to an error, the boolean argument to -" an :if, :elseif, or :while must not be evaluated. -"------------------------------------------------------------------------------- - -XpathINIT - -let calls = 0 - -func P(num) - let g:calls = g:calls + a:num " side effect on call - return 0 -endfunc - -if 1 - Xpath 'a' - asdf " error - Xpath 'b' - if P(1) " should not be called - Xpath 'c' - elseif !P(2) " should not be called - Xpath 'd' - else - Xpath 'e' - endif - Xpath 'f' - while P(4) " should not be called - Xpath 'g' - endwhile - Xpath 'h' -endif -Xpath 'x' - -let g:test11_calls = calls -let g:test11_result = g:Xpath - -unlet calls -delfunction P - -func Test_arg_abort() - call assert_equal(0, g:test11_calls) - call assert_equal('ax', g:test11_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 12: Expressions in braces in skipped code {{{1 -" -" In code skipped over due to an error or inactive conditional, -" an expression in braces as part of a variable or function name -" should not be evaluated. -"------------------------------------------------------------------------------- - -XpathINIT - -func NULL() - Xpath 'a' - return 0 -endfunc - -func ZERO() - Xpath 'b' - return 0 -endfunc - -func! F0() - Xpath 'c' -endfunc - -func! F1(arg) - Xpath 'e' -endfunc - -let V0 = 1 - -Xpath 'f' -echo 0 ? F{NULL() + V{ZERO()}}() : 1 - -Xpath 'g' -if 0 - Xpath 'h' - call F{NULL() + V{ZERO()}}() -endif - -Xpath 'i' -if 1 - asdf " error - Xpath 'j' - call F1(F{NULL() + V{ZERO()}}()) -endif - -Xpath 'k' -if 1 - asdf " error - Xpath 'l' - call F{NULL() + V{ZERO()}}() -endif - -let g:test12_result = g:Xpath - -func Test_braces_skipped() - call assert_equal('fgik', g:test12_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 13: Failure in argument evaluation for :while {{{1 -" -" A failure in the expression evaluation for the condition of a :while -" causes the whole :while loop until the matching :endwhile being -" ignored. Continuation is at the next following line. -"------------------------------------------------------------------------------- - -XpathINIT - -Xpath 'a' -while asdf - Xpath 'b' - while 1 - Xpath 'c' - break - endwhile - Xpath 'd' - break -endwhile -Xpath 'e' - -while asdf | Xpath 'f' | endwhile | Xpath 'g' -Xpath 'h' -let g:test13_result = g:Xpath - -func Test_while_fail() - call assert_equal('aeh', g:test13_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 14: Failure in argument evaluation for :if {{{1 -" -" A failure in the expression evaluation for the condition of an :if -" does not cause the corresponding :else or :endif being matched to -" a previous :if/:elseif. Neither of both branches of the failed :if -" are executed. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() - Xpath 'a' - let x = 0 - if x " false - Xpath 'b' - elseif !x " always true - Xpath 'c' - let x = 1 - if g:boolvar " possibly undefined - Xpath 'd' - else - Xpath 'e' - endif - Xpath 'f' - elseif x " never executed - Xpath 'g' - endif - Xpath 'h' -endfunction - -let boolvar = 1 -call F() -Xpath '-' - -unlet boolvar -call F() -let g:test14_result = g:Xpath - -delfunction F - -func Test_if_fail() - call assert_equal('acdfh-acfh', g:test14_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 15: Failure in argument evaluation for :if (bar) {{{1 -" -" Like previous test, except that the failing :if ... | ... | :endif -" is in a single line. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() - Xpath 'a' - let x = 0 - if x " false - Xpath 'b' - elseif !x " always true - Xpath 'c' - let x = 1 - if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif - Xpath 'f' - elseif x " never executed - Xpath 'g' - endif - Xpath 'h' -endfunction - -let boolvar = 1 -call F() -Xpath '-' - -unlet boolvar -call F() -let g:test15_result = g:Xpath - -delfunction F - -func Test_if_bar_fail() - call assert_equal('acdfh-acfh', g:test15_result) -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 18: Interrupt (Ctrl-C pressed) {{{1 -" -" On an interrupt, the script processing is terminated immediately. -"------------------------------------------------------------------------------- - -func Test_interrupt_while_if() - let test =<< trim [CODE] - try - if 1 - Xpath 'a' - while 1 - Xpath 'b' - if 1 - Xpath 'c' - call interrupt() - call assert_report('should not get here') - break - finish - endif | call assert_report('should not get here') - call assert_report('should not get here') - endwhile | call assert_report('should not get here') - call assert_report('should not get here') - endif | call assert_report('should not get here') - call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'd' - endtry | Xpath 'e' - Xpath 'f' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdef', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_interrupt_try() - let test =<< trim [CODE] - try - try - Xpath 'a' - call interrupt() - call assert_report('should not get here') - endtry | call assert_report('should not get here') - call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'b' - endtry | Xpath 'c' - Xpath 'd' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcd', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_interrupt_func_while_if() - let test =<< trim [CODE] - func F() - if 1 - Xpath 'a' - while 1 - Xpath 'b' - if 1 - Xpath 'c' - call interrupt() - call assert_report('should not get here') - break - return - endif | call assert_report('should not get here') - call assert_report('should not get here') - endwhile | call assert_report('should not get here') - call assert_report('should not get here') - endif | call assert_report('should not get here') - call assert_report('should not get here') - endfunc - - Xpath 'd' - try - call F() | call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'e' - endtry | Xpath 'f' - Xpath 'g' - [CODE] - let verify =<< trim [CODE] - call assert_equal('dabcefg', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_interrupt_func_try() - let test =<< trim [CODE] - func G() - try - Xpath 'a' - call interrupt() - call assert_report('should not get here') - endtry | call assert_report('should not get here') - call assert_report('should not get here') - endfunc - - Xpath 'b' - try - call G() | call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'c' - endtry | Xpath 'd' - Xpath 'e' - [CODE] - let verify =<< trim [CODE] - call assert_equal('bacde', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 19: Aborting on errors inside :try/:endtry {{{1 -" -" An error in a command dynamically enclosed in a :try/:endtry region -" aborts script processing immediately. It does not matter whether -" the failing command is outside or inside a function and whether a -" function has an "abort" attribute. -"------------------------------------------------------------------------------- - -func Test_try_error_abort_1() - let test =<< trim [CODE] - func F() abort - Xpath 'a' - asdf - call assert_report('should not get here') - endfunc - - try - Xpath 'b' - call F() - call assert_report('should not get here') - endtry | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('ba', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_try_error_abort_2() - let test =<< trim [CODE] - func G() - Xpath 'a' - asdf - call assert_report('should not get here') - endfunc - - try - Xpath 'b' - call G() - call assert_report('should not get here') - endtry | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('ba', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_try_error_abort_3() - let test =<< trim [CODE] - try - Xpath 'a' - asdf - call assert_report('should not get here') - endtry | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('a', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_try_error_abort_4() - let test =<< trim [CODE] - if 1 - try - Xpath 'a' - asdf - call assert_report('should not get here') - endtry | call assert_report('should not get here') - endif | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('a', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_try_error_abort_5() - let test =<< trim [CODE] - let p = 1 - while p - let p = 0 - try - Xpath 'a' - asdf - call assert_report('should not get here') - endtry | call assert_report('should not get here') - endwhile | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('a', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_try_error_abort_6() - let test =<< trim [CODE] - let p = 1 - Xpath 'a' - while p - Xpath 'b' - let p = 0 - try - Xpath 'c' - endwhile | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 20: Aborting on errors after :try/:endtry {{{1 -" -" When an error occurs after the last active :try/:endtry region has -" been left, termination behavior is as if no :try/:endtry has been -" seen. -"------------------------------------------------------------------------------- - -func Test_error_after_try_1() - let test =<< trim [CODE] - let p = 1 - while p - let p = 0 - Xpath 'a' - try - Xpath 'b' - endtry - asdf - call assert_report('should not get here') - endwhile | call assert_report('should not get here') - Xpath 'c' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_error_after_try_2() - let test =<< trim [CODE] - while 1 - try - Xpath 'a' - break - call assert_report('should not get here') - endtry - endwhile - Xpath 'b' - asdf - Xpath 'c' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_error_after_try_3() - let test =<< trim [CODE] - while 1 - try - Xpath 'a' - break - call assert_report('should not get here') - finally - Xpath 'b' - endtry - endwhile - Xpath 'c' - asdf - Xpath 'd' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcd', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_error_after_try_4() - let test =<< trim [CODE] - while 1 - try - Xpath 'a' - finally - Xpath 'b' - break - call assert_report('should not get here') - endtry - endwhile - Xpath 'c' - asdf - Xpath 'd' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcd', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_error_after_try_5() - let test =<< trim [CODE] - let p = 1 - while p - let p = 0 - try - Xpath 'a' - continue - call assert_report('should not get here') - endtry - endwhile - Xpath 'b' - asdf - Xpath 'c' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_error_after_try_6() - let test =<< trim [CODE] - let p = 1 - while p - let p = 0 - try - Xpath 'a' - continue - call assert_report('should not get here') - finally - Xpath 'b' - endtry - endwhile - Xpath 'c' - asdf - Xpath 'd' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcd', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_error_after_try_7() - let test =<< trim [CODE] - let p = 1 - while p - let p = 0 - try - Xpath 'a' - finally - Xpath 'b' - continue - call assert_report('should not get here') - endtry - endwhile - Xpath 'c' - asdf - Xpath 'd' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcd', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 21: :finally for :try after :continue/:break/:return/:finish {{{1 -" -" If a :try conditional stays inactive due to a preceding :continue, -" :break, :return, or :finish, its :finally clause should not be -" executed. -"------------------------------------------------------------------------------- - -func Test_finally_after_loop_ctrl_statement() - let test =<< trim [CODE] - func F() - let loops = 2 - while loops > 0 - XloopNEXT - let loops = loops - 1 - try - if loops == 1 - Xloop 'a' - continue - call assert_report('should not get here') - elseif loops == 0 - Xloop 'b' - break - call assert_report('should not get here') - endif - - try " inactive - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - finally - Xloop 'c' - endtry - call assert_report('should not get here') - endwhile - - try - Xpath 'd' - return - call assert_report('should not get here') - try " inactive - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - finally - Xpath 'e' - endtry - call assert_report('should not get here') - endfunc - - try - Xpath 'f' - call F() - Xpath 'g' - finish - call assert_report('should not get here') - try " inactive - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - finally - Xpath 'h' - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('fa2c2b3c3degh', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 22: :finally for a :try after an error/interrupt/:throw {{{1 -" -" If a :try conditional stays inactive due to a preceding error or -" interrupt or :throw, its :finally clause should not be executed. -"------------------------------------------------------------------------------- - -func Test_finally_after_error_in_func() - let test =<< trim [CODE] - func Error() - try - Xpath 'b' - asdf " aborting error, triggering error exception - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endfunc - - Xpath 'a' - call Error() - call assert_report('should not get here') - - if 1 " not active due to error - try " not active since :if inactive - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - endif - - try " not active due to error - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('ab', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_finally_after_interrupt() - let test =<< trim [CODE] - func Interrupt() - try - Xpath 'a' - call interrupt() " triggering interrupt exception - call assert_report('should not get here') - endtry - endfunc - - Xpath 'b' - try - call Interrupt() - catch /^Vim:Interrupt$/ - Xpath 'c' - finish - endtry - call assert_report('should not get here') - - if 1 " not active due to interrupt - try " not active since :if inactive - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - endif - - try " not active due to interrupt - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('bac', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_finally_after_throw() - let test =<< trim [CODE] - func Throw() - Xpath 'a' - throw 'xyz' - endfunc - - Xpath 'b' - call Throw() - call assert_report('should not get here') - - if 1 " not active due to :throw - try " not active since :if inactive - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - endif - - try " not active due to :throw - call assert_report('should not get here') - finally - call assert_report('should not get here') - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('ba', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 23: :catch clauses for a :try after a :throw {{{1 -" -" If a :try conditional stays inactive due to a preceding :throw, -" none of its :catch clauses should be executed. -"------------------------------------------------------------------------------- - -func Test_catch_after_throw() - let test =<< trim [CODE] - try - Xpath 'a' - throw "xyz" - call assert_report('should not get here') - - if 1 " not active due to :throw - try " not active since :if inactive - call assert_report('should not get here') - catch /xyz/ - call assert_report('should not get here') - endtry - endif - catch /xyz/ - Xpath 'b' - endtry - - Xpath 'c' - throw "abc" - call assert_report('should not get here') - - try " not active due to :throw - call assert_report('should not get here') - catch /abc/ - call assert_report('should not get here') - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 24: :endtry for a :try after a :throw {{{1 -" -" If a :try conditional stays inactive due to a preceding :throw, -" its :endtry should not rethrow the exception to the next surrounding -" active :try conditional. -"------------------------------------------------------------------------------- - -func Test_endtry_after_throw() - let test =<< trim [CODE] - try " try 1 - try " try 2 - Xpath 'a' - throw "xyz" " makes try 2 inactive - call assert_report('should not get here') - - try " try 3 - call assert_report('should not get here') - endtry " no rethrow to try 1 - catch /xyz/ " should catch although try 2 inactive - Xpath 'b' - endtry - catch /xyz/ " try 1 active, but exception already caught - call assert_report('should not get here') - endtry - Xpath 'c' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 27: Executing :finally clauses after :return {{{1 -" -" For a :return command dynamically enclosed in a :try/:endtry region, -" :finally clauses are executed and the called function is ended. -"------------------------------------------------------------------------------- - -func T27_F() - try - Xpath 'a' - try - Xpath 'b' - return - call assert_report('should not get here') - finally - Xpath 'c' - endtry - Xpath 'd' - finally - Xpath 'e' - endtry - call assert_report('should not get here') -endfunc - -func T27_G() - try - Xpath 'f' - return - call assert_report('should not get here') - finally - Xpath 'g' - call T27_F() - Xpath 'h' - endtry - call assert_report('should not get here') -endfunc - -func T27_H() - try - Xpath 'i' - call T27_G() - Xpath 'j' - finally - Xpath 'k' - return - call assert_report('should not get here') - endtry - call assert_report('should not get here') -endfunction - -func Test_finally_after_return() - XpathINIT - try - Xpath 'l' - call T27_H() - Xpath 'm' - finally - Xpath 'n' - endtry - call assert_equal('lifgabcehjkmn', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 28: Executing :finally clauses after :finish {{{1 -" -" For a :finish command dynamically enclosed in a :try/:endtry region, -" :finally clauses are executed and the sourced file is finished. -" -" This test executes the bodies of the functions F, G, and H from the -" previous test as script files (:return replaced by :finish). -"------------------------------------------------------------------------------- - -func Test_finally_after_finish() - XpathINIT - - let scriptF = MakeScript("T27_F") - let scriptG = MakeScript("T27_G", scriptF) - let scriptH = MakeScript("T27_H", scriptG) - - try - Xpath 'A' - exec "source" scriptH - Xpath 'B' - finally - Xpath 'C' - endtry - Xpath 'D' - call assert_equal('AifgabcehjkBCD', g:Xpath) - call delete(scriptF) - call delete(scriptG) - call delete(scriptH) -endfunc - -"------------------------------------------------------------------------------- -" Test 29: Executing :finally clauses on errors {{{1 -" -" After an error in a command dynamically enclosed in a :try/:endtry -" region, :finally clauses are executed and the script processing is -" terminated. -"------------------------------------------------------------------------------- - -func Test_finally_after_error_1() - let test =<< trim [CODE] - func F() - while 1 - try - Xpath 'a' - while 1 - try - Xpath 'b' - asdf " error - call assert_report('should not get here') - finally - Xpath 'c' - endtry | call assert_report('should not get here') - call assert_report('should not get here') - break - endwhile - call assert_report('should not get here') - finally - Xpath 'd' - endtry | call assert_report('should not get here') - call assert_report('should not get here') - break - endwhile - call assert_report('should not get here') - endfunc - - while 1 - try - Xpath 'e' - while 1 - call F() - call assert_report('should not get here') - break - endwhile | call assert_report('should not get here') - call assert_report('should not get here') - finally - Xpath 'f' - endtry | call assert_report('should not get here') - endwhile | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('eabcdf', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_finally_after_error_2() - let test =<< trim [CODE] - func G() abort - if 1 - try - Xpath 'a' - asdf " error - call assert_report('should not get here') - finally - Xpath 'b' - endtry | Xpath 'c' - endif | Xpath 'd' - call assert_report('should not get here') - endfunc - - if 1 - try - Xpath 'e' - call G() - call assert_report('should not get here') - finally - Xpath 'f' - endtry | call assert_report('should not get here') - endif | call assert_report('should not get here') - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('eabf', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 30: Executing :finally clauses on interrupt {{{1 -" -" After an interrupt in a command dynamically enclosed in -" a :try/:endtry region, :finally clauses are executed and the -" script processing is terminated. -"------------------------------------------------------------------------------- - -func Test_finally_on_interrupt() - let test =<< trim [CODE] - func F() - try - Xloop 'a' - call interrupt() - call assert_report('should not get here') - finally - Xloop 'b' - endtry - call assert_report('should not get here') - endfunc - - try - try - Xpath 'c' - try - Xpath 'd' - call interrupt() - call assert_report('should not get here') - finally - Xpath 'e' - try - Xpath 'f' - try - Xpath 'g' - finally - Xpath 'h' - try - Xpath 'i' - call interrupt() - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - finally - Xpath 'j' - try - Xpath 'k' - call F() - call assert_report('should not get here') - finally - Xpath 'l' - try - Xpath 'm' - XloopNEXT - ExecAsScript F - call assert_report('should not get here') - finally - Xpath 'n' - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'o' - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('cdefghijka1b1lma2b2no', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 31: Executing :finally clauses after :throw {{{1 -" -" After a :throw dynamically enclosed in a :try/:endtry region, -" :finally clauses are executed and the script processing is -" terminated. -"------------------------------------------------------------------------------- - -func Test_finally_after_throw_2() - let test =<< trim [CODE] - func F() - try - Xloop 'a' - throw "exception" - call assert_report('should not get here') - finally - Xloop 'b' - endtry - call assert_report('should not get here') - endfunc - - try - Xpath 'c' - try - Xpath 'd' - throw "exception" - call assert_report('should not get here') - finally - Xpath 'e' - try - Xpath 'f' - try - Xpath 'g' - finally - Xpath 'h' - try - Xpath 'i' - throw "exception" - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - finally - Xpath 'j' - try - Xpath 'k' - call F() - call assert_report('should not get here') - finally - Xpath 'l' - try - Xpath 'm' - XloopNEXT - ExecAsScript F - call assert_report('should not get here') - finally - Xpath 'n' - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('cdefghijka1b1lma2b2n', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 34: :finally reason discarded by :continue {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :continue in the finally clause. -"------------------------------------------------------------------------------- - -func Test_finally_after_continue() - let test =<< trim [CODE] - func C(jump) - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - call interrupt() - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - continue " discards jump that caused the :finally - call assert_report('should not get here') - endtry - call assert_report('should not get here') - elseif loop == 2 - Xloop 'a' - endif - endwhile - endfunc - - call C("continue") - Xpath 'b' - call C("break") - Xpath 'c' - call C("return") - Xpath 'd' - let g:jump = "finish" - ExecAsScript C - unlet g:jump - Xpath 'e' - try - call C("error") - Xpath 'f' - finally - Xpath 'g' - try - call C("interrupt") - Xpath 'h' - finally - Xpath 'i' - call C("throw") - Xpath 'j' - endtry - endtry - Xpath 'k' - [CODE] - let verify =<< trim [CODE] - call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 35: :finally reason discarded by :break {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :break in the finally clause. -"------------------------------------------------------------------------------- - -func Test_finally_discard_by_break() - let test =<< trim [CODE] - func B(jump) - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - call interrupt() - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - break " discards jump that caused the :finally - call assert_report('should not get here') - endtry - elseif loop == 2 - call assert_report('should not get here') - endif - endwhile - Xloop 'a' - endfunc - - call B("continue") - Xpath 'b' - call B("break") - Xpath 'c' - call B("return") - Xpath 'd' - let g:jump = "finish" - ExecAsScript B - unlet g:jump - Xpath 'e' - try - call B("error") - Xpath 'f' - finally - Xpath 'g' - try - call B("interrupt") - Xpath 'h' - finally - Xpath 'i' - call B("throw") - Xpath 'j' - endtry - endtry - Xpath 'k' - [CODE] - let verify =<< trim [CODE] - call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 36: :finally reason discarded by :return {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :return in the finally clause. -"------------------------------------------------------------------------------- - -func Test_finally_discard_by_return() - let test =<< trim [CODE] - func R(jump, retval) abort - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - call interrupt() - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - return a:retval " discards jump that caused the :finally - call assert_report('should not get here') - endtry - elseif loop == 2 - call assert_report('should not get here') - endif - endwhile - call assert_report('should not get here') - endfunc - - let sum = -R("continue", -8) - Xpath 'a' - let sum = sum - R("break", -16) - Xpath 'b' - let sum = sum - R("return", -32) - Xpath 'c' - try - let sum = sum - R("error", -64) - Xpath 'd' - finally - Xpath 'e' - try - let sum = sum - R("interrupt", -128) - Xpath 'f' - finally - Xpath 'g' - let sum = sum - R("throw", -256) - Xpath 'h' - endtry - endtry - Xpath 'i' - - let expected = 8 + 16 + 32 + 64 + 128 + 256 - call assert_equal(sum, expected) - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefghi', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 37: :finally reason discarded by :finish {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :finish in the finally clause. -"------------------------------------------------------------------------------- - -func Test_finally_discard_by_finish() - let test =<< trim [CODE] - func F(jump) " not executed as function, transformed to a script - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "finish" - finish - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - call interrupt() - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - finish " discards jump that caused the :finally - call assert_report('should not get here') - endtry - elseif loop == 2 - call assert_report('should not get here') - endif - endwhile - call assert_report('should not get here') - endfunc - - let scriptF = MakeScript("F") - delfunction F - - let g:jump = "continue" - exec "source" scriptF - Xpath 'a' - let g:jump = "break" - exec "source" scriptF - Xpath 'b' - let g:jump = "finish" - exec "source" scriptF - Xpath 'c' - try - let g:jump = "error" - exec "source" scriptF - Xpath 'd' - finally - Xpath 'e' - try - let g:jump = "interrupt" - exec "source" scriptF - Xpath 'f' - finally - Xpath 'g' - try - let g:jump = "throw" - exec "source" scriptF - Xpath 'h' - finally - Xpath 'i' - endtry - endtry - endtry - unlet g:jump - call delete(scriptF) - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefghi', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 38: :finally reason discarded by an error {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by an error in the finally clause. -"------------------------------------------------------------------------------- - -func Test_finally_discard_by_error() - let test =<< trim [CODE] - func E(jump) - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - call interrupt() - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - asdf " error; discards jump that caused the :finally - endtry - elseif loop == 2 - call assert_report('should not get here') - endif - endwhile - call assert_report('should not get here') - endfunc - - try - Xpath 'a' - call E("continue") - call assert_report('should not get here') - finally - try - Xpath 'b' - call E("break") - call assert_report('should not get here') - finally - try - Xpath 'c' - call E("return") - call assert_report('should not get here') - finally - try - Xpath 'd' - let g:jump = "finish" - ExecAsScript E - call assert_report('should not get here') - finally - unlet g:jump - try - Xpath 'e' - call E("error") - call assert_report('should not get here') - finally - try - Xpath 'f' - call E("interrupt") - call assert_report('should not get here') - finally - try - Xpath 'g' - call E("throw") - call assert_report('should not get here') - finally - Xpath 'h' - delfunction E - endtry - endtry - endtry - endtry - endtry - endtry - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefgh', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 39: :finally reason discarded by an interrupt {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by an interrupt in the finally clause. -"------------------------------------------------------------------------------- - -func Test_finally_discarded_by_interrupt() - let test =<< trim [CODE] - func I(jump) - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - call interrupt() - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - call interrupt() - let dummy = 0 - endtry - elseif loop == 2 - call assert_report('should not get here') - endif - endwhile - call assert_report('should not get here') - endfunc - - try - try - Xpath 'a' - call I("continue") - call assert_report('should not get here') - finally - try - Xpath 'b' - call I("break") - call assert_report('should not get here') - finally - try - Xpath 'c' - call I("return") - call assert_report('should not get here') - finally - try - Xpath 'd' - let g:jump = "finish" - ExecAsScript I - call assert_report('should not get here') - finally - unlet g:jump - try - Xpath 'e' - call I("error") - call assert_report('should not get here') - finally - try - Xpath 'f' - call I("interrupt") - call assert_report('should not get here') - finally - try - Xpath 'g' - call I("throw") - call assert_report('should not get here') - finally - Xpath 'h' - delfunction I - endtry - endtry - endtry - endtry - endtry - endtry - endtry - call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'A' - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefghA', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 40: :finally reason discarded by :throw {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :throw in the finally clause. -"------------------------------------------------------------------------------- - -func Test_finally_discard_by_throw() - let test =<< trim [CODE] - func T(jump) - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - call interrupt() - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - throw "xyz" " discards jump that caused the :finally - endtry - elseif loop == 2 - call assert_report('should not get here') - endif - endwhile - call assert_report('should not get here') - endfunc - - try - Xpath 'a' - call T("continue") - call assert_report('should not get here') - finally - try - Xpath 'b' - call T("break") - call assert_report('should not get here') - finally - try - Xpath 'c' - call T("return") - call assert_report('should not get here') - finally - try - Xpath 'd' - let g:jump = "finish" - ExecAsScript T - call assert_report('should not get here') - finally - unlet g:jump - try - Xpath 'e' - call T("error") - call assert_report('should not get here') - finally - try - Xpath 'f' - call T("interrupt") - call assert_report('should not get here') - finally - try - Xpath 'g' - call T("throw") - call assert_report('should not get here') - finally - Xpath 'h' - delfunction T - endtry - endtry - endtry - endtry - endtry - endtry - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefgh', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 49: Throwing exceptions across functions {{{1 -" -" When an exception is thrown but not caught inside a function, the -" caller is checked for a matching :catch clause. -"------------------------------------------------------------------------------- - -func T49_C() - try - Xpath 'a' - throw "arrgh" - call assert_report('should not get here') - catch /arrgh/ - Xpath 'b' - endtry - Xpath 'c' -endfunc - -func T49_T1() - XloopNEXT - try - Xloop 'd' - throw "arrgh" - call assert_report('should not get here') - finally - Xloop 'e' - endtry - Xloop 'f' -endfunc - -func T49_T2() - try - Xpath 'g' - call T49_T1() - call assert_report('should not get here') - finally - Xpath 'h' - endtry - call assert_report('should not get here') -endfunc - -func Test_throw_exception_across_funcs() - XpathINIT - XloopINIT - try - Xpath 'i' - call T49_C() " throw and catch - Xpath 'j' - catch /.*/ - call assert_report('should not get here') - endtry - - try - Xpath 'k' - call T49_T1() " throw, one level - call assert_report('should not get here') - catch /arrgh/ - Xpath 'l' - catch /.*/ - call assert_report('should not get here') - endtry - - try - Xpath 'm' - call T49_T2() " throw, two levels - call assert_report('should not get here') - catch /arrgh/ - Xpath 'n' - catch /.*/ - call assert_report('should not get here') - endtry - Xpath 'o' - - call assert_equal('iabcjkd2e2lmgd3e3hno', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 50: Throwing exceptions across script files {{{1 -" -" When an exception is thrown but not caught inside a script file, -" the sourcing script or function is checked for a matching :catch -" clause. -" -" This test executes the bodies of the functions C, T1, and T2 from -" the previous test as script files (:return replaced by :finish). -"------------------------------------------------------------------------------- - -func T50_F() - try - Xpath 'A' - exec "source" g:scriptC - Xpath 'B' - catch /.*/ - call assert_report('should not get here') - endtry - - try - Xpath 'C' - exec "source" g:scriptT1 - call assert_report('should not get here') - catch /arrgh/ - Xpath 'D' - catch /.*/ - call assert_report('should not get here') - endtry -endfunc - -func Test_throw_across_script() - XpathINIT - XloopINIT - let g:scriptC = MakeScript("T49_C") - let g:scriptT1 = MakeScript("T49_T1") - let scriptT2 = MakeScript("T49_T2", g:scriptT1) - - try - Xpath 'E' - call T50_F() - Xpath 'F' - exec "source" scriptT2 - call assert_report('should not get here') - catch /arrgh/ - Xpath 'G' - catch /.*/ - call assert_report('should not get here') - endtry - Xpath 'H' - call assert_equal('EAabcBCd2e2DFgd3e3hGH', g:Xpath) - - call delete(g:scriptC) - call delete(g:scriptT1) - call delete(scriptT2) - unlet g:scriptC g:scriptT1 scriptT2 -endfunc - -"------------------------------------------------------------------------------- -" Test 52: Uncaught exceptions {{{1 -" -" When an exception is thrown but not caught, an error message is -" displayed when the script is terminated. In case of an interrupt -" or error exception, the normal interrupt or error message(s) are -" displayed. -"------------------------------------------------------------------------------- - -func Test_uncaught_exception_1() - CheckEnglish - - let test =<< trim [CODE] - Xpath 'a' - throw "arrgh" - call assert_report('should not get here')` - [CODE] - let verify =<< trim [CODE] - call assert_equal('E605: Exception not caught: arrgh', v:errmsg) - call assert_equal('a', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_uncaught_exception_2() - CheckEnglish - - let test =<< trim [CODE] - try - Xpath 'a' - throw "oops" - call assert_report('should not get here')` - catch /arrgh/ - call assert_report('should not get here')` - endtry - call assert_report('should not get here')` - [CODE] - let verify =<< trim [CODE] - call assert_equal('E605: Exception not caught: oops', v:errmsg) - call assert_equal('a', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_uncaught_exception_3() - CheckEnglish - - let test =<< trim [CODE] - func T() - Xpath 'c' - throw "brrr" - call assert_report('should not get here')` - endfunc - - try - Xpath 'a' - throw "arrgh" - call assert_report('should not get here')` - catch /.*/ - Xpath 'b' - call T() - call assert_report('should not get here')` - endtry - call assert_report('should not get here')` - [CODE] - let verify =<< trim [CODE] - call assert_equal('E605: Exception not caught: brrr', v:errmsg) - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_uncaught_exception_4() - CheckEnglish - - let test =<< trim [CODE] - try - Xpath 'a' - throw "arrgh" - call assert_report('should not get here')` - finally - Xpath 'b' - throw "brrr" - call assert_report('should not get here')` - endtry - call assert_report('should not get here')` - [CODE] - let verify =<< trim [CODE] - call assert_equal('E605: Exception not caught: brrr', v:errmsg) - call assert_equal('ab', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_uncaught_exception_5() - CheckEnglish - - " Need to catch and handle interrupt, otherwise the test will wait for the - " user to press <Enter> to continue - let test =<< trim [CODE] - try - try - Xpath 'a' - call interrupt() - call assert_report('should not get here') - endtry - call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'b' - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('ab', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_uncaught_exception_6() - CheckEnglish - - let test =<< trim [CODE] - try - Xpath 'a' - let x = novar " error E121; exception: E121 - catch /E15:/ " should not catch - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('a', g:Xpath) - call assert_equal('E121: Undefined variable: novar', v:errmsg) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_uncaught_exception_7() - CheckEnglish - - let test =<< trim [CODE] - try - Xpath 'a' - " error E108/E488; exception: E488 - unlet novar # - catch /E108:/ " should not catch - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('a', g:Xpath) - call assert_equal('E488: Trailing characters: #', v:errmsg) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 53: Nesting errors: :endif/:else/:elseif {{{1 -" -" For nesting errors of :if conditionals the correct error messages -" should be given. -"------------------------------------------------------------------------------- - -func Test_nested_if_else_errors() - CheckEnglish - - " :endif without :if - let code =<< trim END - endif - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') - - " :endif without :if - let code =<< trim END - while 1 - endif - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') - - " :endif without :if - let code =<< trim END - try - finally - endif - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') - - " :endif without :if - let code =<< trim END - try - endif - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') - - " :endif without :if - let code =<< trim END - try - throw "a" - catch /a/ - endif - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') - - " :else without :if - let code =<< trim END - else - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') - - " :else without :if - let code =<< trim END - while 1 - else - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') - - " :else without :if - let code =<< trim END - try - finally - else - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') - - " :else without :if - let code =<< trim END - try - else - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') - - " :else without :if - let code =<< trim END - try - throw "a" - catch /a/ - else - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') - - " :elseif without :if - let code =<< trim END - elseif 1 - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') - - " :elseif without :if - let code =<< trim END - while 1 - elseif 1 - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') - - " :elseif without :if - let code =<< trim END - try - finally - elseif 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') - - " :elseif without :if - let code =<< trim END - try - elseif 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') - - " :elseif without :if - let code =<< trim END - try - throw "a" - catch /a/ - elseif 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') - - " multiple :else - let code =<< trim END - if 1 - else - else - endif - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(else):E583: multiple :else') - - " :elseif after :else - let code =<< trim END - if 1 - else - elseif 1 - endif - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(elseif):E584: :elseif after :else') - - call delete('Xtest') -endfunc - -"------------------------------------------------------------------------------- -" Test 54: Nesting errors: :while/:endwhile {{{1 -" -" For nesting errors of :while conditionals the correct error messages -" should be given. -" -" This test reuses the function MESSAGES() from the previous test. -" This functions checks the messages in g:msgfile. -"------------------------------------------------------------------------------- - -func Test_nested_while_error() - CheckEnglish - - " :endwhile without :while - let code =<< trim END - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') - - " :endwhile without :while - let code =<< trim END - if 1 - endwhile - endif - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') - - " Missing :endif - let code =<< trim END - while 1 - if 1 - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif') - - " :endwhile without :while - let code =<< trim END - try - finally - endwhile - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') - - " Missing :endtry - let code =<< trim END - while 1 - try - finally - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry') - - " Missing :endtry - let code =<< trim END - while 1 - if 1 - try - finally - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry') - - " Missing :endif - let code =<< trim END - while 1 - try - finally - if 1 - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif') - - " :endwhile without :while - let code =<< trim END - try - endwhile - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') - - " :endwhile without :while - let code =<< trim END - while 1 - try - endwhile - endtry - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') - - " :endwhile without :while - let code =<< trim END - try - throw "a" - catch /a/ - endwhile - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') - - " :endwhile without :while - let code =<< trim END - while 1 - try - throw "a" - catch /a/ - endwhile - endtry - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') - - call delete('Xtest') -endfunc - -"------------------------------------------------------------------------------- -" Test 55: Nesting errors: :continue/:break {{{1 -" -" For nesting errors of :continue and :break commands the correct -" error messages should be given. -" -" This test reuses the function MESSAGES() from the previous test. -" This functions checks the messages in g:msgfile. -"------------------------------------------------------------------------------- - -func Test_nested_cont_break_error() - CheckEnglish - - " :continue without :while - let code =<< trim END - continue - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') - - " :continue without :while - let code =<< trim END - if 1 - continue - endif - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') - - " :continue without :while - let code =<< trim END - try - finally - continue - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') - - " :continue without :while - let code =<< trim END - try - continue - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') - - " :continue without :while - let code =<< trim END - try - throw "a" - catch /a/ - continue - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') - - " :break without :while - let code =<< trim END - break - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') - - " :break without :while - let code =<< trim END - if 1 - break - endif - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') - - " :break without :while - let code =<< trim END - try - finally - break - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') - - " :break without :while - let code =<< trim END - try - break - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') - - " :break without :while - let code =<< trim END - try - throw "a" - catch /a/ - break - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') - - call delete('Xtest') -endfunc - -"------------------------------------------------------------------------------- -" Test 56: Nesting errors: :endtry {{{1 -" -" For nesting errors of :try conditionals the correct error messages -" should be given. -" -" This test reuses the function MESSAGES() from the previous test. -" This functions checks the messages in g:msgfile. -"------------------------------------------------------------------------------- - -func Test_nested_endtry_error() - CheckEnglish - - " :endtry without :try - let code =<< trim END - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try') - - " :endtry without :try - let code =<< trim END - if 1 - endtry - endif - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try') - - " :endtry without :try - let code =<< trim END - while 1 - endtry - endwhile - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try') - - " Missing :endif - let code =<< trim END - try - if 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif') - - " Missing :endwhile - let code =<< trim END - try - while 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile') - - " Missing :endif - let code =<< trim END - try - finally - if 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif') - - " Missing :endwhile - let code =<< trim END - try - finally - while 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile') - - " Missing :endif - let code =<< trim END - try - throw "a" - catch /a/ - if 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif') - - " Missing :endwhile - let code =<< trim END - try - throw "a" - catch /a/ - while 1 - endtry - END - call writefile(code, 'Xtest') - call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile') - - call delete('Xtest') -endfunc - -"------------------------------------------------------------------------------- -" Test 57: v:exception and v:throwpoint for user exceptions {{{1 -" -" v:exception evaluates to the value of the exception that was caught -" most recently and is not finished. (A caught exception is finished -" when the next ":catch", ":finally", or ":endtry" is reached.) -" v:throwpoint evaluates to the script/function name and line number -" where that exception has been thrown. -"------------------------------------------------------------------------------- - -func Test_user_exception_info() - CheckEnglish - - XpathINIT - XloopINIT - - func FuncException() - let g:exception = v:exception - endfunc - - func FuncThrowpoint() - let g:throwpoint = v:throwpoint - endfunc - - let scriptException = MakeScript("FuncException") - let scriptThrowPoint = MakeScript("FuncThrowpoint") - - command! CmdException let g:exception = v:exception - command! CmdThrowpoint let g:throwpoint = v:throwpoint - - func T(arg, line) - if a:line == 2 - throw a:arg " in line 2 - elseif a:line == 4 - throw a:arg " in line 4 - elseif a:line == 6 - throw a:arg " in line 6 - elseif a:line == 8 - throw a:arg " in line 8 - endif - endfunc - - func G(arg, line) - call T(a:arg, a:line) - endfunc - - func F(arg, line) - call G(a:arg, a:line) - endfunc - - let scriptT = MakeScript("T") - let scriptG = MakeScript("G", scriptT) - let scriptF = MakeScript("F", scriptG) - - try - Xpath 'a' - call F("oops", 2) - catch /.*/ - Xpath 'b' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("oops", v:exception) - call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<2\>', v:throwpoint) - - exec "let exception = v:exception" - exec "let throwpoint = v:throwpoint" - call assert_equal("oops", v:exception) - call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<2\>', v:throwpoint) - - CmdException - CmdThrowpoint - call assert_equal("oops", v:exception) - call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<2\>', v:throwpoint) - - call FuncException() - call FuncThrowpoint() - call assert_equal("oops", v:exception) - call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<2\>', v:throwpoint) - - exec "source" scriptException - exec "source" scriptThrowPoint - call assert_equal("oops", v:exception) - call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<2\>', v:throwpoint) - - try - Xpath 'c' - call G("arrgh", 4) - catch /.*/ - Xpath 'd' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("arrgh", v:exception) - call assert_match('\<G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<4\>', v:throwpoint) - - try - Xpath 'e' - let g:arg = "autsch" - let g:line = 6 - exec "source" scriptF - catch /.*/ - Xpath 'f' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("autsch", v:exception) - call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint) - call assert_match('\<6\>', v:throwpoint) - finally - Xpath 'g' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("arrgh", v:exception) - call assert_match('\<G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<4\>', v:throwpoint) - try - Xpath 'h' - let g:arg = "brrrr" - let g:line = 8 - exec "source" scriptG - catch /.*/ - Xpath 'i' - let exception = v:exception - let throwpoint = v:throwpoint - " Resolve scriptT for matching it against v:throwpoint. - call assert_equal("brrrr", v:exception) - call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint) - call assert_match('\<8\>', v:throwpoint) - finally - Xpath 'j' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("arrgh", v:exception) - call assert_match('\<G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<4\>', v:throwpoint) - endtry - Xpath 'k' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("arrgh", v:exception) - call assert_match('\<G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<4\>', v:throwpoint) - endtry - Xpath 'l' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("arrgh", v:exception) - call assert_match('\<G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<4\>', v:throwpoint) - finally - Xpath 'm' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("oops", v:exception) - call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<2\>', v:throwpoint) - endtry - Xpath 'n' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("oops", v:exception) - call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint) - call assert_match('\<2\>', v:throwpoint) - finally - Xpath 'o' - let exception = v:exception - let throwpoint = v:throwpoint - call assert_equal("", v:exception) - call assert_match('^$', v:throwpoint) - call assert_match('^$', v:throwpoint) - endtry - - call assert_equal('abcdefghijklmno', g:Xpath) - - unlet exception throwpoint - delfunction FuncException - delfunction FuncThrowpoint - call delete(scriptException) - call delete(scriptThrowPoint) - unlet scriptException scriptThrowPoint - delcommand CmdException - delcommand CmdThrowpoint - delfunction T - delfunction G - delfunction F - call delete(scriptT) - call delete(scriptG) - call delete(scriptF) - unlet scriptT scriptG scriptF -endfunc - -"------------------------------------------------------------------------------- -" -" Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1 -" -" v:exception and v:throwpoint work also for error and interrupt -" exceptions. -"------------------------------------------------------------------------------- - -func Test_execption_info_for_error() - CheckEnglish - - let test =<< trim [CODE] - func T(line) - if a:line == 2 - delfunction T " error (function in use) in line 2 - elseif a:line == 4 - call interrupt() - endif - endfunc - - while 1 - try - Xpath 'a' - call T(2) - call assert_report('should not get here') - catch /.*/ - Xpath 'b' - if v:exception !~ 'Vim(delfunction):' - call assert_report('should not get here') - endif - if v:throwpoint !~ '\<T\>' - call assert_report('should not get here') - endif - if v:throwpoint !~ '\<2\>' - call assert_report('should not get here') - endif - finally - Xpath 'c' - if v:exception != "" - call assert_report('should not get here') - endif - if v:throwpoint != "" - call assert_report('should not get here') - endif - break - endtry - endwhile - - Xpath 'd' - if v:exception != "" - call assert_report('should not get here') - endif - if v:throwpoint != "" - call assert_report('should not get here') - endif - - while 1 - try - Xpath 'e' - call T(4) - call assert_report('should not get here') - catch /.*/ - Xpath 'f' - if v:exception != 'Vim:Interrupt' - call assert_report('should not get here') - endif - if v:throwpoint !~ 'function T' - call assert_report('should not get here') - endif - if v:throwpoint !~ '\<4\>' - call assert_report('should not get here') - endif - finally - Xpath 'g' - if v:exception != "" - call assert_report('should not get here') - endif - if v:throwpoint != "" - call assert_report('should not get here') - endif - break - endtry - endwhile - - Xpath 'h' - if v:exception != "" - call assert_report('should not get here') - endif - if v:throwpoint != "" - call assert_report('should not get here') - endif - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefgh', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" -" Test 59: v:exception and v:throwpoint when discarding exceptions {{{1 -" -" When a :catch clause is left by a ":break" etc or an error or -" interrupt exception, v:exception and v:throwpoint are reset. They -" are not affected by an exception that is discarded before being -" caught. -"------------------------------------------------------------------------------- -func Test_exception_info_on_discard() - CheckEnglish - - let test =<< trim [CODE] - let sfile = expand("<sfile>") - - while 1 - try - throw "x1" - catch /.*/ - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - while 1 - try - throw "x2" - catch /.*/ - break - finally - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - endtry - break - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - while 1 - try - let errcaught = 0 - try - try - throw "x3" - catch /.*/ - let lnum = expand("<sflnum>") - asdf - endtry - catch /.*/ - let errcaught = 1 - call assert_match('Vim:E492: Not an editor command:', v:exception) - call assert_match('line ' .. (lnum + 1), v:throwpoint) - endtry - finally - call assert_equal(1, errcaught) - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - Xpath 'a' - - while 1 - try - let intcaught = 0 - try - try - throw "x4" - catch /.*/ - let lnum = expand("<sflnum>") - call interrupt() - endtry - catch /.*/ - let intcaught = 1 - call assert_match('Vim:Interrupt', v:exception) - call assert_match('line ' .. (lnum + 1), v:throwpoint) - endtry - finally - call assert_equal(1, intcaught) - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - Xpath 'b' - - while 1 - try - let errcaught = 0 - try - try - if 1 - let lnum = expand("<sflnum>") - throw "x5" - " missing endif - catch /.*/ - call assert_report('should not get here') - endtry - catch /.*/ - let errcaught = 1 - call assert_match('Vim(catch):E171: Missing :endif:', v:exception) - call assert_match('line ' .. (lnum + 3), v:throwpoint) - endtry - finally - call assert_equal(1, errcaught) - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - Xpath 'c' - - try - while 1 - try - throw "x6" - finally - break - endtry - break - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - try - while 1 - try - throw "x7" - finally - break - endtry - break - endwhile - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - endtry - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - while 1 - try - let errcaught = 0 - try - try - throw "x8" - finally - let lnum = expand("<sflnum>") - asdf - endtry - catch /.*/ - let errcaught = 1 - call assert_match('Vim:E492: Not an editor command:', v:exception) - call assert_match('line ' .. (lnum + 1), v:throwpoint) - endtry - finally - call assert_equal(1, errcaught) - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - Xpath 'd' - - while 1 - try - let intcaught = 0 - try - try - throw "x9" - finally - let lnum = expand("<sflnum>") - call interrupt() - endtry - catch /.*/ - let intcaught = 1 - call assert_match('Vim:Interrupt', v:exception) - call assert_match('line ' .. (lnum + 1), v:throwpoint) - endtry - finally - call assert_equal(1, intcaught) - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - Xpath 'e' - - while 1 - try - let errcaught = 0 - try - try - if 1 - let lnum = expand("<sflnum>") - throw "x10" - " missing endif - finally - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - endtry - catch /.*/ - let errcaught = 1 - call assert_match('Vim(finally):E171: Missing :endif:', v:exception) - call assert_match('line ' .. (lnum + 3), v:throwpoint) - endtry - finally - call assert_equal(1, errcaught) - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - Xpath 'f' - - while 1 - try - let errcaught = 0 - try - try - if 1 - let lnum = expand("<sflnum>") - throw "x11" - " missing endif - endtry - catch /.*/ - let errcaught = 1 - call assert_match('Vim(endtry):E171: Missing :endif:', v:exception) - call assert_match('line ' .. (lnum + 3), v:throwpoint) - endtry - finally - call assert_equal(1, errcaught) - break - endtry - endwhile - call assert_equal('', v:exception) - call assert_equal('', v:throwpoint) - - Xpath 'g' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefg', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" -" Test 60: (Re)throwing v:exception; :echoerr. {{{1 -" -" A user exception can be rethrown after catching by throwing -" v:exception. An error or interrupt exception cannot be rethrown -" because Vim exceptions cannot be faked. A Vim exception using the -" value of v:exception can, however, be triggered by the :echoerr -" command. -"------------------------------------------------------------------------------- - -func Test_rethrow_exception_1() - XpathINIT - try - try - Xpath 'a' - throw "oops" - catch /oops/ - Xpath 'b' - throw v:exception " rethrow user exception - catch /.*/ - call assert_report('should not get here') - endtry - catch /^oops$/ " catches rethrown user exception - Xpath 'c' - catch /.*/ - call assert_report('should not get here') - endtry - call assert_equal('abc', g:Xpath) -endfunc - -func Test_rethrow_exception_2() - XpathINIT - try - let caught = 0 - try - Xpath 'a' - write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e - call assert_report('should not get here') - catch /^Vim(write):/ - let caught = 1 - throw v:exception " throw error: cannot fake Vim exception - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'b' - call assert_equal(1, caught) - endtry - catch /^Vim(throw):/ " catches throw error - let caught = caught + 1 - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - call assert_equal(2, caught) - endtry - call assert_equal('abc', g:Xpath) -endfunc - -func Test_rethrow_exception_3() - XpathINIT - try - let caught = 0 - try - Xpath 'a' - asdf - catch /^Vim/ " catch error exception - let caught = 1 - " Trigger Vim error exception with value specified after :echoerr - let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "") - echoerr value - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'b' - call assert_equal(1, caught) - endtry - catch /^Vim(echoerr):/ - let caught = caught + 1 - call assert_match(value, v:exception) - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - call assert_equal(2, caught) - endtry - call assert_equal('abc', g:Xpath) -endfunc - -func Test_rethrow_exception_3() - XpathINIT - try - let errcaught = 0 - try - Xpath 'a' - let intcaught = 0 - call interrupt() - catch /^Vim:/ " catch interrupt exception - let intcaught = 1 - " Trigger Vim error exception with value specified after :echoerr - echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "") - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'b' - call assert_equal(1, intcaught) - endtry - catch /^Vim(echoerr):/ - let errcaught = 1 - call assert_match('Interrupt', v:exception) - finally - Xpath 'c' - call assert_equal(1, errcaught) - endtry - call assert_equal('abc', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 61: Catching interrupt exceptions {{{1 -" -" When an interrupt occurs inside a :try/:endtry region, an -" interrupt exception is thrown and can be caught. Its value is -" "Vim:Interrupt". If the interrupt occurs after an error or a :throw -" but before a matching :catch is reached, all following :catches of -" that try block are ignored, but the interrupt exception can be -" caught by the next surrounding try conditional. An interrupt is -" ignored when there is a previous interrupt that has not been caught -" or causes a :finally clause to be executed. -"------------------------------------------------------------------------------- - -func Test_catch_intr_exception() - let test =<< trim [CODE] - while 1 - try - try - Xpath 'a' - call interrupt() - call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'b' - finally - Xpath 'c' - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'd' - break - endtry - endwhile - - while 1 - try - try - try - Xpath 'e' - asdf - call assert_report('should not get here') - catch /do_not_catch/ - call assert_report('should not get here') - catch /.*/ - Xpath 'f' - call interrupt() - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'g' - call interrupt() - call assert_report('should not get here') - endtry - catch /^Vim:Interrupt$/ - Xpath 'h' - finally - Xpath 'i' - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'j' - break - endtry - endwhile - - while 1 - try - try - try - Xpath 'k' - throw "x" - call assert_report('should not get here') - catch /do_not_catch/ - call assert_report('should not get here') - catch /x/ - Xpath 'l' - call interrupt() - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - catch /^Vim:Interrupt$/ - Xpath 'm' - finally - Xpath 'n' - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'o' - break - endtry - endwhile - - while 1 - try - try - Xpath 'p' - call interrupt() - call assert_report('should not get here') - catch /do_not_catch/ - call interrupt() - call assert_report('should not get here') - catch /^Vim:Interrupt$/ - Xpath 'q' - finally - Xpath 'r' - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 's' - break - endtry - endwhile - - Xpath 't' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefghijklmnopqrst', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 62: Catching error exceptions {{{1 -" -" An error inside a :try/:endtry region is converted to an exception -" and can be caught. The error exception has a "Vim(cmdname):" prefix -" where cmdname is the name of the failing command, or a "Vim:" prefix -" if no command name is known. The "Vim" prefixes cannot be faked. -"------------------------------------------------------------------------------- - -func Test_catch_err_exception_1() - XpathINIT - while 1 - try - try - let caught = 0 - unlet novar - catch /^Vim(unlet):/ - Xpath 'a' - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "") - finally - Xpath 'b' - call assert_equal(1, caught) - call assert_match('E108: No such variable: "novar"', v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abc', g:Xpath) -endfunc - -func Test_catch_err_exception_2() - XpathINIT - while 1 - try - try - let caught = 0 - throw novar " error in :throw - catch /^Vim(throw):/ - Xpath 'a' - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") - finally - Xpath 'b' - call assert_equal(1, caught) - call assert_match('E121: Undefined variable: novar', v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abc', g:Xpath) -endfunc - -func Test_catch_err_exception_3() - XpathINIT - while 1 - try - try - let caught = 0 - throw "Vim:faked" " error: cannot fake Vim exception - catch /^Vim(throw):/ - Xpath 'a' - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") - finally - Xpath 'b' - call assert_equal(1, caught) - call assert_match("E608: Cannot :throw exceptions with 'Vim' prefix", - \ v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abc', g:Xpath) -endfunc - -func Test_catch_err_exception_4() - XpathINIT - func F() - while 1 - " Missing :endwhile - endfunc - - while 1 - try - try - let caught = 0 - call F() - catch /^Vim(endfunction):/ - Xpath 'a' - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "") - finally - Xpath 'b' - call assert_equal(1, caught) - call assert_match("E170: Missing :endwhile", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abc', g:Xpath) - delfunc F -endfunc - -func Test_catch_err_exception_5() - XpathINIT - func F() - while 1 - " Missing :endwhile - endfunc - - while 1 - try - try - let caught = 0 - ExecAsScript F - catch /^Vim:/ - Xpath 'a' - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim:', '', "") - finally - Xpath 'b' - call assert_equal(1, caught) - call assert_match("E170: Missing :endwhile", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abc', g:Xpath) - delfunc F -endfunc - -func Test_catch_err_exception_6() - XpathINIT - func G() - call G() - endfunc - - while 1 - try - let mfd_save = &mfd - set mfd=3 - try - let caught = 0 - call G() - catch /^Vim(call):/ - Xpath 'a' - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(call):', '', "") - finally - Xpath 'b' - call assert_equal(1, caught) - call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - let &mfd = mfd_save - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abc', g:Xpath) - delfunc G -endfunc - -func Test_catch_err_exception_7() - XpathINIT - func H() - return H() - endfunc - - while 1 - try - let mfd_save = &mfd - set mfd=3 - try - let caught = 0 - call H() - catch /^Vim(return):/ - Xpath 'a' - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(return):', '', "") - finally - Xpath 'b' - call assert_equal(1, caught) - call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - let &mfd = mfd_save - break " discard error for $VIMNOERRTHROW - endtry - call assert_report('should not get here') - endwhile - - call assert_equal('abc', g:Xpath) - delfunc H -endfunc - -"------------------------------------------------------------------------------- -" Test 63: Suppressing error exceptions by :silent!. {{{1 -" -" A :silent! command inside a :try/:endtry region suppresses the -" conversion of errors to an exception and the immediate abortion on -" error. When the commands executed by the :silent! themselves open -" a new :try/:endtry region, conversion of errors to exception and -" immediate abortion is switched on again - until the next :silent! -" etc. The :silent! has the effect of setting v:errmsg to the error -" message text (without displaying it) and continuing with the next -" script line. -" -" When a command triggering autocommands is executed by :silent! -" inside a :try/:endtry, the autocommand execution is not suppressed -" on error. -" -" This test reuses the function MSG() from the previous test. -"------------------------------------------------------------------------------- - -func Test_silent_exception() - XpathINIT - XloopINIT - let g:taken = "" - - func S(n) abort - XloopNEXT - let g:taken = g:taken . "E" . a:n - let v:errmsg = "" - exec "asdf" . a:n - - " Check that ":silent!" continues: - Xloop 'a' - - " Check that ":silent!" sets "v:errmsg": - call assert_match("E492: Not an editor command", v:errmsg) - endfunc - - func Foo() - while 1 - try - try - let caught = 0 - " This is not silent: - call S(3) - catch /^Vim:/ - Xpath 'b' - let caught = 1 - let errmsg3 = substitute(v:exception, '^Vim:', '', "") - silent! call S(4) - finally - call assert_equal(1, caught) - Xpath 'c' - call assert_match("E492: Not an editor command", errmsg3) - silent! call S(5) - " Break out of try conditionals that cover ":silent!". This also - " discards the aborting error when $VIMNOERRTHROW is non-zero. - break - endtry - catch /.*/ - call assert_report('should not get here') - endtry - endwhile - " This is a double ":silent!" (see caller). - silent! call S(6) - endfunc - - func Bar() - try - silent! call S(2) - silent! execute "call Foo() | call S(7)" - silent! call S(8) - endtry " normal end of try cond that covers ":silent!" - " This has a ":silent!" from the caller: - call S(9) - endfunc - - silent! call S(1) - silent! call Bar() - silent! call S(10) - - call assert_equal("E1E2E3E4E5E6E7E8E9E10", g:taken) - - augroup TMP - au! - autocmd BufWritePost * Xpath 'd' - augroup END - - Xpath 'e' - silent! write /i/m/p/o/s/s/i/b/l/e - Xpath 'f' - - call assert_equal('a2a3ba5ca6a7a8a9a10a11edf', g:Xpath) - - augroup TMP - au! - augroup END - augroup! TMP - delfunction S - delfunction Foo - delfunction Bar -endfunc - -"------------------------------------------------------------------------------- -" Test 64: Error exceptions after error, interrupt or :throw {{{1 -" -" When an error occurs after an interrupt or a :throw but before -" a matching :catch is reached, all following :catches of that try -" block are ignored, but the error exception can be caught by the next -" surrounding try conditional. Any previous error exception is -" discarded. An error is ignored when there is a previous error that -" has not been caught. -"------------------------------------------------------------------------------- - -func Test_exception_after_error_1() - XpathINIT - while 1 - try - try - Xpath 'a' - let caught = 0 - while 1 - if 1 - " Missing :endif - endwhile " throw error exception - catch /^Vim(/ - Xpath 'b' - let caught = 1 - finally - Xpath 'c' - call assert_equal(1, caught) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'd' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abcd', g:Xpath) -endfunc - -func Test_exception_after_error_2() - XpathINIT - while 1 - try - try - Xpath 'a' - let caught = 0 - try - if 1 - " Missing :endif - catch /.*/ " throw error exception - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - catch /^Vim(/ - Xpath 'b' - let caught = 1 - finally - Xpath 'c' - call assert_equal(1, caught) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'd' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abcd', g:Xpath) -endfunc - -func Test_exception_after_error_3() - XpathINIT - while 1 - try - try - let caught = 0 - try - Xpath 'a' - call interrupt() - catch /do_not_catch/ - call assert_report('should not get here') - if 1 - " Missing :endif - catch /.*/ " throw error exception - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - catch /^Vim(/ - Xpath 'b' - let caught = 1 - finally - Xpath 'c' - call assert_equal(1, caught) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'd' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abcd', g:Xpath) -endfunc - -func Test_exception_after_error_4() - XpathINIT - while 1 - try - try - let caught = 0 - try - Xpath 'a' - throw "x" - catch /do_not_catch/ - call assert_report('should not get here') - if 1 - " Missing :endif - catch /x/ " throw error exception - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - catch /^Vim(/ - Xpath 'b' - let caught = 1 - finally - Xpath 'c' - call assert_equal(1, caught) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'd' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abcd', g:Xpath) -endfunc - -func Test_exception_after_error_5() - XpathINIT - while 1 - try - try - let caught = 0 - Xpath 'a' - endif " :endif without :if; throw error exception - if 1 - " Missing :endif - catch /do_not_catch/ " ignore new error - call assert_report('should not get here') - catch /^Vim(endif):/ - Xpath 'b' - let caught = 1 - catch /^Vim(/ - call assert_report('should not get here') - finally - Xpath 'c' - call assert_equal(1, caught) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'd' - break - endtry - call assert_report('should not get here') - endwhile - call assert_equal('abcd', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 65: Errors in the /pattern/ argument of a :catch {{{1 -" -" On an error in the /pattern/ argument of a :catch, the :catch does -" not match. Any following :catches of the same :try/:endtry don't -" match either. Finally clauses are executed. -"------------------------------------------------------------------------------- - -func Test_catch_pattern_error() - CheckEnglish - XpathINIT - - try - try - Xpath 'a' - throw "oops" - catch /^oops$/ - Xpath 'b' - catch /\)/ " not checked; exception has already been caught - call assert_report('should not get here') - endtry - Xpath 'c' - catch /.*/ - call assert_report('should not get here') - endtry - call assert_equal('abc', g:Xpath) - - XpathINIT - func F() - try - try - try - Xpath 'a' - throw "ab" - catch /abc/ " does not catch - call assert_report('should not get here') - catch /\)/ " error; discards exception - call assert_report('should not get here') - catch /.*/ " not checked - call assert_report('should not get here') - finally - Xpath 'b' - endtry - call assert_report('should not get here') - catch /^ab$/ " checked, but original exception is discarded - call assert_report('should not get here') - catch /^Vim(catch):/ - Xpath 'c' - call assert_match('Vim(catch):E475: Invalid argument:', v:exception) - finally - Xpath 'd' - endtry - Xpath 'e' - catch /.*/ - call assert_report('should not get here') - endtry - Xpath 'f' - endfunc - - call F() - call assert_equal('abcdef', g:Xpath) - - delfunc F -endfunc - -"------------------------------------------------------------------------------- -" Test 66: Stop range :call on error, interrupt, or :throw {{{1 -" -" When a function which is multiply called for a range since it -" doesn't handle the range itself has an error in a command -" dynamically enclosed by :try/:endtry or gets an interrupt or -" executes a :throw, no more calls for the remaining lines in the -" range are made. On an error in a command not dynamically enclosed -" by :try/:endtry, the function is executed again for the remaining -" lines in the range. -"------------------------------------------------------------------------------- - -func Test_stop_range_on_error() - let test =<< trim [CODE] - let file = tempname() - exec "edit" file - call setline(1, ['line 1', 'line 2', 'line 3']) - let taken = "" - let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)" - - func F(reason, n) abort - let g:taken = g:taken .. "F" .. a:n .. - \ substitute(a:reason, '\(\l\).*', '\u\1', "") .. - \ "(" .. line(".") .. ")" - - if a:reason == "error" - asdf - elseif a:reason == "interrupt" - call interrupt() - elseif a:reason == "throw" - throw "xyz" - elseif a:reason == "aborting error" - XloopNEXT - call assert_equal(g:taken, g:expected) - try - bwipeout! - call delete(g:file) - asdf - endtry - endif - endfunc - - func G(reason, n) - let g:taken = g:taken .. "G" .. a:n .. - \ substitute(a:reason, '\(\l\).*', '\u\1', "") - 1,3call F(a:reason, a:n) - endfunc - - Xpath 'a' - call G("error", 1) - try - Xpath 'b' - try - call G("error", 2) - call assert_report('should not get here') - finally - Xpath 'c' - try - call G("interrupt", 3) - call assert_report('should not get here') - finally - Xpath 'd' - try - call G("throw", 4) - call assert_report('should not get here') - endtry - endtry - endtry - catch /xyz/ - Xpath 'e' - catch /.*/ - call assert_report('should not get here') - endtry - Xpath 'f' - call G("aborting error", 5) - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdef', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 67: :throw across :call command {{{1 -" -" On a call command, an exception might be thrown when evaluating the -" function name, during evaluation of the arguments, or when the -" function is being executed. The exception can be caught by the -" caller. -"------------------------------------------------------------------------------- - -func THROW(x, n) - if a:n == 1 - Xpath 'A' - elseif a:n == 2 - Xpath 'B' - elseif a:n == 3 - Xpath 'C' - endif - throw a:x -endfunc - -func NAME(x, n) - if a:n == 1 - call assert_report('should not get here') - elseif a:n == 2 - Xpath 'D' - elseif a:n == 3 - Xpath 'E' - elseif a:n == 4 - Xpath 'F' - endif - return a:x -endfunc - -func ARG(x, n) - if a:n == 1 - call assert_report('should not get here') - elseif a:n == 2 - call assert_report('should not get here') - elseif a:n == 3 - Xpath 'G' - elseif a:n == 4 - Xpath 'I' - endif - return a:x -endfunc - -func Test_throw_across_call_cmd() - XpathINIT - - func F(x, n) - if a:n == 2 - call assert_report('should not get here') - elseif a:n == 4 - Xpath 'a' - endif - endfunc - - while 1 - try - let v:errmsg = "" - - while 1 - try - Xpath 'b' - call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) - call assert_report('should not get here') - catch /^name$/ - Xpath 'c' - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - - while 1 - try - Xpath 'd' - call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) - call assert_report('should not get here') - catch /^arg$/ - Xpath 'e' - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - - while 1 - try - Xpath 'f' - call {NAME("THROW", 3)}(ARG("call", 3), 3) - call assert_report('should not get here') - catch /^call$/ - Xpath 'g' - catch /^0$/ " default return value - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - - while 1 - try - Xpath 'h' - call {NAME("F", 4)}(ARG(4711, 4), 4) - Xpath 'i' - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - - catch /^0$/ " default return value - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - - call assert_equal('bAcdDBefEGCghFIai', g:Xpath) - delfunction F -endfunc - -"------------------------------------------------------------------------------- -" Test 68: :throw across function calls in expressions {{{1 -" -" On a function call within an expression, an exception might be -" thrown when evaluating the function name, during evaluation of the -" arguments, or when the function is being executed. The exception -" can be caught by the caller. -" -" This test reuses the functions THROW(), NAME(), and ARG() from the -" previous test. -"------------------------------------------------------------------------------- - -func Test_throw_across_call_expr() - XpathINIT - - func F(x, n) - if a:n == 2 - call assert_report('should not get here') - elseif a:n == 4 - Xpath 'a' - endif - return a:x - endfunction - - while 1 - try - let error = 0 - let v:errmsg = "" - - while 1 - try - Xpath 'b' - let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) - call assert_report('should not get here') - catch /^name$/ - Xpath 'c' - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - call assert_true(!exists('var1')) - - while 1 - try - Xpath 'd' - let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) - call assert_report('should not get here') - catch /^arg$/ - Xpath 'e' - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - call assert_true(!exists('var2')) - - while 1 - try - Xpath 'f' - let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3) - call assert_report('should not get here') - catch /^call$/ - Xpath 'g' - catch /^0$/ " default return value - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - call assert_true(!exists('var3')) - - while 1 - try - Xpath 'h' - let var4 = {NAME("F", 4)}(ARG(4711, 4), 4) - Xpath 'i' - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - let v:errmsg = "" - break - endtry - endwhile - call assert_true(exists('var4') && var4 == 4711) - - catch /^0$/ " default return value - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - finally - call assert_equal("", v:errmsg) - break - endtry - endwhile - - call assert_equal('bAcdDBefEGCghFIai', g:Xpath) - delfunc F -endfunc - -"------------------------------------------------------------------------------- -" Test 76: Errors, interrupts, :throw during expression evaluation {{{1 -" -" When a function call made during expression evaluation is aborted -" due to an error inside a :try/:endtry region or due to an interrupt -" or a :throw, the expression evaluation is aborted as well. No -" message is displayed for the cancelled expression evaluation. On an -" error not inside :try/:endtry, the expression evaluation continues. -"------------------------------------------------------------------------------- - -func Test_expr_eval_error() - let test =<< trim [CODE] - let taken = "" - - func ERR(n) - let g:taken = g:taken .. "E" .. a:n - asdf - endfunc - - func ERRabort(n) abort - let g:taken = g:taken .. "A" .. a:n - asdf - endfunc " returns -1; may cause follow-up msg for illegal var/func name - - func WRAP(n, arg) - let g:taken = g:taken .. "W" .. a:n - let g:saved_errmsg = v:errmsg - return arg - endfunc - - func INT(n) - let g:taken = g:taken .. "I" .. a:n - call interrupt() - endfunc - - func THR(n) - let g:taken = g:taken .. "T" .. a:n - throw "should not be caught" - endfunc - - func CONT(n) - let g:taken = g:taken .. "C" .. a:n - endfunc - - func MSG(n) - let g:taken = g:taken .. "M" .. a:n - let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg - let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf" - call assert_match(msgptn, errmsg) - let v:errmsg = "" - let g:saved_errmsg = "" - endfunc - - let v:errmsg = "" - - try - let t = 1 - while t <= 9 - Xloop 'a' - try - if t == 1 - let v{ERR(t) + CONT(t)} = 0 - elseif t == 2 - let v{ERR(t) + CONT(t)} - elseif t == 3 - let var = exists('v{ERR(t) + CONT(t)}') - elseif t == 4 - unlet v{ERR(t) + CONT(t)} - elseif t == 5 - function F{ERR(t) + CONT(t)}() - endfunction - elseif t == 6 - function F{ERR(t) + CONT(t)} - elseif t == 7 - let var = exists('*F{ERR(t) + CONT(t)}') - elseif t == 8 - delfunction F{ERR(t) + CONT(t)} - elseif t == 9 - let var = ERR(t) + CONT(t) - endif - catch /asdf/ - " v:errmsg is not set when the error message is converted to an - " exception. Set it to the original error message. - let v:errmsg = substitute(v:exception, '^Vim:', '', "") - catch /^Vim\((\a\+)\)\=:/ - " An error exception has been thrown after the original error. - let v:errmsg = "" - finally - call MSG(t) - let t = t + 1 - XloopNEXT - continue " discard an aborting error - endtry - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - - try - let t = 10 - while t <= 18 - Xloop 'b' - try - if t == 10 - let v{INT(t) + CONT(t)} = 0 - elseif t == 11 - let v{INT(t) + CONT(t)} - elseif t == 12 - let var = exists('v{INT(t) + CONT(t)}') - elseif t == 13 - unlet v{INT(t) + CONT(t)} - elseif t == 14 - function F{INT(t) + CONT(t)}() - endfunction - elseif t == 15 - function F{INT(t) + CONT(t)} - elseif t == 16 - let var = exists('*F{INT(t) + CONT(t)}') - elseif t == 17 - delfunction F{INT(t) + CONT(t)} - elseif t == 18 - let var = INT(t) + CONT(t) - endif - catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/ - " An error exception has been triggered after the interrupt. - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - call MSG(t) - let t = t + 1 - XloopNEXT - continue " discard interrupt - endtry - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - - try - let t = 19 - while t <= 27 - Xloop 'c' - try - if t == 19 - let v{THR(t) + CONT(t)} = 0 - elseif t == 20 - let v{THR(t) + CONT(t)} - elseif t == 21 - let var = exists('v{THR(t) + CONT(t)}') - elseif t == 22 - unlet v{THR(t) + CONT(t)} - elseif t == 23 - function F{THR(t) + CONT(t)}() - endfunction - elseif t == 24 - function F{THR(t) + CONT(t)} - elseif t == 25 - let var = exists('*F{THR(t) + CONT(t)}') - elseif t == 26 - delfunction F{THR(t) + CONT(t)} - elseif t == 27 - let var = THR(t) + CONT(t) - endif - catch /^Vim\((\a\+)\)\=:/ - " An error exception has been triggered after the :throw. - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - call MSG(t) - let t = t + 1 - XloopNEXT - continue " discard exception - endtry - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - - let v{ERR(28) + CONT(28)} = 0 - call MSG(28) - let v{ERR(29) + CONT(29)} - call MSG(29) - let var = exists('v{ERR(30) + CONT(30)}') - call MSG(30) - unlet v{ERR(31) + CONT(31)} - call MSG(31) - function F{ERR(32) + CONT(32)}() - endfunction - call MSG(32) - function F{ERR(33) + CONT(33)} - call MSG(33) - let var = exists('*F{ERR(34) + CONT(34)}') - call MSG(34) - delfunction F{ERR(35) + CONT(35)} - call MSG(35) - let var = ERR(36) + CONT(36) - call MSG(36) - - let saved_errmsg = "" - - let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0 - call MSG(37) - let v{WRAP(38, ERRabort(38)) + CONT(38)} - call MSG(38) - let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}') - call MSG(39) - unlet v{WRAP(40, ERRabort(40)) + CONT(40)} - call MSG(40) - function F{WRAP(41, ERRabort(41)) + CONT(41)}() - endfunction - call MSG(41) - function F{WRAP(42, ERRabort(42)) + CONT(42)} - call MSG(42) - let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}') - call MSG(43) - delfunction F{WRAP(44, ERRabort(44)) + CONT(44)} - call MSG(44) - let var = ERRabort(45) + CONT(45) - call MSG(45) - Xpath 'd' - - let expected = "" - \ .. "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9" - \ .. "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18" - \ .. "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27" - \ .. "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33" - \ .. "E34C34M34E35C35M35E36C36M36" - \ .. "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41" - \ .. "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45" - call assert_equal(expected, taken) - [CODE] - let verify =<< trim [CODE] - let expected = "a1a2a3a4a5a6a7a8a9" - \ .. "b10b11b12b13b14b15b16b17b18" - \ .. "c19c20c21c22c23c24c25c26c27d" - call assert_equal(expected, g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1 -" -" When a function call made during evaluation of an expression in -" braces as part of a function name after ":function" is aborted due -" to an error inside a :try/:endtry region or due to an interrupt or -" a :throw, the expression evaluation is aborted as well, and the -" function definition is ignored, skipping all commands to the -" ":endfunction". On an error not inside :try/:endtry, the expression -" evaluation continues and the function gets defined, and can be -" called and deleted. -"------------------------------------------------------------------------------- -func Test_brace_expr_error() - let test =<< trim [CODE] - func ERR() abort - Xloop 'a' - asdf - endfunc " returns -1 - - func OK() - Xloop 'b' - let v:errmsg = "" - return 0 - endfunc - - let v:errmsg = "" - - Xpath 'c' - func F{1 + ERR() + OK()}(arg) - " F0 should be defined. - if exists("a:arg") && a:arg == "calling" - Xpath 'd' - else - call assert_report('should not get here') - endif - endfunction - call assert_equal("", v:errmsg) - XloopNEXT - - Xpath 'e' - call F{1 + ERR() + OK()}("calling") - call assert_equal("", v:errmsg) - XloopNEXT - - Xpath 'f' - delfunction F{1 + ERR() + OK()} - call assert_equal("", v:errmsg) - XloopNEXT - - try - while 1 - try - Xpath 'g' - func G{1 + ERR() + OK()}(arg) - " G0 should not be defined, and the function body should be - " skipped. - call assert_report('should not get here') - " Use an unmatched ":finally" to check whether the body is - " skipped when an error occurs in ERR(). This works whether or - " not the exception is converted to an exception. - finally - call assert_report('should not get here') - endtry - try - call assert_report('should not get here') - endfunction - - call assert_report('should not get here') - catch /asdf/ - " Jumped to when the function is not defined and the body is - " skipped. - Xpath 'h' - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'i' - break - endtry " jumped to when the body is not skipped - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - [CODE] - let verify =<< trim [CODE] - call assert_equal('ca1b1ea2b2dfa3b3ga4hi', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 78: Messages on parsing errors in expression evaluation {{{1 -" -" When an expression evaluation detects a parsing error, an error -" message is given and converted to an exception, and the expression -" evaluation is aborted. -"------------------------------------------------------------------------------- -func Test_expr_eval_error_msg() - CheckEnglish - - let test =<< trim [CODE] - let taken = "" - - func F(n) - let g:taken = g:taken . "F" . a:n - endfunc - - func MSG(n, enr, emsg) - let g:taken = g:taken . "M" . a:n - call assert_match('^' .. a:enr .. ':', v:errmsg) - call assert_match(a:emsg, v:errmsg) - endfunc - - func CONT(n) - let g:taken = g:taken . "C" . a:n - endfunc - - let v:errmsg = "" - try - let t = 1 - while t <= 14 - let g:taken = g:taken . "T" . t - let v:errmsg = "" - try - if t == 1 - let v{novar + CONT(t)} = 0 - elseif t == 2 - let v{novar + CONT(t)} - elseif t == 3 - let var = exists('v{novar + CONT(t)}') - elseif t == 4 - unlet v{novar + CONT(t)} - elseif t == 5 - function F{novar + CONT(t)}() - endfunction - elseif t == 6 - function F{novar + CONT(t)} - elseif t == 7 - let var = exists('*F{novar + CONT(t)}') - elseif t == 8 - delfunction F{novar + CONT(t)} - elseif t == 9 - echo novar + CONT(t) - elseif t == 10 - echo v{novar + CONT(t)} - elseif t == 11 - echo F{novar + CONT(t)} - elseif t == 12 - let var = novar + CONT(t) - elseif t == 13 - let var = v{novar + CONT(t)} - elseif t == 14 - let var = F{novar + CONT(t)}() - endif - catch /^Vim\((\a\+)\)\=:/ - Xloop 'a' - " v:errmsg is not set when the error message is converted to an - " exception. Set it to the original error message. - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xloop 'b' - if t <= 8 && t != 3 && t != 7 - call MSG(t, 'E475', 'Invalid argument\>') - else - call MSG(t, 'E121', "Undefined variable") - endif - let t = t + 1 - XloopNEXT - continue " discard an aborting error - endtry - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - - func T(n, expr, enr, emsg) - try - let g:taken = g:taken . "T" . a:n - let v:errmsg = "" - try - execute "let var = " . a:expr - catch /^Vim\((\a\+)\)\=:/ - Xloop 'c' - " v:errmsg is not set when the error message is converted to an - " exception. Set it to the original error message. - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xloop 'd' - call MSG(a:n, a:enr, a:emsg) - XloopNEXT - " Discard an aborting error: - return - endtry - catch /.*/ - call assert_report('should not get here') - endtry - endfunc - - call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function") - call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments") - call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments") - call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments") - call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'") - call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'") - call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression") - call T(22, '1 2 + CONT(22)', 'E488', "Trailing characters: 2 +") - call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'") - call T(24, '("abc) + CONT(24)', 'E114', "Missing quote") - call T(25, "('abc) + CONT(25)", 'E115', "Missing quote") - call T(26, '& + CONT(26)', 'E112', "Option name missing") - call T(27, '&asdf + CONT(27)', 'E113', "Unknown option") - - let expected = "" - \ .. "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14" - \ .. "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25" - \ .. "T26M26T27M27" - - call assert_equal(expected, taken) - [CODE] - let verify =<< trim [CODE] - let expected = "a1b1a2b2a3b3a4b4a5b5a6b6a7b7a8b8a9b9a10b10a11b11a12b12" - \ .. "a13b13a14b14c15d15c16d16c17d17c18d18c19d19c20d20" - \ .. "c21d21c22d22c23d23c24d24c25d25c26d26c27d27" - call assert_equal(expected, g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 79: Throwing one of several errors for the same command {{{1 -" -" When several errors appear in a row (for instance during expression -" evaluation), the first as the most specific one is used when -" throwing an error exception. If, however, a syntax error is -" detected afterwards, this one is used for the error exception. -" On a syntax error, the next command is not executed, on a normal -" error, however, it is (relevant only in a function without the -" "abort" flag). v:errmsg is not set. -" -" If throwing error exceptions is configured off, v:errmsg is always -" set to the latest error message, that is, to the more general -" message or the syntax error, respectively. -"------------------------------------------------------------------------------- -func Test_throw_multi_error() - CheckEnglish - - let test =<< trim [CODE] - func NEXT(cmd) - exec a:cmd . " | Xloop 'a'" - endfun - - call NEXT('echo novar') " (checks nextcmd) - XloopNEXT - call NEXT('let novar #') " (skips nextcmd) - XloopNEXT - call NEXT('unlet novar #') " (skips nextcmd) - XloopNEXT - call NEXT('let {novar}') " (skips nextcmd) - XloopNEXT - call NEXT('unlet{ novar}') " (skips nextcmd) - - call assert_equal('a1', g:Xpath) - XpathINIT - XloopINIT - - func EXEC(cmd) - exec a:cmd - endfunc - - try - while 1 " dummy loop - try - let v:errmsg = "" - call EXEC('echo novar') " normal error - catch /^Vim\((\a\+)\)\=:/ - Xpath 'b' - call assert_match('E121: Undefined variable: novar', v:exception) - finally - Xpath 'c' - call assert_equal("", v:errmsg) - break - endtry - endwhile - - Xpath 'd' - let cmd = "let" - while cmd != "" - try - let v:errmsg = "" - call EXEC(cmd . ' novar #') " normal plus syntax error - catch /^Vim\((\a\+)\)\=:/ - Xloop 'e' - call assert_match('E488: Trailing characters', v:exception) - finally - Xloop 'f' - call assert_equal("", v:errmsg) - if cmd == "let" - let cmd = "unlet" - else - let cmd = "" - endif - XloopNEXT - continue - endtry - endwhile - - Xpath 'g' - let cmd = "let" - while cmd != "" - try - let v:errmsg = "" - call EXEC(cmd . ' {novar}') " normal plus syntax error - catch /^Vim\((\a\+)\)\=:/ - Xloop 'h' - call assert_match('E475: Invalid argument: {novar}', v:exception) - finally - Xloop 'i' - call assert_equal("", v:errmsg) - if cmd == "let" - let cmd = "unlet" - else - let cmd = "" - endif - XloopNEXT - continue - endtry - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - Xpath 'j' - [CODE] - let verify =<< trim [CODE] - call assert_equal('bcde1f1e2f2gh3i3h4i4j', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 80: Syntax error in expression for illegal :elseif {{{1 -" -" If there is a syntax error in the expression after an illegal -" :elseif, an error message is given (or an error exception thrown) -" for the illegal :elseif rather than the expression error. -"------------------------------------------------------------------------------- -func Test_if_syntax_error() - CheckEnglish - - let test =<< trim [CODE] - let v:errmsg = "" - if 0 - else - elseif 1 ||| 2 - endif - Xpath 'a' - call assert_match('E584: :elseif after :else', v:errmsg) - - let v:errmsg = "" - if 1 - else - elseif 1 ||| 2 - endif - Xpath 'b' - call assert_match('E584: :elseif after :else', v:errmsg) - - let v:errmsg = "" - elseif 1 ||| 2 - Xpath 'c' - call assert_match('E582: :elseif without :if', v:errmsg) - - let v:errmsg = "" - while 1 - elseif 1 ||| 2 - endwhile - Xpath 'd' - call assert_match('E582: :elseif without :if', v:errmsg) - - while 1 - try - try - let v:errmsg = "" - if 0 - else - elseif 1 ||| 2 - endif - catch /^Vim\((\a\+)\)\=:/ - Xpath 'e' - call assert_match('E584: :elseif after :else', v:exception) - finally - Xpath 'f' - call assert_equal("", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'g' - break - endtry - endwhile - - while 1 - try - try - let v:errmsg = "" - if 1 - else - elseif 1 ||| 2 - endif - catch /^Vim\((\a\+)\)\=:/ - Xpath 'h' - call assert_match('E584: :elseif after :else', v:exception) - finally - Xpath 'i' - call assert_equal("", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'j' - break - endtry - endwhile - - while 1 - try - try - let v:errmsg = "" - elseif 1 ||| 2 - catch /^Vim\((\a\+)\)\=:/ - Xpath 'k' - call assert_match('E582: :elseif without :if', v:exception) - finally - Xpath 'l' - call assert_equal("", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'm' - break - endtry - endwhile - - while 1 - try - try - let v:errmsg = "" - while 1 - elseif 1 ||| 2 - endwhile - catch /^Vim\((\a\+)\)\=:/ - Xpath 'n' - call assert_match('E582: :elseif without :if', v:exception) - finally - Xpath 'o' - call assert_equal("", v:errmsg) - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'p' - break - endtry - endwhile - Xpath 'q' - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefghijklmnopq', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 81: Discarding exceptions after an error or interrupt {{{1 -" -" When an exception is thrown from inside a :try conditional without -" :catch and :finally clauses and an error or interrupt occurs before -" the :endtry is reached, the exception is discarded. -"------------------------------------------------------------------------------- - -func Test_discard_exception_after_error_1() - let test =<< trim [CODE] - try - Xpath 'a' - try - Xpath 'b' - throw "arrgh" - call assert_report('should not get here') - if 1 - call assert_report('should not get here') - " error after :throw: missing :endif - endtry - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('ab', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -" interrupt the code before the endtry is invoked -func Test_discard_exception_after_error_2() - XpathINIT - let lines =<< trim [CODE] - try - Xpath 'a' - try - Xpath 'b' - throw "arrgh" - call assert_report('should not get here') - endtry " interrupt here - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - call writefile(lines, 'Xscript') - - breakadd file 7 Xscript - try - let caught_intr = 0 - debuggreedy - call feedkeys(":source Xscript\<CR>quit\<CR>", "xt") - catch /^Vim:Interrupt$/ - call assert_match('Xscript, line 7', v:throwpoint) - let caught_intr = 1 - endtry - 0debuggreedy - call assert_equal(1, caught_intr) - call assert_equal('ab', g:Xpath) - breakdel * - call delete('Xscript') -endfunc - -"------------------------------------------------------------------------------- -" Test 82: Ignoring :catch clauses after an error or interrupt {{{1 -" -" When an exception is thrown and an error or interrupt occurs before -" the matching :catch clause is reached, the exception is discarded -" and the :catch clause is ignored (also for the error or interrupt -" exception being thrown then). -"------------------------------------------------------------------------------- - -func Test_ignore_catch_after_error_1() - let test =<< trim [CODE] - try - try - Xpath 'a' - throw "arrgh" - call assert_report('should not get here') - if 1 - call assert_report('should not get here') - " error after :throw: missing :endif - catch /.*/ - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('a', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -func Test_ignore_catch_after_error_2() - let test =<< trim [CODE] - func E() - try - try - Xpath 'a' - throw "arrgh" - call assert_report('should not get here') - if 1 - call assert_report('should not get here') - " error after :throw: missing :endif - catch /.*/ - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - endfunc - - call E() - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('a', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -" interrupt right before a catch is invoked in a script -func Test_ignore_catch_after_intr_1() - XpathINIT - let lines =<< trim [CODE] - try - try - Xpath 'a' - throw "arrgh" - call assert_report('should not get here') - catch /.*/ " interrupt here - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - call writefile(lines, 'Xscript') - - breakadd file 6 Xscript - try - let caught_intr = 0 - debuggreedy - call feedkeys(":source Xscript\<CR>quit\<CR>", "xt") - catch /^Vim:Interrupt$/ - call assert_match('Xscript, line 6', v:throwpoint) - let caught_intr = 1 - endtry - 0debuggreedy - call assert_equal(1, caught_intr) - call assert_equal('a', g:Xpath) - breakdel * - call delete('Xscript') -endfunc - -" interrupt right before a catch is invoked inside a function. -func Test_ignore_catch_after_intr_2() - XpathINIT - func F() - try - try - Xpath 'a' - throw "arrgh" - call assert_report('should not get here') - catch /.*/ " interrupt here - call assert_report('should not get here') - catch /.*/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - endfunc - - breakadd func 6 F - try - let caught_intr = 0 - debuggreedy - call feedkeys(":call F()\<CR>quit\<CR>", "xt") - catch /^Vim:Interrupt$/ - call assert_match('\.F, line 6', v:throwpoint) - let caught_intr = 1 - endtry - 0debuggreedy - call assert_equal(1, caught_intr) - call assert_equal('a', g:Xpath) - breakdel * - delfunc F -endfunc - -"------------------------------------------------------------------------------- -" Test 83: Executing :finally clauses after an error or interrupt {{{1 -" -" When an exception is thrown and an error or interrupt occurs before -" the :finally of the innermost :try is reached, the exception is -" discarded and the :finally clause is executed. -"------------------------------------------------------------------------------- - -func Test_finally_after_error() - let test =<< trim [CODE] - try - Xpath 'a' - try - Xpath 'b' - throw "arrgh" - call assert_report('should not get here') - if 1 - call assert_report('should not get here') - " error after :throw: missing :endif - finally - Xpath 'c' - endtry - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - let verify =<< trim [CODE] - call assert_equal('abc', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -" interrupt the code right before the finally is invoked -func Test_finally_after_intr() - XpathINIT - let lines =<< trim [CODE] - try - Xpath 'a' - try - Xpath 'b' - throw "arrgh" - call assert_report('should not get here') - finally " interrupt here - Xpath 'c' - endtry - call assert_report('should not get here') - catch /arrgh/ - call assert_report('should not get here') - endtry - call assert_report('should not get here') - [CODE] - call writefile(lines, 'Xscript') - - breakadd file 7 Xscript - try - let caught_intr = 0 - debuggreedy - call feedkeys(":source Xscript\<CR>quit\<CR>", "xt") - catch /^Vim:Interrupt$/ - call assert_match('Xscript, line 7', v:throwpoint) - let caught_intr = 1 - endtry - 0debuggreedy - call assert_equal(1, caught_intr) - call assert_equal('abc', g:Xpath) - breakdel * - call delete('Xscript') -endfunc - -"------------------------------------------------------------------------------- -" Test 84: Exceptions in autocommand sequences. {{{1 -" -" When an exception occurs in a sequence of autocommands for -" a specific event, the rest of the sequence is not executed. The -" command that triggered the autocommand execution aborts, and the -" exception is propagated to the caller. -" -" For the FuncUndefined event under a function call expression or -" :call command, the function is not executed, even when it has -" been defined by the autocommands before the exception occurred. -"------------------------------------------------------------------------------- - -func Test_autocmd_exception() - let test =<< trim [CODE] - func INT() - call interrupt() - endfunc - - aug TMP - autocmd! - - autocmd User x1 Xpath 'a' - autocmd User x1 throw "x1" - autocmd User x1 call assert_report('should not get here') - - autocmd User x2 Xpath 'b' - autocmd User x2 asdf - autocmd User x2 call assert_report('should not get here') - - autocmd User x3 Xpath 'c' - autocmd User x3 call INT() - autocmd User x3 call assert_report('should not get here') - - autocmd FuncUndefined U1 func U1() - autocmd FuncUndefined U1 call assert_report('should not get here') - autocmd FuncUndefined U1 endfunc - autocmd FuncUndefined U1 Xpath 'd' - autocmd FuncUndefined U1 throw "U1" - autocmd FuncUndefined U1 call assert_report('should not get here') - - autocmd FuncUndefined U2 func U2() - autocmd FuncUndefined U2 call assert_report('should not get here') - autocmd FuncUndefined U2 endfunc - autocmd FuncUndefined U2 Xpath 'e' - autocmd FuncUndefined U2 ASDF - autocmd FuncUndefined U2 call assert_report('should not get here') - - autocmd FuncUndefined U3 func U3() - autocmd FuncUndefined U3 call assert_report('should not get here') - autocmd FuncUndefined U3 endfunc - autocmd FuncUndefined U3 Xpath 'f' - autocmd FuncUndefined U3 call INT() - autocmd FuncUndefined U3 call assert_report('should not get here') - aug END - - try - try - Xpath 'g' - doautocmd User x1 - catch /x1/ - Xpath 'h' - endtry - - while 1 - try - Xpath 'i' - doautocmd User x2 - catch /asdf/ - Xpath 'j' - finally - Xpath 'k' - break - endtry - endwhile - - while 1 - try - Xpath 'l' - doautocmd User x3 - catch /Vim:Interrupt/ - Xpath 'm' - finally - Xpath 'n' - " ... but break loop for caught interrupt exception, - " or discard interrupt and break loop if $VIMNOINTTHROW - break - endtry - endwhile - - if exists("*U1") | delfunction U1 | endif - if exists("*U2") | delfunction U2 | endif - if exists("*U3") | delfunction U3 | endif - - try - Xpath 'o' - call U1() - catch /U1/ - Xpath 'p' - endtry - - while 1 - try - Xpath 'q' - call U2() - catch /ASDF/ - Xpath 'r' - finally - Xpath 's' - " ... but break loop for caught error exception, - " or discard error and break loop if $VIMNOERRTHROW - break - endtry - endwhile - - while 1 - try - Xpath 't' - call U3() - catch /Vim:Interrupt/ - Xpath 'u' - finally - Xpath 'v' - " ... but break loop for caught interrupt exception, - " or discard interrupt and break loop if $VIMNOINTTHROW - break - endtry - endwhile - catch /.*/ - call assert_report('should not get here') - endtry - Xpath 'w' - [CODE] - let verify =<< trim [CODE] - call assert_equal('gahibjklcmnodpqerstfuvw', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -endfunc - -"------------------------------------------------------------------------------- -" Test 85: Error exceptions in autocommands for I/O command events {{{1 -" -" When an I/O command is inside :try/:endtry, autocommands to be -" executed after it should be skipped on an error (exception) in the -" command itself or in autocommands to be executed before the command. -" In the latter case, the I/O command should not be executed either. -" Example 1: BufWritePre, :write, BufWritePost -" Example 2: FileReadPre, :read, FileReadPost. -"------------------------------------------------------------------------------- - -func Test_autocmd_error_io_exception() - let test =<< trim [CODE] - " Remove the autocommands for the events specified as arguments in all used - " autogroups. - func Delete_autocommands(...) - let augfile = tempname() - while 1 - try - exec "redir >" . augfile - aug - redir END - exec "edit" augfile - g/^$/d - norm G$ - let wrap = "w" - while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0 - let wrap = "W" - exec "norm y/ \n" - let argno = 1 - while argno <= a:0 - exec "au!" escape(@", " ") a:{argno} - let argno = argno + 1 - endwhile - endwhile - catch /.*/ - finally - bwipeout! - call delete(augfile) - break - endtry - endwhile - endfunc - - call Delete_autocommands("BufWritePre", "BufWritePost") - - while 1 - try - try - let post = 0 - aug TMP - au! BufWritePost * let post = 1 - aug END - write /n/o/n/e/x/i/s/t/e/n/t - catch /^Vim(write):/ - Xpath 'a' - call assert_match("E212: Can't open file for writing", v:exception) - finally - Xpath 'b' - call assert_equal(0, post) - au! TMP - aug! TMP - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'c' - break - endtry - endwhile - - while 1 - try - try - let post = 0 - aug TMP - au! BufWritePre * asdf - au! BufWritePost * let post = 1 - aug END - let tmpfile = tempname() - exec "write" tmpfile - catch /^Vim\((write)\)\=:/ - Xpath 'd' - call assert_match('E492: Not an editor command', v:exception) - finally - Xpath 'e' - if filereadable(tmpfile) - call assert_report('should not get here') - endif - call assert_equal(0, post) - au! TMP - aug! TMP - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'f' - break - endtry - endwhile - - call delete(tmpfile) - - call Delete_autocommands("BufWritePre", "BufWritePost", - \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost") - - while 1 - try - try - let post = 0 - aug TMP - au! FileReadPost * let post = 1 - aug END - let caught = 0 - read /n/o/n/e/x/i/s/t/e/n/t - catch /^Vim(read):/ - Xpath 'g' - call assert_match("E484: Can't open file", v:exception) - finally - Xpath 'h' - call assert_equal(0, post) - au! TMP - aug! TMP - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'i' - break - endtry - endwhile - - while 1 - try - let infile = tempname() - let tmpfile = tempname() - call writefile(["XYZ"], infile) - exec "edit" tmpfile - try - Xpath 'j' - try - let post = 0 - aug TMP - au! FileReadPre * asdf - au! FileReadPost * let post = 1 - aug END - exec "0read" infile - catch /^Vim\((read)\)\=:/ - Xpath 'k' - call assert_match('E492: Not an editor command', v:exception) - finally - Xpath 'l' - if getline("1") == "XYZ" - call assert_report('should not get here') - endif - call assert_equal(0, post) - au! TMP - aug! TMP - endtry - finally - Xpath 'm' - bwipeout! - endtry - catch /.*/ - call assert_report('should not get here') - finally - Xpath 'n' - break - endtry - endwhile - - call delete(infile) - call delete(tmpfile) - [CODE] - let verify =<< trim [CODE] - call assert_equal('abcdefghijklmn', g:Xpath) - [CODE] - call RunInNewVim(test, verify) -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 -"------------------------------------------------------------------------------- - -func Test_curlies() - let s:var = 66 - let ns = 's' - call assert_equal(66, {ns}:var) - - let g:a = {} - let g:b = 't' - let g:a[g:b] = 77 - call assert_equal(77, g:a['t']) -endfunc - -"------------------------------------------------------------------------------- -" Test 91: using type(). {{{1 -"------------------------------------------------------------------------------- - -func Test_type() - call assert_equal(0, type(0)) - call assert_equal(1, type("")) - call assert_equal(2, type(function("tr"))) - call assert_equal(2, type(function("tr", [8]))) - call assert_equal(3, type([])) - call assert_equal(4, type({})) - call assert_equal(5, type(0.0)) - call assert_equal(6, type(v:false)) - call assert_equal(6, type(v:true)) - call assert_equal(7, type(v:null)) - call assert_equal(v:t_number, type(0)) - call assert_equal(v:t_string, type("")) - call assert_equal(v:t_func, type(function("tr"))) - call assert_equal(v:t_list, type([])) - call assert_equal(v:t_dict, type({})) - call assert_equal(v:t_float, type(0.0)) - call assert_equal(v:t_bool, type(v:false)) - call assert_equal(v:t_bool, type(v:true)) - call assert_equal(v:t_string, type(v:_null_string)) - call assert_equal(v:t_list, type(v:_null_list)) - call assert_equal(v:t_dict, type(v:_null_dict)) - call assert_equal(v:t_blob, type(v:_null_blob)) - - call assert_equal(0, 0 + v:false) - call assert_equal(1, 0 + v:true) - " call assert_equal(0, 0 + v:none) - call assert_equal(0, 0 + v:null) - - call assert_equal('v:false', '' . v:false) - call assert_equal('v:true', '' . v:true) - " call assert_equal('v:none', '' . v:none) - call assert_equal('v:null', '' . v:null) - - call assert_true(v:false == 0) - call assert_false(v:false != 0) - call assert_true(v:true == 1) - call assert_false(v:true != 1) - call assert_false(v:true == v:false) - call assert_true(v:true != v:false) - - call assert_true(v:null == 0) - call assert_false(v:null != 0) - " call assert_true(v:none == 0) - " call assert_false(v:none != 0) - - call assert_true(v:false is v:false) - call assert_true(v:true is v:true) - " call assert_true(v:none is v:none) - call assert_true(v:null is v:null) - - call assert_false(v:false isnot v:false) - call assert_false(v:true isnot v:true) - " call assert_false(v:none isnot v:none) - call assert_false(v:null isnot v:null) - - call assert_false(v:false is 0) - call assert_false(v:true is 1) - call assert_false(v:true is v:false) - " call assert_false(v:none is 0) - call assert_false(v:null is 0) - " call assert_false(v:null is v:none) - - call assert_true(v:false isnot 0) - call assert_true(v:true isnot 1) - call assert_true(v:true isnot v:false) - " call assert_true(v:none isnot 0) - call assert_true(v:null isnot 0) - " call assert_true(v:null isnot v:none) - - call assert_equal(v:false, eval(string(v:false))) - call assert_equal(v:true, eval(string(v:true))) - " call assert_equal(v:none, eval(string(v:none))) - call assert_equal(v:null, eval(string(v:null))) - - call assert_equal(v:false, copy(v:false)) - call assert_equal(v:true, copy(v:true)) - " call assert_equal(v:none, copy(v:none)) - call assert_equal(v:null, copy(v:null)) - - call assert_equal([v:false], deepcopy([v:false])) - call assert_equal([v:true], deepcopy([v:true])) - " call assert_equal([v:none], deepcopy([v:none])) - call assert_equal([v:null], deepcopy([v:null])) - - call assert_true(empty(v:false)) - call assert_false(empty(v:true)) - call assert_true(empty(v:null)) - " call assert_true(empty(v:none)) - - func ChangeYourMind() - try - return v:true - finally - return 'something else' - endtry - endfunc - - call ChangeYourMind() -endfunc - -"------------------------------------------------------------------------------- -" Test 92: skipping code {{{1 -"------------------------------------------------------------------------------- - -func Test_skip() - let Fn = function('Test_type') - call assert_false(0 && Fn[1]) - call assert_false(0 && string(Fn)) - call assert_false(0 && len(Fn)) - let l = [] - call assert_false(0 && l[1]) - call assert_false(0 && string(l)) - call assert_false(0 && len(l)) - let f = 1.0 - call assert_false(0 && f[1]) - call assert_false(0 && string(f)) - call assert_false(0 && len(f)) - let sp = v:null - call assert_false(0 && sp[1]) - call assert_false(0 && string(sp)) - call assert_false(0 && len(sp)) - -endfunc - -"------------------------------------------------------------------------------- -" Test 93: :echo and string() {{{1 -"------------------------------------------------------------------------------- - -func Test_echo_and_string() - " String - let a = 'foo bar' - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["foo bar", - \ "'foo bar'"], l) - - " Float - if has('float') - let a = -1.2e0 - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["-1.2", - \ "-1.2"], l) - endif - - " Funcref - redir => result - echo function('string') - echo string(function('string')) - redir END - let l = split(result, "\n") - call assert_equal(["string", - \ "function('string')"], l) - - " Empty dictionaries in a list - let a = {} - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[{}, {}, {}]", - \ "[{}, {}, {}]"], l) - - " Empty dictionaries in a dictionary - let a = {} - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': {}, 'b': {}}", - \ "{'a': {}, 'b': {}}"], l) - - " Empty lists in a list - let a = [] - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[[], [], []]", - \ "[[], [], []]"], l) - - " Empty lists in a dictionary - let a = [] - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': [], 'b': []}", - \ "{'a': [], 'b': []}"], l) -endfunc - -"------------------------------------------------------------------------------- -" Test 94: 64-bit Numbers {{{1 -"------------------------------------------------------------------------------- - -func Test_num64() - call assert_notequal( 4294967296, 0) - call assert_notequal(-4294967296, 0) - call assert_equal( 4294967296, 0xFFFFffff + 1) - call assert_equal(-4294967296, -0xFFFFffff - 1) - - call assert_equal( 9223372036854775807, 1 / 0) - call assert_equal(-9223372036854775807, -1 / 0) - call assert_equal(-9223372036854775807 - 1, 0 / 0) - - if has('float') - call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) - call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) - endif - - let rng = range(0xFFFFffff, 0x100000001) - call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng) - call assert_equal(0x100000001, max(rng)) - call assert_equal(0xFFFFffff, min(rng)) - call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N')) -endfunc - -"------------------------------------------------------------------------------- -" Test 95: lines of :append, :change, :insert {{{1 -"------------------------------------------------------------------------------- - -func DefineFunction(name, body) - let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n") - exec func -endfunc - -func Test_script_lines() - " :append - try - call DefineFunction('T_Append', [ - \ 'append', - \ 'py <<EOS', - \ '.', - \ ]) - catch - call assert_report("Can't define function") - endtry - try - call DefineFunction('T_Append', [ - \ 'append', - \ 'abc', - \ ]) - call assert_report("Shouldn't be able to define function") - catch - call assert_exception('Vim(function):E126: Missing :endfunction') - endtry - - " :change - try - call DefineFunction('T_Change', [ - \ 'change', - \ 'py <<EOS', - \ '.', - \ ]) - catch - call assert_report("Can't define function") - endtry - try - call DefineFunction('T_Change', [ - \ 'change', - \ 'abc', - \ ]) - call assert_report("Shouldn't be able to define function") - catch - call assert_exception('Vim(function):E126: Missing :endfunction') - endtry - - " :insert - try - call DefineFunction('T_Insert', [ - \ 'insert', - \ 'py <<EOS', - \ '.', - \ ]) - catch - call assert_report("Can't define function") - endtry - try - call DefineFunction('T_Insert', [ - \ 'insert', - \ 'abc', - \ ]) - call assert_report("Shouldn't be able to define function") - catch - call assert_exception('Vim(function):E126: Missing :endfunction') - endtry -endfunc - -"------------------------------------------------------------------------------- -" Test 96: line continuation {{{1 -" -" Undefined behavior was detected by ubsan with line continuation -" after an empty line. -"------------------------------------------------------------------------------- -func Test_script_empty_line_continuation() - - \ -endfunc - -"------------------------------------------------------------------------------- -" Test 97: bitwise functions {{{1 -"------------------------------------------------------------------------------- -func Test_bitwise_functions() - " and - call assert_equal(127, and(127, 127)) - call assert_equal(16, and(127, 16)) - eval 127->and(16)->assert_equal(16) - call assert_equal(0, and(127, 128)) - call assert_fails("call and(1.0, 1)", 'E805:') - call assert_fails("call and([], 1)", 'E745:') - call assert_fails("call and({}, 1)", 'E728:') - call assert_fails("call and(1, 1.0)", 'E805:') - call assert_fails("call and(1, [])", 'E745:') - call assert_fails("call and(1, {})", 'E728:') - " or - call assert_equal(23, or(16, 7)) - call assert_equal(15, or(8, 7)) - eval 8->or(7)->assert_equal(15) - call assert_equal(123, or(0, 123)) - call assert_fails("call or(1.0, 1)", 'E805:') - call assert_fails("call or([], 1)", 'E745:') - call assert_fails("call or({}, 1)", 'E728:') - call assert_fails("call or(1, 1.0)", 'E805:') - call assert_fails("call or(1, [])", 'E745:') - call assert_fails("call or(1, {})", 'E728:') - " xor - call assert_equal(0, xor(127, 127)) - call assert_equal(111, xor(127, 16)) - eval 127->xor(16)->assert_equal(111) - call assert_equal(255, xor(127, 128)) - call assert_fails("call xor(1.0, 1)", 'E805:') - call assert_fails("call xor([], 1)", 'E745:') - call assert_fails("call xor({}, 1)", 'E728:') - call assert_fails("call xor(1, 1.0)", 'E805:') - call assert_fails("call xor(1, [])", 'E745:') - call assert_fails("call xor(1, {})", 'E728:') - " invert - call assert_equal(65408, and(invert(127), 65535)) - eval 127->invert()->and(65535)->assert_equal(65408) - call assert_equal(65519, and(invert(16), 65535)) - call assert_equal(65407, and(invert(128), 65535)) - call assert_fails("call invert(1.0)", 'E805:') - call assert_fails("call invert([])", 'E745:') - call assert_fails("call invert({})", 'E728:') -endfunc - -" Test using bang after user command {{{1 -func Test_user_command_with_bang() - command -bang Nieuw let nieuw = 1 - Ni! - call assert_equal(1, nieuw) - unlet nieuw - delcommand Nieuw -endfunc - -func Test_script_expand_sfile() - let lines =<< trim END - func s:snr() - return expand('<sfile>') - endfunc - let g:result = s:snr() - END - call writefile(lines, 'Xexpand') - source Xexpand - call assert_match('<SNR>\d\+_snr', g:result) - source Xexpand - call assert_match('<SNR>\d\+_snr', g:result) - - call delete('Xexpand') - unlet g:result -endfunc - -func Test_compound_assignment_operators() - " Test for number - let x = 1 - let x += 10 - call assert_equal(11, x) - let x -= 5 - call assert_equal(6, x) - let x *= 4 - call assert_equal(24, x) - let x /= 3 - call assert_equal(8, x) - let x %= 3 - call assert_equal(2, x) - let x .= 'n' - call assert_equal('2n', x) - - " Test special cases: division or modulus with 0. - let x = 1 - let x /= 0 - call assert_equal(0x7FFFFFFFFFFFFFFF, x) - - let x = -1 - let x /= 0 - call assert_equal(-0x7FFFFFFFFFFFFFFF, x) - - let x = 0 - let x /= 0 - call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x) - - let x = 1 - let x %= 0 - call assert_equal(0, x) - - let x = -1 - let x %= 0 - call assert_equal(0, x) - - let x = 0 - let x %= 0 - call assert_equal(0, x) - - " Test for string - let x = 'str' - let x .= 'ing' - call assert_equal('string', x) - let x += 1 - call assert_equal(1, x) - - if has('float') - " Test for float - let x -= 1.5 - call assert_equal(-0.5, x) - let x = 0.5 - let x += 4.5 - call assert_equal(5.0, x) - let x -= 1.5 - call assert_equal(3.5, x) - let x *= 3.0 - call assert_equal(10.5, x) - let x /= 2.5 - call assert_equal(4.2, x) - call assert_fails('let x %= 0.5', 'E734') - call assert_fails('let x .= "f"', 'E734') - let x = !3.14 - call assert_equal(0.0, x) - - " integer and float operations - let x = 1 - let x *= 2.1 - call assert_equal(2.1, x) - let x = 1 - let x /= 0.25 - call assert_equal(4.0, x) - let x = 1 - call assert_fails('let x %= 0.25', 'E734:') - let x = 1 - call assert_fails('let x .= 0.25', 'E734:') - let x = 1.0 - call assert_fails('let x += [1.1]', 'E734:') - endif - - " Test for environment variable - let $FOO = 1 - call assert_fails('let $FOO += 1', 'E734') - call assert_fails('let $FOO -= 1', 'E734') - call assert_fails('let $FOO *= 1', 'E734') - call assert_fails('let $FOO /= 1', 'E734') - call assert_fails('let $FOO %= 1', 'E734') - let $FOO .= 's' - call assert_equal('1s', $FOO) - unlet $FOO - - " Test for option variable (type: number) - let &scrolljump = 1 - let &scrolljump += 5 - call assert_equal(6, &scrolljump) - let &scrolljump -= 2 - call assert_equal(4, &scrolljump) - let &scrolljump *= 3 - call assert_equal(12, &scrolljump) - let &scrolljump /= 2 - call assert_equal(6, &scrolljump) - let &scrolljump %= 5 - call assert_equal(1, &scrolljump) - call assert_fails('let &scrolljump .= "j"', 'E734:') - set scrolljump&vim - - let &foldlevelstart = 2 - let &foldlevelstart -= 1 - call assert_equal(1, &foldlevelstart) - let &foldlevelstart -= 1 - call assert_equal(0, &foldlevelstart) - let &foldlevelstart = 2 - let &foldlevelstart -= 2 - call assert_equal(0, &foldlevelstart) - - " Test for register - let @/ = 1 - call assert_fails('let @/ += 1', 'E734:') - call assert_fails('let @/ -= 1', 'E734:') - call assert_fails('let @/ *= 1', 'E734:') - call assert_fails('let @/ /= 1', 'E734:') - call assert_fails('let @/ %= 1', 'E734:') - let @/ .= 's' - call assert_equal('1s', @/) - let @/ = '' -endfunc - -func Test_unlet_env() - let $TESTVAR = 'yes' - call assert_equal('yes', $TESTVAR) - call assert_fails('lockvar $TESTVAR', 'E940') - call assert_fails('unlockvar $TESTVAR', 'E940') - call assert_equal('yes', $TESTVAR) - if 0 - unlet $TESTVAR - endif - call assert_equal('yes', $TESTVAR) - unlet $TESTVAR - call assert_equal('', $TESTVAR) -endfunc - -" Test for missing :endif, :endfor, :endwhile and :endtry {{{1 -func Test_missing_end() - call writefile(['if 2 > 1', 'echo ">"'], 'Xscript') - call assert_fails('source Xscript', 'E171:') - call writefile(['for i in range(5)', 'echo i'], 'Xscript') - call assert_fails('source Xscript', 'E170:') - call writefile(['while v:true', 'echo "."'], 'Xscript') - call assert_fails('source Xscript', 'E170:') - call writefile(['try', 'echo "."'], 'Xscript') - call assert_fails('source Xscript', 'E600:') - call delete('Xscript') - - " Using endfor with :while - let caught_e732 = 0 - try - while v:true - endfor - catch /E732:/ - let caught_e732 = 1 - endtry - call assert_equal(1, caught_e732) - - " Using endwhile with :for - let caught_e733 = 0 - try - for i in range(1) - endwhile - catch /E733:/ - let caught_e733 = 1 - endtry - call assert_equal(1, caught_e733) - - " Using endfunc with :if - call assert_fails('exe "if 1 | endfunc | endif"', 'E193:') - - " Missing 'in' in a :for statement - call assert_fails('for i range(1) | endfor', 'E690:') - - " Incorrect number of variables in for - call assert_fails('for [i,] in range(3) | endfor', 'E475:') -endfunc - -" Test for deep nesting of if/for/while/try statements {{{1 -func Test_deep_nest() - CheckRunVimInTerminal - - let lines =<< trim [SCRIPT] - " Deep nesting of if ... endif - func Test1() - let @a = join(repeat(['if v:true'], 51), "\n") - let @a ..= "\n" - let @a ..= join(repeat(['endif'], 51), "\n") - @a - let @a = '' - endfunc - - " Deep nesting of for ... endfor - func Test2() - let @a = join(repeat(['for i in [1]'], 51), "\n") - let @a ..= "\n" - let @a ..= join(repeat(['endfor'], 51), "\n") - @a - let @a = '' - endfunc - - " Deep nesting of while ... endwhile - func Test3() - let @a = join(repeat(['while v:true'], 51), "\n") - let @a ..= "\n" - let @a ..= join(repeat(['endwhile'], 51), "\n") - @a - let @a = '' - endfunc - - " Deep nesting of try ... endtry - func Test4() - let @a = join(repeat(['try'], 51), "\n") - let @a ..= "\necho v:true\n" - let @a ..= join(repeat(['endtry'], 51), "\n") - @a - let @a = '' - endfunc - - " Deep nesting of function ... endfunction - func Test5() - let @a = join(repeat(['function X()'], 51), "\n") - let @a ..= "\necho v:true\n" - let @a ..= join(repeat(['endfunction'], 51), "\n") - @a - let @a = '' - endfunc - [SCRIPT] - call writefile(lines, 'Xscript') - - let buf = RunVimInTerminal('-S Xscript', {'rows': 6}) - - " Deep nesting of if ... endif - call term_sendkeys(buf, ":call Test1()\n") - call term_wait(buf) - call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))}) - - " Deep nesting of for ... endfor - call term_sendkeys(buf, ":call Test2()\n") - call term_wait(buf) - call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) - - " Deep nesting of while ... endwhile - call term_sendkeys(buf, ":call Test3()\n") - call term_wait(buf) - call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) - - " Deep nesting of try ... endtry - call term_sendkeys(buf, ":call Test4()\n") - call term_wait(buf) - call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))}) - - " Deep nesting of function ... endfunction - call term_sendkeys(buf, ":call Test5()\n") - call term_wait(buf) - call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))}) - call term_sendkeys(buf, "\<C-C>\n") - call term_wait(buf) - - "let l = '' - "for i in range(1, 6) - " let l ..= term_getline(buf, i) . "\n" - "endfor - "call assert_report(l) - - call StopVimInTerminal(buf) - call delete('Xscript') -endfunc - -" Test for errors in converting to float from various types {{{1 -func Test_float_conversion_errors() - if has('float') - call assert_fails('let x = 4.0 % 2.0', 'E804') - call assert_fails('echo 1.1[0]', 'E806') - call assert_fails('echo sort([function("min"), 1], "f")', 'E891:') - call assert_fails('echo 3.2 == "vim"', 'E892:') - call assert_fails('echo sort([[], 1], "f")', 'E893:') - call assert_fails('echo sort([{}, 1], "f")', 'E894:') - call assert_fails('echo 3.2 == v:true', 'E362:') - " call assert_fails('echo 3.2 == v:none', 'E907:') - endif -endfunc - -" invalid function names {{{1 -func Test_invalid_function_names() - " function name not starting with capital - let caught_e128 = 0 - try - func! g:test() - echo "test" - endfunc - catch /E128:/ - let caught_e128 = 1 - endtry - call assert_equal(1, caught_e128) - - " function name includes a colon - let caught_e884 = 0 - try - func! b:test() - echo "test" - endfunc - catch /E884:/ - let caught_e884 = 1 - endtry - call assert_equal(1, caught_e884) - - " function name followed by # - let caught_e128 = 0 - try - func! test2() "# - echo "test2" - endfunc - catch /E128:/ - let caught_e128 = 1 - endtry - call assert_equal(1, caught_e128) - - " function name starting with/without "g:", buffer-local funcref. - function! g:Foo(n) - return 'called Foo(' . a:n . ')' - endfunction - let b:my_func = function('Foo') - call assert_equal('called Foo(1)', b:my_func(1)) - call assert_equal('called Foo(2)', g:Foo(2)) - call assert_equal('called Foo(3)', Foo(3)) - delfunc g:Foo - - " script-local function used in Funcref must exist. - let lines =<< trim END - func s:Testje() - return "foo" - endfunc - let Bar = function('s:Testje') - call assert_equal(0, exists('s:Testje')) - call assert_equal(1, exists('*s:Testje')) - call assert_equal(1, exists('Bar')) - call assert_equal(1, exists('*Bar')) - END - call writefile(lines, 'Xscript') - source Xscript - call delete('Xscript') -endfunc - -" substring and variable name {{{1 -func Test_substring_var() - let str = 'abcdef' - let n = 3 - call assert_equal('def', str[n:]) - call assert_equal('abcd', str[:n]) - call assert_equal('d', str[n:n]) - unlet n - let nn = 3 - call assert_equal('def', str[nn:]) - call assert_equal('abcd', str[:nn]) - call assert_equal('d', str[nn:nn]) - unlet nn - let b:nn = 4 - call assert_equal('ef', str[b:nn:]) - call assert_equal('abcde', str[:b:nn]) - call assert_equal('e', str[b:nn:b:nn]) - unlet b:nn -endfunc - -" Test using s: with a typed command {{{1 -func Test_typed_script_var() - CheckRunVimInTerminal - - let buf = RunVimInTerminal('', {'rows': 6}) - - " Deep nesting of if ... endif - call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n") - call TermWait(buf) - call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))}) - - call StopVimInTerminal(buf) -endfunc - -func Test_for_over_string() - let res = '' - for c in 'aéc̀d' - let res ..= c .. '-' - endfor - call assert_equal('a-é-c̀-d-', res) - - let res = '' - for c in '' - let res ..= c .. '-' - endfor - call assert_equal('', res) - - let res = '' - for c in v:_null_string - let res ..= c .. '-' - endfor - call assert_equal('', res) -endfunc - -"------------------------------------------------------------------------------- -" Modelines {{{1 -" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker -"------------------------------------------------------------------------------- |