blob: 8c931992441ebf6b739df2f1227fcc72ab012332 [file] [log] [blame]
Bram Moolenaar5d7ead32018-02-27 17:17:42 +01001" Test various aspects of the Vim script language.
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02002" Most of this was formerly in test49.vim (developed by Servatius Brandt
3" <Servatius.Brandt@fujitsu-siemens.com>)
Bram Moolenaarf49e2402015-12-30 15:59:25 +01004
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02005source check.vim
Bram Moolenaar93344c22019-08-14 21:12:05 +02006source shared.vim
Bram Moolenaara6296202020-08-05 11:23:13 +02007source script_util.vim
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02008
Bram Moolenaarf49e2402015-12-30 15:59:25 +01009"-------------------------------------------------------------------------------
10" Test environment {{{1
11"-------------------------------------------------------------------------------
12
Bram Moolenaarf49e2402015-12-30 15:59:25 +010013" Append a message to the "messages" file
Bram Moolenaar1e115362019-01-09 23:01:02 +010014func Xout(text)
Bram Moolenaarf49e2402015-12-30 15:59:25 +010015 split messages
16 $put =a:text
17 wq
18endfunc
19
20com! -nargs=1 Xout call Xout(<args>)
21
Bram Moolenaara6296202020-08-05 11:23:13 +020022" Create a new instance of Vim and run the commands in 'test' and then 'verify'
23" The commands in 'test' are expected to store the test results in the Xtest.out
24" file. If the test passes successfully, then Xtest.out should be empty.
25func RunInNewVim(test, verify)
26 let init =<< trim END
Bram Moolenaarefb64822020-08-10 22:15:30 +020027 set cpo-=C " support line-continuation in sourced script
Bram Moolenaara6296202020-08-05 11:23:13 +020028 source script_util.vim
29 XpathINIT
30 XloopINIT
31 END
32 let cleanup =<< trim END
33 call writefile(v:errors, 'Xtest.out')
34 qall
35 END
36 call writefile(init, 'Xtest.vim')
37 call writefile(a:test, 'Xtest.vim', 'a')
38 call writefile(a:verify, 'Xverify.vim')
39 call writefile(cleanup, 'Xverify.vim', 'a')
40 call RunVim([], [], "-S Xtest.vim -S Xverify.vim")
41 call assert_equal([], readfile('Xtest.out'))
42 call delete('Xtest.out')
43 call delete('Xtest.vim')
44 call delete('Xverify.vim')
Bram Moolenaar1e115362019-01-09 23:01:02 +010045endfunc
Bram Moolenaarf49e2402015-12-30 15:59:25 +010046
Bram Moolenaarf49e2402015-12-30 15:59:25 +010047"-------------------------------------------------------------------------------
48" Test 1: :endwhile in function {{{1
49"
50" Detect if a broken loop is (incorrectly) reactivated by the
51" :endwhile. Use a :return to prevent an endless loop, and make
52" this test first to get a meaningful result on an error before other
53" tests will hang.
54"-------------------------------------------------------------------------------
55
Bram Moolenaara6296202020-08-05 11:23:13 +020056func T1_F()
Bram Moolenaarf49e2402015-12-30 15:59:25 +010057 Xpath 'a'
58 let first = 1
59 while 1
60 Xpath 'b'
61 if first
62 Xpath 'c'
63 let first = 0
64 break
65 else
66 Xpath 'd'
67 return
68 endif
69 endwhile
Bram Moolenaara6296202020-08-05 11:23:13 +020070endfunc
Bram Moolenaarf49e2402015-12-30 15:59:25 +010071
Bram Moolenaara6296202020-08-05 11:23:13 +020072func T1_G()
Bram Moolenaarf49e2402015-12-30 15:59:25 +010073 Xpath 'h'
74 let first = 1
75 while 1
76 Xpath 'i'
77 if first
78 Xpath 'j'
79 let first = 0
80 break
81 else
82 Xpath 'k'
83 return
84 endif
85 if 1 " unmatched :if
86 endwhile
Bram Moolenaara6296202020-08-05 11:23:13 +020087endfunc
Bram Moolenaarf49e2402015-12-30 15:59:25 +010088
89func Test_endwhile_function()
90 XpathINIT
91 call T1_F()
92 Xpath 'F'
93
94 try
95 call T1_G()
96 catch
97 " Catch missing :endif
Bram Moolenaare2e40752020-09-04 21:18:46 +020098 call assert_true(v:exception =~ 'E171:')
Bram Moolenaarf49e2402015-12-30 15:59:25 +010099 Xpath 'x'
100 endtry
101 Xpath 'G'
102
103 call assert_equal('abcFhijxG', g:Xpath)
104endfunc
105
106"-------------------------------------------------------------------------------
107" Test 2: :endwhile in script {{{1
108"
109" Detect if a broken loop is (incorrectly) reactivated by the
110" :endwhile. Use a :finish to prevent an endless loop, and place
111" this test before others that might hang to get a meaningful result
112" on an error.
113"
114" This test executes the bodies of the functions T1_F and T1_G from
115" the previous test as script files (:return replaced by :finish).
116"-------------------------------------------------------------------------------
117
118func Test_endwhile_script()
119 XpathINIT
120 ExecAsScript T1_F
121 Xpath 'F'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100122 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100123
124 try
125 ExecAsScript T1_G
126 catch
127 " Catch missing :endif
Bram Moolenaare2e40752020-09-04 21:18:46 +0200128 call assert_true(v:exception =~ 'E171:')
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100129 Xpath 'x'
130 endtry
131 Xpath 'G'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100132 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100133
134 call assert_equal('abcFhijxG', g:Xpath)
135endfunc
136
137"-------------------------------------------------------------------------------
138" Test 3: :if, :elseif, :while, :continue, :break {{{1
139"-------------------------------------------------------------------------------
140
Bram Moolenaara6296202020-08-05 11:23:13 +0200141func Test_if_while()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100142 XpathINIT
143 if 1
144 Xpath 'a'
145 let loops = 3
146 while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
147 if loops <= 0
148 let break_err = 1
149 let loops = -1
150 else
151 Xpath 'b' . loops
152 endif
153 if (loops == 2)
154 while loops == 2 " dummy loop
155 Xpath 'c' . loops
156 let loops = loops - 1
157 continue " stop dummy loop
158 Xpath 'd' . loops
159 endwhile
160 continue " continue main loop
161 Xpath 'e' . loops
162 elseif (loops == 1)
163 let p = 1
164 while p " dummy loop
165 Xpath 'f' . loops
166 let p = 0
167 break " break dummy loop
168 Xpath 'g' . loops
169 endwhile
170 Xpath 'h' . loops
171 unlet p
172 break " break main loop
173 Xpath 'i' . loops
174 endif
175 if (loops > 0)
176 Xpath 'j' . loops
177 endif
178 while loops == 3 " dummy loop
179 let loops = loops - 1
180 endwhile " end dummy loop
181 endwhile " end main loop
182 Xpath 'k'
183 else
184 Xpath 'l'
185 endif
186 Xpath 'm'
187 if exists("break_err")
188 Xpath 'm'
189 unlet break_err
190 endif
191
192 unlet loops
193
194 call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
195endfunc
196
197"-------------------------------------------------------------------------------
198" Test 4: :return {{{1
199"-------------------------------------------------------------------------------
200
Bram Moolenaara6296202020-08-05 11:23:13 +0200201func T4_F()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100202 if 1
203 Xpath 'a'
204 let loops = 3
205 while loops > 0 " 3: 2: 1:
206 Xpath 'b' . loops
207 if (loops == 2)
208 Xpath 'c' . loops
209 return
210 Xpath 'd' . loops
211 endif
212 Xpath 'e' . loops
213 let loops = loops - 1
214 endwhile
215 Xpath 'f'
216 else
217 Xpath 'g'
218 endif
Bram Moolenaara6296202020-08-05 11:23:13 +0200219endfunc
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100220
Bram Moolenaara6296202020-08-05 11:23:13 +0200221func Test_return()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100222 XpathINIT
223 call T4_F()
224 Xpath '4'
225
226 call assert_equal('ab3e3b2c24', g:Xpath)
Bram Moolenaara6296202020-08-05 11:23:13 +0200227endfunc
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100228
229
230"-------------------------------------------------------------------------------
231" Test 5: :finish {{{1
232"
233" This test executes the body of the function T4_F from the previous
234" test as a script file (:return replaced by :finish).
235"-------------------------------------------------------------------------------
236
Bram Moolenaara6296202020-08-05 11:23:13 +0200237func Test_finish()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100238 XpathINIT
239 ExecAsScript T4_F
240 Xpath '5'
Bram Moolenaarf4f79b82016-01-25 20:38:30 +0100241 call DeleteTheScript()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100242
243 call assert_equal('ab3e3b2c25', g:Xpath)
Bram Moolenaara6296202020-08-05 11:23:13 +0200244endfunc
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100245
246
247
248"-------------------------------------------------------------------------------
249" Test 6: Defining functions in :while loops {{{1
250"
251" Functions can be defined inside other functions. An inner function
252" gets defined when the outer function is executed. Functions may
253" also be defined inside while loops. Expressions in braces for
254" defining the function name are allowed.
255"
256" The functions are defined when sourcing the script, only the
257" resulting path is checked in the test function.
258"-------------------------------------------------------------------------------
259
260XpathINIT
261
262" The command CALL collects the argument of all its invocations in "calls"
263" when used from a function (that is, when the global variable "calls" needs
264" the "g:" prefix). This is to check that the function code is skipped when
265" the function is defined. For inner functions, do so only if the outer
266" function is not being executed.
267"
268let calls = ""
269com! -nargs=1 CALL
Bram Moolenaar1e115362019-01-09 23:01:02 +0100270 \ if !exists("calls") && !exists("outer") |
271 \ let g:calls = g:calls . <args> |
272 \ endif
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100273
274let i = 0
275while i < 3
276 let i = i + 1
277 if i == 1
278 Xpath 'a'
279 function! F1(arg)
280 CALL a:arg
281 let outer = 1
282
283 let j = 0
284 while j < 1
285 Xpath 'b'
286 let j = j + 1
287 function! G1(arg)
288 CALL a:arg
289 endfunction
290 Xpath 'c'
291 endwhile
292 endfunction
293 Xpath 'd'
294
295 continue
296 endif
297
298 Xpath 'e' . i
299 function! F{i}(i, arg)
300 CALL a:arg
301 let outer = 1
302
303 if a:i == 3
304 Xpath 'f'
305 endif
306 let k = 0
307 while k < 3
308 Xpath 'g' . k
309 let k = k + 1
310 function! G{a:i}{k}(arg)
311 CALL a:arg
312 endfunction
313 Xpath 'h' . k
314 endwhile
315 endfunction
316 Xpath 'i'
317
318endwhile
319
320if exists("*G1")
321 Xpath 'j'
322endif
323if exists("*F1")
324 call F1("F1")
325 if exists("*G1")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100326 call G1("G1")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100327 endif
328endif
329
330if exists("G21") || exists("G22") || exists("G23")
331 Xpath 'k'
332endif
333if exists("*F2")
334 call F2(2, "F2")
335 if exists("*G21")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100336 call G21("G21")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100337 endif
338 if exists("*G22")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100339 call G22("G22")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100340 endif
341 if exists("*G23")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100342 call G23("G23")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100343 endif
344endif
345
346if exists("G31") || exists("G32") || exists("G33")
347 Xpath 'l'
348endif
349if exists("*F3")
350 call F3(3, "F3")
351 if exists("*G31")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100352 call G31("G31")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100353 endif
354 if exists("*G32")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100355 call G32("G32")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100356 endif
357 if exists("*G33")
Bram Moolenaar1e115362019-01-09 23:01:02 +0100358 call G33("G33")
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100359 endif
360endif
361
362Xpath 'm'
363
364let g:test6_result = g:Xpath
365let g:test6_calls = calls
366
367unlet calls
368delfunction F1
369delfunction G1
370delfunction F2
371delfunction G21
372delfunction G22
373delfunction G23
374delfunction G31
375delfunction G32
376delfunction G33
377
Bram Moolenaara6296202020-08-05 11:23:13 +0200378func Test_defining_functions()
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100379 call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
380 call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
381endfunc
382
383"-------------------------------------------------------------------------------
Bram Moolenaara2cce862016-01-02 19:50:04 +0100384" Test 7: Continuing on errors outside functions {{{1
385"
386" On an error outside a function, the script processing continues
387" at the line following the outermost :endif or :endwhile. When not
388" inside an :if or :while, the script processing continues at the next
389" line.
390"-------------------------------------------------------------------------------
391
392XpathINIT
393
394if 1
395 Xpath 'a'
396 while 1
397 Xpath 'b'
398 asdf
399 Xpath 'c'
400 break
401 endwhile | Xpath 'd'
402 Xpath 'e'
403endif | Xpath 'f'
404Xpath 'g'
405
406while 1
407 Xpath 'h'
408 if 1
409 Xpath 'i'
410 asdf
411 Xpath 'j'
412 endif | Xpath 'k'
413 Xpath 'l'
414 break
415endwhile | Xpath 'm'
416Xpath 'n'
417
418asdf
419Xpath 'o'
420
421asdf | Xpath 'p'
422Xpath 'q'
423
424let g:test7_result = g:Xpath
425
426func Test_error_in_script()
427 call assert_equal('abghinoq', g:test7_result)
428endfunc
429
430"-------------------------------------------------------------------------------
431" Test 8: Aborting and continuing on errors inside functions {{{1
432"
433" On an error inside a function without the "abort" attribute, the
434" script processing continues at the next line (unless the error was
435" in a :return command). On an error inside a function with the
436" "abort" attribute, the function is aborted and the script processing
437" continues after the function call; the value -1 is returned then.
438"-------------------------------------------------------------------------------
439
440XpathINIT
441
Bram Moolenaara6296202020-08-05 11:23:13 +0200442func T8_F()
Bram Moolenaara2cce862016-01-02 19:50:04 +0100443 if 1
444 Xpath 'a'
445 while 1
446 Xpath 'b'
447 asdf
448 Xpath 'c'
449 asdf | Xpath 'd'
450 Xpath 'e'
451 break
452 endwhile
453 Xpath 'f'
454 endif | Xpath 'g'
455 Xpath 'h'
456
457 while 1
458 Xpath 'i'
459 if 1
460 Xpath 'j'
461 asdf
462 Xpath 'k'
463 asdf | Xpath 'l'
464 Xpath 'm'
465 endif
466 Xpath 'n'
467 break
468 endwhile | Xpath 'o'
469 Xpath 'p'
470
471 return novar " returns (default return value 0)
472 Xpath 'q'
473 return 1 " not reached
Bram Moolenaara6296202020-08-05 11:23:13 +0200474endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100475
Bram Moolenaara6296202020-08-05 11:23:13 +0200476func T8_G() abort
Bram Moolenaara2cce862016-01-02 19:50:04 +0100477 if 1
478 Xpath 'r'
479 while 1
480 Xpath 's'
481 asdf " returns -1
482 Xpath 't'
483 break
484 endwhile
485 Xpath 'v'
486 endif | Xpath 'w'
487 Xpath 'x'
488
489 return -4 " not reached
Bram Moolenaara6296202020-08-05 11:23:13 +0200490endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100491
Bram Moolenaara6296202020-08-05 11:23:13 +0200492func T8_H() abort
Bram Moolenaara2cce862016-01-02 19:50:04 +0100493 while 1
494 Xpath 'A'
495 if 1
496 Xpath 'B'
497 asdf " returns -1
498 Xpath 'C'
499 endif
500 Xpath 'D'
501 break
502 endwhile | Xpath 'E'
503 Xpath 'F'
504
505 return -4 " not reached
Bram Moolenaara6296202020-08-05 11:23:13 +0200506endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100507
508" Aborted functions (T8_G and T8_H) return -1.
509let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
510Xpath 'X'
511let g:test8_result = g:Xpath
512
513func Test_error_in_function()
514 call assert_equal(13, g:test8_sum)
515 call assert_equal('abcefghijkmnoprsABX', g:test8_result)
516
517 delfunction T8_F
518 delfunction T8_G
519 delfunction T8_H
520endfunc
521
522
523"-------------------------------------------------------------------------------
524" Test 9: Continuing after aborted functions {{{1
525"
526" When a function with the "abort" attribute is aborted due to an
527" error, the next function back in the call hierarchy without an
528" "abort" attribute continues; the value -1 is returned then.
529"-------------------------------------------------------------------------------
530
531XpathINIT
532
Bram Moolenaara6296202020-08-05 11:23:13 +0200533func F() abort
Bram Moolenaara2cce862016-01-02 19:50:04 +0100534 Xpath 'a'
535 let result = G() " not aborted
536 Xpath 'b'
537 if result != 2
538 Xpath 'c'
539 endif
540 return 1
Bram Moolenaara6296202020-08-05 11:23:13 +0200541endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100542
Bram Moolenaara6296202020-08-05 11:23:13 +0200543func G() " no abort attribute
Bram Moolenaara2cce862016-01-02 19:50:04 +0100544 Xpath 'd'
545 if H() != -1 " aborted
546 Xpath 'e'
547 endif
548 Xpath 'f'
549 return 2
Bram Moolenaara6296202020-08-05 11:23:13 +0200550endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100551
Bram Moolenaara6296202020-08-05 11:23:13 +0200552func H() abort
Bram Moolenaara2cce862016-01-02 19:50:04 +0100553 Xpath 'g'
554 call I() " aborted
555 Xpath 'h'
556 return 4
Bram Moolenaara6296202020-08-05 11:23:13 +0200557endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100558
Bram Moolenaara6296202020-08-05 11:23:13 +0200559func I() abort
Bram Moolenaara2cce862016-01-02 19:50:04 +0100560 Xpath 'i'
561 asdf " error
562 Xpath 'j'
563 return 8
Bram Moolenaara6296202020-08-05 11:23:13 +0200564endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100565
566if F() != 1
567 Xpath 'k'
568endif
569
570let g:test9_result = g:Xpath
571
572delfunction F
573delfunction G
574delfunction H
575delfunction I
576
577func Test_func_abort()
578 call assert_equal('adgifb', g:test9_result)
579endfunc
580
581
582"-------------------------------------------------------------------------------
583" Test 10: :if, :elseif, :while argument parsing {{{1
584"
585" A '"' or '|' in an argument expression must not be mixed up with
586" a comment or a next command after a bar. Parsing errors should
587" be recognized.
588"-------------------------------------------------------------------------------
589
590XpathINIT
591
Bram Moolenaara6296202020-08-05 11:23:13 +0200592func MSG(enr, emsg)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100593 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
594 if a:enr == ""
595 Xout "TODO: Add message number for:" a:emsg
596 let v:errmsg = ":" . v:errmsg
597 endif
598 let match = 1
599 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
600 let match = 0
601 if v:errmsg == ""
602 Xout "Message missing."
603 else
Bram Moolenaara4208962019-08-24 20:50:19 +0200604 let v:errmsg = v:errmsg->escape('"')
Bram Moolenaara2cce862016-01-02 19:50:04 +0100605 Xout "Unexpected message:" v:errmsg
606 endif
607 endif
608 return match
Bram Moolenaar1e115362019-01-09 23:01:02 +0100609endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100610
611if 1 || strlen("\"") | Xpath 'a'
612 Xpath 'b'
613endif
614Xpath 'c'
615
616if 0
617elseif 1 || strlen("\"") | Xpath 'd'
618 Xpath 'e'
619endif
620Xpath 'f'
621
622while 1 || strlen("\"") | Xpath 'g'
623 Xpath 'h'
624 break
625endwhile
626Xpath 'i'
627
628let v:errmsg = ""
629if 1 ||| strlen("\"") | Xpath 'j'
630 Xpath 'k'
631endif
632Xpath 'l'
633if !MSG('E15', "Invalid expression")
634 Xpath 'm'
635endif
636
637let v:errmsg = ""
638if 0
639elseif 1 ||| strlen("\"") | Xpath 'n'
640 Xpath 'o'
641endif
642Xpath 'p'
643if !MSG('E15', "Invalid expression")
644 Xpath 'q'
645endif
646
647let v:errmsg = ""
648while 1 ||| strlen("\"") | Xpath 'r'
649 Xpath 's'
650 break
651endwhile
652Xpath 't'
653if !MSG('E15', "Invalid expression")
654 Xpath 'u'
655endif
656
657let g:test10_result = g:Xpath
658delfunction MSG
659
660func Test_expr_parsing()
661 call assert_equal('abcdefghilpt', g:test10_result)
662endfunc
663
664
665"-------------------------------------------------------------------------------
666" Test 11: :if, :elseif, :while argument evaluation after abort {{{1
667"
668" When code is skipped over due to an error, the boolean argument to
669" an :if, :elseif, or :while must not be evaluated.
670"-------------------------------------------------------------------------------
671
672XpathINIT
673
674let calls = 0
675
Bram Moolenaara6296202020-08-05 11:23:13 +0200676func P(num)
Bram Moolenaara2cce862016-01-02 19:50:04 +0100677 let g:calls = g:calls + a:num " side effect on call
678 return 0
Bram Moolenaara6296202020-08-05 11:23:13 +0200679endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100680
681if 1
682 Xpath 'a'
683 asdf " error
684 Xpath 'b'
685 if P(1) " should not be called
686 Xpath 'c'
687 elseif !P(2) " should not be called
688 Xpath 'd'
689 else
690 Xpath 'e'
691 endif
692 Xpath 'f'
693 while P(4) " should not be called
694 Xpath 'g'
695 endwhile
696 Xpath 'h'
697endif
698Xpath 'x'
699
700let g:test11_calls = calls
701let g:test11_result = g:Xpath
702
703unlet calls
704delfunction P
705
706func Test_arg_abort()
707 call assert_equal(0, g:test11_calls)
708 call assert_equal('ax', g:test11_result)
709endfunc
710
711
712"-------------------------------------------------------------------------------
713" Test 12: Expressions in braces in skipped code {{{1
714"
715" In code skipped over due to an error or inactive conditional,
716" an expression in braces as part of a variable or function name
717" should not be evaluated.
718"-------------------------------------------------------------------------------
719
720XpathINIT
721
722function! NULL()
723 Xpath 'a'
724 return 0
725endfunction
726
727function! ZERO()
728 Xpath 'b'
729 return 0
730endfunction
731
732function! F0()
733 Xpath 'c'
734endfunction
735
736function! F1(arg)
737 Xpath 'e'
738endfunction
739
740let V0 = 1
741
742Xpath 'f'
743echo 0 ? F{NULL() + V{ZERO()}}() : 1
744
745Xpath 'g'
746if 0
747 Xpath 'h'
748 call F{NULL() + V{ZERO()}}()
749endif
750
751Xpath 'i'
752if 1
753 asdf " error
754 Xpath 'j'
755 call F1(F{NULL() + V{ZERO()}}())
756endif
757
758Xpath 'k'
759if 1
760 asdf " error
761 Xpath 'l'
762 call F{NULL() + V{ZERO()}}()
763endif
764
765let g:test12_result = g:Xpath
766
767func Test_braces_skipped()
768 call assert_equal('fgik', g:test12_result)
769endfunc
770
771
772"-------------------------------------------------------------------------------
773" Test 13: Failure in argument evaluation for :while {{{1
774"
775" A failure in the expression evaluation for the condition of a :while
776" causes the whole :while loop until the matching :endwhile being
777" ignored. Continuation is at the next following line.
778"-------------------------------------------------------------------------------
779
780XpathINIT
781
782Xpath 'a'
783while asdf
784 Xpath 'b'
785 while 1
786 Xpath 'c'
787 break
788 endwhile
789 Xpath 'd'
790 break
791endwhile
792Xpath 'e'
793
794while asdf | Xpath 'f' | endwhile | Xpath 'g'
795Xpath 'h'
796let g:test13_result = g:Xpath
797
798func Test_while_fail()
799 call assert_equal('aeh', g:test13_result)
800endfunc
801
802
803"-------------------------------------------------------------------------------
804" Test 14: Failure in argument evaluation for :if {{{1
805"
806" A failure in the expression evaluation for the condition of an :if
807" does not cause the corresponding :else or :endif being matched to
808" a previous :if/:elseif. Neither of both branches of the failed :if
809" are executed.
810"-------------------------------------------------------------------------------
811
812XpathINIT
813
814function! F()
815 Xpath 'a'
816 let x = 0
817 if x " false
818 Xpath 'b'
819 elseif !x " always true
820 Xpath 'c'
821 let x = 1
822 if g:boolvar " possibly undefined
823 Xpath 'd'
824 else
825 Xpath 'e'
826 endif
827 Xpath 'f'
828 elseif x " never executed
829 Xpath 'g'
830 endif
831 Xpath 'h'
832endfunction
833
834let boolvar = 1
835call F()
836Xpath '-'
837
838unlet boolvar
839call F()
840let g:test14_result = g:Xpath
841
842delfunction F
843
844func Test_if_fail()
845 call assert_equal('acdfh-acfh', g:test14_result)
846endfunc
847
848
849"-------------------------------------------------------------------------------
850" Test 15: Failure in argument evaluation for :if (bar) {{{1
851"
852" Like previous test, except that the failing :if ... | ... | :endif
853" is in a single line.
854"-------------------------------------------------------------------------------
855
856XpathINIT
857
858function! F()
859 Xpath 'a'
860 let x = 0
861 if x " false
862 Xpath 'b'
863 elseif !x " always true
864 Xpath 'c'
865 let x = 1
866 if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
867 Xpath 'f'
868 elseif x " never executed
869 Xpath 'g'
870 endif
871 Xpath 'h'
872endfunction
873
874let boolvar = 1
875call F()
876Xpath '-'
877
878unlet boolvar
879call F()
880let g:test15_result = g:Xpath
881
882delfunction F
883
884func Test_if_bar_fail()
885 call assert_equal('acdfh-acfh', g:test15_result)
886endfunc
887
Bram Moolenaar4119cf82016-01-17 14:59:01 +0100888"-------------------------------------------------------------------------------
Bram Moolenaar1f068232019-11-03 16:17:26 +0100889" Test 16: Double :else or :elseif after :else {{{1
890"
891" Multiple :elses or an :elseif after an :else are forbidden.
892"-------------------------------------------------------------------------------
893
894func T16_F() abort
895 if 0
896 Xpath 'a'
897 else
898 Xpath 'b'
899 else " aborts function
900 Xpath 'c'
901 endif
902 Xpath 'd'
903endfunc
904
905func T16_G() abort
906 if 0
907 Xpath 'a'
908 else
909 Xpath 'b'
910 elseif 1 " aborts function
911 Xpath 'c'
912 else
913 Xpath 'd'
914 endif
915 Xpath 'e'
916endfunc
917
918func T16_H() abort
919 if 0
920 Xpath 'a'
921 elseif 0
922 Xpath 'b'
923 else
924 Xpath 'c'
925 else " aborts function
926 Xpath 'd'
927 endif
928 Xpath 'e'
929endfunc
930
931func T16_I() abort
932 if 0
933 Xpath 'a'
934 elseif 0
935 Xpath 'b'
936 else
937 Xpath 'c'
938 elseif 1 " aborts function
939 Xpath 'd'
940 else
941 Xpath 'e'
942 endif
943 Xpath 'f'
944endfunc
945
946func Test_Multi_Else()
947 XpathINIT
948 try
949 call T16_F()
950 catch /E583:/
951 Xpath 'e'
952 endtry
953 call assert_equal('be', g:Xpath)
954
955 XpathINIT
956 try
957 call T16_G()
958 catch /E584:/
959 Xpath 'f'
960 endtry
961 call assert_equal('bf', g:Xpath)
962
963 XpathINIT
964 try
965 call T16_H()
966 catch /E583:/
967 Xpath 'f'
968 endtry
969 call assert_equal('cf', g:Xpath)
970
971 XpathINIT
972 try
973 call T16_I()
974 catch /E584:/
975 Xpath 'g'
976 endtry
977 call assert_equal('cg', g:Xpath)
978endfunc
979
980"-------------------------------------------------------------------------------
981" Test 17: Nesting of unmatched :if or :endif inside a :while {{{1
982"
983" The :while/:endwhile takes precedence in nesting over an unclosed
984" :if or an unopened :endif.
985"-------------------------------------------------------------------------------
986
987" While loops inside a function are continued on error.
988func T17_F()
989 let loops = 3
990 while loops > 0
991 let loops -= 1
992 Xpath 'a' . loops
993 if (loops == 1)
994 Xpath 'b' . loops
995 continue
996 elseif (loops == 0)
997 Xpath 'c' . loops
998 break
999 elseif 1
1000 Xpath 'd' . loops
1001 " endif missing!
1002 endwhile " :endwhile after :if 1
1003 Xpath 'e'
1004endfunc
1005
1006func T17_G()
1007 let loops = 2
1008 while loops > 0
1009 let loops -= 1
1010 Xpath 'a' . loops
1011 if 0
1012 Xpath 'b' . loops
1013 " endif missing
1014 endwhile " :endwhile after :if 0
1015endfunc
1016
1017func T17_H()
1018 let loops = 2
1019 while loops > 0
1020 let loops -= 1
1021 Xpath 'a' . loops
1022 " if missing!
1023 endif " :endif without :if in while
1024 Xpath 'b' . loops
1025 endwhile
1026endfunc
1027
1028" Error continuation outside a function is at the outermost :endwhile or :endif.
1029XpathINIT
1030let v:errmsg = ''
1031let loops = 2
1032while loops > 0
1033 let loops -= 1
1034 Xpath 'a' . loops
1035 if 0
1036 Xpath 'b' . loops
1037 " endif missing! Following :endwhile fails.
1038endwhile | Xpath 'c'
1039Xpath 'd'
1040call assert_match('E171:', v:errmsg)
1041call assert_equal('a1d', g:Xpath)
1042
1043func Test_unmatched_if_in_while()
1044 XpathINIT
1045 call assert_fails('call T17_F()', 'E171:')
1046 call assert_equal('a2d2a1b1a0c0e', g:Xpath)
1047
1048 XpathINIT
1049 call assert_fails('call T17_G()', 'E171:')
1050 call assert_equal('a1a0', g:Xpath)
1051
1052 XpathINIT
1053 call assert_fails('call T17_H()', 'E580:')
1054 call assert_equal('a1b1a0b0', g:Xpath)
1055endfunc
1056
1057"-------------------------------------------------------------------------------
Bram Moolenaara6296202020-08-05 11:23:13 +02001058" Test 18: Interrupt (Ctrl-C pressed) {{{1
1059"
1060" On an interrupt, the script processing is terminated immediately.
Bram Moolenaar1f068232019-11-03 16:17:26 +01001061"-------------------------------------------------------------------------------
Bram Moolenaara6296202020-08-05 11:23:13 +02001062
1063func Test_interrupt_while_if()
1064 let test =<< trim [CODE]
1065 try
1066 if 1
1067 Xpath 'a'
1068 while 1
1069 Xpath 'b'
1070 if 1
1071 Xpath 'c'
1072 call interrupt()
1073 call assert_report('should not get here')
1074 break
1075 finish
1076 endif | call assert_report('should not get here')
1077 call assert_report('should not get here')
1078 endwhile | call assert_report('should not get here')
1079 call assert_report('should not get here')
1080 endif | call assert_report('should not get here')
1081 call assert_report('should not get here')
1082 catch /^Vim:Interrupt$/
1083 Xpath 'd'
1084 endtry | Xpath 'e'
1085 Xpath 'f'
1086 [CODE]
1087 let verify =<< trim [CODE]
1088 call assert_equal('abcdef', g:Xpath)
1089 [CODE]
1090 call RunInNewVim(test, verify)
1091endfunc
1092
1093func Test_interrupt_try()
1094 let test =<< trim [CODE]
1095 try
1096 try
1097 Xpath 'a'
1098 call interrupt()
1099 call assert_report('should not get here')
1100 endtry | call assert_report('should not get here')
1101 call assert_report('should not get here')
1102 catch /^Vim:Interrupt$/
1103 Xpath 'b'
1104 endtry | Xpath 'c'
1105 Xpath 'd'
1106 [CODE]
1107 let verify =<< trim [CODE]
1108 call assert_equal('abcd', g:Xpath)
1109 [CODE]
1110 call RunInNewVim(test, verify)
1111endfunc
1112
1113func Test_interrupt_func_while_if()
1114 let test =<< trim [CODE]
1115 func F()
1116 if 1
1117 Xpath 'a'
1118 while 1
1119 Xpath 'b'
1120 if 1
1121 Xpath 'c'
1122 call interrupt()
1123 call assert_report('should not get here')
1124 break
1125 return
1126 endif | call assert_report('should not get here')
1127 call assert_report('should not get here')
1128 endwhile | call assert_report('should not get here')
1129 call assert_report('should not get here')
1130 endif | call assert_report('should not get here')
1131 call assert_report('should not get here')
1132 endfunc
1133
1134 Xpath 'd'
1135 try
1136 call F() | call assert_report('should not get here')
1137 catch /^Vim:Interrupt$/
1138 Xpath 'e'
1139 endtry | Xpath 'f'
1140 Xpath 'g'
1141 [CODE]
1142 let verify =<< trim [CODE]
1143 call assert_equal('dabcefg', g:Xpath)
1144 [CODE]
1145 call RunInNewVim(test, verify)
1146endfunc
1147
1148func Test_interrupt_func_try()
1149 let test =<< trim [CODE]
1150 func G()
1151 try
1152 Xpath 'a'
1153 call interrupt()
1154 call assert_report('should not get here')
1155 endtry | call assert_report('should not get here')
1156 call assert_report('should not get here')
1157 endfunc
1158
1159 Xpath 'b'
1160 try
1161 call G() | call assert_report('should not get here')
1162 catch /^Vim:Interrupt$/
1163 Xpath 'c'
1164 endtry | Xpath 'd'
1165 Xpath 'e'
1166 [CODE]
1167 let verify =<< trim [CODE]
1168 call assert_equal('bacde', g:Xpath)
1169 [CODE]
1170 call RunInNewVim(test, verify)
1171endfunc
1172
1173"-------------------------------------------------------------------------------
1174" Test 19: Aborting on errors inside :try/:endtry {{{1
1175"
1176" An error in a command dynamically enclosed in a :try/:endtry region
1177" aborts script processing immediately. It does not matter whether
1178" the failing command is outside or inside a function and whether a
1179" function has an "abort" attribute.
1180"-------------------------------------------------------------------------------
1181
1182func Test_try_error_abort_1()
1183 let test =<< trim [CODE]
1184 func F() abort
1185 Xpath 'a'
1186 asdf
1187 call assert_report('should not get here')
1188 endfunc
1189
1190 try
1191 Xpath 'b'
1192 call F()
1193 call assert_report('should not get here')
1194 endtry | call assert_report('should not get here')
1195 call assert_report('should not get here')
1196 [CODE]
1197 let verify =<< trim [CODE]
1198 call assert_equal('ba', g:Xpath)
1199 [CODE]
1200 call RunInNewVim(test, verify)
1201endfunc
1202
1203func Test_try_error_abort_2()
1204 let test =<< trim [CODE]
1205 func G()
1206 Xpath 'a'
1207 asdf
1208 call assert_report('should not get here')
1209 endfunc
1210
1211 try
1212 Xpath 'b'
1213 call G()
1214 call assert_report('should not get here')
1215 endtry | call assert_report('should not get here')
1216 call assert_report('should not get here')
1217 [CODE]
1218 let verify =<< trim [CODE]
1219 call assert_equal('ba', g:Xpath)
1220 [CODE]
1221 call RunInNewVim(test, verify)
1222endfunc
1223
1224func Test_try_error_abort_3()
1225 let test =<< trim [CODE]
1226 try
1227 Xpath 'a'
1228 asdf
1229 call assert_report('should not get here')
1230 endtry | call assert_report('should not get here')
1231 call assert_report('should not get here')
1232 [CODE]
1233 let verify =<< trim [CODE]
1234 call assert_equal('a', g:Xpath)
1235 [CODE]
1236 call RunInNewVim(test, verify)
1237endfunc
1238
1239func Test_try_error_abort_4()
1240 let test =<< trim [CODE]
1241 if 1
1242 try
1243 Xpath 'a'
1244 asdf
1245 call assert_report('should not get here')
1246 endtry | call assert_report('should not get here')
1247 endif | call assert_report('should not get here')
1248 call assert_report('should not get here')
1249 [CODE]
1250 let verify =<< trim [CODE]
1251 call assert_equal('a', g:Xpath)
1252 [CODE]
1253 call RunInNewVim(test, verify)
1254endfunc
1255
1256func Test_try_error_abort_5()
1257 let test =<< trim [CODE]
1258 let p = 1
1259 while p
1260 let p = 0
1261 try
1262 Xpath 'a'
1263 asdf
1264 call assert_report('should not get here')
1265 endtry | call assert_report('should not get here')
1266 endwhile | call assert_report('should not get here')
1267 call assert_report('should not get here')
1268 [CODE]
1269 let verify =<< trim [CODE]
1270 call assert_equal('a', g:Xpath)
1271 [CODE]
1272 call RunInNewVim(test, verify)
1273endfunc
1274
1275func Test_try_error_abort_6()
1276 let test =<< trim [CODE]
1277 let p = 1
1278 Xpath 'a'
1279 while p
1280 Xpath 'b'
1281 let p = 0
1282 try
1283 Xpath 'c'
1284 endwhile | call assert_report('should not get here')
1285 call assert_report('should not get here')
1286 [CODE]
1287 let verify =<< trim [CODE]
1288 call assert_equal('abc', g:Xpath)
1289 [CODE]
1290 call RunInNewVim(test, verify)
1291endfunc
1292
1293"-------------------------------------------------------------------------------
1294" Test 20: Aborting on errors after :try/:endtry {{{1
1295"
1296" When an error occurs after the last active :try/:endtry region has
1297" been left, termination behavior is as if no :try/:endtry has been
1298" seen.
1299"-------------------------------------------------------------------------------
1300
1301func Test_error_after_try_1()
1302 let test =<< trim [CODE]
1303 let p = 1
1304 while p
1305 let p = 0
1306 Xpath 'a'
1307 try
1308 Xpath 'b'
1309 endtry
1310 asdf
1311 call assert_report('should not get here')
1312 endwhile | call assert_report('should not get here')
1313 Xpath 'c'
1314 [CODE]
1315 let verify =<< trim [CODE]
1316 call assert_equal('abc', g:Xpath)
1317 [CODE]
1318 call RunInNewVim(test, verify)
1319endfunc
1320
1321func Test_error_after_try_2()
1322 let test =<< trim [CODE]
1323 while 1
1324 try
1325 Xpath 'a'
1326 break
1327 call assert_report('should not get here')
1328 endtry
1329 endwhile
1330 Xpath 'b'
1331 asdf
1332 Xpath 'c'
1333 [CODE]
1334 let verify =<< trim [CODE]
1335 call assert_equal('abc', g:Xpath)
1336 [CODE]
1337 call RunInNewVim(test, verify)
1338endfunc
1339
1340func Test_error_after_try_3()
1341 let test =<< trim [CODE]
1342 while 1
1343 try
1344 Xpath 'a'
1345 break
1346 call assert_report('should not get here')
1347 finally
1348 Xpath 'b'
1349 endtry
1350 endwhile
1351 Xpath 'c'
1352 asdf
1353 Xpath 'd'
1354 [CODE]
1355 let verify =<< trim [CODE]
1356 call assert_equal('abcd', g:Xpath)
1357 [CODE]
1358 call RunInNewVim(test, verify)
1359endfunc
1360
1361func Test_error_after_try_4()
1362 let test =<< trim [CODE]
1363 while 1
1364 try
1365 Xpath 'a'
1366 finally
1367 Xpath 'b'
1368 break
1369 call assert_report('should not get here')
1370 endtry
1371 endwhile
1372 Xpath 'c'
1373 asdf
1374 Xpath 'd'
1375 [CODE]
1376 let verify =<< trim [CODE]
1377 call assert_equal('abcd', g:Xpath)
1378 [CODE]
1379 call RunInNewVim(test, verify)
1380endfunc
1381
1382func Test_error_after_try_5()
1383 let test =<< trim [CODE]
1384 let p = 1
1385 while p
1386 let p = 0
1387 try
1388 Xpath 'a'
1389 continue
1390 call assert_report('should not get here')
1391 endtry
1392 endwhile
1393 Xpath 'b'
1394 asdf
1395 Xpath 'c'
1396 [CODE]
1397 let verify =<< trim [CODE]
1398 call assert_equal('abc', g:Xpath)
1399 [CODE]
1400 call RunInNewVim(test, verify)
1401endfunc
1402
1403func Test_error_after_try_6()
1404 let test =<< trim [CODE]
1405 let p = 1
1406 while p
1407 let p = 0
1408 try
1409 Xpath 'a'
1410 continue
1411 call assert_report('should not get here')
1412 finally
1413 Xpath 'b'
1414 endtry
1415 endwhile
1416 Xpath 'c'
1417 asdf
1418 Xpath 'd'
1419 [CODE]
1420 let verify =<< trim [CODE]
1421 call assert_equal('abcd', g:Xpath)
1422 [CODE]
1423 call RunInNewVim(test, verify)
1424endfunc
1425
1426func Test_error_after_try_7()
1427 let test =<< trim [CODE]
1428 let p = 1
1429 while p
1430 let p = 0
1431 try
1432 Xpath 'a'
1433 finally
1434 Xpath 'b'
1435 continue
1436 call assert_report('should not get here')
1437 endtry
1438 endwhile
1439 Xpath 'c'
1440 asdf
1441 Xpath 'd'
1442 [CODE]
1443 let verify =<< trim [CODE]
1444 call assert_equal('abcd', g:Xpath)
1445 [CODE]
1446 call RunInNewVim(test, verify)
1447endfunc
1448
1449"-------------------------------------------------------------------------------
1450" Test 21: :finally for :try after :continue/:break/:return/:finish {{{1
1451"
1452" If a :try conditional stays inactive due to a preceding :continue,
1453" :break, :return, or :finish, its :finally clause should not be
1454" executed.
1455"-------------------------------------------------------------------------------
1456
1457func Test_finally_after_loop_ctrl_statement()
1458 let test =<< trim [CODE]
1459 func F()
1460 let loops = 2
1461 while loops > 0
1462 XloopNEXT
1463 let loops = loops - 1
1464 try
1465 if loops == 1
1466 Xloop 'a'
1467 continue
1468 call assert_report('should not get here')
1469 elseif loops == 0
1470 Xloop 'b'
1471 break
1472 call assert_report('should not get here')
1473 endif
1474
1475 try " inactive
1476 call assert_report('should not get here')
1477 finally
1478 call assert_report('should not get here')
1479 endtry
1480 finally
1481 Xloop 'c'
1482 endtry
1483 call assert_report('should not get here')
1484 endwhile
1485
1486 try
1487 Xpath 'd'
1488 return
1489 call assert_report('should not get here')
1490 try " inactive
1491 call assert_report('should not get here')
1492 finally
1493 call assert_report('should not get here')
1494 endtry
1495 finally
1496 Xpath 'e'
1497 endtry
1498 call assert_report('should not get here')
1499 endfunc
1500
1501 try
1502 Xpath 'f'
1503 call F()
1504 Xpath 'g'
1505 finish
1506 call assert_report('should not get here')
1507 try " inactive
1508 call assert_report('should not get here')
1509 finally
1510 call assert_report('should not get here')
1511 endtry
1512 finally
1513 Xpath 'h'
1514 endtry
1515 call assert_report('should not get here')
1516 [CODE]
1517 let verify =<< trim [CODE]
1518 call assert_equal('fa2c2b3c3degh', g:Xpath)
1519 [CODE]
1520 call RunInNewVim(test, verify)
1521endfunc
1522
1523"-------------------------------------------------------------------------------
1524" Test 22: :finally for a :try after an error/interrupt/:throw {{{1
1525"
1526" If a :try conditional stays inactive due to a preceding error or
1527" interrupt or :throw, its :finally clause should not be executed.
1528"-------------------------------------------------------------------------------
1529
1530func Test_finally_after_error_in_func()
1531 let test =<< trim [CODE]
1532 func Error()
1533 try
1534 Xpath 'b'
1535 asdf " aborting error, triggering error exception
1536 call assert_report('should not get here')
1537 endtry
1538 call assert_report('should not get here')
1539 endfunc
1540
1541 Xpath 'a'
1542 call Error()
1543 call assert_report('should not get here')
1544
1545 if 1 " not active due to error
1546 try " not active since :if inactive
1547 call assert_report('should not get here')
1548 finally
1549 call assert_report('should not get here')
1550 endtry
1551 endif
1552
1553 try " not active due to error
1554 call assert_report('should not get here')
1555 finally
1556 call assert_report('should not get here')
1557 endtry
1558 [CODE]
1559 let verify =<< trim [CODE]
1560 call assert_equal('ab', g:Xpath)
1561 [CODE]
1562 call RunInNewVim(test, verify)
1563endfunc
1564
1565func Test_finally_after_interrupt()
1566 let test =<< trim [CODE]
1567 func Interrupt()
1568 try
1569 Xpath 'a'
1570 call interrupt() " triggering interrupt exception
1571 call assert_report('should not get here')
1572 endtry
1573 endfunc
1574
1575 Xpath 'b'
1576 try
1577 call Interrupt()
1578 catch /^Vim:Interrupt$/
1579 Xpath 'c'
1580 finish
1581 endtry
1582 call assert_report('should not get here')
1583
1584 if 1 " not active due to interrupt
1585 try " not active since :if inactive
1586 call assert_report('should not get here')
1587 finally
1588 call assert_report('should not get here')
1589 endtry
1590 endif
1591
1592 try " not active due to interrupt
1593 call assert_report('should not get here')
1594 finally
1595 call assert_report('should not get here')
1596 endtry
1597 [CODE]
1598 let verify =<< trim [CODE]
1599 call assert_equal('bac', g:Xpath)
1600 [CODE]
1601 call RunInNewVim(test, verify)
1602endfunc
1603
1604func Test_finally_after_throw()
1605 let test =<< trim [CODE]
1606 func Throw()
1607 Xpath 'a'
1608 throw 'xyz'
1609 endfunc
1610
1611 Xpath 'b'
1612 call Throw()
1613 call assert_report('should not get here')
1614
1615 if 1 " not active due to :throw
1616 try " not active since :if inactive
1617 call assert_report('should not get here')
1618 finally
1619 call assert_report('should not get here')
1620 endtry
1621 endif
1622
1623 try " not active due to :throw
1624 call assert_report('should not get here')
1625 finally
1626 call assert_report('should not get here')
1627 endtry
1628 [CODE]
1629 let verify =<< trim [CODE]
1630 call assert_equal('ba', g:Xpath)
1631 [CODE]
1632 call RunInNewVim(test, verify)
1633endfunc
1634
1635"-------------------------------------------------------------------------------
1636" Test 23: :catch clauses for a :try after a :throw {{{1
1637"
1638" If a :try conditional stays inactive due to a preceding :throw,
1639" none of its :catch clauses should be executed.
1640"-------------------------------------------------------------------------------
1641
1642func Test_catch_after_throw()
1643 let test =<< trim [CODE]
1644 try
1645 Xpath 'a'
1646 throw "xyz"
1647 call assert_report('should not get here')
1648
1649 if 1 " not active due to :throw
1650 try " not active since :if inactive
1651 call assert_report('should not get here')
1652 catch /xyz/
1653 call assert_report('should not get here')
1654 endtry
1655 endif
1656 catch /xyz/
1657 Xpath 'b'
1658 endtry
1659
1660 Xpath 'c'
1661 throw "abc"
1662 call assert_report('should not get here')
1663
1664 try " not active due to :throw
1665 call assert_report('should not get here')
1666 catch /abc/
1667 call assert_report('should not get here')
1668 endtry
1669 [CODE]
1670 let verify =<< trim [CODE]
1671 call assert_equal('abc', g:Xpath)
1672 [CODE]
1673 call RunInNewVim(test, verify)
1674endfunc
1675
1676"-------------------------------------------------------------------------------
1677" Test 24: :endtry for a :try after a :throw {{{1
1678"
1679" If a :try conditional stays inactive due to a preceding :throw,
1680" its :endtry should not rethrow the exception to the next surrounding
1681" active :try conditional.
1682"-------------------------------------------------------------------------------
1683
1684func Test_endtry_after_throw()
1685 let test =<< trim [CODE]
1686 try " try 1
1687 try " try 2
1688 Xpath 'a'
1689 throw "xyz" " makes try 2 inactive
1690 call assert_report('should not get here')
1691
1692 try " try 3
1693 call assert_report('should not get here')
1694 endtry " no rethrow to try 1
1695 catch /xyz/ " should catch although try 2 inactive
1696 Xpath 'b'
1697 endtry
1698 catch /xyz/ " try 1 active, but exception already caught
1699 call assert_report('should not get here')
1700 endtry
1701 Xpath 'c'
1702 [CODE]
1703 let verify =<< trim [CODE]
1704 call assert_equal('abc', g:Xpath)
1705 [CODE]
1706 call RunInNewVim(test, verify)
1707endfunc
1708
1709"-------------------------------------------------------------------------------
1710" Test 27: Executing :finally clauses after :return {{{1
1711"
1712" For a :return command dynamically enclosed in a :try/:endtry region,
1713" :finally clauses are executed and the called function is ended.
1714"-------------------------------------------------------------------------------
1715
1716func T27_F()
1717 try
1718 Xpath 'a'
1719 try
1720 Xpath 'b'
1721 return
1722 call assert_report('should not get here')
1723 finally
1724 Xpath 'c'
1725 endtry
1726 Xpath 'd'
1727 finally
1728 Xpath 'e'
1729 endtry
1730 call assert_report('should not get here')
1731endfunc
1732
1733func T27_G()
1734 try
1735 Xpath 'f'
1736 return
1737 call assert_report('should not get here')
1738 finally
1739 Xpath 'g'
1740 call T27_F()
1741 Xpath 'h'
1742 endtry
1743 call assert_report('should not get here')
1744endfunc
1745
1746func T27_H()
1747 try
1748 Xpath 'i'
1749 call T27_G()
1750 Xpath 'j'
1751 finally
1752 Xpath 'k'
1753 return
1754 call assert_report('should not get here')
1755 endtry
1756 call assert_report('should not get here')
1757endfunction
1758
1759func Test_finally_after_return()
1760 XpathINIT
1761 try
1762 Xpath 'l'
1763 call T27_H()
1764 Xpath 'm'
1765 finally
1766 Xpath 'n'
1767 endtry
1768 call assert_equal('lifgabcehjkmn', g:Xpath)
1769endfunc
1770
1771"-------------------------------------------------------------------------------
1772" Test 28: Executing :finally clauses after :finish {{{1
1773"
1774" For a :finish command dynamically enclosed in a :try/:endtry region,
1775" :finally clauses are executed and the sourced file is finished.
1776"
1777" This test executes the bodies of the functions F, G, and H from the
1778" previous test as script files (:return replaced by :finish).
1779"-------------------------------------------------------------------------------
1780
1781func Test_finally_after_finish()
1782 XpathINIT
1783
1784 let scriptF = MakeScript("T27_F")
1785 let scriptG = MakeScript("T27_G", scriptF)
1786 let scriptH = MakeScript("T27_H", scriptG)
1787
1788 try
1789 Xpath 'A'
1790 exec "source" scriptH
1791 Xpath 'B'
1792 finally
1793 Xpath 'C'
1794 endtry
1795 Xpath 'D'
1796 call assert_equal('AifgabcehjkBCD', g:Xpath)
1797 call delete(scriptF)
1798 call delete(scriptG)
1799 call delete(scriptH)
1800endfunc
1801
1802"-------------------------------------------------------------------------------
1803" Test 29: Executing :finally clauses on errors {{{1
1804"
1805" After an error in a command dynamically enclosed in a :try/:endtry
1806" region, :finally clauses are executed and the script processing is
1807" terminated.
1808"-------------------------------------------------------------------------------
1809
1810func Test_finally_after_error_1()
1811 let test =<< trim [CODE]
1812 func F()
1813 while 1
1814 try
1815 Xpath 'a'
1816 while 1
1817 try
1818 Xpath 'b'
1819 asdf " error
1820 call assert_report('should not get here')
1821 finally
1822 Xpath 'c'
1823 endtry | call assert_report('should not get here')
1824 call assert_report('should not get here')
1825 break
1826 endwhile
1827 call assert_report('should not get here')
1828 finally
1829 Xpath 'd'
1830 endtry | call assert_report('should not get here')
1831 call assert_report('should not get here')
1832 break
1833 endwhile
1834 call assert_report('should not get here')
1835 endfunc
1836
1837 while 1
1838 try
1839 Xpath 'e'
1840 while 1
1841 call F()
1842 call assert_report('should not get here')
1843 break
1844 endwhile | call assert_report('should not get here')
1845 call assert_report('should not get here')
1846 finally
1847 Xpath 'f'
1848 endtry | call assert_report('should not get here')
1849 endwhile | call assert_report('should not get here')
1850 call assert_report('should not get here')
1851 [CODE]
1852 let verify =<< trim [CODE]
1853 call assert_equal('eabcdf', g:Xpath)
1854 [CODE]
1855 call RunInNewVim(test, verify)
1856endfunc
1857
1858func Test_finally_after_error_2()
1859 let test =<< trim [CODE]
1860 func G() abort
1861 if 1
1862 try
1863 Xpath 'a'
1864 asdf " error
1865 call assert_report('should not get here')
1866 finally
1867 Xpath 'b'
1868 endtry | Xpath 'c'
1869 endif | Xpath 'd'
1870 call assert_report('should not get here')
1871 endfunc
1872
1873 if 1
1874 try
1875 Xpath 'e'
1876 call G()
1877 call assert_report('should not get here')
1878 finally
1879 Xpath 'f'
1880 endtry | call assert_report('should not get here')
1881 endif | call assert_report('should not get here')
1882 call assert_report('should not get here')
1883 [CODE]
1884 let verify =<< trim [CODE]
1885 call assert_equal('eabf', g:Xpath)
1886 [CODE]
1887 call RunInNewVim(test, verify)
1888endfunc
1889
1890"-------------------------------------------------------------------------------
1891" Test 30: Executing :finally clauses on interrupt {{{1
1892"
1893" After an interrupt in a command dynamically enclosed in
1894" a :try/:endtry region, :finally clauses are executed and the
1895" script processing is terminated.
1896"-------------------------------------------------------------------------------
1897
1898func Test_finally_on_interrupt()
1899 let test =<< trim [CODE]
1900 func F()
1901 try
1902 Xloop 'a'
1903 call interrupt()
1904 call assert_report('should not get here')
1905 finally
1906 Xloop 'b'
1907 endtry
1908 call assert_report('should not get here')
1909 endfunc
1910
1911 try
1912 try
1913 Xpath 'c'
1914 try
1915 Xpath 'd'
1916 call interrupt()
1917 call assert_report('should not get here')
1918 finally
1919 Xpath 'e'
1920 try
1921 Xpath 'f'
1922 try
1923 Xpath 'g'
1924 finally
1925 Xpath 'h'
1926 try
1927 Xpath 'i'
1928 call interrupt()
1929 call assert_report('should not get here')
1930 endtry
1931 call assert_report('should not get here')
1932 endtry
1933 call assert_report('should not get here')
1934 endtry
1935 call assert_report('should not get here')
1936 endtry
1937 call assert_report('should not get here')
1938 finally
1939 Xpath 'j'
1940 try
1941 Xpath 'k'
1942 call F()
1943 call assert_report('should not get here')
1944 finally
1945 Xpath 'l'
1946 try
1947 Xpath 'm'
1948 XloopNEXT
1949 ExecAsScript F
1950 call assert_report('should not get here')
1951 finally
1952 Xpath 'n'
1953 endtry
1954 call assert_report('should not get here')
1955 endtry
1956 call assert_report('should not get here')
1957 endtry
1958 call assert_report('should not get here')
1959 catch /^Vim:Interrupt$/
1960 Xpath 'o'
1961 endtry
1962 [CODE]
1963 let verify =<< trim [CODE]
1964 call assert_equal('cdefghijka1b1lma2b2no', g:Xpath)
1965 [CODE]
1966 call RunInNewVim(test, verify)
1967endfunc
1968
1969"-------------------------------------------------------------------------------
1970" Test 31: Executing :finally clauses after :throw {{{1
1971"
1972" After a :throw dynamically enclosed in a :try/:endtry region,
1973" :finally clauses are executed and the script processing is
1974" terminated.
1975"-------------------------------------------------------------------------------
1976
1977func Test_finally_after_throw_2()
1978 let test =<< trim [CODE]
1979 func F()
1980 try
1981 Xloop 'a'
1982 throw "exception"
1983 call assert_report('should not get here')
1984 finally
1985 Xloop 'b'
1986 endtry
1987 call assert_report('should not get here')
1988 endfunc
1989
1990 try
1991 Xpath 'c'
1992 try
1993 Xpath 'd'
1994 throw "exception"
1995 call assert_report('should not get here')
1996 finally
1997 Xpath 'e'
1998 try
1999 Xpath 'f'
2000 try
2001 Xpath 'g'
2002 finally
2003 Xpath 'h'
2004 try
2005 Xpath 'i'
2006 throw "exception"
2007 call assert_report('should not get here')
2008 endtry
2009 call assert_report('should not get here')
2010 endtry
2011 call assert_report('should not get here')
2012 endtry
2013 call assert_report('should not get here')
2014 endtry
2015 call assert_report('should not get here')
2016 finally
2017 Xpath 'j'
2018 try
2019 Xpath 'k'
2020 call F()
2021 call assert_report('should not get here')
2022 finally
2023 Xpath 'l'
2024 try
2025 Xpath 'm'
2026 XloopNEXT
2027 ExecAsScript F
2028 call assert_report('should not get here')
2029 finally
2030 Xpath 'n'
2031 endtry
2032 call assert_report('should not get here')
2033 endtry
2034 call assert_report('should not get here')
2035 endtry
2036 call assert_report('should not get here')
2037 [CODE]
2038 let verify =<< trim [CODE]
2039 call assert_equal('cdefghijka1b1lma2b2n', g:Xpath)
2040 [CODE]
2041 call RunInNewVim(test, verify)
2042endfunc
2043
2044"-------------------------------------------------------------------------------
2045" Test 34: :finally reason discarded by :continue {{{1
2046"
2047" When a :finally clause is executed due to a :continue, :break,
2048" :return, :finish, error, interrupt or :throw, the jump reason is
2049" discarded by a :continue in the finally clause.
2050"-------------------------------------------------------------------------------
2051
2052func Test_finally_after_continue()
2053 let test =<< trim [CODE]
2054 func C(jump)
2055 XloopNEXT
2056 let loop = 0
2057 while loop < 2
2058 let loop = loop + 1
2059 if loop == 1
2060 try
2061 if a:jump == "continue"
2062 continue
2063 elseif a:jump == "break"
2064 break
2065 elseif a:jump == "return" || a:jump == "finish"
2066 return
2067 elseif a:jump == "error"
2068 asdf
2069 elseif a:jump == "interrupt"
2070 call interrupt()
2071 let dummy = 0
2072 elseif a:jump == "throw"
2073 throw "abc"
2074 endif
2075 finally
2076 continue " discards jump that caused the :finally
2077 call assert_report('should not get here')
2078 endtry
2079 call assert_report('should not get here')
2080 elseif loop == 2
2081 Xloop 'a'
2082 endif
2083 endwhile
2084 endfunc
2085
2086 call C("continue")
2087 Xpath 'b'
2088 call C("break")
2089 Xpath 'c'
2090 call C("return")
2091 Xpath 'd'
2092 let g:jump = "finish"
2093 ExecAsScript C
2094 unlet g:jump
2095 Xpath 'e'
2096 try
2097 call C("error")
2098 Xpath 'f'
2099 finally
2100 Xpath 'g'
2101 try
2102 call C("interrupt")
2103 Xpath 'h'
2104 finally
2105 Xpath 'i'
2106 call C("throw")
2107 Xpath 'j'
2108 endtry
2109 endtry
2110 Xpath 'k'
2111 [CODE]
2112 let verify =<< trim [CODE]
2113 call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
2114 [CODE]
2115 call RunInNewVim(test, verify)
2116endfunc
2117
2118"-------------------------------------------------------------------------------
2119" Test 35: :finally reason discarded by :break {{{1
2120"
2121" When a :finally clause is executed due to a :continue, :break,
2122" :return, :finish, error, interrupt or :throw, the jump reason is
2123" discarded by a :break in the finally clause.
2124"-------------------------------------------------------------------------------
2125
2126func Test_finally_discard_by_break()
2127 let test =<< trim [CODE]
2128 func B(jump)
2129 XloopNEXT
2130 let loop = 0
2131 while loop < 2
2132 let loop = loop + 1
2133 if loop == 1
2134 try
2135 if a:jump == "continue"
2136 continue
2137 elseif a:jump == "break"
2138 break
2139 elseif a:jump == "return" || a:jump == "finish"
2140 return
2141 elseif a:jump == "error"
2142 asdf
2143 elseif a:jump == "interrupt"
2144 call interrupt()
2145 let dummy = 0
2146 elseif a:jump == "throw"
2147 throw "abc"
2148 endif
2149 finally
2150 break " discards jump that caused the :finally
2151 call assert_report('should not get here')
2152 endtry
2153 elseif loop == 2
2154 call assert_report('should not get here')
2155 endif
2156 endwhile
2157 Xloop 'a'
2158 endfunc
2159
2160 call B("continue")
2161 Xpath 'b'
2162 call B("break")
2163 Xpath 'c'
2164 call B("return")
2165 Xpath 'd'
2166 let g:jump = "finish"
2167 ExecAsScript B
2168 unlet g:jump
2169 Xpath 'e'
2170 try
2171 call B("error")
2172 Xpath 'f'
2173 finally
2174 Xpath 'g'
2175 try
2176 call B("interrupt")
2177 Xpath 'h'
2178 finally
2179 Xpath 'i'
2180 call B("throw")
2181 Xpath 'j'
2182 endtry
2183 endtry
2184 Xpath 'k'
2185 [CODE]
2186 let verify =<< trim [CODE]
2187 call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
2188 [CODE]
2189 call RunInNewVim(test, verify)
2190endfunc
2191
2192"-------------------------------------------------------------------------------
2193" Test 36: :finally reason discarded by :return {{{1
2194"
2195" When a :finally clause is executed due to a :continue, :break,
2196" :return, :finish, error, interrupt or :throw, the jump reason is
2197" discarded by a :return in the finally clause.
2198"-------------------------------------------------------------------------------
2199
2200func Test_finally_discard_by_return()
2201 let test =<< trim [CODE]
2202 func R(jump, retval) abort
2203 let loop = 0
2204 while loop < 2
2205 let loop = loop + 1
2206 if loop == 1
2207 try
2208 if a:jump == "continue"
2209 continue
2210 elseif a:jump == "break"
2211 break
2212 elseif a:jump == "return"
2213 return
2214 elseif a:jump == "error"
2215 asdf
2216 elseif a:jump == "interrupt"
2217 call interrupt()
2218 let dummy = 0
2219 elseif a:jump == "throw"
2220 throw "abc"
2221 endif
2222 finally
2223 return a:retval " discards jump that caused the :finally
2224 call assert_report('should not get here')
2225 endtry
2226 elseif loop == 2
2227 call assert_report('should not get here')
2228 endif
2229 endwhile
2230 call assert_report('should not get here')
2231 endfunc
2232
2233 let sum = -R("continue", -8)
2234 Xpath 'a'
2235 let sum = sum - R("break", -16)
2236 Xpath 'b'
2237 let sum = sum - R("return", -32)
2238 Xpath 'c'
2239 try
2240 let sum = sum - R("error", -64)
2241 Xpath 'd'
2242 finally
2243 Xpath 'e'
2244 try
2245 let sum = sum - R("interrupt", -128)
2246 Xpath 'f'
2247 finally
2248 Xpath 'g'
2249 let sum = sum - R("throw", -256)
2250 Xpath 'h'
2251 endtry
2252 endtry
2253 Xpath 'i'
2254
2255 let expected = 8 + 16 + 32 + 64 + 128 + 256
2256 call assert_equal(sum, expected)
2257 [CODE]
2258 let verify =<< trim [CODE]
2259 call assert_equal('abcdefghi', g:Xpath)
2260 [CODE]
2261 call RunInNewVim(test, verify)
2262endfunc
2263
2264"-------------------------------------------------------------------------------
2265" Test 37: :finally reason discarded by :finish {{{1
2266"
2267" When a :finally clause is executed due to a :continue, :break,
2268" :return, :finish, error, interrupt or :throw, the jump reason is
2269" discarded by a :finish in the finally clause.
2270"-------------------------------------------------------------------------------
2271
2272func Test_finally_discard_by_finish()
2273 let test =<< trim [CODE]
2274 func F(jump) " not executed as function, transformed to a script
2275 let loop = 0
2276 while loop < 2
2277 let loop = loop + 1
2278 if loop == 1
2279 try
2280 if a:jump == "continue"
2281 continue
2282 elseif a:jump == "break"
2283 break
2284 elseif a:jump == "finish"
2285 finish
2286 elseif a:jump == "error"
2287 asdf
2288 elseif a:jump == "interrupt"
2289 call interrupt()
2290 let dummy = 0
2291 elseif a:jump == "throw"
2292 throw "abc"
2293 endif
2294 finally
2295 finish " discards jump that caused the :finally
2296 call assert_report('should not get here')
2297 endtry
2298 elseif loop == 2
2299 call assert_report('should not get here')
2300 endif
2301 endwhile
2302 call assert_report('should not get here')
2303 endfunc
2304
2305 let scriptF = MakeScript("F")
2306 delfunction F
2307
2308 let g:jump = "continue"
2309 exec "source" scriptF
2310 Xpath 'a'
2311 let g:jump = "break"
2312 exec "source" scriptF
2313 Xpath 'b'
2314 let g:jump = "finish"
2315 exec "source" scriptF
2316 Xpath 'c'
2317 try
2318 let g:jump = "error"
2319 exec "source" scriptF
2320 Xpath 'd'
2321 finally
2322 Xpath 'e'
2323 try
2324 let g:jump = "interrupt"
2325 exec "source" scriptF
2326 Xpath 'f'
2327 finally
2328 Xpath 'g'
2329 try
2330 let g:jump = "throw"
2331 exec "source" scriptF
2332 Xpath 'h'
2333 finally
2334 Xpath 'i'
2335 endtry
2336 endtry
2337 endtry
2338 unlet g:jump
2339 call delete(scriptF)
2340 [CODE]
2341 let verify =<< trim [CODE]
2342 call assert_equal('abcdefghi', g:Xpath)
2343 [CODE]
2344 call RunInNewVim(test, verify)
2345endfunc
2346
2347"-------------------------------------------------------------------------------
2348" Test 38: :finally reason discarded by an error {{{1
2349"
2350" When a :finally clause is executed due to a :continue, :break,
2351" :return, :finish, error, interrupt or :throw, the jump reason is
2352" discarded by an error in the finally clause.
2353"-------------------------------------------------------------------------------
2354
2355func Test_finally_discard_by_error()
2356 let test =<< trim [CODE]
2357 func E(jump)
2358 let loop = 0
2359 while loop < 2
2360 let loop = loop + 1
2361 if loop == 1
2362 try
2363 if a:jump == "continue"
2364 continue
2365 elseif a:jump == "break"
2366 break
2367 elseif a:jump == "return" || a:jump == "finish"
2368 return
2369 elseif a:jump == "error"
2370 asdf
2371 elseif a:jump == "interrupt"
2372 call interrupt()
2373 let dummy = 0
2374 elseif a:jump == "throw"
2375 throw "abc"
2376 endif
2377 finally
2378 asdf " error; discards jump that caused the :finally
2379 endtry
2380 elseif loop == 2
2381 call assert_report('should not get here')
2382 endif
2383 endwhile
2384 call assert_report('should not get here')
2385 endfunc
2386
2387 try
2388 Xpath 'a'
2389 call E("continue")
2390 call assert_report('should not get here')
2391 finally
2392 try
2393 Xpath 'b'
2394 call E("break")
2395 call assert_report('should not get here')
2396 finally
2397 try
2398 Xpath 'c'
2399 call E("return")
2400 call assert_report('should not get here')
2401 finally
2402 try
2403 Xpath 'd'
2404 let g:jump = "finish"
2405 ExecAsScript E
2406 call assert_report('should not get here')
2407 finally
2408 unlet g:jump
2409 try
2410 Xpath 'e'
2411 call E("error")
2412 call assert_report('should not get here')
2413 finally
2414 try
2415 Xpath 'f'
2416 call E("interrupt")
2417 call assert_report('should not get here')
2418 finally
2419 try
2420 Xpath 'g'
2421 call E("throw")
2422 call assert_report('should not get here')
2423 finally
2424 Xpath 'h'
2425 delfunction E
2426 endtry
2427 endtry
2428 endtry
2429 endtry
2430 endtry
2431 endtry
2432 endtry
2433 call assert_report('should not get here')
2434 [CODE]
2435 let verify =<< trim [CODE]
2436 call assert_equal('abcdefgh', g:Xpath)
2437 [CODE]
2438 call RunInNewVim(test, verify)
2439endfunc
2440
2441"-------------------------------------------------------------------------------
2442" Test 39: :finally reason discarded by an interrupt {{{1
2443"
2444" When a :finally clause is executed due to a :continue, :break,
2445" :return, :finish, error, interrupt or :throw, the jump reason is
2446" discarded by an interrupt in the finally clause.
2447"-------------------------------------------------------------------------------
2448
2449func Test_finally_discarded_by_interrupt()
2450 let test =<< trim [CODE]
2451 func I(jump)
2452 let loop = 0
2453 while loop < 2
2454 let loop = loop + 1
2455 if loop == 1
2456 try
2457 if a:jump == "continue"
2458 continue
2459 elseif a:jump == "break"
2460 break
2461 elseif a:jump == "return" || a:jump == "finish"
2462 return
2463 elseif a:jump == "error"
2464 asdf
2465 elseif a:jump == "interrupt"
2466 call interrupt()
2467 let dummy = 0
2468 elseif a:jump == "throw"
2469 throw "abc"
2470 endif
2471 finally
2472 call interrupt()
2473 let dummy = 0
2474 endtry
2475 elseif loop == 2
2476 call assert_report('should not get here')
2477 endif
2478 endwhile
2479 call assert_report('should not get here')
2480 endfunc
2481
2482 try
2483 try
2484 Xpath 'a'
2485 call I("continue")
2486 call assert_report('should not get here')
2487 finally
2488 try
2489 Xpath 'b'
2490 call I("break")
2491 call assert_report('should not get here')
2492 finally
2493 try
2494 Xpath 'c'
2495 call I("return")
2496 call assert_report('should not get here')
2497 finally
2498 try
2499 Xpath 'd'
2500 let g:jump = "finish"
2501 ExecAsScript I
2502 call assert_report('should not get here')
2503 finally
2504 unlet g:jump
2505 try
2506 Xpath 'e'
2507 call I("error")
2508 call assert_report('should not get here')
2509 finally
2510 try
2511 Xpath 'f'
2512 call I("interrupt")
2513 call assert_report('should not get here')
2514 finally
2515 try
2516 Xpath 'g'
2517 call I("throw")
2518 call assert_report('should not get here')
2519 finally
2520 Xpath 'h'
2521 delfunction I
2522 endtry
2523 endtry
2524 endtry
2525 endtry
2526 endtry
2527 endtry
2528 endtry
2529 call assert_report('should not get here')
2530 catch /^Vim:Interrupt$/
2531 Xpath 'A'
2532 endtry
2533 [CODE]
2534 let verify =<< trim [CODE]
2535 call assert_equal('abcdefghA', g:Xpath)
2536 [CODE]
2537 call RunInNewVim(test, verify)
2538endfunc
2539
2540"-------------------------------------------------------------------------------
2541" Test 40: :finally reason discarded by :throw {{{1
2542"
2543" When a :finally clause is executed due to a :continue, :break,
2544" :return, :finish, error, interrupt or :throw, the jump reason is
2545" discarded by a :throw in the finally clause.
2546"-------------------------------------------------------------------------------
2547
2548func Test_finally_discard_by_throw()
2549 let test =<< trim [CODE]
2550 func T(jump)
2551 let loop = 0
2552 while loop < 2
2553 let loop = loop + 1
2554 if loop == 1
2555 try
2556 if a:jump == "continue"
2557 continue
2558 elseif a:jump == "break"
2559 break
2560 elseif a:jump == "return" || a:jump == "finish"
2561 return
2562 elseif a:jump == "error"
2563 asdf
2564 elseif a:jump == "interrupt"
2565 call interrupt()
2566 let dummy = 0
2567 elseif a:jump == "throw"
2568 throw "abc"
2569 endif
2570 finally
2571 throw "xyz" " discards jump that caused the :finally
2572 endtry
2573 elseif loop == 2
2574 call assert_report('should not get here')
2575 endif
2576 endwhile
2577 call assert_report('should not get here')
2578 endfunc
2579
2580 try
2581 Xpath 'a'
2582 call T("continue")
2583 call assert_report('should not get here')
2584 finally
2585 try
2586 Xpath 'b'
2587 call T("break")
2588 call assert_report('should not get here')
2589 finally
2590 try
2591 Xpath 'c'
2592 call T("return")
2593 call assert_report('should not get here')
2594 finally
2595 try
2596 Xpath 'd'
2597 let g:jump = "finish"
2598 ExecAsScript T
2599 call assert_report('should not get here')
2600 finally
2601 unlet g:jump
2602 try
2603 Xpath 'e'
2604 call T("error")
2605 call assert_report('should not get here')
2606 finally
2607 try
2608 Xpath 'f'
2609 call T("interrupt")
2610 call assert_report('should not get here')
2611 finally
2612 try
2613 Xpath 'g'
2614 call T("throw")
2615 call assert_report('should not get here')
2616 finally
2617 Xpath 'h'
2618 delfunction T
2619 endtry
2620 endtry
2621 endtry
2622 endtry
2623 endtry
2624 endtry
2625 endtry
2626 call assert_report('should not get here')
2627 [CODE]
2628 let verify =<< trim [CODE]
2629 call assert_equal('abcdefgh', g:Xpath)
2630 [CODE]
2631 call RunInNewVim(test, verify)
2632endfunc
2633
2634"-------------------------------------------------------------------------------
2635" Test 49: Throwing exceptions across functions {{{1
2636"
2637" When an exception is thrown but not caught inside a function, the
2638" caller is checked for a matching :catch clause.
2639"-------------------------------------------------------------------------------
2640
2641func T49_C()
2642 try
2643 Xpath 'a'
2644 throw "arrgh"
2645 call assert_report('should not get here')
2646 catch /arrgh/
2647 Xpath 'b'
2648 endtry
2649 Xpath 'c'
2650endfunc
2651
2652func T49_T1()
2653 XloopNEXT
2654 try
2655 Xloop 'd'
2656 throw "arrgh"
2657 call assert_report('should not get here')
2658 finally
2659 Xloop 'e'
2660 endtry
2661 Xloop 'f'
2662endfunc
2663
2664func T49_T2()
2665 try
2666 Xpath 'g'
2667 call T49_T1()
2668 call assert_report('should not get here')
2669 finally
2670 Xpath 'h'
2671 endtry
2672 call assert_report('should not get here')
2673endfunc
2674
2675func Test_throw_exception_across_funcs()
2676 XpathINIT
2677 XloopINIT
2678 try
2679 Xpath 'i'
2680 call T49_C() " throw and catch
2681 Xpath 'j'
2682 catch /.*/
2683 call assert_report('should not get here')
2684 endtry
2685
2686 try
2687 Xpath 'k'
2688 call T49_T1() " throw, one level
2689 call assert_report('should not get here')
2690 catch /arrgh/
2691 Xpath 'l'
2692 catch /.*/
2693 call assert_report('should not get here')
2694 endtry
2695
2696 try
2697 Xpath 'm'
2698 call T49_T2() " throw, two levels
2699 call assert_report('should not get here')
2700 catch /arrgh/
2701 Xpath 'n'
2702 catch /.*/
2703 call assert_report('should not get here')
2704 endtry
2705 Xpath 'o'
2706
2707 call assert_equal('iabcjkd2e2lmgd3e3hno', g:Xpath)
2708endfunc
2709
2710"-------------------------------------------------------------------------------
2711" Test 50: Throwing exceptions across script files {{{1
2712"
2713" When an exception is thrown but not caught inside a script file,
2714" the sourcing script or function is checked for a matching :catch
2715" clause.
2716"
2717" This test executes the bodies of the functions C, T1, and T2 from
2718" the previous test as script files (:return replaced by :finish).
2719"-------------------------------------------------------------------------------
2720
2721func T50_F()
2722 try
2723 Xpath 'A'
2724 exec "source" g:scriptC
2725 Xpath 'B'
2726 catch /.*/
2727 call assert_report('should not get here')
2728 endtry
2729
2730 try
2731 Xpath 'C'
2732 exec "source" g:scriptT1
2733 call assert_report('should not get here')
2734 catch /arrgh/
2735 Xpath 'D'
2736 catch /.*/
2737 call assert_report('should not get here')
2738 endtry
2739endfunc
2740
2741func Test_throw_across_script()
2742 XpathINIT
2743 XloopINIT
2744 let g:scriptC = MakeScript("T49_C")
2745 let g:scriptT1 = MakeScript("T49_T1")
2746 let scriptT2 = MakeScript("T49_T2", g:scriptT1)
2747
2748 try
2749 Xpath 'E'
2750 call T50_F()
2751 Xpath 'F'
2752 exec "source" scriptT2
2753 call assert_report('should not get here')
2754 catch /arrgh/
2755 Xpath 'G'
2756 catch /.*/
2757 call assert_report('should not get here')
2758 endtry
2759 Xpath 'H'
2760 call assert_equal('EAabcBCd2e2DFgd3e3hGH', g:Xpath)
2761
2762 call delete(g:scriptC)
2763 call delete(g:scriptT1)
2764 call delete(scriptT2)
2765 unlet g:scriptC g:scriptT1 scriptT2
2766endfunc
2767
Bram Moolenaar1f068232019-11-03 16:17:26 +01002768"-------------------------------------------------------------------------------
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02002769" Test 52: Uncaught exceptions {{{1
2770"
2771" When an exception is thrown but not caught, an error message is
2772" displayed when the script is terminated. In case of an interrupt
2773" or error exception, the normal interrupt or error message(s) are
2774" displayed.
2775"-------------------------------------------------------------------------------
2776
2777func Test_uncaught_exception_1()
2778 CheckEnglish
2779
2780 let test =<< trim [CODE]
2781 Xpath 'a'
2782 throw "arrgh"
2783 call assert_report('should not get here')`
2784 [CODE]
2785 let verify =<< trim [CODE]
2786 call assert_equal('E605: Exception not caught: arrgh', v:errmsg)
2787 call assert_equal('a', g:Xpath)
2788 [CODE]
2789 call RunInNewVim(test, verify)
2790endfunc
2791
2792func Test_uncaught_exception_2()
2793 CheckEnglish
2794
2795 let test =<< trim [CODE]
2796 try
2797 Xpath 'a'
2798 throw "oops"
2799 call assert_report('should not get here')`
2800 catch /arrgh/
2801 call assert_report('should not get here')`
2802 endtry
2803 call assert_report('should not get here')`
2804 [CODE]
2805 let verify =<< trim [CODE]
2806 call assert_equal('E605: Exception not caught: oops', v:errmsg)
2807 call assert_equal('a', g:Xpath)
2808 [CODE]
2809 call RunInNewVim(test, verify)
2810endfunc
2811
2812func Test_uncaught_exception_3()
2813 CheckEnglish
2814
2815 let test =<< trim [CODE]
2816 func T()
2817 Xpath 'c'
2818 throw "brrr"
2819 call assert_report('should not get here')`
2820 endfunc
2821
2822 try
2823 Xpath 'a'
2824 throw "arrgh"
2825 call assert_report('should not get here')`
2826 catch /.*/
2827 Xpath 'b'
2828 call T()
2829 call assert_report('should not get here')`
2830 endtry
2831 call assert_report('should not get here')`
2832 [CODE]
2833 let verify =<< trim [CODE]
2834 call assert_equal('E605: Exception not caught: brrr', v:errmsg)
2835 call assert_equal('abc', g:Xpath)
2836 [CODE]
2837 call RunInNewVim(test, verify)
2838endfunc
2839
2840func Test_uncaught_exception_4()
2841 CheckEnglish
2842
2843 let test =<< trim [CODE]
2844 try
2845 Xpath 'a'
2846 throw "arrgh"
2847 call assert_report('should not get here')`
2848 finally
2849 Xpath 'b'
2850 throw "brrr"
2851 call assert_report('should not get here')`
2852 endtry
2853 call assert_report('should not get here')`
2854 [CODE]
2855 let verify =<< trim [CODE]
2856 call assert_equal('E605: Exception not caught: brrr', v:errmsg)
2857 call assert_equal('ab', g:Xpath)
2858 [CODE]
2859 call RunInNewVim(test, verify)
2860endfunc
2861
2862func Test_uncaught_exception_5()
2863 CheckEnglish
2864
2865 " Need to catch and handle interrupt, otherwise the test will wait for the
2866 " user to press <Enter> to continue
2867 let test =<< trim [CODE]
2868 try
2869 try
2870 Xpath 'a'
2871 call interrupt()
2872 call assert_report('should not get here')
2873 endtry
2874 call assert_report('should not get here')
2875 catch /^Vim:Interrupt$/
2876 Xpath 'b'
2877 endtry
2878 [CODE]
2879 let verify =<< trim [CODE]
2880 call assert_equal('ab', g:Xpath)
2881 [CODE]
2882 call RunInNewVim(test, verify)
2883endfunc
2884
2885func Test_uncaught_exception_6()
2886 CheckEnglish
2887
2888 let test =<< trim [CODE]
2889 try
2890 Xpath 'a'
2891 let x = novar " error E121; exception: E121
2892 catch /E15:/ " should not catch
2893 call assert_report('should not get here')
2894 endtry
2895 call assert_report('should not get here')
2896 [CODE]
2897 let verify =<< trim [CODE]
2898 call assert_equal('a', g:Xpath)
2899 call assert_equal('E121: Undefined variable: novar', v:errmsg)
2900 [CODE]
2901 call RunInNewVim(test, verify)
2902endfunc
2903
2904func Test_uncaught_exception_7()
2905 CheckEnglish
2906
2907 let test =<< trim [CODE]
2908 try
2909 Xpath 'a'
2910 " error E108/E488; exception: E488
2911 unlet novar #
2912 catch /E108:/ " should not catch
2913 call assert_report('should not get here')
2914 endtry
2915 call assert_report('should not get here')
2916 [CODE]
2917 let verify =<< trim [CODE]
2918 call assert_equal('a', g:Xpath)
2919 call assert_equal('E488: Trailing characters: #', v:errmsg)
2920 [CODE]
2921 call RunInNewVim(test, verify)
2922endfunc
2923
2924"-------------------------------------------------------------------------------
2925" Test 53: Nesting errors: :endif/:else/:elseif {{{1
2926"
2927" For nesting errors of :if conditionals the correct error messages
2928" should be given.
2929"-------------------------------------------------------------------------------
2930
2931func Test_nested_if_else_errors()
2932 CheckEnglish
2933
2934 " :endif without :if
2935 let code =<< trim END
2936 endif
2937 END
2938 call writefile(code, 'Xtest')
2939 call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2940
2941 " :endif without :if
2942 let code =<< trim END
2943 while 1
2944 endif
2945 endwhile
2946 END
2947 call writefile(code, 'Xtest')
2948 call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2949
2950 " :endif without :if
2951 let code =<< trim END
2952 try
2953 finally
2954 endif
2955 endtry
2956 END
2957 call writefile(code, 'Xtest')
2958 call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2959
2960 " :endif without :if
2961 let code =<< trim END
2962 try
2963 endif
2964 endtry
2965 END
2966 call writefile(code, 'Xtest')
2967 call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2968
2969 " :endif without :if
2970 let code =<< trim END
2971 try
2972 throw "a"
2973 catch /a/
2974 endif
2975 endtry
2976 END
2977 call writefile(code, 'Xtest')
2978 call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2979
2980 " :else without :if
2981 let code =<< trim END
2982 else
2983 END
2984 call writefile(code, 'Xtest')
2985 call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
2986
2987 " :else without :if
2988 let code =<< trim END
2989 while 1
2990 else
2991 endwhile
2992 END
2993 call writefile(code, 'Xtest')
2994 call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
2995
2996 " :else without :if
2997 let code =<< trim END
2998 try
2999 finally
3000 else
3001 endtry
3002 END
3003 call writefile(code, 'Xtest')
3004 call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3005
3006 " :else without :if
3007 let code =<< trim END
3008 try
3009 else
3010 endtry
3011 END
3012 call writefile(code, 'Xtest')
3013 call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3014
3015 " :else without :if
3016 let code =<< trim END
3017 try
3018 throw "a"
3019 catch /a/
3020 else
3021 endtry
3022 END
3023 call writefile(code, 'Xtest')
3024 call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3025
3026 " :elseif without :if
3027 let code =<< trim END
3028 elseif
3029 END
3030 call writefile(code, 'Xtest')
3031 call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3032
3033 " :elseif without :if
3034 let code =<< trim END
3035 while 1
3036 elseif
3037 endwhile
3038 END
3039 call writefile(code, 'Xtest')
3040 call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3041
3042 " :elseif without :if
3043 let code =<< trim END
3044 try
3045 finally
3046 elseif
3047 endtry
3048 END
3049 call writefile(code, 'Xtest')
3050 call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3051
3052 " :elseif without :if
3053 let code =<< trim END
3054 try
3055 elseif
3056 endtry
3057 END
3058 call writefile(code, 'Xtest')
3059 call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3060
3061 " :elseif without :if
3062 let code =<< trim END
3063 try
3064 throw "a"
3065 catch /a/
3066 elseif
3067 endtry
3068 END
3069 call writefile(code, 'Xtest')
3070 call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3071
3072 " multiple :else
3073 let code =<< trim END
3074 if 1
3075 else
3076 else
3077 endif
3078 END
3079 call writefile(code, 'Xtest')
3080 call AssertException(['source Xtest'], 'Vim(else):E583: multiple :else')
3081
3082 " :elseif after :else
3083 let code =<< trim END
3084 if 1
3085 else
3086 elseif 1
3087 endif
3088 END
3089 call writefile(code, 'Xtest')
3090 call AssertException(['source Xtest'], 'Vim(elseif):E584: :elseif after :else')
3091
3092 call delete('Xtest')
3093endfunc
3094
3095"-------------------------------------------------------------------------------
3096" Test 54: Nesting errors: :while/:endwhile {{{1
3097"
3098" For nesting errors of :while conditionals the correct error messages
3099" should be given.
3100"
3101" This test reuses the function MESSAGES() from the previous test.
3102" This functions checks the messages in g:msgfile.
3103"-------------------------------------------------------------------------------
3104
3105func Test_nested_while_error()
3106 CheckEnglish
3107
3108 " :endwhile without :while
3109 let code =<< trim END
3110 endwhile
3111 END
3112 call writefile(code, 'Xtest')
3113 call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3114
3115 " :endwhile without :while
3116 let code =<< trim END
3117 if 1
3118 endwhile
3119 endif
3120 END
3121 call writefile(code, 'Xtest')
3122 call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3123
3124 " Missing :endif
3125 let code =<< trim END
3126 while 1
3127 if 1
3128 endwhile
3129 END
3130 call writefile(code, 'Xtest')
3131 call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
3132
3133 " :endwhile without :while
3134 let code =<< trim END
3135 try
3136 finally
3137 endwhile
3138 endtry
3139 END
3140 call writefile(code, 'Xtest')
3141 call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3142
3143 " Missing :endtry
3144 let code =<< trim END
3145 while 1
3146 try
3147 finally
3148 endwhile
3149 END
3150 call writefile(code, 'Xtest')
3151 call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
3152
3153 " Missing :endtry
3154 let code =<< trim END
3155 while 1
3156 if 1
3157 try
3158 finally
3159 endwhile
3160 END
3161 call writefile(code, 'Xtest')
3162 call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
3163
3164 " Missing :endif
3165 let code =<< trim END
3166 while 1
3167 try
3168 finally
3169 if 1
3170 endwhile
3171 END
3172 call writefile(code, 'Xtest')
3173 call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
3174
3175 " :endwhile without :while
3176 let code =<< trim END
3177 try
3178 endwhile
3179 endtry
3180 END
3181 call writefile(code, 'Xtest')
3182 call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3183
3184 " :endwhile without :while
3185 let code =<< trim END
3186 while 1
3187 try
3188 endwhile
3189 endtry
3190 endwhile
3191 END
3192 call writefile(code, 'Xtest')
3193 call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3194
3195 " :endwhile without :while
3196 let code =<< trim END
3197 try
3198 throw "a"
3199 catch /a/
3200 endwhile
3201 endtry
3202 END
3203 call writefile(code, 'Xtest')
3204 call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3205
3206 " :endwhile without :while
3207 let code =<< trim END
3208 while 1
3209 try
3210 throw "a"
3211 catch /a/
3212 endwhile
3213 endtry
3214 endwhile
3215 END
3216 call writefile(code, 'Xtest')
3217 call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3218
3219 call delete('Xtest')
3220endfunc
3221
3222"-------------------------------------------------------------------------------
3223" Test 55: Nesting errors: :continue/:break {{{1
3224"
3225" For nesting errors of :continue and :break commands the correct
3226" error messages should be given.
3227"
3228" This test reuses the function MESSAGES() from the previous test.
3229" This functions checks the messages in g:msgfile.
3230"-------------------------------------------------------------------------------
3231
3232func Test_nested_cont_break_error()
3233 CheckEnglish
3234
3235 " :continue without :while
3236 let code =<< trim END
3237 continue
3238 END
3239 call writefile(code, 'Xtest')
3240 call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3241
3242 " :continue without :while
3243 let code =<< trim END
3244 if 1
3245 continue
3246 endif
3247 END
3248 call writefile(code, 'Xtest')
3249 call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3250
3251 " :continue without :while
3252 let code =<< trim END
3253 try
3254 finally
3255 continue
3256 endtry
3257 END
3258 call writefile(code, 'Xtest')
3259 call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3260
3261 " :continue without :while
3262 let code =<< trim END
3263 try
3264 continue
3265 endtry
3266 END
3267 call writefile(code, 'Xtest')
3268 call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3269
3270 " :continue without :while
3271 let code =<< trim END
3272 try
3273 throw "a"
3274 catch /a/
3275 continue
3276 endtry
3277 END
3278 call writefile(code, 'Xtest')
3279 call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3280
3281 " :break without :while
3282 let code =<< trim END
3283 break
3284 END
3285 call writefile(code, 'Xtest')
3286 call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3287
3288 " :break without :while
3289 let code =<< trim END
3290 if 1
3291 break
3292 endif
3293 END
3294 call writefile(code, 'Xtest')
3295 call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3296
3297 " :break without :while
3298 let code =<< trim END
3299 try
3300 finally
3301 break
3302 endtry
3303 END
3304 call writefile(code, 'Xtest')
3305 call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3306
3307 " :break without :while
3308 let code =<< trim END
3309 try
3310 break
3311 endtry
3312 END
3313 call writefile(code, 'Xtest')
3314 call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3315
3316 " :break without :while
3317 let code =<< trim END
3318 try
3319 throw "a"
3320 catch /a/
3321 break
3322 endtry
3323 END
3324 call writefile(code, 'Xtest')
3325 call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3326
3327 call delete('Xtest')
3328endfunc
3329
3330"-------------------------------------------------------------------------------
3331" Test 56: Nesting errors: :endtry {{{1
3332"
3333" For nesting errors of :try conditionals the correct error messages
3334" should be given.
3335"
3336" This test reuses the function MESSAGES() from the previous test.
3337" This functions checks the messages in g:msgfile.
3338"-------------------------------------------------------------------------------
3339
3340func Test_nested_endtry_error()
3341 CheckEnglish
3342
3343 " :endtry without :try
3344 let code =<< trim END
3345 endtry
3346 END
3347 call writefile(code, 'Xtest')
3348 call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3349
3350 " :endtry without :try
3351 let code =<< trim END
3352 if 1
3353 endtry
3354 endif
3355 END
3356 call writefile(code, 'Xtest')
3357 call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3358
3359 " :endtry without :try
3360 let code =<< trim END
3361 while 1
3362 endtry
3363 endwhile
3364 END
3365 call writefile(code, 'Xtest')
3366 call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3367
3368 " Missing :endif
3369 let code =<< trim END
3370 try
3371 if 1
3372 endtry
3373 END
3374 call writefile(code, 'Xtest')
3375 call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3376
3377 " Missing :endwhile
3378 let code =<< trim END
3379 try
3380 while 1
3381 endtry
3382 END
3383 call writefile(code, 'Xtest')
3384 call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3385
3386 " Missing :endif
3387 let code =<< trim END
3388 try
3389 finally
3390 if 1
3391 endtry
3392 END
3393 call writefile(code, 'Xtest')
3394 call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3395
3396 " Missing :endwhile
3397 let code =<< trim END
3398 try
3399 finally
3400 while 1
3401 endtry
3402 END
3403 call writefile(code, 'Xtest')
3404 call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3405
3406 " Missing :endif
3407 let code =<< trim END
3408 try
3409 throw "a"
3410 catch /a/
3411 if 1
3412 endtry
3413 END
3414 call writefile(code, 'Xtest')
3415 call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3416
3417 " Missing :endwhile
3418 let code =<< trim END
3419 try
3420 throw "a"
3421 catch /a/
3422 while 1
3423 endtry
3424 END
3425 call writefile(code, 'Xtest')
3426 call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3427
3428 call delete('Xtest')
3429endfunc
3430
3431"-------------------------------------------------------------------------------
3432" Test 57: v:exception and v:throwpoint for user exceptions {{{1
3433"
3434" v:exception evaluates to the value of the exception that was caught
3435" most recently and is not finished. (A caught exception is finished
3436" when the next ":catch", ":finally", or ":endtry" is reached.)
3437" v:throwpoint evaluates to the script/function name and line number
3438" where that exception has been thrown.
3439"-------------------------------------------------------------------------------
3440
3441func Test_user_exception_info()
3442 CheckEnglish
3443
3444 XpathINIT
3445 XloopINIT
3446
3447 func FuncException()
3448 let g:exception = v:exception
3449 endfunc
3450
3451 func FuncThrowpoint()
3452 let g:throwpoint = v:throwpoint
3453 endfunc
3454
3455 let scriptException = MakeScript("FuncException")
3456 let scriptThrowPoint = MakeScript("FuncThrowpoint")
3457
3458 command! CmdException let g:exception = v:exception
3459 command! CmdThrowpoint let g:throwpoint = v:throwpoint
3460
3461 func T(arg, line)
3462 if a:line == 2
3463 throw a:arg " in line 2
3464 elseif a:line == 4
3465 throw a:arg " in line 4
3466 elseif a:line == 6
3467 throw a:arg " in line 6
3468 elseif a:line == 8
3469 throw a:arg " in line 8
3470 endif
3471 endfunc
3472
3473 func G(arg, line)
3474 call T(a:arg, a:line)
3475 endfunc
3476
3477 func F(arg, line)
3478 call G(a:arg, a:line)
3479 endfunc
3480
3481 let scriptT = MakeScript("T")
3482 let scriptG = MakeScript("G", scriptT)
3483 let scriptF = MakeScript("F", scriptG)
3484
3485 try
3486 Xpath 'a'
3487 call F("oops", 2)
3488 catch /.*/
3489 Xpath 'b'
3490 let exception = v:exception
3491 let throwpoint = v:throwpoint
3492 call assert_equal("oops", v:exception)
3493 call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3494 call assert_match('\<2\>', v:throwpoint)
3495
3496 exec "let exception = v:exception"
3497 exec "let throwpoint = v:throwpoint"
3498 call assert_equal("oops", v:exception)
3499 call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3500 call assert_match('\<2\>', v:throwpoint)
3501
3502 CmdException
3503 CmdThrowpoint
3504 call assert_equal("oops", v:exception)
3505 call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3506 call assert_match('\<2\>', v:throwpoint)
3507
3508 call FuncException()
3509 call FuncThrowpoint()
3510 call assert_equal("oops", v:exception)
3511 call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3512 call assert_match('\<2\>', v:throwpoint)
3513
3514 exec "source" scriptException
3515 exec "source" scriptThrowPoint
3516 call assert_equal("oops", v:exception)
3517 call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3518 call assert_match('\<2\>', v:throwpoint)
3519
3520 try
3521 Xpath 'c'
3522 call G("arrgh", 4)
3523 catch /.*/
3524 Xpath 'd'
3525 let exception = v:exception
3526 let throwpoint = v:throwpoint
3527 call assert_equal("arrgh", v:exception)
3528 call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3529 call assert_match('\<4\>', v:throwpoint)
3530
3531 try
3532 Xpath 'e'
3533 let g:arg = "autsch"
3534 let g:line = 6
3535 exec "source" scriptF
3536 catch /.*/
3537 Xpath 'f'
3538 let exception = v:exception
3539 let throwpoint = v:throwpoint
3540 call assert_equal("autsch", v:exception)
3541 call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
3542 call assert_match('\<6\>', v:throwpoint)
3543 finally
3544 Xpath 'g'
3545 let exception = v:exception
3546 let throwpoint = v:throwpoint
3547 call assert_equal("arrgh", v:exception)
3548 call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3549 call assert_match('\<4\>', v:throwpoint)
3550 try
3551 Xpath 'h'
3552 let g:arg = "brrrr"
3553 let g:line = 8
3554 exec "source" scriptG
3555 catch /.*/
3556 Xpath 'i'
3557 let exception = v:exception
3558 let throwpoint = v:throwpoint
3559 " Resolve scriptT for matching it against v:throwpoint.
3560 call assert_equal("brrrr", v:exception)
3561 call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
3562 call assert_match('\<8\>', v:throwpoint)
3563 finally
3564 Xpath 'j'
3565 let exception = v:exception
3566 let throwpoint = v:throwpoint
3567 call assert_equal("arrgh", v:exception)
3568 call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3569 call assert_match('\<4\>', v:throwpoint)
3570 endtry
3571 Xpath 'k'
3572 let exception = v:exception
3573 let throwpoint = v:throwpoint
3574 call assert_equal("arrgh", v:exception)
3575 call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3576 call assert_match('\<4\>', v:throwpoint)
3577 endtry
3578 Xpath 'l'
3579 let exception = v:exception
3580 let throwpoint = v:throwpoint
3581 call assert_equal("arrgh", v:exception)
3582 call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3583 call assert_match('\<4\>', v:throwpoint)
3584 finally
3585 Xpath 'm'
3586 let exception = v:exception
3587 let throwpoint = v:throwpoint
3588 call assert_equal("oops", v:exception)
3589 call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3590 call assert_match('\<2\>', v:throwpoint)
3591 endtry
3592 Xpath 'n'
3593 let exception = v:exception
3594 let throwpoint = v:throwpoint
3595 call assert_equal("oops", v:exception)
3596 call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3597 call assert_match('\<2\>', v:throwpoint)
3598 finally
3599 Xpath 'o'
3600 let exception = v:exception
3601 let throwpoint = v:throwpoint
3602 call assert_equal("", v:exception)
3603 call assert_match('^$', v:throwpoint)
3604 call assert_match('^$', v:throwpoint)
3605 endtry
3606
3607 call assert_equal('abcdefghijklmno', g:Xpath)
3608
3609 unlet exception throwpoint
3610 delfunction FuncException
3611 delfunction FuncThrowpoint
3612 call delete(scriptException)
3613 call delete(scriptThrowPoint)
3614 unlet scriptException scriptThrowPoint
3615 delcommand CmdException
3616 delcommand CmdThrowpoint
3617 delfunction T
3618 delfunction G
3619 delfunction F
3620 call delete(scriptT)
3621 call delete(scriptG)
3622 call delete(scriptF)
3623 unlet scriptT scriptG scriptF
3624endfunc
3625
3626"-------------------------------------------------------------------------------
3627"
3628" Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1
3629"
3630" v:exception and v:throwpoint work also for error and interrupt
3631" exceptions.
3632"-------------------------------------------------------------------------------
3633
3634func Test_execption_info_for_error()
3635 CheckEnglish
3636
3637 let test =<< trim [CODE]
3638 func T(line)
3639 if a:line == 2
3640 delfunction T " error (function in use) in line 2
3641 elseif a:line == 4
3642 call interrupt()
3643 endif
3644 endfunc
3645
3646 while 1
3647 try
3648 Xpath 'a'
3649 call T(2)
3650 call assert_report('should not get here')
3651 catch /.*/
3652 Xpath 'b'
3653 if v:exception !~ 'Vim(delfunction):'
3654 call assert_report('should not get here')
3655 endif
3656 if v:throwpoint !~ '\<T\>'
3657 call assert_report('should not get here')
3658 endif
3659 if v:throwpoint !~ '\<2\>'
3660 call assert_report('should not get here')
3661 endif
3662 finally
3663 Xpath 'c'
3664 if v:exception != ""
3665 call assert_report('should not get here')
3666 endif
3667 if v:throwpoint != ""
3668 call assert_report('should not get here')
3669 endif
3670 break
3671 endtry
3672 endwhile
3673
3674 Xpath 'd'
3675 if v:exception != ""
3676 call assert_report('should not get here')
3677 endif
3678 if v:throwpoint != ""
3679 call assert_report('should not get here')
3680 endif
3681
3682 while 1
3683 try
3684 Xpath 'e'
3685 call T(4)
3686 call assert_report('should not get here')
3687 catch /.*/
3688 Xpath 'f'
3689 if v:exception != 'Vim:Interrupt'
3690 call assert_report('should not get here')
3691 endif
3692 if v:throwpoint !~ 'function T'
3693 call assert_report('should not get here')
3694 endif
3695 if v:throwpoint !~ '\<4\>'
3696 call assert_report('should not get here')
3697 endif
3698 finally
3699 Xpath 'g'
3700 if v:exception != ""
3701 call assert_report('should not get here')
3702 endif
3703 if v:throwpoint != ""
3704 call assert_report('should not get here')
3705 endif
3706 break
3707 endtry
3708 endwhile
3709
3710 Xpath 'h'
3711 if v:exception != ""
3712 call assert_report('should not get here')
3713 endif
3714 if v:throwpoint != ""
3715 call assert_report('should not get here')
3716 endif
3717 [CODE]
3718 let verify =<< trim [CODE]
3719 call assert_equal('abcdefgh', g:Xpath)
3720 [CODE]
3721 call RunInNewVim(test, verify)
3722endfunc
3723
3724"-------------------------------------------------------------------------------
Bram Moolenaarefb64822020-08-10 22:15:30 +02003725"
3726" Test 59: v:exception and v:throwpoint when discarding exceptions {{{1
3727"
3728" When a :catch clause is left by a ":break" etc or an error or
3729" interrupt exception, v:exception and v:throwpoint are reset. They
3730" are not affected by an exception that is discarded before being
3731" caught.
3732"-------------------------------------------------------------------------------
3733func Test_exception_info_on_discard()
3734 CheckEnglish
3735
3736 let test =<< trim [CODE]
3737 let sfile = expand("<sfile>")
3738
3739 while 1
3740 try
3741 throw "x1"
3742 catch /.*/
3743 break
3744 endtry
3745 endwhile
3746 call assert_equal('', v:exception)
3747 call assert_equal('', v:throwpoint)
3748
3749 while 1
3750 try
3751 throw "x2"
3752 catch /.*/
3753 break
3754 finally
3755 call assert_equal('', v:exception)
3756 call assert_equal('', v:throwpoint)
3757 endtry
3758 break
3759 endwhile
3760 call assert_equal('', v:exception)
3761 call assert_equal('', v:throwpoint)
3762
3763 while 1
3764 try
3765 let errcaught = 0
3766 try
3767 try
3768 throw "x3"
3769 catch /.*/
3770 let lnum = expand("<sflnum>")
3771 asdf
3772 endtry
3773 catch /.*/
3774 let errcaught = 1
3775 call assert_match('Vim:E492: Not an editor command:', v:exception)
3776 call assert_match('line ' .. (lnum + 1), v:throwpoint)
3777 endtry
3778 finally
3779 call assert_equal(1, errcaught)
3780 break
3781 endtry
3782 endwhile
3783 call assert_equal('', v:exception)
3784 call assert_equal('', v:throwpoint)
3785
3786 Xpath 'a'
3787
3788 while 1
3789 try
3790 let intcaught = 0
3791 try
3792 try
3793 throw "x4"
3794 catch /.*/
3795 let lnum = expand("<sflnum>")
3796 call interrupt()
3797 endtry
3798 catch /.*/
3799 let intcaught = 1
3800 call assert_match('Vim:Interrupt', v:exception)
3801 call assert_match('line ' .. (lnum + 1), v:throwpoint)
3802 endtry
3803 finally
3804 call assert_equal(1, intcaught)
3805 break
3806 endtry
3807 endwhile
3808 call assert_equal('', v:exception)
3809 call assert_equal('', v:throwpoint)
3810
3811 Xpath 'b'
3812
3813 while 1
3814 try
3815 let errcaught = 0
3816 try
3817 try
3818 if 1
3819 let lnum = expand("<sflnum>")
3820 throw "x5"
3821 " missing endif
3822 catch /.*/
3823 call assert_report('should not get here')
3824 endtry
3825 catch /.*/
3826 let errcaught = 1
3827 call assert_match('Vim(catch):E171: Missing :endif:', v:exception)
3828 call assert_match('line ' .. (lnum + 3), v:throwpoint)
3829 endtry
3830 finally
3831 call assert_equal(1, errcaught)
3832 break
3833 endtry
3834 endwhile
3835 call assert_equal('', v:exception)
3836 call assert_equal('', v:throwpoint)
3837
3838 Xpath 'c'
3839
3840 try
3841 while 1
3842 try
3843 throw "x6"
3844 finally
3845 break
3846 endtry
3847 break
3848 endwhile
3849 catch /.*/
3850 call assert_report('should not get here')
3851 endtry
3852 call assert_equal('', v:exception)
3853 call assert_equal('', v:throwpoint)
3854
3855 try
3856 while 1
3857 try
3858 throw "x7"
3859 finally
3860 break
3861 endtry
3862 break
3863 endwhile
3864 catch /.*/
3865 call assert_report('should not get here')
3866 finally
3867 call assert_equal('', v:exception)
3868 call assert_equal('', v:throwpoint)
3869 endtry
3870 call assert_equal('', v:exception)
3871 call assert_equal('', v:throwpoint)
3872
3873 while 1
3874 try
3875 let errcaught = 0
3876 try
3877 try
3878 throw "x8"
3879 finally
3880 let lnum = expand("<sflnum>")
3881 asdf
3882 endtry
3883 catch /.*/
3884 let errcaught = 1
3885 call assert_match('Vim:E492: Not an editor command:', v:exception)
3886 call assert_match('line ' .. (lnum + 1), v:throwpoint)
3887 endtry
3888 finally
3889 call assert_equal(1, errcaught)
3890 break
3891 endtry
3892 endwhile
3893 call assert_equal('', v:exception)
3894 call assert_equal('', v:throwpoint)
3895
3896 Xpath 'd'
3897
3898 while 1
3899 try
3900 let intcaught = 0
3901 try
3902 try
3903 throw "x9"
3904 finally
3905 let lnum = expand("<sflnum>")
3906 call interrupt()
3907 endtry
3908 catch /.*/
3909 let intcaught = 1
3910 call assert_match('Vim:Interrupt', v:exception)
3911 call assert_match('line ' .. (lnum + 1), v:throwpoint)
3912 endtry
3913 finally
3914 call assert_equal(1, intcaught)
3915 break
3916 endtry
3917 endwhile
3918 call assert_equal('', v:exception)
3919 call assert_equal('', v:throwpoint)
3920
3921 Xpath 'e'
3922
3923 while 1
3924 try
3925 let errcaught = 0
3926 try
3927 try
3928 if 1
3929 let lnum = expand("<sflnum>")
3930 throw "x10"
3931 " missing endif
3932 finally
3933 call assert_equal('', v:exception)
3934 call assert_equal('', v:throwpoint)
3935 endtry
3936 catch /.*/
3937 let errcaught = 1
3938 call assert_match('Vim(finally):E171: Missing :endif:', v:exception)
3939 call assert_match('line ' .. (lnum + 3), v:throwpoint)
3940 endtry
3941 finally
3942 call assert_equal(1, errcaught)
3943 break
3944 endtry
3945 endwhile
3946 call assert_equal('', v:exception)
3947 call assert_equal('', v:throwpoint)
3948
3949 Xpath 'f'
3950
3951 while 1
3952 try
3953 let errcaught = 0
3954 try
3955 try
3956 if 1
3957 let lnum = expand("<sflnum>")
3958 throw "x11"
3959 " missing endif
3960 endtry
3961 catch /.*/
3962 let errcaught = 1
3963 call assert_match('Vim(endtry):E171: Missing :endif:', v:exception)
3964 call assert_match('line ' .. (lnum + 3), v:throwpoint)
3965 endtry
3966 finally
3967 call assert_equal(1, errcaught)
3968 break
3969 endtry
3970 endwhile
3971 call assert_equal('', v:exception)
3972 call assert_equal('', v:throwpoint)
3973
3974 Xpath 'g'
3975 [CODE]
3976 let verify =<< trim [CODE]
3977 call assert_equal('abcdefg', g:Xpath)
3978 [CODE]
3979 call RunInNewVim(test, verify)
3980endfunc
3981
3982"-------------------------------------------------------------------------------
3983"
3984" Test 60: (Re)throwing v:exception; :echoerr. {{{1
3985"
3986" A user exception can be rethrown after catching by throwing
3987" v:exception. An error or interrupt exception cannot be rethrown
3988" because Vim exceptions cannot be faked. A Vim exception using the
3989" value of v:exception can, however, be triggered by the :echoerr
3990" command.
3991"-------------------------------------------------------------------------------
3992
3993func Test_rethrow_exception_1()
3994 XpathINIT
3995 try
3996 try
3997 Xpath 'a'
3998 throw "oops"
3999 catch /oops/
4000 Xpath 'b'
4001 throw v:exception " rethrow user exception
4002 catch /.*/
4003 call assert_report('should not get here')
4004 endtry
4005 catch /^oops$/ " catches rethrown user exception
4006 Xpath 'c'
4007 catch /.*/
4008 call assert_report('should not get here')
4009 endtry
4010 call assert_equal('abc', g:Xpath)
4011endfunc
4012
4013func Test_rethrow_exception_2()
4014 XpathINIT
4015 try
4016 let caught = 0
4017 try
4018 Xpath 'a'
4019 write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
4020 call assert_report('should not get here')
4021 catch /^Vim(write):/
4022 let caught = 1
4023 throw v:exception " throw error: cannot fake Vim exception
4024 catch /.*/
4025 call assert_report('should not get here')
4026 finally
4027 Xpath 'b'
4028 call assert_equal(1, caught)
4029 endtry
4030 catch /^Vim(throw):/ " catches throw error
4031 let caught = caught + 1
4032 catch /.*/
4033 call assert_report('should not get here')
4034 finally
4035 Xpath 'c'
4036 call assert_equal(2, caught)
4037 endtry
4038 call assert_equal('abc', g:Xpath)
4039endfunc
4040
4041func Test_rethrow_exception_3()
4042 XpathINIT
4043 try
4044 let caught = 0
4045 try
4046 Xpath 'a'
4047 asdf
4048 catch /^Vim/ " catch error exception
4049 let caught = 1
4050 " Trigger Vim error exception with value specified after :echoerr
4051 let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
4052 echoerr value
4053 catch /.*/
4054 call assert_report('should not get here')
4055 finally
4056 Xpath 'b'
4057 call assert_equal(1, caught)
4058 endtry
4059 catch /^Vim(echoerr):/
4060 let caught = caught + 1
4061 call assert_match(value, v:exception)
4062 catch /.*/
4063 call assert_report('should not get here')
4064 finally
4065 Xpath 'c'
4066 call assert_equal(2, caught)
4067 endtry
4068 call assert_equal('abc', g:Xpath)
4069endfunc
4070
4071func Test_rethrow_exception_3()
4072 XpathINIT
4073 try
4074 let errcaught = 0
4075 try
4076 Xpath 'a'
4077 let intcaught = 0
4078 call interrupt()
4079 catch /^Vim:/ " catch interrupt exception
4080 let intcaught = 1
4081 " Trigger Vim error exception with value specified after :echoerr
4082 echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
4083 catch /.*/
4084 call assert_report('should not get here')
4085 finally
4086 Xpath 'b'
4087 call assert_equal(1, intcaught)
4088 endtry
4089 catch /^Vim(echoerr):/
4090 let errcaught = 1
4091 call assert_match('Interrupt', v:exception)
4092 finally
4093 Xpath 'c'
4094 call assert_equal(1, errcaught)
4095 endtry
4096 call assert_equal('abc', g:Xpath)
4097endfunc
4098
4099"-------------------------------------------------------------------------------
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02004100" Test 61: Catching interrupt exceptions {{{1
4101"
4102" When an interrupt occurs inside a :try/:endtry region, an
4103" interrupt exception is thrown and can be caught. Its value is
4104" "Vim:Interrupt". If the interrupt occurs after an error or a :throw
4105" but before a matching :catch is reached, all following :catches of
4106" that try block are ignored, but the interrupt exception can be
4107" caught by the next surrounding try conditional. An interrupt is
4108" ignored when there is a previous interrupt that has not been caught
4109" or causes a :finally clause to be executed.
4110"-------------------------------------------------------------------------------
4111
4112func Test_catch_intr_exception()
4113 let test =<< trim [CODE]
4114 while 1
4115 try
4116 try
4117 Xpath 'a'
4118 call interrupt()
4119 call assert_report('should not get here')
4120 catch /^Vim:Interrupt$/
4121 Xpath 'b'
4122 finally
4123 Xpath 'c'
4124 endtry
4125 catch /.*/
4126 call assert_report('should not get here')
4127 finally
4128 Xpath 'd'
4129 break
4130 endtry
4131 endwhile
4132
4133 while 1
4134 try
4135 try
4136 try
4137 Xpath 'e'
4138 asdf
4139 call assert_report('should not get here')
4140 catch /do_not_catch/
4141 call assert_report('should not get here')
4142 catch /.*/
4143 Xpath 'f'
4144 call interrupt()
4145 call assert_report('should not get here')
4146 catch /.*/
4147 call assert_report('should not get here')
4148 finally
4149 Xpath 'g'
4150 call interrupt()
4151 call assert_report('should not get here')
4152 endtry
4153 catch /^Vim:Interrupt$/
4154 Xpath 'h'
4155 finally
4156 Xpath 'i'
4157 endtry
4158 catch /.*/
4159 call assert_report('should not get here')
4160 finally
4161 Xpath 'j'
4162 break
4163 endtry
4164 endwhile
4165
4166 while 1
4167 try
4168 try
4169 try
4170 Xpath 'k'
4171 throw "x"
4172 call assert_report('should not get here')
4173 catch /do_not_catch/
4174 call assert_report('should not get here')
4175 catch /x/
4176 Xpath 'l'
4177 call interrupt()
4178 call assert_report('should not get here')
4179 catch /.*/
4180 call assert_report('should not get here')
4181 endtry
4182 catch /^Vim:Interrupt$/
4183 Xpath 'm'
4184 finally
4185 Xpath 'n'
4186 endtry
4187 catch /.*/
4188 call assert_report('should not get here')
4189 finally
4190 Xpath 'o'
4191 break
4192 endtry
4193 endwhile
4194
4195 while 1
4196 try
4197 try
4198 Xpath 'p'
4199 call interrupt()
4200 call assert_report('should not get here')
4201 catch /do_not_catch/
4202 call interrupt()
4203 call assert_report('should not get here')
4204 catch /^Vim:Interrupt$/
4205 Xpath 'q'
4206 finally
4207 Xpath 'r'
4208 endtry
4209 catch /.*/
4210 call assert_report('should not get here')
4211 finally
4212 Xpath 's'
4213 break
4214 endtry
4215 endwhile
4216
4217 Xpath 't'
4218 [CODE]
4219 let verify =<< trim [CODE]
4220 call assert_equal('abcdefghijklmnopqrst', g:Xpath)
4221 [CODE]
4222 call RunInNewVim(test, verify)
4223endfunc
4224
4225"-------------------------------------------------------------------------------
Bram Moolenaarefb64822020-08-10 22:15:30 +02004226" Test 62: Catching error exceptions {{{1
4227"
4228" An error inside a :try/:endtry region is converted to an exception
4229" and can be caught. The error exception has a "Vim(cmdname):" prefix
4230" where cmdname is the name of the failing command, or a "Vim:" prefix
4231" if no command name is known. The "Vim" prefixes cannot be faked.
4232"-------------------------------------------------------------------------------
4233
4234func Test_catch_err_exception_1()
4235 XpathINIT
4236 while 1
4237 try
4238 try
4239 let caught = 0
4240 unlet novar
4241 catch /^Vim(unlet):/
4242 Xpath 'a'
4243 let caught = 1
4244 let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
4245 finally
4246 Xpath 'b'
4247 call assert_equal(1, caught)
4248 call assert_match('E108: No such variable: "novar"', v:errmsg)
4249 endtry
4250 catch /.*/
4251 call assert_report('should not get here')
4252 finally
4253 Xpath 'c'
4254 break
4255 endtry
4256 call assert_report('should not get here')
4257 endwhile
4258 call assert_equal('abc', g:Xpath)
4259endfunc
4260
4261func Test_catch_err_exception_2()
4262 XpathINIT
4263 while 1
4264 try
4265 try
4266 let caught = 0
4267 throw novar " error in :throw
4268 catch /^Vim(throw):/
4269 Xpath 'a'
4270 let caught = 1
4271 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
4272 finally
4273 Xpath 'b'
4274 call assert_equal(1, caught)
4275 call assert_match('E121: Undefined variable: novar', v:errmsg)
4276 endtry
4277 catch /.*/
4278 call assert_report('should not get here')
4279 finally
4280 Xpath 'c'
4281 break
4282 endtry
4283 call assert_report('should not get here')
4284 endwhile
4285 call assert_equal('abc', g:Xpath)
4286endfunc
4287
4288func Test_catch_err_exception_3()
4289 XpathINIT
4290 while 1
4291 try
4292 try
4293 let caught = 0
4294 throw "Vim:faked" " error: cannot fake Vim exception
4295 catch /^Vim(throw):/
4296 Xpath 'a'
4297 let caught = 1
4298 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
4299 finally
4300 Xpath 'b'
4301 call assert_equal(1, caught)
4302 call assert_match("E608: Cannot :throw exceptions with 'Vim' prefix",
4303 \ v:errmsg)
4304 endtry
4305 catch /.*/
4306 call assert_report('should not get here')
4307 finally
4308 Xpath 'c'
4309 break
4310 endtry
4311 call assert_report('should not get here')
4312 endwhile
4313 call assert_equal('abc', g:Xpath)
4314endfunc
4315
4316func Test_catch_err_exception_4()
4317 XpathINIT
4318 func F()
4319 while 1
4320 " Missing :endwhile
4321 endfunc
4322
4323 while 1
4324 try
4325 try
4326 let caught = 0
4327 call F()
4328 catch /^Vim(endfunction):/
4329 Xpath 'a'
4330 let caught = 1
4331 let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
4332 finally
4333 Xpath 'b'
4334 call assert_equal(1, caught)
4335 call assert_match("E170: Missing :endwhile", v:errmsg)
4336 endtry
4337 catch /.*/
4338 call assert_report('should not get here')
4339 finally
4340 Xpath 'c'
4341 break
4342 endtry
4343 call assert_report('should not get here')
4344 endwhile
4345 call assert_equal('abc', g:Xpath)
4346 delfunc F
4347endfunc
4348
4349func Test_catch_err_exception_5()
4350 XpathINIT
4351 func F()
4352 while 1
4353 " Missing :endwhile
4354 endfunc
4355
4356 while 1
4357 try
4358 try
4359 let caught = 0
4360 ExecAsScript F
4361 catch /^Vim:/
4362 Xpath 'a'
4363 let caught = 1
4364 let v:errmsg = substitute(v:exception, '^Vim:', '', "")
4365 finally
4366 Xpath 'b'
4367 call assert_equal(1, caught)
4368 call assert_match("E170: Missing :endwhile", v:errmsg)
4369 endtry
4370 catch /.*/
4371 call assert_report('should not get here')
4372 finally
4373 Xpath 'c'
4374 break
4375 endtry
4376 call assert_report('should not get here')
4377 endwhile
4378 call assert_equal('abc', g:Xpath)
4379 delfunc F
4380endfunc
4381
4382func Test_catch_err_exception_6()
4383 XpathINIT
4384 func G()
4385 call G()
4386 endfunc
4387
4388 while 1
4389 try
4390 let mfd_save = &mfd
4391 set mfd=3
4392 try
4393 let caught = 0
4394 call G()
4395 catch /^Vim(call):/
4396 Xpath 'a'
4397 let caught = 1
4398 let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
4399 finally
4400 Xpath 'b'
4401 call assert_equal(1, caught)
4402 call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
4403 endtry
4404 catch /.*/
4405 call assert_report('should not get here')
4406 finally
4407 Xpath 'c'
4408 let &mfd = mfd_save
4409 break
4410 endtry
4411 call assert_report('should not get here')
4412 endwhile
4413 call assert_equal('abc', g:Xpath)
4414 delfunc G
4415endfunc
4416
4417func Test_catch_err_exception_7()
4418 XpathINIT
4419 func H()
4420 return H()
4421 endfunc
4422
4423 while 1
4424 try
4425 let mfd_save = &mfd
4426 set mfd=3
4427 try
4428 let caught = 0
4429 call H()
4430 catch /^Vim(return):/
4431 Xpath 'a'
4432 let caught = 1
4433 let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
4434 finally
4435 Xpath 'b'
4436 call assert_equal(1, caught)
4437 call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
4438 endtry
4439 catch /.*/
4440 call assert_report('should not get here')
4441 finally
4442 Xpath 'c'
4443 let &mfd = mfd_save
4444 break " discard error for $VIMNOERRTHROW
4445 endtry
4446 call assert_report('should not get here')
4447 endwhile
4448
4449 call assert_equal('abc', g:Xpath)
4450 delfunc H
4451endfunc
4452
4453"-------------------------------------------------------------------------------
4454" Test 63: Suppressing error exceptions by :silent!. {{{1
4455"
4456" A :silent! command inside a :try/:endtry region suppresses the
4457" conversion of errors to an exception and the immediate abortion on
4458" error. When the commands executed by the :silent! themselves open
4459" a new :try/:endtry region, conversion of errors to exception and
4460" immediate abortion is switched on again - until the next :silent!
4461" etc. The :silent! has the effect of setting v:errmsg to the error
4462" message text (without displaying it) and continuing with the next
4463" script line.
4464"
4465" When a command triggering autocommands is executed by :silent!
4466" inside a :try/:endtry, the autocommand execution is not suppressed
4467" on error.
4468"
4469" This test reuses the function MSG() from the previous test.
4470"-------------------------------------------------------------------------------
4471
4472func Test_silent_exception()
4473 XpathINIT
4474 XloopINIT
4475 let g:taken = ""
4476
4477 func S(n) abort
4478 XloopNEXT
4479 let g:taken = g:taken . "E" . a:n
4480 let v:errmsg = ""
4481 exec "asdf" . a:n
4482
4483 " Check that ":silent!" continues:
4484 Xloop 'a'
4485
4486 " Check that ":silent!" sets "v:errmsg":
4487 call assert_match("E492: Not an editor command", v:errmsg)
4488 endfunc
4489
4490 func Foo()
4491 while 1
4492 try
4493 try
4494 let caught = 0
4495 " This is not silent:
4496 call S(3)
4497 catch /^Vim:/
4498 Xpath 'b'
4499 let caught = 1
4500 let errmsg3 = substitute(v:exception, '^Vim:', '', "")
4501 silent! call S(4)
4502 finally
4503 call assert_equal(1, caught)
4504 Xpath 'c'
4505 call assert_match("E492: Not an editor command", errmsg3)
4506 silent! call S(5)
4507 " Break out of try conditionals that cover ":silent!". This also
4508 " discards the aborting error when $VIMNOERRTHROW is non-zero.
4509 break
4510 endtry
4511 catch /.*/
4512 call assert_report('should not get here')
4513 endtry
4514 endwhile
4515 " This is a double ":silent!" (see caller).
4516 silent! call S(6)
4517 endfunc
4518
4519 func Bar()
4520 try
4521 silent! call S(2)
4522 silent! execute "call Foo() | call S(7)"
4523 silent! call S(8)
4524 endtry " normal end of try cond that covers ":silent!"
4525 " This has a ":silent!" from the caller:
4526 call S(9)
4527 endfunc
4528
4529 silent! call S(1)
4530 silent! call Bar()
4531 silent! call S(10)
4532
4533 call assert_equal("E1E2E3E4E5E6E7E8E9E10", g:taken)
4534
4535 augroup TMP
4536 au!
4537 autocmd BufWritePost * Xpath 'd'
4538 augroup END
4539
4540 Xpath 'e'
4541 silent! write /i/m/p/o/s/s/i/b/l/e
4542 Xpath 'f'
4543
4544 call assert_equal('a2a3ba5ca6a7a8a9a10a11edf', g:Xpath)
4545
4546 augroup TMP
4547 au!
4548 augroup END
4549 augroup! TMP
4550 delfunction S
4551 delfunction Foo
4552 delfunction Bar
4553endfunc
4554
4555"-------------------------------------------------------------------------------
4556" Test 64: Error exceptions after error, interrupt or :throw {{{1
4557"
4558" When an error occurs after an interrupt or a :throw but before
4559" a matching :catch is reached, all following :catches of that try
4560" block are ignored, but the error exception can be caught by the next
4561" surrounding try conditional. Any previous error exception is
4562" discarded. An error is ignored when there is a previous error that
4563" has not been caught.
4564"-------------------------------------------------------------------------------
4565
4566func Test_exception_after_error_1()
4567 XpathINIT
4568 while 1
4569 try
4570 try
4571 Xpath 'a'
4572 let caught = 0
4573 while 1
4574 if 1
4575 " Missing :endif
4576 endwhile " throw error exception
4577 catch /^Vim(/
4578 Xpath 'b'
4579 let caught = 1
4580 finally
4581 Xpath 'c'
4582 call assert_equal(1, caught)
4583 endtry
4584 catch /.*/
4585 call assert_report('should not get here')
4586 finally
4587 Xpath 'd'
4588 break
4589 endtry
4590 call assert_report('should not get here')
4591 endwhile
4592 call assert_equal('abcd', g:Xpath)
4593endfunc
4594
4595func Test_exception_after_error_2()
4596 XpathINIT
4597 while 1
4598 try
4599 try
4600 Xpath 'a'
4601 let caught = 0
4602 try
4603 if 1
4604 " Missing :endif
4605 catch /.*/ " throw error exception
4606 call assert_report('should not get here')
4607 catch /.*/
4608 call assert_report('should not get here')
4609 endtry
4610 catch /^Vim(/
4611 Xpath 'b'
4612 let caught = 1
4613 finally
4614 Xpath 'c'
4615 call assert_equal(1, caught)
4616 endtry
4617 catch /.*/
4618 call assert_report('should not get here')
4619 finally
4620 Xpath 'd'
4621 break
4622 endtry
4623 call assert_report('should not get here')
4624 endwhile
4625 call assert_equal('abcd', g:Xpath)
4626endfunc
4627
4628func Test_exception_after_error_3()
4629 XpathINIT
4630 while 1
4631 try
4632 try
4633 let caught = 0
4634 try
4635 Xpath 'a'
4636 call interrupt()
4637 catch /do_not_catch/
4638 call assert_report('should not get here')
4639 if 1
4640 " Missing :endif
4641 catch /.*/ " throw error exception
4642 call assert_report('should not get here')
4643 catch /.*/
4644 call assert_report('should not get here')
4645 endtry
4646 catch /^Vim(/
4647 Xpath 'b'
4648 let caught = 1
4649 finally
4650 Xpath 'c'
4651 call assert_equal(1, caught)
4652 endtry
4653 catch /.*/
4654 call assert_report('should not get here')
4655 finally
4656 Xpath 'd'
4657 break
4658 endtry
4659 call assert_report('should not get here')
4660 endwhile
4661 call assert_equal('abcd', g:Xpath)
4662endfunc
4663
4664func Test_exception_after_error_4()
4665 XpathINIT
4666 while 1
4667 try
4668 try
4669 let caught = 0
4670 try
4671 Xpath 'a'
4672 throw "x"
4673 catch /do_not_catch/
4674 call assert_report('should not get here')
4675 if 1
4676 " Missing :endif
4677 catch /x/ " throw error exception
4678 call assert_report('should not get here')
4679 catch /.*/
4680 call assert_report('should not get here')
4681 endtry
4682 catch /^Vim(/
4683 Xpath 'b'
4684 let caught = 1
4685 finally
4686 Xpath 'c'
4687 call assert_equal(1, caught)
4688 endtry
4689 catch /.*/
4690 call assert_report('should not get here')
4691 finally
4692 Xpath 'd'
4693 break
4694 endtry
4695 call assert_report('should not get here')
4696 endwhile
4697 call assert_equal('abcd', g:Xpath)
4698endfunc
4699
4700func Test_exception_after_error_5()
4701 XpathINIT
4702 while 1
4703 try
4704 try
4705 let caught = 0
4706 Xpath 'a'
4707 endif " :endif without :if; throw error exception
4708 if 1
4709 " Missing :endif
4710 catch /do_not_catch/ " ignore new error
4711 call assert_report('should not get here')
4712 catch /^Vim(endif):/
4713 Xpath 'b'
4714 let caught = 1
4715 catch /^Vim(/
4716 call assert_report('should not get here')
4717 finally
4718 Xpath 'c'
4719 call assert_equal(1, caught)
4720 endtry
4721 catch /.*/
4722 call assert_report('should not get here')
4723 finally
4724 Xpath 'd'
4725 break
4726 endtry
4727 call assert_report('should not get here')
4728 endwhile
4729 call assert_equal('abcd', g:Xpath)
4730endfunc
4731
4732"-------------------------------------------------------------------------------
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02004733" Test 65: Errors in the /pattern/ argument of a :catch {{{1
4734"
4735" On an error in the /pattern/ argument of a :catch, the :catch does
4736" not match. Any following :catches of the same :try/:endtry don't
4737" match either. Finally clauses are executed.
4738"-------------------------------------------------------------------------------
4739
4740func Test_catch_pattern_error()
4741 CheckEnglish
4742 XpathINIT
4743
4744 try
4745 try
4746 Xpath 'a'
4747 throw "oops"
4748 catch /^oops$/
4749 Xpath 'b'
4750 catch /\)/ " not checked; exception has already been caught
4751 call assert_report('should not get here')
4752 endtry
4753 Xpath 'c'
4754 catch /.*/
4755 call assert_report('should not get here')
4756 endtry
4757 call assert_equal('abc', g:Xpath)
4758
4759 XpathINIT
4760 func F()
4761 try
4762 try
4763 try
4764 Xpath 'a'
4765 throw "ab"
4766 catch /abc/ " does not catch
4767 call assert_report('should not get here')
4768 catch /\)/ " error; discards exception
4769 call assert_report('should not get here')
4770 catch /.*/ " not checked
4771 call assert_report('should not get here')
4772 finally
4773 Xpath 'b'
4774 endtry
4775 call assert_report('should not get here')
4776 catch /^ab$/ " checked, but original exception is discarded
4777 call assert_report('should not get here')
4778 catch /^Vim(catch):/
4779 Xpath 'c'
4780 call assert_match('Vim(catch):E475: Invalid argument:', v:exception)
4781 finally
4782 Xpath 'd'
4783 endtry
4784 Xpath 'e'
4785 catch /.*/
4786 call assert_report('should not get here')
4787 endtry
4788 Xpath 'f'
4789 endfunc
4790
4791 call F()
4792 call assert_equal('abcdef', g:Xpath)
4793
4794 delfunc F
4795endfunc
4796
4797"-------------------------------------------------------------------------------
Bram Moolenaarefb64822020-08-10 22:15:30 +02004798" Test 66: Stop range :call on error, interrupt, or :throw {{{1
4799"
4800" When a function which is multiply called for a range since it
4801" doesn't handle the range itself has an error in a command
4802" dynamically enclosed by :try/:endtry or gets an interrupt or
4803" executes a :throw, no more calls for the remaining lines in the
4804" range are made. On an error in a command not dynamically enclosed
4805" by :try/:endtry, the function is executed again for the remaining
4806" lines in the range.
4807"-------------------------------------------------------------------------------
4808
4809func Test_stop_range_on_error()
4810 let test =<< trim [CODE]
4811 let file = tempname()
4812 exec "edit" file
4813 call setline(1, ['line 1', 'line 2', 'line 3'])
4814 let taken = ""
4815 let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
4816
4817 func F(reason, n) abort
4818 let g:taken = g:taken .. "F" .. a:n ..
4819 \ substitute(a:reason, '\(\l\).*', '\u\1', "") ..
4820 \ "(" .. line(".") .. ")"
4821
4822 if a:reason == "error"
4823 asdf
4824 elseif a:reason == "interrupt"
4825 call interrupt()
4826 elseif a:reason == "throw"
4827 throw "xyz"
4828 elseif a:reason == "aborting error"
4829 XloopNEXT
4830 call assert_equal(g:taken, g:expected)
4831 try
4832 bwipeout!
4833 call delete(g:file)
4834 asdf
4835 endtry
4836 endif
4837 endfunc
4838
4839 func G(reason, n)
4840 let g:taken = g:taken .. "G" .. a:n ..
4841 \ substitute(a:reason, '\(\l\).*', '\u\1', "")
4842 1,3call F(a:reason, a:n)
4843 endfunc
4844
4845 Xpath 'a'
4846 call G("error", 1)
4847 try
4848 Xpath 'b'
4849 try
4850 call G("error", 2)
4851 call assert_report('should not get here')
4852 finally
4853 Xpath 'c'
4854 try
4855 call G("interrupt", 3)
4856 call assert_report('should not get here')
4857 finally
4858 Xpath 'd'
4859 try
4860 call G("throw", 4)
4861 call assert_report('should not get here')
4862 endtry
4863 endtry
4864 endtry
4865 catch /xyz/
4866 Xpath 'e'
4867 catch /.*/
4868 call assert_report('should not get here')
4869 endtry
4870 Xpath 'f'
4871 call G("aborting error", 5)
4872 call assert_report('should not get here')
4873 [CODE]
4874 let verify =<< trim [CODE]
4875 call assert_equal('abcdef', g:Xpath)
4876 [CODE]
4877 call RunInNewVim(test, verify)
4878endfunc
4879
4880"-------------------------------------------------------------------------------
4881" Test 67: :throw across :call command {{{1
4882"
4883" On a call command, an exception might be thrown when evaluating the
4884" function name, during evaluation of the arguments, or when the
4885" function is being executed. The exception can be caught by the
4886" caller.
4887"-------------------------------------------------------------------------------
4888
4889func THROW(x, n)
4890 if a:n == 1
4891 Xpath 'A'
4892 elseif a:n == 2
4893 Xpath 'B'
4894 elseif a:n == 3
4895 Xpath 'C'
4896 endif
4897 throw a:x
4898endfunc
4899
4900func NAME(x, n)
4901 if a:n == 1
4902 call assert_report('should not get here')
4903 elseif a:n == 2
4904 Xpath 'D'
4905 elseif a:n == 3
4906 Xpath 'E'
4907 elseif a:n == 4
4908 Xpath 'F'
4909 endif
4910 return a:x
4911endfunc
4912
4913func ARG(x, n)
4914 if a:n == 1
4915 call assert_report('should not get here')
4916 elseif a:n == 2
4917 call assert_report('should not get here')
4918 elseif a:n == 3
4919 Xpath 'G'
4920 elseif a:n == 4
4921 Xpath 'I'
4922 endif
4923 return a:x
4924endfunc
4925
4926func Test_throw_across_call_cmd()
4927 XpathINIT
4928
4929 func F(x, n)
4930 if a:n == 2
4931 call assert_report('should not get here')
4932 elseif a:n == 4
4933 Xpath 'a'
4934 endif
4935 endfunc
4936
4937 while 1
4938 try
4939 let v:errmsg = ""
4940
4941 while 1
4942 try
4943 Xpath 'b'
4944 call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
4945 call assert_report('should not get here')
4946 catch /^name$/
4947 Xpath 'c'
4948 catch /.*/
4949 call assert_report('should not get here')
4950 finally
4951 call assert_equal("", v:errmsg)
4952 let v:errmsg = ""
4953 break
4954 endtry
4955 endwhile
4956
4957 while 1
4958 try
4959 Xpath 'd'
4960 call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
4961 call assert_report('should not get here')
4962 catch /^arg$/
4963 Xpath 'e'
4964 catch /.*/
4965 call assert_report('should not get here')
4966 finally
4967 call assert_equal("", v:errmsg)
4968 let v:errmsg = ""
4969 break
4970 endtry
4971 endwhile
4972
4973 while 1
4974 try
4975 Xpath 'f'
4976 call {NAME("THROW", 3)}(ARG("call", 3), 3)
4977 call assert_report('should not get here')
4978 catch /^call$/
4979 Xpath 'g'
4980 catch /^0$/ " default return value
4981 call assert_report('should not get here')
4982 catch /.*/
4983 call assert_report('should not get here')
4984 finally
4985 call assert_equal("", v:errmsg)
4986 let v:errmsg = ""
4987 break
4988 endtry
4989 endwhile
4990
4991 while 1
4992 try
4993 Xpath 'h'
4994 call {NAME("F", 4)}(ARG(4711, 4), 4)
4995 Xpath 'i'
4996 catch /.*/
4997 call assert_report('should not get here')
4998 finally
4999 call assert_equal("", v:errmsg)
5000 let v:errmsg = ""
5001 break
5002 endtry
5003 endwhile
5004
5005 catch /^0$/ " default return value
5006 call assert_report('should not get here')
5007 catch /.*/
5008 call assert_report('should not get here')
5009 finally
5010 call assert_equal("", v:errmsg)
5011 let v:errmsg = ""
5012 break
5013 endtry
5014 endwhile
5015
5016 call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
5017 delfunction F
5018endfunc
5019
5020"-------------------------------------------------------------------------------
5021" Test 68: :throw across function calls in expressions {{{1
5022"
5023" On a function call within an expression, an exception might be
5024" thrown when evaluating the function name, during evaluation of the
5025" arguments, or when the function is being executed. The exception
5026" can be caught by the caller.
5027"
5028" This test reuses the functions THROW(), NAME(), and ARG() from the
5029" previous test.
5030"-------------------------------------------------------------------------------
5031
5032func Test_throw_across_call_expr()
5033 XpathINIT
5034
5035 func F(x, n)
5036 if a:n == 2
5037 call assert_report('should not get here')
5038 elseif a:n == 4
5039 Xpath 'a'
5040 endif
5041 return a:x
5042 endfunction
5043
5044 while 1
5045 try
5046 let error = 0
5047 let v:errmsg = ""
5048
5049 while 1
5050 try
5051 Xpath 'b'
5052 let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
5053 call assert_report('should not get here')
5054 catch /^name$/
5055 Xpath 'c'
5056 catch /.*/
5057 call assert_report('should not get here')
5058 finally
5059 call assert_equal("", v:errmsg)
5060 let v:errmsg = ""
5061 break
5062 endtry
5063 endwhile
5064 call assert_true(!exists('var1'))
5065
5066 while 1
5067 try
5068 Xpath 'd'
5069 let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
5070 call assert_report('should not get here')
5071 catch /^arg$/
5072 Xpath 'e'
5073 catch /.*/
5074 call assert_report('should not get here')
5075 finally
5076 call assert_equal("", v:errmsg)
5077 let v:errmsg = ""
5078 break
5079 endtry
5080 endwhile
5081 call assert_true(!exists('var2'))
5082
5083 while 1
5084 try
5085 Xpath 'f'
5086 let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
5087 call assert_report('should not get here')
5088 catch /^call$/
5089 Xpath 'g'
5090 catch /^0$/ " default return value
5091 call assert_report('should not get here')
5092 catch /.*/
5093 call assert_report('should not get here')
5094 finally
5095 call assert_equal("", v:errmsg)
5096 let v:errmsg = ""
5097 break
5098 endtry
5099 endwhile
5100 call assert_true(!exists('var3'))
5101
5102 while 1
5103 try
5104 Xpath 'h'
5105 let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
5106 Xpath 'i'
5107 catch /.*/
5108 call assert_report('should not get here')
5109 finally
5110 call assert_equal("", v:errmsg)
5111 let v:errmsg = ""
5112 break
5113 endtry
5114 endwhile
5115 call assert_true(exists('var4') && var4 == 4711)
5116
5117 catch /^0$/ " default return value
5118 call assert_report('should not get here')
5119 catch /.*/
5120 call assert_report('should not get here')
5121 finally
5122 call assert_equal("", v:errmsg)
5123 break
5124 endtry
5125 endwhile
5126
5127 call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
5128 delfunc F
5129endfunc
5130
5131"-------------------------------------------------------------------------------
5132" Test 76: Errors, interrupts, :throw during expression evaluation {{{1
5133"
5134" When a function call made during expression evaluation is aborted
5135" due to an error inside a :try/:endtry region or due to an interrupt
5136" or a :throw, the expression evaluation is aborted as well. No
5137" message is displayed for the cancelled expression evaluation. On an
5138" error not inside :try/:endtry, the expression evaluation continues.
5139"-------------------------------------------------------------------------------
5140
5141func Test_expr_eval_error()
5142 let test =<< trim [CODE]
5143 let taken = ""
5144
5145 func ERR(n)
5146 let g:taken = g:taken .. "E" .. a:n
5147 asdf
5148 endfunc
5149
5150 func ERRabort(n) abort
5151 let g:taken = g:taken .. "A" .. a:n
5152 asdf
5153 endfunc " returns -1; may cause follow-up msg for illegal var/func name
5154
5155 func WRAP(n, arg)
5156 let g:taken = g:taken .. "W" .. a:n
5157 let g:saved_errmsg = v:errmsg
5158 return arg
5159 endfunc
5160
5161 func INT(n)
5162 let g:taken = g:taken .. "I" .. a:n
5163 call interrupt()
5164 endfunc
5165
5166 func THR(n)
5167 let g:taken = g:taken .. "T" .. a:n
5168 throw "should not be caught"
5169 endfunc
5170
5171 func CONT(n)
5172 let g:taken = g:taken .. "C" .. a:n
5173 endfunc
5174
5175 func MSG(n)
5176 let g:taken = g:taken .. "M" .. a:n
5177 let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg
5178 let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf"
5179 call assert_match(msgptn, errmsg)
5180 let v:errmsg = ""
5181 let g:saved_errmsg = ""
5182 endfunc
5183
5184 let v:errmsg = ""
5185
5186 try
5187 let t = 1
5188 while t <= 9
5189 Xloop 'a'
5190 try
5191 if t == 1
5192 let v{ERR(t) + CONT(t)} = 0
5193 elseif t == 2
5194 let v{ERR(t) + CONT(t)}
5195 elseif t == 3
5196 let var = exists('v{ERR(t) + CONT(t)}')
5197 elseif t == 4
5198 unlet v{ERR(t) + CONT(t)}
5199 elseif t == 5
5200 function F{ERR(t) + CONT(t)}()
5201 endfunction
5202 elseif t == 6
5203 function F{ERR(t) + CONT(t)}
5204 elseif t == 7
5205 let var = exists('*F{ERR(t) + CONT(t)}')
5206 elseif t == 8
5207 delfunction F{ERR(t) + CONT(t)}
5208 elseif t == 9
5209 let var = ERR(t) + CONT(t)
5210 endif
5211 catch /asdf/
5212 " v:errmsg is not set when the error message is converted to an
5213 " exception. Set it to the original error message.
5214 let v:errmsg = substitute(v:exception, '^Vim:', '', "")
5215 catch /^Vim\((\a\+)\)\=:/
5216 " An error exception has been thrown after the original error.
5217 let v:errmsg = ""
5218 finally
5219 call MSG(t)
5220 let t = t + 1
5221 XloopNEXT
5222 continue " discard an aborting error
5223 endtry
5224 endwhile
5225 catch /.*/
5226 call assert_report('should not get here')
5227 endtry
5228
5229 try
5230 let t = 10
5231 while t <= 18
5232 Xloop 'b'
5233 try
5234 if t == 10
5235 let v{INT(t) + CONT(t)} = 0
5236 elseif t == 11
5237 let v{INT(t) + CONT(t)}
5238 elseif t == 12
5239 let var = exists('v{INT(t) + CONT(t)}')
5240 elseif t == 13
5241 unlet v{INT(t) + CONT(t)}
5242 elseif t == 14
5243 function F{INT(t) + CONT(t)}()
5244 endfunction
5245 elseif t == 15
5246 function F{INT(t) + CONT(t)}
5247 elseif t == 16
5248 let var = exists('*F{INT(t) + CONT(t)}')
5249 elseif t == 17
5250 delfunction F{INT(t) + CONT(t)}
5251 elseif t == 18
5252 let var = INT(t) + CONT(t)
5253 endif
5254 catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
5255 " An error exception has been triggered after the interrupt.
5256 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5257 finally
5258 call MSG(t)
5259 let t = t + 1
5260 XloopNEXT
5261 continue " discard interrupt
5262 endtry
5263 endwhile
5264 catch /.*/
5265 call assert_report('should not get here')
5266 endtry
5267
5268 try
5269 let t = 19
5270 while t <= 27
5271 Xloop 'c'
5272 try
5273 if t == 19
5274 let v{THR(t) + CONT(t)} = 0
5275 elseif t == 20
5276 let v{THR(t) + CONT(t)}
5277 elseif t == 21
5278 let var = exists('v{THR(t) + CONT(t)}')
5279 elseif t == 22
5280 unlet v{THR(t) + CONT(t)}
5281 elseif t == 23
5282 function F{THR(t) + CONT(t)}()
5283 endfunction
5284 elseif t == 24
5285 function F{THR(t) + CONT(t)}
5286 elseif t == 25
5287 let var = exists('*F{THR(t) + CONT(t)}')
5288 elseif t == 26
5289 delfunction F{THR(t) + CONT(t)}
5290 elseif t == 27
5291 let var = THR(t) + CONT(t)
5292 endif
5293 catch /^Vim\((\a\+)\)\=:/
5294 " An error exception has been triggered after the :throw.
5295 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5296 finally
5297 call MSG(t)
5298 let t = t + 1
5299 XloopNEXT
5300 continue " discard exception
5301 endtry
5302 endwhile
5303 catch /.*/
5304 call assert_report('should not get here')
5305 endtry
5306
5307 let v{ERR(28) + CONT(28)} = 0
5308 call MSG(28)
5309 let v{ERR(29) + CONT(29)}
5310 call MSG(29)
5311 let var = exists('v{ERR(30) + CONT(30)}')
5312 call MSG(30)
5313 unlet v{ERR(31) + CONT(31)}
5314 call MSG(31)
5315 function F{ERR(32) + CONT(32)}()
5316 endfunction
5317 call MSG(32)
5318 function F{ERR(33) + CONT(33)}
5319 call MSG(33)
5320 let var = exists('*F{ERR(34) + CONT(34)}')
5321 call MSG(34)
5322 delfunction F{ERR(35) + CONT(35)}
5323 call MSG(35)
5324 let var = ERR(36) + CONT(36)
5325 call MSG(36)
5326
5327 let saved_errmsg = ""
5328
5329 let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0
5330 call MSG(37)
5331 let v{WRAP(38, ERRabort(38)) + CONT(38)}
5332 call MSG(38)
5333 let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}')
5334 call MSG(39)
5335 unlet v{WRAP(40, ERRabort(40)) + CONT(40)}
5336 call MSG(40)
5337 function F{WRAP(41, ERRabort(41)) + CONT(41)}()
5338 endfunction
5339 call MSG(41)
5340 function F{WRAP(42, ERRabort(42)) + CONT(42)}
5341 call MSG(42)
5342 let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}')
5343 call MSG(43)
5344 delfunction F{WRAP(44, ERRabort(44)) + CONT(44)}
5345 call MSG(44)
5346 let var = ERRabort(45) + CONT(45)
5347 call MSG(45)
5348 Xpath 'd'
5349
5350 let expected = ""
5351 \ .. "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
5352 \ .. "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
5353 \ .. "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
5354 \ .. "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
5355 \ .. "E34C34M34E35C35M35E36C36M36"
5356 \ .. "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41"
5357 \ .. "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45"
5358 call assert_equal(expected, taken)
5359 [CODE]
5360 let verify =<< trim [CODE]
5361 let expected = "a1a2a3a4a5a6a7a8a9"
5362 \ .. "b10b11b12b13b14b15b16b17b18"
5363 \ .. "c19c20c21c22c23c24c25c26c27d"
5364 call assert_equal(expected, g:Xpath)
5365 [CODE]
5366 call RunInNewVim(test, verify)
5367endfunc
5368
5369"-------------------------------------------------------------------------------
5370" Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1
5371"
5372" When a function call made during evaluation of an expression in
5373" braces as part of a function name after ":function" is aborted due
5374" to an error inside a :try/:endtry region or due to an interrupt or
5375" a :throw, the expression evaluation is aborted as well, and the
5376" function definition is ignored, skipping all commands to the
5377" ":endfunction". On an error not inside :try/:endtry, the expression
5378" evaluation continues and the function gets defined, and can be
5379" called and deleted.
5380"-------------------------------------------------------------------------------
5381func Test_brace_expr_error()
5382 let test =<< trim [CODE]
5383 func ERR() abort
5384 Xloop 'a'
5385 asdf
5386 endfunc " returns -1
5387
5388 func OK()
5389 Xloop 'b'
5390 let v:errmsg = ""
5391 return 0
5392 endfunc
5393
5394 let v:errmsg = ""
5395
5396 Xpath 'c'
5397 func F{1 + ERR() + OK()}(arg)
5398 " F0 should be defined.
5399 if exists("a:arg") && a:arg == "calling"
5400 Xpath 'd'
5401 else
5402 call assert_report('should not get here')
5403 endif
5404 endfunction
5405 call assert_equal("", v:errmsg)
5406 XloopNEXT
5407
5408 Xpath 'e'
5409 call F{1 + ERR() + OK()}("calling")
5410 call assert_equal("", v:errmsg)
5411 XloopNEXT
5412
5413 Xpath 'f'
5414 delfunction F{1 + ERR() + OK()}
5415 call assert_equal("", v:errmsg)
5416 XloopNEXT
5417
5418 try
5419 while 1
5420 try
5421 Xpath 'g'
5422 func G{1 + ERR() + OK()}(arg)
5423 " G0 should not be defined, and the function body should be
5424 " skipped.
5425 call assert_report('should not get here')
5426 " Use an unmatched ":finally" to check whether the body is
5427 " skipped when an error occurs in ERR(). This works whether or
5428 " not the exception is converted to an exception.
5429 finally
5430 call assert_report('should not get here')
5431 endtry
5432 try
5433 call assert_report('should not get here')
5434 endfunction
5435
5436 call assert_report('should not get here')
5437 catch /asdf/
5438 " Jumped to when the function is not defined and the body is
5439 " skipped.
5440 Xpath 'h'
5441 catch /.*/
5442 call assert_report('should not get here')
5443 finally
5444 Xpath 'i'
5445 break
5446 endtry " jumped to when the body is not skipped
5447 endwhile
5448 catch /.*/
5449 call assert_report('should not get here')
5450 endtry
5451 [CODE]
5452 let verify =<< trim [CODE]
5453 call assert_equal('ca1b1ea2b2dfa3b3ga4hi', g:Xpath)
5454 [CODE]
5455 call RunInNewVim(test, verify)
5456endfunc
5457
5458"-------------------------------------------------------------------------------
5459" Test 78: Messages on parsing errors in expression evaluation {{{1
5460"
5461" When an expression evaluation detects a parsing error, an error
5462" message is given and converted to an exception, and the expression
5463" evaluation is aborted.
5464"-------------------------------------------------------------------------------
5465func Test_expr_eval_error_msg()
5466 CheckEnglish
5467
5468 let test =<< trim [CODE]
5469 let taken = ""
5470
5471 func F(n)
5472 let g:taken = g:taken . "F" . a:n
5473 endfunc
5474
5475 func MSG(n, enr, emsg)
5476 let g:taken = g:taken . "M" . a:n
5477 call assert_match('^' .. a:enr .. ':', v:errmsg)
5478 call assert_match(a:emsg, v:errmsg)
5479 endfunc
5480
5481 func CONT(n)
5482 let g:taken = g:taken . "C" . a:n
5483 endfunc
5484
5485 let v:errmsg = ""
5486 try
5487 let t = 1
5488 while t <= 14
5489 let g:taken = g:taken . "T" . t
5490 let v:errmsg = ""
5491 try
5492 if t == 1
5493 let v{novar + CONT(t)} = 0
5494 elseif t == 2
5495 let v{novar + CONT(t)}
5496 elseif t == 3
5497 let var = exists('v{novar + CONT(t)}')
5498 elseif t == 4
5499 unlet v{novar + CONT(t)}
5500 elseif t == 5
5501 function F{novar + CONT(t)}()
5502 endfunction
5503 elseif t == 6
5504 function F{novar + CONT(t)}
5505 elseif t == 7
5506 let var = exists('*F{novar + CONT(t)}')
5507 elseif t == 8
5508 delfunction F{novar + CONT(t)}
5509 elseif t == 9
5510 echo novar + CONT(t)
5511 elseif t == 10
5512 echo v{novar + CONT(t)}
5513 elseif t == 11
5514 echo F{novar + CONT(t)}
5515 elseif t == 12
5516 let var = novar + CONT(t)
5517 elseif t == 13
5518 let var = v{novar + CONT(t)}
5519 elseif t == 14
5520 let var = F{novar + CONT(t)}()
5521 endif
5522 catch /^Vim\((\a\+)\)\=:/
5523 Xloop 'a'
5524 " v:errmsg is not set when the error message is converted to an
5525 " exception. Set it to the original error message.
5526 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5527 finally
5528 Xloop 'b'
5529 if t <= 8 && t != 3 && t != 7
5530 call MSG(t, 'E475', 'Invalid argument\>')
5531 else
5532 call MSG(t, 'E121', "Undefined variable")
5533 endif
5534 let t = t + 1
5535 XloopNEXT
5536 continue " discard an aborting error
5537 endtry
5538 endwhile
5539 catch /.*/
5540 call assert_report('should not get here')
5541 endtry
5542
5543 func T(n, expr, enr, emsg)
5544 try
5545 let g:taken = g:taken . "T" . a:n
5546 let v:errmsg = ""
5547 try
5548 execute "let var = " . a:expr
5549 catch /^Vim\((\a\+)\)\=:/
5550 Xloop 'c'
5551 " v:errmsg is not set when the error message is converted to an
5552 " exception. Set it to the original error message.
5553 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5554 finally
5555 Xloop 'd'
5556 call MSG(a:n, a:enr, a:emsg)
5557 XloopNEXT
5558 " Discard an aborting error:
5559 return
5560 endtry
5561 catch /.*/
5562 call assert_report('should not get here')
5563 endtry
5564 endfunc
5565
5566 call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function")
5567 call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments")
5568 call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments")
5569 call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments")
5570 call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
5571 call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
5572 call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
5573 call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression")
5574 call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
5575 call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
5576 call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")
5577 call T(26, '& + CONT(26)', 'E112', "Option name missing")
5578 call T(27, '&asdf + CONT(27)', 'E113', "Unknown option")
5579
5580 let expected = ""
5581 \ .. "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
5582 \ .. "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
5583 \ .. "T26M26T27M27"
5584
5585 call assert_equal(expected, taken)
5586 [CODE]
5587 let verify =<< trim [CODE]
5588 let expected = "a1b1a2b2a3b3a4b4a5b5a6b6a7b7a8b8a9b9a10b10a11b11a12b12"
5589 \ .. "a13b13a14b14c15d15c16d16c17d17c18d18c19d19c20d20"
5590 \ .. "c21d21c22d22c23d23c24d24c25d25c26d26c27d27"
5591 call assert_equal(expected, g:Xpath)
5592 [CODE]
5593 call RunInNewVim(test, verify)
5594endfunc
5595
5596"-------------------------------------------------------------------------------
5597" Test 79: Throwing one of several errors for the same command {{{1
5598"
5599" When several errors appear in a row (for instance during expression
5600" evaluation), the first as the most specific one is used when
5601" throwing an error exception. If, however, a syntax error is
5602" detected afterwards, this one is used for the error exception.
5603" On a syntax error, the next command is not executed, on a normal
5604" error, however, it is (relevant only in a function without the
5605" "abort" flag). v:errmsg is not set.
5606"
5607" If throwing error exceptions is configured off, v:errmsg is always
5608" set to the latest error message, that is, to the more general
5609" message or the syntax error, respectively.
5610"-------------------------------------------------------------------------------
5611func Test_throw_multi_error()
5612 CheckEnglish
5613
5614 let test =<< trim [CODE]
5615 func NEXT(cmd)
5616 exec a:cmd . " | Xloop 'a'"
5617 endfun
5618
5619 call NEXT('echo novar') " (checks nextcmd)
5620 XloopNEXT
5621 call NEXT('let novar #') " (skips nextcmd)
5622 XloopNEXT
5623 call NEXT('unlet novar #') " (skips nextcmd)
5624 XloopNEXT
5625 call NEXT('let {novar}') " (skips nextcmd)
5626 XloopNEXT
5627 call NEXT('unlet{ novar}') " (skips nextcmd)
5628
5629 call assert_equal('a1', g:Xpath)
5630 XpathINIT
5631 XloopINIT
5632
5633 func EXEC(cmd)
5634 exec a:cmd
5635 endfunc
5636
5637 try
5638 while 1 " dummy loop
5639 try
5640 let v:errmsg = ""
5641 call EXEC('echo novar') " normal error
5642 catch /^Vim\((\a\+)\)\=:/
5643 Xpath 'b'
5644 call assert_match('E121: Undefined variable: novar', v:exception)
5645 finally
5646 Xpath 'c'
5647 call assert_equal("", v:errmsg)
5648 break
5649 endtry
5650 endwhile
5651
5652 Xpath 'd'
5653 let cmd = "let"
5654 while cmd != ""
5655 try
5656 let v:errmsg = ""
5657 call EXEC(cmd . ' novar #') " normal plus syntax error
5658 catch /^Vim\((\a\+)\)\=:/
5659 Xloop 'e'
5660 call assert_match('E488: Trailing characters', v:exception)
5661 finally
5662 Xloop 'f'
5663 call assert_equal("", v:errmsg)
5664 if cmd == "let"
5665 let cmd = "unlet"
5666 else
5667 let cmd = ""
5668 endif
5669 XloopNEXT
5670 continue
5671 endtry
5672 endwhile
5673
5674 Xpath 'g'
5675 let cmd = "let"
5676 while cmd != ""
5677 try
5678 let v:errmsg = ""
5679 call EXEC(cmd . ' {novar}') " normal plus syntax error
5680 catch /^Vim\((\a\+)\)\=:/
5681 Xloop 'h'
5682 call assert_match('E475: Invalid argument: {novar}', v:exception)
5683 finally
5684 Xloop 'i'
5685 call assert_equal("", v:errmsg)
5686 if cmd == "let"
5687 let cmd = "unlet"
5688 else
5689 let cmd = ""
5690 endif
5691 XloopNEXT
5692 continue
5693 endtry
5694 endwhile
5695 catch /.*/
5696 call assert_report('should not get here')
5697 endtry
5698 Xpath 'j'
5699 [CODE]
5700 let verify =<< trim [CODE]
5701 call assert_equal('bcde1f1e2f2gh3i3h4i4j', g:Xpath)
5702 [CODE]
5703 call RunInNewVim(test, verify)
5704endfunc
5705
5706"-------------------------------------------------------------------------------
5707" Test 80: Syntax error in expression for illegal :elseif {{{1
5708"
5709" If there is a syntax error in the expression after an illegal
5710" :elseif, an error message is given (or an error exception thrown)
5711" for the illegal :elseif rather than the expression error.
5712"-------------------------------------------------------------------------------
5713func Test_if_syntax_error()
5714 CheckEnglish
5715
5716 let test =<< trim [CODE]
5717 let v:errmsg = ""
5718 if 0
5719 else
5720 elseif 1 ||| 2
5721 endif
5722 Xpath 'a'
5723 call assert_match('E584: :elseif after :else', v:errmsg)
5724
5725 let v:errmsg = ""
5726 if 1
5727 else
5728 elseif 1 ||| 2
5729 endif
5730 Xpath 'b'
5731 call assert_match('E584: :elseif after :else', v:errmsg)
5732
5733 let v:errmsg = ""
5734 elseif 1 ||| 2
5735 Xpath 'c'
5736 call assert_match('E582: :elseif without :if', v:errmsg)
5737
5738 let v:errmsg = ""
5739 while 1
5740 elseif 1 ||| 2
5741 endwhile
5742 Xpath 'd'
5743 call assert_match('E582: :elseif without :if', v:errmsg)
5744
5745 while 1
5746 try
5747 try
5748 let v:errmsg = ""
5749 if 0
5750 else
5751 elseif 1 ||| 2
5752 endif
5753 catch /^Vim\((\a\+)\)\=:/
5754 Xpath 'e'
5755 call assert_match('E584: :elseif after :else', v:exception)
5756 finally
5757 Xpath 'f'
5758 call assert_equal("", v:errmsg)
5759 endtry
5760 catch /.*/
5761 call assert_report('should not get here')
5762 finally
5763 Xpath 'g'
5764 break
5765 endtry
5766 endwhile
5767
5768 while 1
5769 try
5770 try
5771 let v:errmsg = ""
5772 if 1
5773 else
5774 elseif 1 ||| 2
5775 endif
5776 catch /^Vim\((\a\+)\)\=:/
5777 Xpath 'h'
5778 call assert_match('E584: :elseif after :else', v:exception)
5779 finally
5780 Xpath 'i'
5781 call assert_equal("", v:errmsg)
5782 endtry
5783 catch /.*/
5784 call assert_report('should not get here')
5785 finally
5786 Xpath 'j'
5787 break
5788 endtry
5789 endwhile
5790
5791 while 1
5792 try
5793 try
5794 let v:errmsg = ""
5795 elseif 1 ||| 2
5796 catch /^Vim\((\a\+)\)\=:/
5797 Xpath 'k'
5798 call assert_match('E582: :elseif without :if', v:exception)
5799 finally
5800 Xpath 'l'
5801 call assert_equal("", v:errmsg)
5802 endtry
5803 catch /.*/
5804 call assert_report('should not get here')
5805 finally
5806 Xpath 'm'
5807 break
5808 endtry
5809 endwhile
5810
5811 while 1
5812 try
5813 try
5814 let v:errmsg = ""
5815 while 1
5816 elseif 1 ||| 2
5817 endwhile
5818 catch /^Vim\((\a\+)\)\=:/
5819 Xpath 'n'
5820 call assert_match('E582: :elseif without :if', v:exception)
5821 finally
5822 Xpath 'o'
5823 call assert_equal("", v:errmsg)
5824 endtry
5825 catch /.*/
5826 call assert_report('should not get here')
5827 finally
5828 Xpath 'p'
5829 break
5830 endtry
5831 endwhile
5832 Xpath 'q'
5833 [CODE]
5834 let verify =<< trim [CODE]
5835 call assert_equal('abcdefghijklmnopq', g:Xpath)
5836 [CODE]
5837 call RunInNewVim(test, verify)
5838endfunc
5839
5840"-------------------------------------------------------------------------------
5841" Test 81: Discarding exceptions after an error or interrupt {{{1
5842"
5843" When an exception is thrown from inside a :try conditional without
5844" :catch and :finally clauses and an error or interrupt occurs before
5845" the :endtry is reached, the exception is discarded.
5846"-------------------------------------------------------------------------------
5847
5848func Test_discard_exception_after_error_1()
5849 let test =<< trim [CODE]
5850 try
5851 Xpath 'a'
5852 try
5853 Xpath 'b'
5854 throw "arrgh"
5855 call assert_report('should not get here')
5856 if 1
5857 call assert_report('should not get here')
5858 " error after :throw: missing :endif
5859 endtry
5860 call assert_report('should not get here')
5861 catch /arrgh/
5862 call assert_report('should not get here')
5863 endtry
5864 call assert_report('should not get here')
5865 [CODE]
5866 let verify =<< trim [CODE]
5867 call assert_equal('ab', g:Xpath)
5868 [CODE]
5869 call RunInNewVim(test, verify)
5870endfunc
5871
Bram Moolenaar16c62322020-08-13 19:20:04 +02005872" interrupt the code before the endtry is invoked
5873func Test_discard_exception_after_error_2()
5874 XpathINIT
5875 let lines =<< trim [CODE]
Bram Moolenaarefb64822020-08-10 22:15:30 +02005876 try
5877 Xpath 'a'
5878 try
5879 Xpath 'b'
5880 throw "arrgh"
Bram Moolenaarefb64822020-08-10 22:15:30 +02005881 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02005882 endtry " interrupt here
Bram Moolenaarefb64822020-08-10 22:15:30 +02005883 call assert_report('should not get here')
5884 catch /arrgh/
5885 call assert_report('should not get here')
5886 endtry
5887 call assert_report('should not get here')
5888 [CODE]
Bram Moolenaar16c62322020-08-13 19:20:04 +02005889 call writefile(lines, 'Xscript')
5890
5891 breakadd file 7 Xscript
5892 try
5893 let caught_intr = 0
5894 debuggreedy
5895 call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
5896 catch /^Vim:Interrupt$/
5897 call assert_match('Xscript, line 7', v:throwpoint)
5898 let caught_intr = 1
5899 endtry
5900 0debuggreedy
5901 call assert_equal(1, caught_intr)
5902 call assert_equal('ab', g:Xpath)
5903 breakdel *
5904 call delete('Xscript')
Bram Moolenaarefb64822020-08-10 22:15:30 +02005905endfunc
5906
5907"-------------------------------------------------------------------------------
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02005908" Test 82: Ignoring :catch clauses after an error or interrupt {{{1
5909"
5910" When an exception is thrown and an error or interrupt occurs before
5911" the matching :catch clause is reached, the exception is discarded
5912" and the :catch clause is ignored (also for the error or interrupt
5913" exception being thrown then).
5914"-------------------------------------------------------------------------------
5915
5916func Test_ignore_catch_after_error_1()
5917 let test =<< trim [CODE]
5918 try
5919 try
5920 Xpath 'a'
5921 throw "arrgh"
5922 call assert_report('should not get here')
5923 if 1
5924 call assert_report('should not get here')
5925 " error after :throw: missing :endif
5926 catch /.*/
5927 call assert_report('should not get here')
5928 catch /.*/
5929 call assert_report('should not get here')
5930 endtry
5931 call assert_report('should not get here')
5932 catch /arrgh/
5933 call assert_report('should not get here')
5934 endtry
5935 call assert_report('should not get here')
5936 [CODE]
5937 let verify =<< trim [CODE]
5938 call assert_equal('a', g:Xpath)
5939 [CODE]
5940 call RunInNewVim(test, verify)
5941endfunc
5942
5943func Test_ignore_catch_after_error_2()
5944 let test =<< trim [CODE]
5945 func E()
5946 try
5947 try
5948 Xpath 'a'
5949 throw "arrgh"
5950 call assert_report('should not get here')
5951 if 1
5952 call assert_report('should not get here')
5953 " error after :throw: missing :endif
5954 catch /.*/
5955 call assert_report('should not get here')
5956 catch /.*/
5957 call assert_report('should not get here')
5958 endtry
5959 call assert_report('should not get here')
5960 catch /arrgh/
5961 call assert_report('should not get here')
5962 endtry
5963 endfunc
5964
5965 call E()
5966 call assert_report('should not get here')
5967 [CODE]
5968 let verify =<< trim [CODE]
5969 call assert_equal('a', g:Xpath)
5970 [CODE]
5971 call RunInNewVim(test, verify)
5972endfunc
5973
Bram Moolenaar16c62322020-08-13 19:20:04 +02005974" interrupt right before a catch is invoked in a script
5975func Test_ignore_catch_after_intr_1()
5976 XpathINIT
5977 let lines =<< trim [CODE]
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02005978 try
5979 try
5980 Xpath 'a'
5981 throw "arrgh"
5982 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02005983 catch /.*/ " interrupt here
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02005984 call assert_report('should not get here')
5985 catch /.*/
5986 call assert_report('should not get here')
5987 endtry
5988 call assert_report('should not get here')
5989 catch /arrgh/
5990 call assert_report('should not get here')
5991 endtry
5992 call assert_report('should not get here')
5993 [CODE]
Bram Moolenaar16c62322020-08-13 19:20:04 +02005994 call writefile(lines, 'Xscript')
5995
5996 breakadd file 6 Xscript
5997 try
5998 let caught_intr = 0
5999 debuggreedy
6000 call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
6001 catch /^Vim:Interrupt$/
6002 call assert_match('Xscript, line 6', v:throwpoint)
6003 let caught_intr = 1
6004 endtry
6005 0debuggreedy
6006 call assert_equal(1, caught_intr)
6007 call assert_equal('a', g:Xpath)
6008 breakdel *
6009 call delete('Xscript')
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006010endfunc
6011
Bram Moolenaar16c62322020-08-13 19:20:04 +02006012" interrupt right before a catch is invoked inside a function.
6013func Test_ignore_catch_after_intr_2()
6014 XpathINIT
6015 func F()
6016 try
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006017 try
Bram Moolenaar16c62322020-08-13 19:20:04 +02006018 Xpath 'a'
6019 throw "arrgh"
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006020 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006021 catch /.*/ " interrupt here
6022 call assert_report('should not get here')
6023 catch /.*/
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006024 call assert_report('should not get here')
6025 endtry
Bram Moolenaar16c62322020-08-13 19:20:04 +02006026 call assert_report('should not get here')
6027 catch /arrgh/
6028 call assert_report('should not get here')
6029 endtry
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006030 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006031 endfunc
6032
6033 breakadd func 6 F
6034 try
6035 let caught_intr = 0
6036 debuggreedy
6037 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
6038 catch /^Vim:Interrupt$/
6039 call assert_match('\.F, line 6', v:throwpoint)
6040 let caught_intr = 1
6041 endtry
6042 0debuggreedy
6043 call assert_equal(1, caught_intr)
6044 call assert_equal('a', g:Xpath)
6045 breakdel *
6046 delfunc F
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006047endfunc
6048
6049"-------------------------------------------------------------------------------
6050" Test 83: Executing :finally clauses after an error or interrupt {{{1
6051"
6052" When an exception is thrown and an error or interrupt occurs before
6053" the :finally of the innermost :try is reached, the exception is
6054" discarded and the :finally clause is executed.
6055"-------------------------------------------------------------------------------
6056
6057func Test_finally_after_error()
6058 let test =<< trim [CODE]
6059 try
6060 Xpath 'a'
6061 try
6062 Xpath 'b'
6063 throw "arrgh"
6064 call assert_report('should not get here')
6065 if 1
6066 call assert_report('should not get here')
6067 " error after :throw: missing :endif
6068 finally
6069 Xpath 'c'
6070 endtry
6071 call assert_report('should not get here')
6072 catch /arrgh/
6073 call assert_report('should not get here')
6074 endtry
6075 call assert_report('should not get here')
6076 [CODE]
6077 let verify =<< trim [CODE]
6078 call assert_equal('abc', g:Xpath)
6079 [CODE]
6080 call RunInNewVim(test, verify)
6081endfunc
6082
Bram Moolenaar16c62322020-08-13 19:20:04 +02006083" interrupt the code right before the finally is invoked
6084func Test_finally_after_intr()
6085 XpathINIT
6086 let lines =<< trim [CODE]
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006087 try
6088 Xpath 'a'
6089 try
6090 Xpath 'b'
6091 throw "arrgh"
6092 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006093 finally " interrupt here
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006094 Xpath 'c'
6095 endtry
6096 call assert_report('should not get here')
6097 catch /arrgh/
6098 call assert_report('should not get here')
6099 endtry
6100 call assert_report('should not get here')
6101 [CODE]
Bram Moolenaar16c62322020-08-13 19:20:04 +02006102 call writefile(lines, 'Xscript')
6103
6104 breakadd file 7 Xscript
6105 try
6106 let caught_intr = 0
6107 debuggreedy
6108 call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
6109 catch /^Vim:Interrupt$/
6110 call assert_match('Xscript, line 7', v:throwpoint)
6111 let caught_intr = 1
6112 endtry
6113 0debuggreedy
6114 call assert_equal(1, caught_intr)
6115 call assert_equal('abc', g:Xpath)
6116 breakdel *
6117 call delete('Xscript')
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006118endfunc
6119
6120"-------------------------------------------------------------------------------
6121" Test 84: Exceptions in autocommand sequences. {{{1
6122"
6123" When an exception occurs in a sequence of autocommands for
6124" a specific event, the rest of the sequence is not executed. The
6125" command that triggered the autocommand execution aborts, and the
6126" exception is propagated to the caller.
6127"
6128" For the FuncUndefined event under a function call expression or
6129" :call command, the function is not executed, even when it has
6130" been defined by the autocommands before the exception occurred.
6131"-------------------------------------------------------------------------------
6132
6133func Test_autocmd_exception()
6134 let test =<< trim [CODE]
6135 func INT()
6136 call interrupt()
6137 endfunc
6138
6139 aug TMP
6140 autocmd!
6141
6142 autocmd User x1 Xpath 'a'
6143 autocmd User x1 throw "x1"
6144 autocmd User x1 call assert_report('should not get here')
6145
6146 autocmd User x2 Xpath 'b'
6147 autocmd User x2 asdf
6148 autocmd User x2 call assert_report('should not get here')
6149
6150 autocmd User x3 Xpath 'c'
6151 autocmd User x3 call INT()
6152 autocmd User x3 call assert_report('should not get here')
6153
6154 autocmd FuncUndefined U1 func U1()
6155 autocmd FuncUndefined U1 call assert_report('should not get here')
6156 autocmd FuncUndefined U1 endfunc
6157 autocmd FuncUndefined U1 Xpath 'd'
6158 autocmd FuncUndefined U1 throw "U1"
6159 autocmd FuncUndefined U1 call assert_report('should not get here')
6160
6161 autocmd FuncUndefined U2 func U2()
6162 autocmd FuncUndefined U2 call assert_report('should not get here')
6163 autocmd FuncUndefined U2 endfunc
6164 autocmd FuncUndefined U2 Xpath 'e'
6165 autocmd FuncUndefined U2 ASDF
6166 autocmd FuncUndefined U2 call assert_report('should not get here')
6167
6168 autocmd FuncUndefined U3 func U3()
6169 autocmd FuncUndefined U3 call assert_report('should not get here')
6170 autocmd FuncUndefined U3 endfunc
6171 autocmd FuncUndefined U3 Xpath 'f'
6172 autocmd FuncUndefined U3 call INT()
6173 autocmd FuncUndefined U3 call assert_report('should not get here')
6174 aug END
6175
6176 try
6177 try
6178 Xpath 'g'
6179 doautocmd User x1
6180 catch /x1/
6181 Xpath 'h'
6182 endtry
6183
6184 while 1
6185 try
6186 Xpath 'i'
6187 doautocmd User x2
6188 catch /asdf/
6189 Xpath 'j'
6190 finally
6191 Xpath 'k'
6192 break
6193 endtry
6194 endwhile
6195
6196 while 1
6197 try
6198 Xpath 'l'
6199 doautocmd User x3
6200 catch /Vim:Interrupt/
6201 Xpath 'm'
6202 finally
6203 Xpath 'n'
6204 " ... but break loop for caught interrupt exception,
6205 " or discard interrupt and break loop if $VIMNOINTTHROW
6206 break
6207 endtry
6208 endwhile
6209
6210 if exists("*U1") | delfunction U1 | endif
6211 if exists("*U2") | delfunction U2 | endif
6212 if exists("*U3") | delfunction U3 | endif
6213
6214 try
6215 Xpath 'o'
6216 call U1()
6217 catch /U1/
6218 Xpath 'p'
6219 endtry
6220
6221 while 1
6222 try
6223 Xpath 'q'
6224 call U2()
6225 catch /ASDF/
6226 Xpath 'r'
6227 finally
6228 Xpath 's'
6229 " ... but break loop for caught error exception,
6230 " or discard error and break loop if $VIMNOERRTHROW
6231 break
6232 endtry
6233 endwhile
6234
6235 while 1
6236 try
6237 Xpath 't'
6238 call U3()
6239 catch /Vim:Interrupt/
6240 Xpath 'u'
6241 finally
6242 Xpath 'v'
6243 " ... but break loop for caught interrupt exception,
6244 " or discard interrupt and break loop if $VIMNOINTTHROW
6245 break
6246 endtry
6247 endwhile
6248 catch /.*/
6249 call assert_report('should not get here')
6250 endtry
6251 Xpath 'w'
6252 [CODE]
6253 let verify =<< trim [CODE]
6254 call assert_equal('gahibjklcmnodpqerstfuvw', g:Xpath)
6255 [CODE]
6256 call RunInNewVim(test, verify)
6257endfunc
6258
6259"-------------------------------------------------------------------------------
6260" Test 85: Error exceptions in autocommands for I/O command events {{{1
6261"
6262" When an I/O command is inside :try/:endtry, autocommands to be
6263" executed after it should be skipped on an error (exception) in the
6264" command itself or in autocommands to be executed before the command.
6265" In the latter case, the I/O command should not be executed either.
6266" Example 1: BufWritePre, :write, BufWritePost
6267" Example 2: FileReadPre, :read, FileReadPost.
6268"-------------------------------------------------------------------------------
6269
6270func Test_autocmd_error_io_exception()
6271 let test =<< trim [CODE]
6272 " Remove the autocommands for the events specified as arguments in all used
6273 " autogroups.
6274 func Delete_autocommands(...)
6275 let augfile = tempname()
6276 while 1
6277 try
6278 exec "redir >" . augfile
6279 aug
6280 redir END
6281 exec "edit" augfile
6282 g/^$/d
6283 norm G$
6284 let wrap = "w"
6285 while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0
6286 let wrap = "W"
6287 exec "norm y/ \n"
6288 let argno = 1
6289 while argno <= a:0
6290 exec "au!" escape(@", " ") a:{argno}
6291 let argno = argno + 1
6292 endwhile
6293 endwhile
6294 catch /.*/
6295 finally
6296 bwipeout!
6297 call delete(augfile)
6298 break
6299 endtry
6300 endwhile
6301 endfunc
6302
6303 call Delete_autocommands("BufWritePre", "BufWritePost")
6304
6305 while 1
6306 try
6307 try
6308 let post = 0
6309 aug TMP
6310 au! BufWritePost * let post = 1
6311 aug END
6312 write /n/o/n/e/x/i/s/t/e/n/t
6313 catch /^Vim(write):/
6314 Xpath 'a'
6315 call assert_match("E212: Can't open file for writing", v:exception)
6316 finally
6317 Xpath 'b'
6318 call assert_equal(0, post)
6319 au! TMP
6320 aug! TMP
6321 endtry
6322 catch /.*/
6323 call assert_report('should not get here')
6324 finally
6325 Xpath 'c'
6326 break
6327 endtry
6328 endwhile
6329
6330 while 1
6331 try
6332 try
6333 let post = 0
6334 aug TMP
6335 au! BufWritePre * asdf
6336 au! BufWritePost * let post = 1
6337 aug END
6338 let tmpfile = tempname()
6339 exec "write" tmpfile
6340 catch /^Vim\((write)\)\=:/
6341 Xpath 'd'
6342 call assert_match('E492: Not an editor command', v:exception)
6343 finally
6344 Xpath 'e'
6345 if filereadable(tmpfile)
6346 call assert_report('should not get here')
6347 endif
6348 call assert_equal(0, post)
6349 au! TMP
6350 aug! TMP
6351 endtry
6352 catch /.*/
6353 call assert_report('should not get here')
6354 finally
6355 Xpath 'f'
6356 break
6357 endtry
6358 endwhile
6359
6360 call delete(tmpfile)
6361
6362 call Delete_autocommands("BufWritePre", "BufWritePost",
6363 \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
6364
6365 while 1
6366 try
6367 try
6368 let post = 0
6369 aug TMP
6370 au! FileReadPost * let post = 1
6371 aug END
6372 let caught = 0
6373 read /n/o/n/e/x/i/s/t/e/n/t
6374 catch /^Vim(read):/
6375 Xpath 'g'
6376 call assert_match("E484: Can't open file", v:exception)
6377 finally
6378 Xpath 'h'
6379 call assert_equal(0, post)
6380 au! TMP
6381 aug! TMP
6382 endtry
6383 catch /.*/
6384 call assert_report('should not get here')
6385 finally
6386 Xpath 'i'
6387 break
6388 endtry
6389 endwhile
6390
6391 while 1
6392 try
6393 let infile = tempname()
6394 let tmpfile = tempname()
6395 call writefile(["XYZ"], infile)
6396 exec "edit" tmpfile
6397 try
6398 Xpath 'j'
6399 try
6400 let post = 0
6401 aug TMP
6402 au! FileReadPre * asdf
6403 au! FileReadPost * let post = 1
6404 aug END
6405 exec "0read" infile
6406 catch /^Vim\((read)\)\=:/
6407 Xpath 'k'
6408 call assert_match('E492: Not an editor command', v:exception)
6409 finally
6410 Xpath 'l'
6411 if getline("1") == "XYZ"
6412 call assert_report('should not get here')
6413 endif
6414 call assert_equal(0, post)
6415 au! TMP
6416 aug! TMP
6417 endtry
6418 finally
6419 Xpath 'm'
6420 bwipeout!
6421 endtry
6422 catch /.*/
6423 call assert_report('should not get here')
6424 finally
6425 Xpath 'n'
6426 break
6427 endtry
6428 endwhile
6429
6430 call delete(infile)
6431 call delete(tmpfile)
6432 [CODE]
6433 let verify =<< trim [CODE]
6434 call assert_equal('abcdefghijklmn', g:Xpath)
6435 [CODE]
6436 call RunInNewVim(test, verify)
6437endfunc
6438
6439"-------------------------------------------------------------------------------
Bram Moolenaar1f068232019-11-03 16:17:26 +01006440" Test 87 using (expr) ? funcref : funcref {{{1
6441"
6442" Vim needs to correctly parse the funcref and even when it does
6443" not execute the funcref, it needs to consume the trailing ()
6444"-------------------------------------------------------------------------------
6445
6446func Add2(x1, x2)
6447 return a:x1 + a:x2
6448endfu
6449
6450func GetStr()
6451 return "abcdefghijklmnopqrstuvwxyp"
6452endfu
6453
6454func Test_funcref_with_condexpr()
6455 call assert_equal(5, function('Add2')(2,3))
6456
6457 call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
6458 call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
6459 " Make sure, GetStr() still works.
6460 call assert_equal('abcdefghijk', GetStr()[0:10])
6461endfunc
6462
Bram Moolenaar4119cf82016-01-17 14:59:01 +01006463" Test 90: Recognizing {} in variable name. {{{1
6464"-------------------------------------------------------------------------------
6465
6466func Test_curlies()
6467 let s:var = 66
6468 let ns = 's'
6469 call assert_equal(66, {ns}:var)
6470
6471 let g:a = {}
6472 let g:b = 't'
6473 let g:a[g:b] = 77
6474 call assert_equal(77, g:a['t'])
6475endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +01006476
6477"-------------------------------------------------------------------------------
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006478" Test 91: using type(). {{{1
6479"-------------------------------------------------------------------------------
6480
6481func Test_type()
6482 call assert_equal(0, type(0))
6483 call assert_equal(1, type(""))
6484 call assert_equal(2, type(function("tr")))
Bram Moolenaar953cc7f2016-03-19 18:52:29 +01006485 call assert_equal(2, type(function("tr", [8])))
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006486 call assert_equal(3, type([]))
6487 call assert_equal(4, type({}))
Bram Moolenaar5feabe02020-01-30 18:24:53 +01006488 if has('float')
6489 call assert_equal(5, type(0.0))
6490 endif
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006491 call assert_equal(6, type(v:false))
6492 call assert_equal(6, type(v:true))
6493 call assert_equal(7, type(v:none))
6494 call assert_equal(7, type(v:null))
Bram Moolenaarf562e722016-07-19 17:25:25 +02006495 call assert_equal(8, v:t_job)
6496 call assert_equal(9, v:t_channel)
6497 call assert_equal(v:t_number, type(0))
6498 call assert_equal(v:t_string, type(""))
6499 call assert_equal(v:t_func, type(function("tr")))
6500 call assert_equal(v:t_func, type(function("tr", [8])))
6501 call assert_equal(v:t_list, type([]))
6502 call assert_equal(v:t_dict, type({}))
Bram Moolenaar5feabe02020-01-30 18:24:53 +01006503 if has('float')
6504 call assert_equal(v:t_float, type(0.0))
6505 endif
Bram Moolenaarf562e722016-07-19 17:25:25 +02006506 call assert_equal(v:t_bool, type(v:false))
6507 call assert_equal(v:t_bool, type(v:true))
6508 call assert_equal(v:t_none, type(v:none))
6509 call assert_equal(v:t_none, type(v:null))
Bram Moolenaar92b83cc2020-04-25 15:24:44 +02006510 call assert_equal(v:t_string, type(test_null_string()))
6511 call assert_equal(v:t_func, type(test_null_function()))
6512 call assert_equal(v:t_func, type(test_null_partial()))
6513 call assert_equal(v:t_list, type(test_null_list()))
6514 call assert_equal(v:t_dict, type(test_null_dict()))
6515 if has('job')
6516 call assert_equal(v:t_job, type(test_null_job()))
6517 endif
6518 if has('channel')
6519 call assert_equal(v:t_channel, type(test_null_channel()))
6520 endif
6521 call assert_equal(v:t_blob, type(test_null_blob()))
Bram Moolenaarf562e722016-07-19 17:25:25 +02006522
Bram Moolenaar7c215c52020-02-29 13:43:27 +01006523 call assert_fails("call type(test_void())", 'E685:')
6524 call assert_fails("call type(test_unknown())", 'E685:')
Bram Moolenaar17a13432016-01-24 14:22:10 +01006525
6526 call assert_equal(0, 0 + v:false)
6527 call assert_equal(1, 0 + v:true)
6528 call assert_equal(0, 0 + v:none)
6529 call assert_equal(0, 0 + v:null)
6530
Bram Moolenaarf48aa162016-01-24 17:54:24 +01006531 call assert_equal('v:false', '' . v:false)
6532 call assert_equal('v:true', '' . v:true)
6533 call assert_equal('v:none', '' . v:none)
6534 call assert_equal('v:null', '' . v:null)
Bram Moolenaar6039c7f2016-01-24 15:05:32 +01006535
6536 call assert_true(v:false == 0)
6537 call assert_false(v:false != 0)
6538 call assert_true(v:true == 1)
6539 call assert_false(v:true != 1)
6540 call assert_false(v:true == v:false)
6541 call assert_true(v:true != v:false)
6542
6543 call assert_true(v:null == 0)
6544 call assert_false(v:null != 0)
6545 call assert_true(v:none == 0)
6546 call assert_false(v:none != 0)
Bram Moolenaar04369222016-01-24 17:21:29 +01006547
6548 call assert_true(v:false is v:false)
6549 call assert_true(v:true is v:true)
6550 call assert_true(v:none is v:none)
6551 call assert_true(v:null is v:null)
6552
6553 call assert_false(v:false isnot v:false)
6554 call assert_false(v:true isnot v:true)
6555 call assert_false(v:none isnot v:none)
6556 call assert_false(v:null isnot v:null)
6557
6558 call assert_false(v:false is 0)
6559 call assert_false(v:true is 1)
6560 call assert_false(v:true is v:false)
6561 call assert_false(v:none is 0)
6562 call assert_false(v:null is 0)
6563 call assert_false(v:null is v:none)
6564
6565 call assert_true(v:false isnot 0)
6566 call assert_true(v:true isnot 1)
6567 call assert_true(v:true isnot v:false)
6568 call assert_true(v:none isnot 0)
6569 call assert_true(v:null isnot 0)
6570 call assert_true(v:null isnot v:none)
Bram Moolenaar65591002016-01-24 21:51:57 +01006571
6572 call assert_equal(v:false, eval(string(v:false)))
6573 call assert_equal(v:true, eval(string(v:true)))
6574 call assert_equal(v:none, eval(string(v:none)))
6575 call assert_equal(v:null, eval(string(v:null)))
Bram Moolenaar767d8c12016-01-25 20:22:54 +01006576
Bram Moolenaar15550002016-01-31 18:45:24 +01006577 call assert_equal(v:false, copy(v:false))
6578 call assert_equal(v:true, copy(v:true))
6579 call assert_equal(v:none, copy(v:none))
6580 call assert_equal(v:null, copy(v:null))
6581
6582 call assert_equal([v:false], deepcopy([v:false]))
6583 call assert_equal([v:true], deepcopy([v:true]))
6584 call assert_equal([v:none], deepcopy([v:none]))
6585 call assert_equal([v:null], deepcopy([v:null]))
6586
Bram Moolenaar767d8c12016-01-25 20:22:54 +01006587 call assert_true(empty(v:false))
6588 call assert_false(empty(v:true))
6589 call assert_true(empty(v:null))
6590 call assert_true(empty(v:none))
Bram Moolenaar6650a692016-01-26 19:59:10 +01006591
6592 func ChangeYourMind()
Bram Moolenaar1e115362019-01-09 23:01:02 +01006593 try
6594 return v:true
6595 finally
6596 return 'something else'
6597 endtry
Bram Moolenaar6650a692016-01-26 19:59:10 +01006598 endfunc
6599
6600 call ChangeYourMind()
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006601endfunc
6602
6603"-------------------------------------------------------------------------------
Bram Moolenaarea8c2192016-02-07 19:27:53 +01006604" Test 92: skipping code {{{1
6605"-------------------------------------------------------------------------------
6606
6607func Test_skip()
6608 let Fn = function('Test_type')
6609 call assert_false(0 && Fn[1])
6610 call assert_false(0 && string(Fn))
6611 call assert_false(0 && len(Fn))
6612 let l = []
6613 call assert_false(0 && l[1])
6614 call assert_false(0 && string(l))
6615 call assert_false(0 && len(l))
6616 let f = 1.0
6617 call assert_false(0 && f[1])
6618 call assert_false(0 && string(f))
6619 call assert_false(0 && len(f))
6620 let sp = v:null
6621 call assert_false(0 && sp[1])
6622 call assert_false(0 && string(sp))
6623 call assert_false(0 && len(sp))
6624
6625endfunc
6626
6627"-------------------------------------------------------------------------------
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006628" Test 93: :echo and string() {{{1
6629"-------------------------------------------------------------------------------
6630
6631func Test_echo_and_string()
6632 " String
6633 let a = 'foo bar'
6634 redir => result
6635 echo a
6636 echo string(a)
6637 redir END
6638 let l = split(result, "\n")
6639 call assert_equal(["foo bar",
6640 \ "'foo bar'"], l)
6641
6642 " Float
6643 if has('float')
6644 let a = -1.2e0
6645 redir => result
6646 echo a
6647 echo string(a)
6648 redir END
6649 let l = split(result, "\n")
6650 call assert_equal(["-1.2",
6651 \ "-1.2"], l)
6652 endif
6653
6654 " Funcref
6655 redir => result
6656 echo function('string')
6657 echo string(function('string'))
6658 redir END
6659 let l = split(result, "\n")
6660 call assert_equal(["string",
6661 \ "function('string')"], l)
6662
6663 " Recursive dictionary
6664 let a = {}
6665 let a["a"] = a
6666 redir => result
6667 echo a
6668 echo string(a)
6669 redir END
6670 let l = split(result, "\n")
6671 call assert_equal(["{'a': {...}}",
6672 \ "{'a': {...}}"], l)
6673
6674 " Recursive list
6675 let a = [0]
6676 let a[0] = a
6677 redir => result
6678 echo a
6679 echo string(a)
6680 redir END
6681 let l = split(result, "\n")
6682 call assert_equal(["[[...]]",
6683 \ "[[...]]"], l)
6684
6685 " Empty dictionaries in a list
6686 let a = {}
6687 redir => result
6688 echo [a, a, a]
6689 echo string([a, a, a])
6690 redir END
6691 let l = split(result, "\n")
6692 call assert_equal(["[{}, {}, {}]",
6693 \ "[{}, {}, {}]"], l)
6694
6695 " Empty dictionaries in a dictionary
6696 let a = {}
6697 let b = {"a": a, "b": a}
6698 redir => result
6699 echo b
6700 echo string(b)
6701 redir END
6702 let l = split(result, "\n")
6703 call assert_equal(["{'a': {}, 'b': {}}",
6704 \ "{'a': {}, 'b': {}}"], l)
6705
6706 " Empty lists in a list
6707 let a = []
6708 redir => result
6709 echo [a, a, a]
6710 echo string([a, a, a])
6711 redir END
6712 let l = split(result, "\n")
6713 call assert_equal(["[[], [], []]",
6714 \ "[[], [], []]"], l)
6715
6716 " Empty lists in a dictionary
6717 let a = []
6718 let b = {"a": a, "b": a}
6719 redir => result
6720 echo b
6721 echo string(b)
6722 redir END
6723 let l = split(result, "\n")
6724 call assert_equal(["{'a': [], 'b': []}",
6725 \ "{'a': [], 'b': []}"], l)
6726
6727 " Dictionaries in a list
6728 let a = {"one": "yes", "two": "yes", "three": "yes"}
6729 redir => result
6730 echo [a, a, a]
6731 echo string([a, a, a])
6732 redir END
6733 let l = split(result, "\n")
6734 call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
6735 \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
6736
6737 " Dictionaries in a dictionary
6738 let a = {"one": "yes", "two": "yes", "three": "yes"}
6739 let b = {"a": a, "b": a}
6740 redir => result
6741 echo b
6742 echo string(b)
6743 redir END
6744 let l = split(result, "\n")
6745 call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
6746 \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
6747
6748 " Lists in a list
6749 let a = [1, 2, 3]
6750 redir => result
6751 echo [a, a, a]
6752 echo string([a, a, a])
6753 redir END
6754 let l = split(result, "\n")
6755 call assert_equal(["[[1, 2, 3], [...], [...]]",
6756 \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
6757
6758 " Lists in a dictionary
6759 let a = [1, 2, 3]
6760 let b = {"a": a, "b": a}
6761 redir => result
6762 echo b
6763 echo string(b)
6764 redir END
6765 let l = split(result, "\n")
6766 call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
6767 \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
6768
Bram Moolenaar1363a302020-04-12 13:50:26 +02006769 call assert_fails('echo &:', 'E112:')
6770 call assert_fails('echo &g:', 'E112:')
6771 call assert_fails('echo &l:', 'E112:')
6772
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006773endfunc
6774
6775"-------------------------------------------------------------------------------
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006776" Test 94: 64-bit Numbers {{{1
6777"-------------------------------------------------------------------------------
6778
6779func Test_num64()
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006780 call assert_notequal( 4294967296, 0)
6781 call assert_notequal(-4294967296, 0)
6782 call assert_equal( 4294967296, 0xFFFFffff + 1)
6783 call assert_equal(-4294967296, -0xFFFFffff - 1)
6784
6785 call assert_equal( 9223372036854775807, 1 / 0)
6786 call assert_equal(-9223372036854775807, -1 / 0)
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01006787 call assert_equal(-9223372036854775807 - 1, 0 / 0)
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006788
Bram Moolenaar5feabe02020-01-30 18:24:53 +01006789 if has('float')
6790 call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
6791 call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
6792 endif
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006793
6794 let rng = range(0xFFFFffff, 0x100000001)
6795 call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
6796 call assert_equal(0x100000001, max(rng))
6797 call assert_equal(0xFFFFffff, min(rng))
6798 call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
6799endfunc
6800
6801"-------------------------------------------------------------------------------
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006802" Test 95: lines of :append, :change, :insert {{{1
6803"-------------------------------------------------------------------------------
6804
6805function! DefineFunction(name, body)
6806 let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
6807 exec func
6808endfunction
6809
6810func Test_script_lines()
6811 " :append
6812 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006813 call DefineFunction('T_Append', [
6814 \ 'append',
6815 \ 'py <<EOS',
6816 \ '.',
6817 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006818 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006819 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006820 endtry
6821 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006822 call DefineFunction('T_Append', [
6823 \ 'append',
6824 \ 'abc',
6825 \ ])
6826 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006827 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006828 call assert_exception('Vim(function):E126: Missing :endfunction')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006829 endtry
6830
6831 " :change
6832 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006833 call DefineFunction('T_Change', [
6834 \ 'change',
6835 \ 'py <<EOS',
6836 \ '.',
6837 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006838 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006839 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006840 endtry
6841 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006842 call DefineFunction('T_Change', [
6843 \ 'change',
6844 \ 'abc',
6845 \ ])
6846 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006847 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006848 call assert_exception('Vim(function):E126: Missing :endfunction')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006849 endtry
6850
6851 " :insert
6852 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006853 call DefineFunction('T_Insert', [
6854 \ 'insert',
6855 \ 'py <<EOS',
6856 \ '.',
6857 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006858 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006859 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006860 endtry
6861 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006862 call DefineFunction('T_Insert', [
6863 \ 'insert',
6864 \ 'abc',
6865 \ ])
6866 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006867 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006868 call assert_exception('Vim(function):E126: Missing :endfunction')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006869 endtry
6870endfunc
6871
6872"-------------------------------------------------------------------------------
Bram Moolenaar478af672017-04-10 22:22:42 +02006873" Test 96: line continuation {{{1
6874"
Bram Moolenaar1e115362019-01-09 23:01:02 +01006875" Undefined behavior was detected by ubsan with line continuation
6876" after an empty line.
Bram Moolenaar478af672017-04-10 22:22:42 +02006877"-------------------------------------------------------------------------------
6878func Test_script_emty_line_continuation()
6879
6880 \
6881endfunc
6882
6883"-------------------------------------------------------------------------------
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006884" Test 97: bitwise functions {{{1
6885"-------------------------------------------------------------------------------
6886func Test_bitwise_functions()
6887 " and
6888 call assert_equal(127, and(127, 127))
6889 call assert_equal(16, and(127, 16))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006890 eval 127->and(16)->assert_equal(16)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006891 call assert_equal(0, and(127, 128))
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006892 call assert_fails("call and([], 1)", 'E745:')
6893 call assert_fails("call and({}, 1)", 'E728:')
Bram Moolenaar5feabe02020-01-30 18:24:53 +01006894 if has('float')
6895 call assert_fails("call and(1.0, 1)", 'E805:')
6896 call assert_fails("call and(1, 1.0)", 'E805:')
6897 endif
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006898 call assert_fails("call and(1, [])", 'E745:')
6899 call assert_fails("call and(1, {})", 'E728:')
6900 " or
6901 call assert_equal(23, or(16, 7))
6902 call assert_equal(15, or(8, 7))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006903 eval 8->or(7)->assert_equal(15)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006904 call assert_equal(123, or(0, 123))
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006905 call assert_fails("call or([], 1)", 'E745:')
6906 call assert_fails("call or({}, 1)", 'E728:')
Bram Moolenaar5feabe02020-01-30 18:24:53 +01006907 if has('float')
6908 call assert_fails("call or(1.0, 1)", 'E805:')
6909 call assert_fails("call or(1, 1.0)", 'E805:')
6910 endif
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006911 call assert_fails("call or(1, [])", 'E745:')
6912 call assert_fails("call or(1, {})", 'E728:')
6913 " xor
6914 call assert_equal(0, xor(127, 127))
6915 call assert_equal(111, xor(127, 16))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006916 eval 127->xor(16)->assert_equal(111)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006917 call assert_equal(255, xor(127, 128))
Bram Moolenaar5feabe02020-01-30 18:24:53 +01006918 if has('float')
6919 call assert_fails("call xor(1.0, 1)", 'E805:')
6920 call assert_fails("call xor(1, 1.0)", 'E805:')
6921 endif
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006922 call assert_fails("call xor([], 1)", 'E745:')
6923 call assert_fails("call xor({}, 1)", 'E728:')
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006924 call assert_fails("call xor(1, [])", 'E745:')
6925 call assert_fails("call xor(1, {})", 'E728:')
6926 " invert
6927 call assert_equal(65408, and(invert(127), 65535))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006928 eval 127->invert()->and(65535)->assert_equal(65408)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006929 call assert_equal(65519, and(invert(16), 65535))
6930 call assert_equal(65407, and(invert(128), 65535))
Bram Moolenaar5feabe02020-01-30 18:24:53 +01006931 if has('float')
6932 call assert_fails("call invert(1.0)", 'E805:')
6933 endif
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006934 call assert_fails("call invert([])", 'E745:')
6935 call assert_fails("call invert({})", 'E728:')
6936endfunc
6937
Bram Moolenaar6f9a4762017-06-22 20:39:17 +02006938" Test using bang after user command {{{1
6939func Test_user_command_with_bang()
6940 command -bang Nieuw let nieuw = 1
6941 Ni!
6942 call assert_equal(1, nieuw)
6943 unlet nieuw
6944 delcommand Nieuw
6945endfunc
6946
Bram Moolenaarb9adef72020-01-02 14:31:22 +01006947func Test_script_expand_sfile()
6948 let lines =<< trim END
6949 func s:snr()
6950 return expand('<sfile>')
6951 endfunc
6952 let g:result = s:snr()
6953 END
6954 call writefile(lines, 'Xexpand')
6955 source Xexpand
6956 call assert_match('<SNR>\d\+_snr', g:result)
6957 source Xexpand
6958 call assert_match('<SNR>\d\+_snr', g:result)
6959
6960 call delete('Xexpand')
6961 unlet g:result
6962endfunc
6963
Bram Moolenaarff697e62019-02-12 22:28:33 +01006964func Test_compound_assignment_operators()
6965 " Test for number
6966 let x = 1
6967 let x += 10
6968 call assert_equal(11, x)
6969 let x -= 5
6970 call assert_equal(6, x)
6971 let x *= 4
6972 call assert_equal(24, x)
6973 let x /= 3
6974 call assert_equal(8, x)
6975 let x %= 3
6976 call assert_equal(2, x)
6977 let x .= 'n'
6978 call assert_equal('2n', x)
6979
Bram Moolenaare21c1582019-03-02 11:57:09 +01006980 " Test special cases: division or modulus with 0.
6981 let x = 1
6982 let x /= 0
Bram Moolenaar82f654e2020-02-17 22:12:50 +01006983 call assert_equal(0x7FFFFFFFFFFFFFFF, x)
Bram Moolenaare21c1582019-03-02 11:57:09 +01006984
6985 let x = -1
6986 let x /= 0
Bram Moolenaar82f654e2020-02-17 22:12:50 +01006987 call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
Bram Moolenaare21c1582019-03-02 11:57:09 +01006988
6989 let x = 0
6990 let x /= 0
Bram Moolenaar82f654e2020-02-17 22:12:50 +01006991 call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
Bram Moolenaare21c1582019-03-02 11:57:09 +01006992
6993 let x = 1
6994 let x %= 0
6995 call assert_equal(0, x)
6996
6997 let x = -1
6998 let x %= 0
6999 call assert_equal(0, x)
7000
7001 let x = 0
7002 let x %= 0
7003 call assert_equal(0, x)
7004
Bram Moolenaarff697e62019-02-12 22:28:33 +01007005 " Test for string
7006 let x = 'str'
7007 let x .= 'ing'
7008 call assert_equal('string', x)
7009 let x += 1
7010 call assert_equal(1, x)
Bram Moolenaarff697e62019-02-12 22:28:33 +01007011
7012 if has('float')
Bram Moolenaar5feabe02020-01-30 18:24:53 +01007013 " Test for float
7014 let x -= 1.5
7015 call assert_equal(-0.5, x)
7016 let x = 0.5
7017 let x += 4.5
7018 call assert_equal(5.0, x)
7019 let x -= 1.5
7020 call assert_equal(3.5, x)
7021 let x *= 3.0
7022 call assert_equal(10.5, x)
7023 let x /= 2.5
7024 call assert_equal(4.2, x)
Bram Moolenaare2e40752020-09-04 21:18:46 +02007025 call assert_fails('let x %= 0.5', 'E734:')
7026 call assert_fails('let x .= "f"', 'E734:')
Bram Moolenaar8b633132020-03-20 18:20:51 +01007027 let x = !3.14
7028 call assert_equal(0.0, x)
Bram Moolenaarea04a6e2020-04-23 13:38:02 +02007029
7030 " integer and float operations
7031 let x = 1
7032 let x *= 2.1
7033 call assert_equal(2.1, x)
7034 let x = 1
7035 let x /= 0.25
7036 call assert_equal(4.0, x)
7037 let x = 1
7038 call assert_fails('let x %= 0.25', 'E734:')
7039 let x = 1
7040 call assert_fails('let x .= 0.25', 'E734:')
7041 let x = 1.0
7042 call assert_fails('let x += [1.1]', 'E734:')
Bram Moolenaarff697e62019-02-12 22:28:33 +01007043 endif
7044
7045 " Test for environment variable
7046 let $FOO = 1
Bram Moolenaare2e40752020-09-04 21:18:46 +02007047 call assert_fails('let $FOO += 1', 'E734:')
7048 call assert_fails('let $FOO -= 1', 'E734:')
7049 call assert_fails('let $FOO *= 1', 'E734:')
7050 call assert_fails('let $FOO /= 1', 'E734:')
7051 call assert_fails('let $FOO %= 1', 'E734:')
Bram Moolenaarff697e62019-02-12 22:28:33 +01007052 let $FOO .= 's'
7053 call assert_equal('1s', $FOO)
7054 unlet $FOO
7055
7056 " Test for option variable (type: number)
7057 let &scrolljump = 1
7058 let &scrolljump += 5
7059 call assert_equal(6, &scrolljump)
7060 let &scrolljump -= 2
7061 call assert_equal(4, &scrolljump)
7062 let &scrolljump *= 3
7063 call assert_equal(12, &scrolljump)
7064 let &scrolljump /= 2
7065 call assert_equal(6, &scrolljump)
7066 let &scrolljump %= 5
7067 call assert_equal(1, &scrolljump)
Bram Moolenaare2e40752020-09-04 21:18:46 +02007068 call assert_fails('let &scrolljump .= "j"', 'E734:')
Bram Moolenaarff697e62019-02-12 22:28:33 +01007069 set scrolljump&vim
7070
7071 " Test for register
7072 let @/ = 1
Bram Moolenaare2e40752020-09-04 21:18:46 +02007073 call assert_fails('let @/ += 1', 'E734:')
7074 call assert_fails('let @/ -= 1', 'E734:')
7075 call assert_fails('let @/ *= 1', 'E734:')
7076 call assert_fails('let @/ /= 1', 'E734:')
7077 call assert_fails('let @/ %= 1', 'E734:')
Bram Moolenaarff697e62019-02-12 22:28:33 +01007078 let @/ .= 's'
7079 call assert_equal('1s', @/)
7080 let @/ = ''
7081endfunc
7082
Bram Moolenaar7e0868e2020-04-19 17:24:53 +02007083func Test_unlet_env()
7084 let $TESTVAR = 'yes'
7085 call assert_equal('yes', $TESTVAR)
Bram Moolenaare2e40752020-09-04 21:18:46 +02007086 call assert_fails('lockvar $TESTVAR', 'E940:')
7087 call assert_fails('unlockvar $TESTVAR', 'E940:')
Bram Moolenaar7e0868e2020-04-19 17:24:53 +02007088 call assert_equal('yes', $TESTVAR)
7089 if 0
7090 unlet $TESTVAR
7091 endif
7092 call assert_equal('yes', $TESTVAR)
7093 unlet $TESTVAR
7094 call assert_equal('', $TESTVAR)
7095endfunc
7096
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01007097func Test_refcount()
7098 " Immediate values
7099 call assert_equal(-1, test_refcount(1))
7100 call assert_equal(-1, test_refcount('s'))
7101 call assert_equal(-1, test_refcount(v:true))
7102 call assert_equal(0, test_refcount([]))
7103 call assert_equal(0, test_refcount({}))
7104 call assert_equal(0, test_refcount(0zff))
7105 call assert_equal(0, test_refcount({-> line('.')}))
7106 if has('float')
7107 call assert_equal(-1, test_refcount(0.1))
7108 endif
7109 if has('job')
7110 call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
7111 endif
7112
7113 " No refcount types
7114 let x = 1
7115 call assert_equal(-1, test_refcount(x))
7116 let x = 's'
7117 call assert_equal(-1, test_refcount(x))
7118 let x = v:true
7119 call assert_equal(-1, test_refcount(x))
7120 if has('float')
7121 let x = 0.1
7122 call assert_equal(-1, test_refcount(x))
7123 endif
7124
7125 " Check refcount
7126 let x = []
7127 call assert_equal(1, test_refcount(x))
7128
7129 let x = {}
Bram Moolenaarce90e362019-09-08 18:58:44 +02007130 call assert_equal(1, x->test_refcount())
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01007131
7132 let x = 0zff
7133 call assert_equal(1, test_refcount(x))
7134
7135 let X = {-> line('.')}
7136 call assert_equal(1, test_refcount(X))
7137 let Y = X
7138 call assert_equal(2, test_refcount(X))
7139
7140 if has('job')
7141 let job = job_start([&shell, &shellcmdflag, 'echo .'])
7142 call assert_equal(1, test_refcount(job))
7143 call assert_equal(1, test_refcount(job_getchannel(job)))
7144 call assert_equal(1, test_refcount(job))
7145 endif
7146
7147 " Function arguments, copying and unassigning
7148 func ExprCheck(x, i)
7149 let i = a:i + 1
7150 call assert_equal(i, test_refcount(a:x))
7151 let Y = a:x
7152 call assert_equal(i + 1, test_refcount(a:x))
7153 call assert_equal(test_refcount(a:x), test_refcount(Y))
7154 let Y = 0
7155 call assert_equal(i, test_refcount(a:x))
7156 endfunc
7157 call ExprCheck([], 0)
7158 call ExprCheck({}, 0)
7159 call ExprCheck(0zff, 0)
7160 call ExprCheck({-> line('.')}, 0)
7161 if has('job')
7162 call ExprCheck(job, 1)
7163 call ExprCheck(job_getchannel(job), 1)
7164 call job_stop(job)
7165 endif
7166 delfunc ExprCheck
7167
7168 " Regarding function
7169 func Func(x) abort
7170 call assert_equal(2, test_refcount(function('Func')))
7171 call assert_equal(0, test_refcount(funcref('Func')))
7172 endfunc
7173 call assert_equal(1, test_refcount(function('Func')))
7174 call assert_equal(0, test_refcount(function('Func', [1])))
7175 call assert_equal(0, test_refcount(funcref('Func')))
7176 call assert_equal(0, test_refcount(funcref('Func', [1])))
7177 let X = function('Func')
7178 let Y = X
7179 call assert_equal(1, test_refcount(X))
7180 let X = function('Func', [1])
7181 let Y = X
7182 call assert_equal(2, test_refcount(X))
7183 let X = funcref('Func')
7184 let Y = X
7185 call assert_equal(2, test_refcount(X))
7186 let X = funcref('Func', [1])
7187 let Y = X
7188 call assert_equal(2, test_refcount(X))
7189 unlet X
7190 unlet Y
7191 call Func(1)
7192 delfunc Func
7193
7194 " Function with dict
7195 func DictFunc() dict
7196 call assert_equal(3, test_refcount(self))
7197 endfunc
7198 let d = {'Func': function('DictFunc')}
7199 call assert_equal(1, test_refcount(d))
7200 call assert_equal(0, test_refcount(d.Func))
7201 call d.Func()
7202 unlet d
7203 delfunc DictFunc
7204endfunc
7205
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007206" Test for missing :endif, :endfor, :endwhile and :endtry {{{1
7207func Test_missing_end()
7208 call writefile(['if 2 > 1', 'echo ">"'], 'Xscript')
7209 call assert_fails('source Xscript', 'E171:')
7210 call writefile(['for i in range(5)', 'echo i'], 'Xscript')
7211 call assert_fails('source Xscript', 'E170:')
7212 call writefile(['while v:true', 'echo "."'], 'Xscript')
7213 call assert_fails('source Xscript', 'E170:')
7214 call writefile(['try', 'echo "."'], 'Xscript')
7215 call assert_fails('source Xscript', 'E600:')
7216 call delete('Xscript')
Bram Moolenaar818fc9a2020-02-21 17:54:45 +01007217
7218 " Using endfor with :while
7219 let caught_e732 = 0
7220 try
7221 while v:true
7222 endfor
7223 catch /E732:/
7224 let caught_e732 = 1
7225 endtry
7226 call assert_equal(1, caught_e732)
7227
7228 " Using endwhile with :for
7229 let caught_e733 = 0
7230 try
7231 for i in range(1)
7232 endwhile
7233 catch /E733:/
7234 let caught_e733 = 1
7235 endtry
7236 call assert_equal(1, caught_e733)
7237
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007238 " Using endfunc with :if
7239 call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
7240
Bram Moolenaar818fc9a2020-02-21 17:54:45 +01007241 " Missing 'in' in a :for statement
7242 call assert_fails('for i range(1) | endfor', 'E690:')
Bram Moolenaarea04a6e2020-04-23 13:38:02 +02007243
7244 " Incorrect number of variables in for
7245 call assert_fails('for [i,] in range(3) | endfor', 'E475:')
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007246endfunc
7247
7248" Test for deep nesting of if/for/while/try statements {{{1
7249func Test_deep_nest()
Bram Moolenaar494e9062020-05-31 21:28:02 +02007250 CheckRunVimInTerminal
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007251
7252 let lines =<< trim [SCRIPT]
7253 " Deep nesting of if ... endif
7254 func Test1()
7255 let @a = join(repeat(['if v:true'], 51), "\n")
7256 let @a ..= "\n"
7257 let @a ..= join(repeat(['endif'], 51), "\n")
7258 @a
7259 let @a = ''
7260 endfunc
7261
7262 " Deep nesting of for ... endfor
7263 func Test2()
7264 let @a = join(repeat(['for i in [1]'], 51), "\n")
7265 let @a ..= "\n"
7266 let @a ..= join(repeat(['endfor'], 51), "\n")
7267 @a
7268 let @a = ''
7269 endfunc
7270
7271 " Deep nesting of while ... endwhile
7272 func Test3()
7273 let @a = join(repeat(['while v:true'], 51), "\n")
7274 let @a ..= "\n"
7275 let @a ..= join(repeat(['endwhile'], 51), "\n")
7276 @a
7277 let @a = ''
7278 endfunc
7279
7280 " Deep nesting of try ... endtry
7281 func Test4()
7282 let @a = join(repeat(['try'], 51), "\n")
7283 let @a ..= "\necho v:true\n"
7284 let @a ..= join(repeat(['endtry'], 51), "\n")
7285 @a
7286 let @a = ''
7287 endfunc
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007288
7289 " Deep nesting of function ... endfunction
7290 func Test5()
7291 let @a = join(repeat(['function X()'], 51), "\n")
7292 let @a ..= "\necho v:true\n"
7293 let @a ..= join(repeat(['endfunction'], 51), "\n")
7294 @a
7295 let @a = ''
7296 endfunc
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007297 [SCRIPT]
7298 call writefile(lines, 'Xscript')
7299
7300 let buf = RunVimInTerminal('-S Xscript', {'rows': 6})
7301
7302 " Deep nesting of if ... endif
7303 call term_sendkeys(buf, ":call Test1()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007304 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007305 call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
7306
7307 " Deep nesting of for ... endfor
7308 call term_sendkeys(buf, ":call Test2()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007309 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007310 call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
7311
7312 " Deep nesting of while ... endwhile
7313 call term_sendkeys(buf, ":call Test3()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007314 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007315 call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
7316
7317 " Deep nesting of try ... endtry
7318 call term_sendkeys(buf, ":call Test4()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007319 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007320 call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
7321
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007322 " Deep nesting of function ... endfunction
7323 call term_sendkeys(buf, ":call Test5()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007324 call TermWait(buf)
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007325 call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
7326 call term_sendkeys(buf, "\<C-C>\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007327 call TermWait(buf)
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007328
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007329 "let l = ''
7330 "for i in range(1, 6)
7331 " let l ..= term_getline(buf, i) . "\n"
7332 "endfor
7333 "call assert_report(l)
7334
7335 call StopVimInTerminal(buf)
7336 call delete('Xscript')
7337endfunc
7338
Bram Moolenaar8b633132020-03-20 18:20:51 +01007339" Test for errors in converting to float from various types {{{1
7340func Test_float_conversion_errors()
7341 if has('float')
Bram Moolenaare2e40752020-09-04 21:18:46 +02007342 call assert_fails('let x = 4.0 % 2.0', 'E804:')
7343 call assert_fails('echo 1.1[0]', 'E806:')
Bram Moolenaar8b633132020-03-20 18:20:51 +01007344 call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
7345 call assert_fails('echo 3.2 == "vim"', 'E892:')
7346 call assert_fails('echo sort([[], 1], "f")', 'E893:')
7347 call assert_fails('echo sort([{}, 1], "f")', 'E894:')
7348 call assert_fails('echo 3.2 == v:true', 'E362:')
7349 call assert_fails('echo 3.2 == v:none', 'E907:')
7350 endif
7351endfunc
7352
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02007353" invalid function names {{{1
Bram Moolenaar08f41572020-04-20 16:50:00 +02007354func Test_invalid_function_names()
7355 " function name not starting with capital
7356 let caught_e128 = 0
7357 try
7358 func! g:test()
7359 echo "test"
7360 endfunc
7361 catch /E128:/
7362 let caught_e128 = 1
7363 endtry
7364 call assert_equal(1, caught_e128)
7365
7366 " function name includes a colon
7367 let caught_e884 = 0
7368 try
7369 func! b:test()
7370 echo "test"
7371 endfunc
7372 catch /E884:/
7373 let caught_e884 = 1
7374 endtry
7375 call assert_equal(1, caught_e884)
7376
7377 " function name folowed by #
7378 let caught_e128 = 0
7379 try
7380 func! test2() "#
7381 echo "test2"
7382 endfunc
7383 catch /E128:/
7384 let caught_e128 = 1
7385 endtry
7386 call assert_equal(1, caught_e128)
7387
7388 " function name starting with/without "g:", buffer-local funcref.
7389 function! g:Foo(n)
7390 return 'called Foo(' . a:n . ')'
7391 endfunction
7392 let b:my_func = function('Foo')
7393 call assert_equal('called Foo(1)', b:my_func(1))
7394 call assert_equal('called Foo(2)', g:Foo(2))
7395 call assert_equal('called Foo(3)', Foo(3))
7396 delfunc g:Foo
7397
7398 " script-local function used in Funcref must exist.
7399 let lines =<< trim END
7400 func s:Testje()
7401 return "foo"
7402 endfunc
7403 let Bar = function('s:Testje')
7404 call assert_equal(0, exists('s:Testje'))
7405 call assert_equal(1, exists('*s:Testje'))
7406 call assert_equal(1, exists('Bar'))
7407 call assert_equal(1, exists('*Bar'))
7408 END
7409 call writefile(lines, 'Xscript')
7410 source Xscript
7411 call delete('Xscript')
7412endfunc
7413
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02007414" substring and variable name {{{1
Bram Moolenaar08f41572020-04-20 16:50:00 +02007415func Test_substring_var()
7416 let str = 'abcdef'
7417 let n = 3
7418 call assert_equal('def', str[n:])
7419 call assert_equal('abcd', str[:n])
7420 call assert_equal('d', str[n:n])
7421 unlet n
7422 let nn = 3
7423 call assert_equal('def', str[nn:])
7424 call assert_equal('abcd', str[:nn])
7425 call assert_equal('d', str[nn:nn])
7426 unlet nn
7427 let b:nn = 4
7428 call assert_equal('ef', str[b:nn:])
7429 call assert_equal('abcde', str[:b:nn])
7430 call assert_equal('e', str[b:nn:b:nn])
7431 unlet b:nn
7432endfunc
7433
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02007434" Test using s: with a typed command {{{1
7435func Test_typed_script_var()
7436 CheckRunVimInTerminal
7437
7438 let buf = RunVimInTerminal('', {'rows': 6})
7439
7440 " Deep nesting of if ... endif
7441 call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n")
7442 call TermWait(buf)
7443 call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))})
7444
7445 call StopVimInTerminal(buf)
7446endfunc
7447
Bram Moolenaar69e445522020-08-22 22:37:20 +02007448" Test for issue6776 {{{1
7449func Test_trinary_expression()
7450 try
7451 call eval('0 ? 0')
7452 catch
7453 endtry
7454 " previous failure should not cause next expression to fail
7455 call assert_equal(v:false, eval(string(v:false)))
7456
7457 try
7458 call eval('0 ? "burp')
7459 catch
7460 endtry
7461 " previous failure should not cause next expression to fail
7462 call assert_equal(v:false, eval(string(v:false)))
7463
7464 try
7465 call eval('1 ? 0 : "burp')
7466 catch
7467 endtry
7468 " previous failure should not cause next expression to fail
7469 call assert_equal(v:false, eval(string(v:false)))
7470endfunction
7471
Bram Moolenaar863e80b2017-06-04 20:30:00 +02007472"-------------------------------------------------------------------------------
Bram Moolenaarf49e2402015-12-30 15:59:25 +01007473" Modelines {{{1
Bram Moolenaar1f068232019-11-03 16:17:26 +01007474" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
Bram Moolenaarf49e2402015-12-30 15:59:25 +01007475"-------------------------------------------------------------------------------