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