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