blob: 0c4aedb3c6bc082ee217b8b4250f443cd2ee2943 [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.
Christian Brabandtee17b6f2023-09-09 11:23:50 +02003108" This function checks the messages in g:msgfile.
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02003109"-------------------------------------------------------------------------------
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.
Christian Brabandtee17b6f2023-09-09 11:23:50 +02003233" This function checks the messages in g:msgfile.
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02003234"-------------------------------------------------------------------------------
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.
Christian Brabandtee17b6f2023-09-09 11:23:50 +02003339" This function check the messages in g:msgfile.
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02003340"-------------------------------------------------------------------------------
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()
Bram Moolenaar6cf31512022-12-05 15:01:05 +00005980 " for unknown reasons this test sometimes fails on MS-Windows.
5981 let g:test_is_flaky = 1
5982
Bram Moolenaar16c62322020-08-13 19:20:04 +02005983 XpathINIT
5984 let lines =<< trim [CODE]
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02005985 try
5986 try
5987 Xpath 'a'
5988 throw "arrgh"
5989 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02005990 catch /.*/ " interrupt here
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02005991 call assert_report('should not get here')
5992 catch /.*/
5993 call assert_report('should not get here')
5994 endtry
5995 call assert_report('should not get here')
5996 catch /arrgh/
5997 call assert_report('should not get here')
5998 endtry
5999 call assert_report('should not get here')
6000 [CODE]
Bram Moolenaar5b148ef2022-10-15 21:35:56 +01006001 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006002
6003 breakadd file 6 Xscript
6004 try
6005 let caught_intr = 0
6006 debuggreedy
6007 call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
6008 catch /^Vim:Interrupt$/
6009 call assert_match('Xscript, line 6', v:throwpoint)
6010 let caught_intr = 1
6011 endtry
6012 0debuggreedy
6013 call assert_equal(1, caught_intr)
6014 call assert_equal('a', g:Xpath)
6015 breakdel *
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006016endfunc
6017
Bram Moolenaar16c62322020-08-13 19:20:04 +02006018" interrupt right before a catch is invoked inside a function.
6019func Test_ignore_catch_after_intr_2()
Bram Moolenaar72b5b0d2022-12-05 15:24:20 +00006020 " for unknown reasons this test sometimes fails on MS-Windows.
6021 let g:test_is_flaky = 1
6022
Bram Moolenaar16c62322020-08-13 19:20:04 +02006023 XpathINIT
6024 func F()
6025 try
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006026 try
Bram Moolenaar16c62322020-08-13 19:20:04 +02006027 Xpath 'a'
6028 throw "arrgh"
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006029 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006030 catch /.*/ " interrupt here
6031 call assert_report('should not get here')
6032 catch /.*/
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006033 call assert_report('should not get here')
6034 endtry
Bram Moolenaar16c62322020-08-13 19:20:04 +02006035 call assert_report('should not get here')
6036 catch /arrgh/
6037 call assert_report('should not get here')
6038 endtry
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006039 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006040 endfunc
6041
6042 breakadd func 6 F
6043 try
6044 let caught_intr = 0
6045 debuggreedy
6046 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
6047 catch /^Vim:Interrupt$/
6048 call assert_match('\.F, line 6', v:throwpoint)
6049 let caught_intr = 1
6050 endtry
6051 0debuggreedy
6052 call assert_equal(1, caught_intr)
6053 call assert_equal('a', g:Xpath)
6054 breakdel *
6055 delfunc F
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006056endfunc
6057
6058"-------------------------------------------------------------------------------
6059" Test 83: Executing :finally clauses after an error or interrupt {{{1
6060"
6061" When an exception is thrown and an error or interrupt occurs before
6062" the :finally of the innermost :try is reached, the exception is
6063" discarded and the :finally clause is executed.
6064"-------------------------------------------------------------------------------
6065
6066func Test_finally_after_error()
6067 let test =<< trim [CODE]
6068 try
6069 Xpath 'a'
6070 try
6071 Xpath 'b'
6072 throw "arrgh"
6073 call assert_report('should not get here')
6074 if 1
6075 call assert_report('should not get here')
6076 " error after :throw: missing :endif
6077 finally
6078 Xpath 'c'
6079 endtry
6080 call assert_report('should not get here')
6081 catch /arrgh/
6082 call assert_report('should not get here')
6083 endtry
6084 call assert_report('should not get here')
6085 [CODE]
6086 let verify =<< trim [CODE]
6087 call assert_equal('abc', g:Xpath)
6088 [CODE]
6089 call RunInNewVim(test, verify)
6090endfunc
6091
Bram Moolenaar16c62322020-08-13 19:20:04 +02006092" interrupt the code right before the finally is invoked
6093func Test_finally_after_intr()
6094 XpathINIT
6095 let lines =<< trim [CODE]
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006096 try
6097 Xpath 'a'
6098 try
6099 Xpath 'b'
6100 throw "arrgh"
6101 call assert_report('should not get here')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006102 finally " interrupt here
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006103 Xpath 'c'
6104 endtry
6105 call assert_report('should not get here')
6106 catch /arrgh/
6107 call assert_report('should not get here')
6108 endtry
6109 call assert_report('should not get here')
6110 [CODE]
Bram Moolenaar5b148ef2022-10-15 21:35:56 +01006111 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar16c62322020-08-13 19:20:04 +02006112
6113 breakadd file 7 Xscript
6114 try
6115 let caught_intr = 0
6116 debuggreedy
6117 call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
6118 catch /^Vim:Interrupt$/
6119 call assert_match('Xscript, line 7', v:throwpoint)
6120 let caught_intr = 1
6121 endtry
6122 0debuggreedy
6123 call assert_equal(1, caught_intr)
6124 call assert_equal('abc', g:Xpath)
6125 breakdel *
Bram Moolenaarf7c4d832020-08-11 20:42:19 +02006126endfunc
6127
6128"-------------------------------------------------------------------------------
6129" Test 84: Exceptions in autocommand sequences. {{{1
6130"
6131" When an exception occurs in a sequence of autocommands for
6132" a specific event, the rest of the sequence is not executed. The
6133" command that triggered the autocommand execution aborts, and the
6134" exception is propagated to the caller.
6135"
6136" For the FuncUndefined event under a function call expression or
6137" :call command, the function is not executed, even when it has
6138" been defined by the autocommands before the exception occurred.
6139"-------------------------------------------------------------------------------
6140
6141func Test_autocmd_exception()
6142 let test =<< trim [CODE]
6143 func INT()
6144 call interrupt()
6145 endfunc
6146
6147 aug TMP
6148 autocmd!
6149
6150 autocmd User x1 Xpath 'a'
6151 autocmd User x1 throw "x1"
6152 autocmd User x1 call assert_report('should not get here')
6153
6154 autocmd User x2 Xpath 'b'
6155 autocmd User x2 asdf
6156 autocmd User x2 call assert_report('should not get here')
6157
6158 autocmd User x3 Xpath 'c'
6159 autocmd User x3 call INT()
6160 autocmd User x3 call assert_report('should not get here')
6161
6162 autocmd FuncUndefined U1 func U1()
6163 autocmd FuncUndefined U1 call assert_report('should not get here')
6164 autocmd FuncUndefined U1 endfunc
6165 autocmd FuncUndefined U1 Xpath 'd'
6166 autocmd FuncUndefined U1 throw "U1"
6167 autocmd FuncUndefined U1 call assert_report('should not get here')
6168
6169 autocmd FuncUndefined U2 func U2()
6170 autocmd FuncUndefined U2 call assert_report('should not get here')
6171 autocmd FuncUndefined U2 endfunc
6172 autocmd FuncUndefined U2 Xpath 'e'
6173 autocmd FuncUndefined U2 ASDF
6174 autocmd FuncUndefined U2 call assert_report('should not get here')
6175
6176 autocmd FuncUndefined U3 func U3()
6177 autocmd FuncUndefined U3 call assert_report('should not get here')
6178 autocmd FuncUndefined U3 endfunc
6179 autocmd FuncUndefined U3 Xpath 'f'
6180 autocmd FuncUndefined U3 call INT()
6181 autocmd FuncUndefined U3 call assert_report('should not get here')
6182 aug END
6183
6184 try
6185 try
6186 Xpath 'g'
6187 doautocmd User x1
6188 catch /x1/
6189 Xpath 'h'
6190 endtry
6191
6192 while 1
6193 try
6194 Xpath 'i'
6195 doautocmd User x2
6196 catch /asdf/
6197 Xpath 'j'
6198 finally
6199 Xpath 'k'
6200 break
6201 endtry
6202 endwhile
6203
6204 while 1
6205 try
6206 Xpath 'l'
6207 doautocmd User x3
6208 catch /Vim:Interrupt/
6209 Xpath 'm'
6210 finally
6211 Xpath 'n'
6212 " ... but break loop for caught interrupt exception,
6213 " or discard interrupt and break loop if $VIMNOINTTHROW
6214 break
6215 endtry
6216 endwhile
6217
6218 if exists("*U1") | delfunction U1 | endif
6219 if exists("*U2") | delfunction U2 | endif
6220 if exists("*U3") | delfunction U3 | endif
6221
6222 try
6223 Xpath 'o'
6224 call U1()
6225 catch /U1/
6226 Xpath 'p'
6227 endtry
6228
6229 while 1
6230 try
6231 Xpath 'q'
6232 call U2()
6233 catch /ASDF/
6234 Xpath 'r'
6235 finally
6236 Xpath 's'
6237 " ... but break loop for caught error exception,
6238 " or discard error and break loop if $VIMNOERRTHROW
6239 break
6240 endtry
6241 endwhile
6242
6243 while 1
6244 try
6245 Xpath 't'
6246 call U3()
6247 catch /Vim:Interrupt/
6248 Xpath 'u'
6249 finally
6250 Xpath 'v'
6251 " ... but break loop for caught interrupt exception,
6252 " or discard interrupt and break loop if $VIMNOINTTHROW
6253 break
6254 endtry
6255 endwhile
6256 catch /.*/
6257 call assert_report('should not get here')
6258 endtry
6259 Xpath 'w'
6260 [CODE]
6261 let verify =<< trim [CODE]
6262 call assert_equal('gahibjklcmnodpqerstfuvw', g:Xpath)
6263 [CODE]
6264 call RunInNewVim(test, verify)
6265endfunc
6266
6267"-------------------------------------------------------------------------------
6268" Test 85: Error exceptions in autocommands for I/O command events {{{1
6269"
6270" When an I/O command is inside :try/:endtry, autocommands to be
6271" executed after it should be skipped on an error (exception) in the
6272" command itself or in autocommands to be executed before the command.
6273" In the latter case, the I/O command should not be executed either.
6274" Example 1: BufWritePre, :write, BufWritePost
6275" Example 2: FileReadPre, :read, FileReadPost.
6276"-------------------------------------------------------------------------------
6277
6278func Test_autocmd_error_io_exception()
6279 let test =<< trim [CODE]
6280 " Remove the autocommands for the events specified as arguments in all used
6281 " autogroups.
6282 func Delete_autocommands(...)
6283 let augfile = tempname()
6284 while 1
6285 try
6286 exec "redir >" . augfile
6287 aug
6288 redir END
6289 exec "edit" augfile
6290 g/^$/d
6291 norm G$
6292 let wrap = "w"
6293 while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0
6294 let wrap = "W"
6295 exec "norm y/ \n"
6296 let argno = 1
6297 while argno <= a:0
6298 exec "au!" escape(@", " ") a:{argno}
6299 let argno = argno + 1
6300 endwhile
6301 endwhile
6302 catch /.*/
6303 finally
6304 bwipeout!
6305 call delete(augfile)
6306 break
6307 endtry
6308 endwhile
6309 endfunc
6310
6311 call Delete_autocommands("BufWritePre", "BufWritePost")
6312
6313 while 1
6314 try
6315 try
6316 let post = 0
6317 aug TMP
6318 au! BufWritePost * let post = 1
6319 aug END
6320 write /n/o/n/e/x/i/s/t/e/n/t
6321 catch /^Vim(write):/
6322 Xpath 'a'
6323 call assert_match("E212: Can't open file for writing", v:exception)
6324 finally
6325 Xpath 'b'
6326 call assert_equal(0, post)
6327 au! TMP
6328 aug! TMP
6329 endtry
6330 catch /.*/
6331 call assert_report('should not get here')
6332 finally
6333 Xpath 'c'
6334 break
6335 endtry
6336 endwhile
6337
6338 while 1
6339 try
6340 try
6341 let post = 0
6342 aug TMP
6343 au! BufWritePre * asdf
6344 au! BufWritePost * let post = 1
6345 aug END
6346 let tmpfile = tempname()
6347 exec "write" tmpfile
6348 catch /^Vim\((write)\)\=:/
6349 Xpath 'd'
6350 call assert_match('E492: Not an editor command', v:exception)
6351 finally
6352 Xpath 'e'
6353 if filereadable(tmpfile)
6354 call assert_report('should not get here')
6355 endif
6356 call assert_equal(0, post)
6357 au! TMP
6358 aug! TMP
6359 endtry
6360 catch /.*/
6361 call assert_report('should not get here')
6362 finally
6363 Xpath 'f'
6364 break
6365 endtry
6366 endwhile
6367
6368 call delete(tmpfile)
6369
6370 call Delete_autocommands("BufWritePre", "BufWritePost",
6371 \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
6372
6373 while 1
6374 try
6375 try
6376 let post = 0
6377 aug TMP
6378 au! FileReadPost * let post = 1
6379 aug END
6380 let caught = 0
6381 read /n/o/n/e/x/i/s/t/e/n/t
6382 catch /^Vim(read):/
6383 Xpath 'g'
6384 call assert_match("E484: Can't open file", v:exception)
6385 finally
6386 Xpath 'h'
6387 call assert_equal(0, post)
6388 au! TMP
6389 aug! TMP
6390 endtry
6391 catch /.*/
6392 call assert_report('should not get here')
6393 finally
6394 Xpath 'i'
6395 break
6396 endtry
6397 endwhile
6398
6399 while 1
6400 try
6401 let infile = tempname()
6402 let tmpfile = tempname()
6403 call writefile(["XYZ"], infile)
6404 exec "edit" tmpfile
6405 try
6406 Xpath 'j'
6407 try
6408 let post = 0
6409 aug TMP
6410 au! FileReadPre * asdf
6411 au! FileReadPost * let post = 1
6412 aug END
6413 exec "0read" infile
6414 catch /^Vim\((read)\)\=:/
6415 Xpath 'k'
6416 call assert_match('E492: Not an editor command', v:exception)
6417 finally
6418 Xpath 'l'
6419 if getline("1") == "XYZ"
6420 call assert_report('should not get here')
6421 endif
6422 call assert_equal(0, post)
6423 au! TMP
6424 aug! TMP
6425 endtry
6426 finally
6427 Xpath 'm'
6428 bwipeout!
6429 endtry
6430 catch /.*/
6431 call assert_report('should not get here')
6432 finally
6433 Xpath 'n'
6434 break
6435 endtry
6436 endwhile
6437
6438 call delete(infile)
6439 call delete(tmpfile)
6440 [CODE]
6441 let verify =<< trim [CODE]
6442 call assert_equal('abcdefghijklmn', g:Xpath)
6443 [CODE]
6444 call RunInNewVim(test, verify)
6445endfunc
6446
6447"-------------------------------------------------------------------------------
Bram Moolenaar1f068232019-11-03 16:17:26 +01006448" Test 87 using (expr) ? funcref : funcref {{{1
6449"
6450" Vim needs to correctly parse the funcref and even when it does
6451" not execute the funcref, it needs to consume the trailing ()
6452"-------------------------------------------------------------------------------
6453
6454func Add2(x1, x2)
6455 return a:x1 + a:x2
6456endfu
6457
6458func GetStr()
6459 return "abcdefghijklmnopqrstuvwxyp"
6460endfu
6461
6462func Test_funcref_with_condexpr()
6463 call assert_equal(5, function('Add2')(2,3))
6464
6465 call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
6466 call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
6467 " Make sure, GetStr() still works.
6468 call assert_equal('abcdefghijk', GetStr()[0:10])
6469endfunc
6470
Bram Moolenaar4119cf82016-01-17 14:59:01 +01006471" Test 90: Recognizing {} in variable name. {{{1
6472"-------------------------------------------------------------------------------
6473
6474func Test_curlies()
6475 let s:var = 66
6476 let ns = 's'
6477 call assert_equal(66, {ns}:var)
6478
6479 let g:a = {}
6480 let g:b = 't'
6481 let g:a[g:b] = 77
6482 call assert_equal(77, g:a['t'])
6483endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +01006484
6485"-------------------------------------------------------------------------------
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006486" Test 91: using type(). {{{1
6487"-------------------------------------------------------------------------------
6488
6489func Test_type()
6490 call assert_equal(0, type(0))
6491 call assert_equal(1, type(""))
6492 call assert_equal(2, type(function("tr")))
Bram Moolenaar953cc7f2016-03-19 18:52:29 +01006493 call assert_equal(2, type(function("tr", [8])))
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006494 call assert_equal(3, type([]))
6495 call assert_equal(4, type({}))
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006496 call assert_equal(5, type(0.0))
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006497 call assert_equal(6, type(v:false))
6498 call assert_equal(6, type(v:true))
6499 call assert_equal(7, type(v:none))
6500 call assert_equal(7, type(v:null))
Bram Moolenaarf562e722016-07-19 17:25:25 +02006501 call assert_equal(8, v:t_job)
6502 call assert_equal(9, v:t_channel)
6503 call assert_equal(v:t_number, type(0))
6504 call assert_equal(v:t_string, type(""))
6505 call assert_equal(v:t_func, type(function("tr")))
6506 call assert_equal(v:t_func, type(function("tr", [8])))
6507 call assert_equal(v:t_list, type([]))
6508 call assert_equal(v:t_dict, type({}))
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006509 call assert_equal(v:t_float, type(0.0))
Bram Moolenaarf562e722016-07-19 17:25:25 +02006510 call assert_equal(v:t_bool, type(v:false))
6511 call assert_equal(v:t_bool, type(v:true))
6512 call assert_equal(v:t_none, type(v:none))
6513 call assert_equal(v:t_none, type(v:null))
Bram Moolenaar92b83cc2020-04-25 15:24:44 +02006514 call assert_equal(v:t_string, type(test_null_string()))
6515 call assert_equal(v:t_func, type(test_null_function()))
6516 call assert_equal(v:t_func, type(test_null_partial()))
6517 call assert_equal(v:t_list, type(test_null_list()))
6518 call assert_equal(v:t_dict, type(test_null_dict()))
6519 if has('job')
6520 call assert_equal(v:t_job, type(test_null_job()))
6521 endif
6522 if has('channel')
6523 call assert_equal(v:t_channel, type(test_null_channel()))
6524 endif
6525 call assert_equal(v:t_blob, type(test_null_blob()))
Bram Moolenaarf562e722016-07-19 17:25:25 +02006526
Bram Moolenaar097c5372023-05-24 21:02:24 +01006527 call assert_fails("call type(test_void())", ['E340:', 'E685:'])
6528 call assert_fails("call type(test_unknown())", ['E340:', 'E685:'])
Bram Moolenaar17a13432016-01-24 14:22:10 +01006529
6530 call assert_equal(0, 0 + v:false)
6531 call assert_equal(1, 0 + v:true)
6532 call assert_equal(0, 0 + v:none)
6533 call assert_equal(0, 0 + v:null)
6534
Bram Moolenaarf48aa162016-01-24 17:54:24 +01006535 call assert_equal('v:false', '' . v:false)
6536 call assert_equal('v:true', '' . v:true)
6537 call assert_equal('v:none', '' . v:none)
6538 call assert_equal('v:null', '' . v:null)
Bram Moolenaar6039c7f2016-01-24 15:05:32 +01006539
6540 call assert_true(v:false == 0)
6541 call assert_false(v:false != 0)
6542 call assert_true(v:true == 1)
6543 call assert_false(v:true != 1)
6544 call assert_false(v:true == v:false)
6545 call assert_true(v:true != v:false)
6546
6547 call assert_true(v:null == 0)
Bram Moolenaarc6e9d702022-03-02 13:13:30 +00006548 call assert_false(v:null == 1)
Bram Moolenaar6039c7f2016-01-24 15:05:32 +01006549 call assert_false(v:null != 0)
6550 call assert_true(v:none == 0)
Bram Moolenaarc6e9d702022-03-02 13:13:30 +00006551 call assert_false(v:none == 1)
Bram Moolenaar6039c7f2016-01-24 15:05:32 +01006552 call assert_false(v:none != 0)
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006553 call assert_true(v:null == 0.0)
6554 call assert_false(v:null == 0.1)
6555 call assert_false(v:null != 0.0)
Bram Moolenaar04369222016-01-24 17:21:29 +01006556
6557 call assert_true(v:false is v:false)
6558 call assert_true(v:true is v:true)
6559 call assert_true(v:none is v:none)
6560 call assert_true(v:null is v:null)
6561
6562 call assert_false(v:false isnot v:false)
6563 call assert_false(v:true isnot v:true)
6564 call assert_false(v:none isnot v:none)
6565 call assert_false(v:null isnot v:null)
6566
6567 call assert_false(v:false is 0)
6568 call assert_false(v:true is 1)
6569 call assert_false(v:true is v:false)
6570 call assert_false(v:none is 0)
Bram Moolenaared0c62e2022-03-08 19:43:55 +00006571 call assert_false(v:none is [])
6572 call assert_false(v:none is {})
6573 call assert_false(v:none is 'text')
Bram Moolenaar04369222016-01-24 17:21:29 +01006574 call assert_false(v:null is 0)
6575 call assert_false(v:null is v:none)
6576
6577 call assert_true(v:false isnot 0)
6578 call assert_true(v:true isnot 1)
6579 call assert_true(v:true isnot v:false)
6580 call assert_true(v:none isnot 0)
6581 call assert_true(v:null isnot 0)
6582 call assert_true(v:null isnot v:none)
Bram Moolenaar65591002016-01-24 21:51:57 +01006583
6584 call assert_equal(v:false, eval(string(v:false)))
6585 call assert_equal(v:true, eval(string(v:true)))
6586 call assert_equal(v:none, eval(string(v:none)))
6587 call assert_equal(v:null, eval(string(v:null)))
Bram Moolenaar767d8c12016-01-25 20:22:54 +01006588
Bram Moolenaar15550002016-01-31 18:45:24 +01006589 call assert_equal(v:false, copy(v:false))
6590 call assert_equal(v:true, copy(v:true))
6591 call assert_equal(v:none, copy(v:none))
6592 call assert_equal(v:null, copy(v:null))
6593
6594 call assert_equal([v:false], deepcopy([v:false]))
6595 call assert_equal([v:true], deepcopy([v:true]))
6596 call assert_equal([v:none], deepcopy([v:none]))
6597 call assert_equal([v:null], deepcopy([v:null]))
6598
Bram Moolenaar767d8c12016-01-25 20:22:54 +01006599 call assert_true(empty(v:false))
6600 call assert_false(empty(v:true))
6601 call assert_true(empty(v:null))
6602 call assert_true(empty(v:none))
Bram Moolenaar6650a692016-01-26 19:59:10 +01006603
6604 func ChangeYourMind()
Bram Moolenaar1e115362019-01-09 23:01:02 +01006605 try
6606 return v:true
6607 finally
6608 return 'something else'
6609 endtry
Bram Moolenaar6650a692016-01-26 19:59:10 +01006610 endfunc
6611
6612 call ChangeYourMind()
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006613endfunc
6614
Bram Moolenaara47e05f2021-01-12 21:49:00 +01006615func Test_typename()
6616 call assert_equal('number', typename(123))
6617 call assert_equal('string', typename('x'))
6618 call assert_equal('list<number>', typename([123]))
6619 call assert_equal('dict<number>', typename(#{key: 123}))
6620 call assert_equal('list<dict<number>>', typename([#{key: 123}]))
Bram Moolenaar108cf012021-03-18 22:15:04 +01006621
6622 let l = []
6623 let d = #{a: 0}
6624 let l = [d]
6625 let l[0].e = #{b: l}
6626 call assert_equal('list<dict<any>>', typename(l))
6627 call assert_equal('dict<any>', typename(d))
Bram Moolenaara47e05f2021-01-12 21:49:00 +01006628endfunc
6629
Bram Moolenaarf95534c2016-01-23 21:59:52 +01006630"-------------------------------------------------------------------------------
Bram Moolenaarea8c2192016-02-07 19:27:53 +01006631" Test 92: skipping code {{{1
6632"-------------------------------------------------------------------------------
6633
6634func Test_skip()
6635 let Fn = function('Test_type')
6636 call assert_false(0 && Fn[1])
6637 call assert_false(0 && string(Fn))
6638 call assert_false(0 && len(Fn))
6639 let l = []
6640 call assert_false(0 && l[1])
6641 call assert_false(0 && string(l))
6642 call assert_false(0 && len(l))
6643 let f = 1.0
6644 call assert_false(0 && f[1])
6645 call assert_false(0 && string(f))
6646 call assert_false(0 && len(f))
6647 let sp = v:null
6648 call assert_false(0 && sp[1])
6649 call assert_false(0 && string(sp))
6650 call assert_false(0 && len(sp))
6651
6652endfunc
6653
6654"-------------------------------------------------------------------------------
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006655" Test 93: :echo and string() {{{1
6656"-------------------------------------------------------------------------------
6657
6658func Test_echo_and_string()
6659 " String
6660 let a = 'foo bar'
6661 redir => result
6662 echo a
6663 echo string(a)
6664 redir END
6665 let l = split(result, "\n")
6666 call assert_equal(["foo bar",
6667 \ "'foo bar'"], l)
6668
6669 " Float
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006670 let a = -1.2e0
6671 redir => result
6672 echo a
6673 echo string(a)
6674 redir END
6675 let l = split(result, "\n")
6676 call assert_equal(["-1.2",
6677 \ "-1.2"], l)
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006678
6679 " Funcref
6680 redir => result
6681 echo function('string')
6682 echo string(function('string'))
6683 redir END
6684 let l = split(result, "\n")
6685 call assert_equal(["string",
6686 \ "function('string')"], l)
6687
6688 " Recursive dictionary
6689 let a = {}
6690 let a["a"] = a
6691 redir => result
6692 echo a
6693 echo string(a)
6694 redir END
6695 let l = split(result, "\n")
6696 call assert_equal(["{'a': {...}}",
6697 \ "{'a': {...}}"], l)
6698
6699 " Recursive list
6700 let a = [0]
6701 let a[0] = a
6702 redir => result
6703 echo a
6704 echo string(a)
6705 redir END
6706 let l = split(result, "\n")
6707 call assert_equal(["[[...]]",
6708 \ "[[...]]"], l)
6709
6710 " Empty dictionaries in a list
6711 let a = {}
6712 redir => result
6713 echo [a, a, a]
6714 echo string([a, a, a])
6715 redir END
6716 let l = split(result, "\n")
6717 call assert_equal(["[{}, {}, {}]",
6718 \ "[{}, {}, {}]"], l)
6719
6720 " Empty dictionaries in a dictionary
6721 let a = {}
6722 let b = {"a": a, "b": a}
6723 redir => result
6724 echo b
6725 echo string(b)
6726 redir END
6727 let l = split(result, "\n")
6728 call assert_equal(["{'a': {}, 'b': {}}",
6729 \ "{'a': {}, 'b': {}}"], l)
6730
6731 " Empty lists in a list
6732 let a = []
6733 redir => result
6734 echo [a, a, a]
6735 echo string([a, a, a])
6736 redir END
6737 let l = split(result, "\n")
6738 call assert_equal(["[[], [], []]",
6739 \ "[[], [], []]"], l)
6740
6741 " Empty lists in a dictionary
6742 let a = []
6743 let b = {"a": a, "b": a}
6744 redir => result
6745 echo b
6746 echo string(b)
6747 redir END
6748 let l = split(result, "\n")
6749 call assert_equal(["{'a': [], 'b': []}",
6750 \ "{'a': [], 'b': []}"], l)
6751
6752 " Dictionaries in a list
6753 let a = {"one": "yes", "two": "yes", "three": "yes"}
6754 redir => result
6755 echo [a, a, a]
6756 echo string([a, a, a])
6757 redir END
6758 let l = split(result, "\n")
6759 call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
6760 \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
6761
6762 " Dictionaries in a dictionary
6763 let a = {"one": "yes", "two": "yes", "three": "yes"}
6764 let b = {"a": a, "b": a}
6765 redir => result
6766 echo b
6767 echo string(b)
6768 redir END
6769 let l = split(result, "\n")
6770 call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
6771 \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
6772
6773 " Lists in a list
6774 let a = [1, 2, 3]
6775 redir => result
6776 echo [a, a, a]
6777 echo string([a, a, a])
6778 redir END
6779 let l = split(result, "\n")
6780 call assert_equal(["[[1, 2, 3], [...], [...]]",
6781 \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
6782
6783 " Lists in a dictionary
6784 let a = [1, 2, 3]
6785 let b = {"a": a, "b": a}
6786 redir => result
6787 echo b
6788 echo string(b)
6789 redir END
6790 let l = split(result, "\n")
6791 call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
6792 \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
6793
Bram Moolenaar1363a302020-04-12 13:50:26 +02006794 call assert_fails('echo &:', 'E112:')
6795 call assert_fails('echo &g:', 'E112:')
6796 call assert_fails('echo &l:', 'E112:')
6797
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006798endfunc
6799
6800"-------------------------------------------------------------------------------
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006801" Test 94: 64-bit Numbers {{{1
6802"-------------------------------------------------------------------------------
6803
6804func Test_num64()
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006805 call assert_notequal( 4294967296, 0)
6806 call assert_notequal(-4294967296, 0)
6807 call assert_equal( 4294967296, 0xFFFFffff + 1)
6808 call assert_equal(-4294967296, -0xFFFFffff - 1)
6809
6810 call assert_equal( 9223372036854775807, 1 / 0)
6811 call assert_equal(-9223372036854775807, -1 / 0)
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01006812 call assert_equal(-9223372036854775807 - 1, 0 / 0)
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006813
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006814 call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
6815 call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006816
6817 let rng = range(0xFFFFffff, 0x100000001)
6818 call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
6819 call assert_equal(0x100000001, max(rng))
6820 call assert_equal(0xFFFFffff, min(rng))
6821 call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
6822endfunc
6823
6824"-------------------------------------------------------------------------------
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006825" Test 95: lines of :append, :change, :insert {{{1
6826"-------------------------------------------------------------------------------
6827
Bram Moolenaar97f0eb12022-10-06 19:49:13 +01006828func DefineFunction(name, body)
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006829 let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
6830 exec func
Bram Moolenaar97f0eb12022-10-06 19:49:13 +01006831endfunc
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006832
6833func Test_script_lines()
6834 " :append
6835 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006836 call DefineFunction('T_Append', [
6837 \ 'append',
6838 \ 'py <<EOS',
6839 \ '.',
6840 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006841 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006842 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006843 endtry
6844 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006845 call DefineFunction('T_Append', [
6846 \ 'append',
6847 \ 'abc',
6848 \ ])
6849 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006850 catch
Bram Moolenaar8143a532020-12-13 20:26:29 +01006851 call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006852 endtry
6853
6854 " :change
6855 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006856 call DefineFunction('T_Change', [
6857 \ 'change',
6858 \ 'py <<EOS',
6859 \ '.',
6860 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006861 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006862 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006863 endtry
6864 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006865 call DefineFunction('T_Change', [
6866 \ 'change',
6867 \ 'abc',
6868 \ ])
6869 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006870 catch
Bram Moolenaar8143a532020-12-13 20:26:29 +01006871 call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006872 endtry
6873
6874 " :insert
6875 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006876 call DefineFunction('T_Insert', [
6877 \ 'insert',
6878 \ 'py <<EOS',
6879 \ '.',
6880 \ ])
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006881 catch
Bram Moolenaar1e115362019-01-09 23:01:02 +01006882 call assert_report("Can't define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006883 endtry
6884 try
Bram Moolenaar1e115362019-01-09 23:01:02 +01006885 call DefineFunction('T_Insert', [
6886 \ 'insert',
6887 \ 'abc',
6888 \ ])
6889 call assert_report("Shouldn't be able to define function")
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006890 catch
Bram Moolenaar8143a532020-12-13 20:26:29 +01006891 call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
Bram Moolenaar70bcd732017-01-12 22:20:54 +01006892 endtry
6893endfunc
6894
6895"-------------------------------------------------------------------------------
Bram Moolenaar478af672017-04-10 22:22:42 +02006896" Test 96: line continuation {{{1
6897"
Bram Moolenaar1e115362019-01-09 23:01:02 +01006898" Undefined behavior was detected by ubsan with line continuation
6899" after an empty line.
Bram Moolenaar478af672017-04-10 22:22:42 +02006900"-------------------------------------------------------------------------------
dundargocc57b5bc2022-11-02 13:30:51 +00006901func Test_script_empty_line_continuation()
Bram Moolenaar478af672017-04-10 22:22:42 +02006902
6903 \
6904endfunc
6905
6906"-------------------------------------------------------------------------------
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006907" Test 97: bitwise functions {{{1
6908"-------------------------------------------------------------------------------
6909func Test_bitwise_functions()
6910 " and
6911 call assert_equal(127, and(127, 127))
6912 call assert_equal(16, and(127, 16))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006913 eval 127->and(16)->assert_equal(16)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006914 call assert_equal(0, and(127, 128))
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006915 call assert_fails("call and([], 1)", 'E745:')
6916 call assert_fails("call and({}, 1)", 'E728:')
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006917 call assert_fails("call and(1.0, 1)", 'E805:')
6918 call assert_fails("call and(1, 1.0)", 'E805:')
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006919 call assert_fails("call and(1, [])", 'E745:')
6920 call assert_fails("call and(1, {})", 'E728:')
6921 " or
6922 call assert_equal(23, or(16, 7))
6923 call assert_equal(15, or(8, 7))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006924 eval 8->or(7)->assert_equal(15)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006925 call assert_equal(123, or(0, 123))
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006926 call assert_fails("call or([], 1)", 'E745:')
6927 call assert_fails("call or({}, 1)", 'E728:')
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006928 call assert_fails("call or(1.0, 1)", 'E805:')
6929 call assert_fails("call or(1, 1.0)", 'E805:')
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006930 call assert_fails("call or(1, [])", 'E745:')
6931 call assert_fails("call or(1, {})", 'E728:')
6932 " xor
6933 call assert_equal(0, xor(127, 127))
6934 call assert_equal(111, xor(127, 16))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006935 eval 127->xor(16)->assert_equal(111)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006936 call assert_equal(255, xor(127, 128))
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006937 call assert_fails("call xor(1.0, 1)", 'E805:')
6938 call assert_fails("call xor(1, 1.0)", 'E805:')
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006939 call assert_fails("call xor([], 1)", 'E745:')
6940 call assert_fails("call xor({}, 1)", 'E728:')
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006941 call assert_fails("call xor(1, [])", 'E745:')
6942 call assert_fails("call xor(1, {})", 'E728:')
6943 " invert
6944 call assert_equal(65408, and(invert(127), 65535))
Bram Moolenaar073e4b92019-08-18 23:01:56 +02006945 eval 127->invert()->and(65535)->assert_equal(65408)
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006946 call assert_equal(65519, and(invert(16), 65535))
6947 call assert_equal(65407, and(invert(128), 65535))
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01006948 call assert_fails("call invert(1.0)", 'E805:')
Bram Moolenaar863e80b2017-06-04 20:30:00 +02006949 call assert_fails("call invert([])", 'E745:')
6950 call assert_fails("call invert({})", 'E728:')
6951endfunc
6952
Bram Moolenaar6f9a4762017-06-22 20:39:17 +02006953" Test using bang after user command {{{1
6954func Test_user_command_with_bang()
6955 command -bang Nieuw let nieuw = 1
6956 Ni!
6957 call assert_equal(1, nieuw)
6958 unlet nieuw
6959 delcommand Nieuw
6960endfunc
6961
Bram Moolenaarb9adef72020-01-02 14:31:22 +01006962func Test_script_expand_sfile()
6963 let lines =<< trim END
6964 func s:snr()
6965 return expand('<sfile>')
6966 endfunc
6967 let g:result = s:snr()
6968 END
Bram Moolenaar5b148ef2022-10-15 21:35:56 +01006969 call writefile(lines, 'Xexpand', 'D')
Bram Moolenaarb9adef72020-01-02 14:31:22 +01006970 source Xexpand
6971 call assert_match('<SNR>\d\+_snr', g:result)
6972 source Xexpand
6973 call assert_match('<SNR>\d\+_snr', g:result)
6974
Bram Moolenaarb9adef72020-01-02 14:31:22 +01006975 unlet g:result
6976endfunc
6977
Bram Moolenaarff697e62019-02-12 22:28:33 +01006978func Test_compound_assignment_operators()
6979 " Test for number
6980 let x = 1
6981 let x += 10
6982 call assert_equal(11, x)
6983 let x -= 5
6984 call assert_equal(6, x)
6985 let x *= 4
6986 call assert_equal(24, x)
6987 let x /= 3
6988 call assert_equal(8, x)
6989 let x %= 3
6990 call assert_equal(2, x)
6991 let x .= 'n'
6992 call assert_equal('2n', x)
6993
Bram Moolenaare21c1582019-03-02 11:57:09 +01006994 " Test special cases: division or modulus with 0.
6995 let x = 1
6996 let x /= 0
Bram Moolenaar82f654e2020-02-17 22:12:50 +01006997 call assert_equal(0x7FFFFFFFFFFFFFFF, x)
Bram Moolenaare21c1582019-03-02 11:57:09 +01006998
6999 let x = -1
7000 let x /= 0
Bram Moolenaar82f654e2020-02-17 22:12:50 +01007001 call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
Bram Moolenaare21c1582019-03-02 11:57:09 +01007002
7003 let x = 0
7004 let x /= 0
Bram Moolenaar82f654e2020-02-17 22:12:50 +01007005 call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
Bram Moolenaare21c1582019-03-02 11:57:09 +01007006
7007 let x = 1
7008 let x %= 0
7009 call assert_equal(0, x)
7010
7011 let x = -1
7012 let x %= 0
7013 call assert_equal(0, x)
7014
7015 let x = 0
7016 let x %= 0
7017 call assert_equal(0, x)
7018
Bram Moolenaarff697e62019-02-12 22:28:33 +01007019 " Test for string
7020 let x = 'str'
7021 let x .= 'ing'
7022 call assert_equal('string', x)
7023 let x += 1
7024 call assert_equal(1, x)
Bram Moolenaarff697e62019-02-12 22:28:33 +01007025
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01007026 " Test for float
7027 let x -= 1.5
7028 call assert_equal(-0.5, x)
7029 let x = 0.5
7030 let x += 4.5
7031 call assert_equal(5.0, x)
7032 let x -= 1.5
7033 call assert_equal(3.5, x)
7034 let x *= 3.0
7035 call assert_equal(10.5, x)
7036 let x /= 2.5
7037 call assert_equal(4.2, x)
7038 call assert_fails('let x %= 0.5', 'E734:')
7039 call assert_fails('let x .= "f"', 'E734:')
7040 let x = !3.14
7041 call assert_equal(0.0, x)
Bram Moolenaarea04a6e2020-04-23 13:38:02 +02007042
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01007043 " integer and float operations
7044 let x = 1
7045 let x *= 2.1
7046 call assert_equal(2.1, x)
7047 let x = 1
7048 let x /= 0.25
7049 call assert_equal(4.0, x)
7050 let x = 1
7051 call assert_fails('let x %= 0.25', 'E734:')
7052 let x = 1
7053 call assert_fails('let x .= 0.25', 'E734:')
7054 let x = 1.0
7055 call assert_fails('let x += [1.1]', 'E734:')
Bram Moolenaarff697e62019-02-12 22:28:33 +01007056
7057 " Test for environment variable
7058 let $FOO = 1
Bram Moolenaare2e40752020-09-04 21:18:46 +02007059 call assert_fails('let $FOO += 1', 'E734:')
7060 call assert_fails('let $FOO -= 1', 'E734:')
7061 call assert_fails('let $FOO *= 1', 'E734:')
7062 call assert_fails('let $FOO /= 1', 'E734:')
7063 call assert_fails('let $FOO %= 1', 'E734:')
Bram Moolenaarff697e62019-02-12 22:28:33 +01007064 let $FOO .= 's'
7065 call assert_equal('1s', $FOO)
7066 unlet $FOO
7067
7068 " Test for option variable (type: number)
7069 let &scrolljump = 1
7070 let &scrolljump += 5
7071 call assert_equal(6, &scrolljump)
7072 let &scrolljump -= 2
7073 call assert_equal(4, &scrolljump)
7074 let &scrolljump *= 3
7075 call assert_equal(12, &scrolljump)
7076 let &scrolljump /= 2
7077 call assert_equal(6, &scrolljump)
7078 let &scrolljump %= 5
7079 call assert_equal(1, &scrolljump)
zeertzjq4c7cb372023-06-14 16:39:54 +01007080 call assert_fails('let &scrolljump .= "j"', ['E734:', 'E734:'])
Bram Moolenaarff697e62019-02-12 22:28:33 +01007081 set scrolljump&vim
7082
Bram Moolenaara42e6e02021-06-10 18:43:25 +02007083 let &foldlevelstart = 2
7084 let &foldlevelstart -= 1
7085 call assert_equal(1, &foldlevelstart)
7086 let &foldlevelstart -= 1
7087 call assert_equal(0, &foldlevelstart)
7088 let &foldlevelstart = 2
7089 let &foldlevelstart -= 2
7090 call assert_equal(0, &foldlevelstart)
7091
Bram Moolenaarff697e62019-02-12 22:28:33 +01007092 " Test for register
7093 let @/ = 1
Bram Moolenaare2e40752020-09-04 21:18:46 +02007094 call assert_fails('let @/ += 1', 'E734:')
7095 call assert_fails('let @/ -= 1', 'E734:')
7096 call assert_fails('let @/ *= 1', 'E734:')
7097 call assert_fails('let @/ /= 1', 'E734:')
7098 call assert_fails('let @/ %= 1', 'E734:')
Bram Moolenaarff697e62019-02-12 22:28:33 +01007099 let @/ .= 's'
7100 call assert_equal('1s', @/)
7101 let @/ = ''
7102endfunc
7103
Bram Moolenaar7e0868e2020-04-19 17:24:53 +02007104func Test_unlet_env()
7105 let $TESTVAR = 'yes'
7106 call assert_equal('yes', $TESTVAR)
Bram Moolenaare2e40752020-09-04 21:18:46 +02007107 call assert_fails('lockvar $TESTVAR', 'E940:')
7108 call assert_fails('unlockvar $TESTVAR', 'E940:')
Bram Moolenaar7e0868e2020-04-19 17:24:53 +02007109 call assert_equal('yes', $TESTVAR)
7110 if 0
7111 unlet $TESTVAR
7112 endif
7113 call assert_equal('yes', $TESTVAR)
7114 unlet $TESTVAR
7115 call assert_equal('', $TESTVAR)
7116endfunc
7117
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01007118func Test_refcount()
7119 " Immediate values
7120 call assert_equal(-1, test_refcount(1))
7121 call assert_equal(-1, test_refcount('s'))
7122 call assert_equal(-1, test_refcount(v:true))
7123 call assert_equal(0, test_refcount([]))
7124 call assert_equal(0, test_refcount({}))
7125 call assert_equal(0, test_refcount(0zff))
7126 call assert_equal(0, test_refcount({-> line('.')}))
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01007127 call assert_equal(-1, test_refcount(0.1))
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01007128 if has('job')
7129 call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
7130 endif
7131
7132 " No refcount types
7133 let x = 1
7134 call assert_equal(-1, test_refcount(x))
7135 let x = 's'
7136 call assert_equal(-1, test_refcount(x))
7137 let x = v:true
7138 call assert_equal(-1, test_refcount(x))
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01007139 let x = 0.1
7140 call assert_equal(-1, test_refcount(x))
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01007141
7142 " Check refcount
7143 let x = []
7144 call assert_equal(1, test_refcount(x))
7145
7146 let x = {}
Bram Moolenaarce90e362019-09-08 18:58:44 +02007147 call assert_equal(1, x->test_refcount())
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01007148
7149 let x = 0zff
7150 call assert_equal(1, test_refcount(x))
7151
7152 let X = {-> line('.')}
7153 call assert_equal(1, test_refcount(X))
7154 let Y = X
7155 call assert_equal(2, test_refcount(X))
7156
7157 if has('job')
7158 let job = job_start([&shell, &shellcmdflag, 'echo .'])
7159 call assert_equal(1, test_refcount(job))
7160 call assert_equal(1, test_refcount(job_getchannel(job)))
7161 call assert_equal(1, test_refcount(job))
7162 endif
7163
7164 " Function arguments, copying and unassigning
7165 func ExprCheck(x, i)
7166 let i = a:i + 1
7167 call assert_equal(i, test_refcount(a:x))
7168 let Y = a:x
7169 call assert_equal(i + 1, test_refcount(a:x))
7170 call assert_equal(test_refcount(a:x), test_refcount(Y))
7171 let Y = 0
7172 call assert_equal(i, test_refcount(a:x))
7173 endfunc
7174 call ExprCheck([], 0)
7175 call ExprCheck({}, 0)
7176 call ExprCheck(0zff, 0)
7177 call ExprCheck({-> line('.')}, 0)
7178 if has('job')
7179 call ExprCheck(job, 1)
7180 call ExprCheck(job_getchannel(job), 1)
7181 call job_stop(job)
7182 endif
7183 delfunc ExprCheck
7184
7185 " Regarding function
7186 func Func(x) abort
7187 call assert_equal(2, test_refcount(function('Func')))
7188 call assert_equal(0, test_refcount(funcref('Func')))
7189 endfunc
7190 call assert_equal(1, test_refcount(function('Func')))
7191 call assert_equal(0, test_refcount(function('Func', [1])))
7192 call assert_equal(0, test_refcount(funcref('Func')))
7193 call assert_equal(0, test_refcount(funcref('Func', [1])))
7194 let X = function('Func')
7195 let Y = X
7196 call assert_equal(1, test_refcount(X))
7197 let X = function('Func', [1])
7198 let Y = X
7199 call assert_equal(2, test_refcount(X))
7200 let X = funcref('Func')
7201 let Y = X
7202 call assert_equal(2, test_refcount(X))
7203 let X = funcref('Func', [1])
7204 let Y = X
7205 call assert_equal(2, test_refcount(X))
7206 unlet X
7207 unlet Y
7208 call Func(1)
7209 delfunc Func
7210
7211 " Function with dict
7212 func DictFunc() dict
7213 call assert_equal(3, test_refcount(self))
7214 endfunc
7215 let d = {'Func': function('DictFunc')}
7216 call assert_equal(1, test_refcount(d))
7217 call assert_equal(0, test_refcount(d.Func))
7218 call d.Func()
7219 unlet d
7220 delfunc DictFunc
Yegappan Lakshmanane24b5e02022-09-22 13:44:00 +01007221
Bram Moolenaara9b0f8f2022-09-23 21:01:54 +01007222 if has('channel')
7223 call assert_equal(-1, test_refcount(test_null_job()))
7224 call assert_equal(-1, test_refcount(test_null_channel()))
7225 endif
Yegappan Lakshmanane24b5e02022-09-22 13:44:00 +01007226 call assert_equal(-1, test_refcount(test_null_function()))
7227 call assert_equal(-1, test_refcount(test_null_partial()))
7228 call assert_equal(-1, test_refcount(test_null_blob()))
7229 call assert_equal(-1, test_refcount(test_null_list()))
7230 call assert_equal(-1, test_refcount(test_null_dict()))
Bram Moolenaarc3e92c12019-03-23 14:23:07 +01007231endfunc
7232
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007233" Test for missing :endif, :endfor, :endwhile and :endtry {{{1
7234func Test_missing_end()
Bram Moolenaar5b148ef2022-10-15 21:35:56 +01007235 call writefile(['if 2 > 1', 'echo ">"'], 'Xscript', 'D')
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007236 call assert_fails('source Xscript', 'E171:')
7237 call writefile(['for i in range(5)', 'echo i'], 'Xscript')
7238 call assert_fails('source Xscript', 'E170:')
7239 call writefile(['while v:true', 'echo "."'], 'Xscript')
7240 call assert_fails('source Xscript', 'E170:')
7241 call writefile(['try', 'echo "."'], 'Xscript')
7242 call assert_fails('source Xscript', 'E600:')
Bram Moolenaar818fc9a2020-02-21 17:54:45 +01007243
7244 " Using endfor with :while
7245 let caught_e732 = 0
7246 try
7247 while v:true
7248 endfor
7249 catch /E732:/
7250 let caught_e732 = 1
7251 endtry
7252 call assert_equal(1, caught_e732)
7253
7254 " Using endwhile with :for
7255 let caught_e733 = 0
7256 try
7257 for i in range(1)
7258 endwhile
7259 catch /E733:/
7260 let caught_e733 = 1
7261 endtry
7262 call assert_equal(1, caught_e733)
7263
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007264 " Using endfunc with :if
7265 call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
7266
Bram Moolenaar818fc9a2020-02-21 17:54:45 +01007267 " Missing 'in' in a :for statement
7268 call assert_fails('for i range(1) | endfor', 'E690:')
Bram Moolenaarea04a6e2020-04-23 13:38:02 +02007269
7270 " Incorrect number of variables in for
7271 call assert_fails('for [i,] in range(3) | endfor', 'E475:')
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007272endfunc
7273
7274" Test for deep nesting of if/for/while/try statements {{{1
7275func Test_deep_nest()
Bram Moolenaar494e9062020-05-31 21:28:02 +02007276 CheckRunVimInTerminal
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007277
7278 let lines =<< trim [SCRIPT]
7279 " Deep nesting of if ... endif
7280 func Test1()
7281 let @a = join(repeat(['if v:true'], 51), "\n")
7282 let @a ..= "\n"
7283 let @a ..= join(repeat(['endif'], 51), "\n")
7284 @a
7285 let @a = ''
7286 endfunc
7287
7288 " Deep nesting of for ... endfor
7289 func Test2()
7290 let @a = join(repeat(['for i in [1]'], 51), "\n")
7291 let @a ..= "\n"
7292 let @a ..= join(repeat(['endfor'], 51), "\n")
7293 @a
7294 let @a = ''
7295 endfunc
7296
7297 " Deep nesting of while ... endwhile
7298 func Test3()
7299 let @a = join(repeat(['while v:true'], 51), "\n")
7300 let @a ..= "\n"
7301 let @a ..= join(repeat(['endwhile'], 51), "\n")
7302 @a
7303 let @a = ''
7304 endfunc
7305
7306 " Deep nesting of try ... endtry
7307 func Test4()
7308 let @a = join(repeat(['try'], 51), "\n")
7309 let @a ..= "\necho v:true\n"
7310 let @a ..= join(repeat(['endtry'], 51), "\n")
7311 @a
7312 let @a = ''
7313 endfunc
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007314
7315 " Deep nesting of function ... endfunction
7316 func Test5()
7317 let @a = join(repeat(['function X()'], 51), "\n")
7318 let @a ..= "\necho v:true\n"
7319 let @a ..= join(repeat(['endfunction'], 51), "\n")
7320 @a
7321 let @a = ''
7322 endfunc
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007323 [SCRIPT]
Bram Moolenaar5b148ef2022-10-15 21:35:56 +01007324 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007325
7326 let buf = RunVimInTerminal('-S Xscript', {'rows': 6})
7327
7328 " Deep nesting of if ... endif
7329 call term_sendkeys(buf, ":call Test1()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007330 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007331 call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
7332
7333 " Deep nesting of for ... endfor
7334 call term_sendkeys(buf, ":call Test2()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007335 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007336 call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
7337
7338 " Deep nesting of while ... endwhile
7339 call term_sendkeys(buf, ":call Test3()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007340 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007341 call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
7342
7343 " Deep nesting of try ... endtry
7344 call term_sendkeys(buf, ":call Test4()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007345 call TermWait(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007346 call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
7347
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007348 " Deep nesting of function ... endfunction
7349 call term_sendkeys(buf, ":call Test5()\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007350 call TermWait(buf)
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007351 call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
7352 call term_sendkeys(buf, "\<C-C>\n")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +02007353 call TermWait(buf)
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02007354
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007355 "let l = ''
7356 "for i in range(1, 6)
7357 " let l ..= term_getline(buf, i) . "\n"
7358 "endfor
7359 "call assert_report(l)
7360
7361 call StopVimInTerminal(buf)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +01007362endfunc
7363
Bram Moolenaar8b633132020-03-20 18:20:51 +01007364" Test for errors in converting to float from various types {{{1
7365func Test_float_conversion_errors()
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01007366 call assert_fails('let x = 4.0 % 2.0', 'E804:')
7367 call assert_fails('echo 1.1[0]', 'E806:')
7368 call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
7369 call assert_fails('echo 3.2 == "vim"', 'E892:')
7370 call assert_fails('echo sort([[], 1], "f")', 'E893:')
7371 call assert_fails('echo sort([{}, 1], "f")', 'E894:')
7372 call assert_fails('echo 3.2 == v:true', 'E362:')
7373 call assert_fails('echo 3.2 == v:none', 'E907:')
Bram Moolenaar8b633132020-03-20 18:20:51 +01007374endfunc
7375
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02007376" invalid function names {{{1
Bram Moolenaar08f41572020-04-20 16:50:00 +02007377func Test_invalid_function_names()
7378 " function name not starting with capital
7379 let caught_e128 = 0
7380 try
7381 func! g:test()
7382 echo "test"
7383 endfunc
7384 catch /E128:/
7385 let caught_e128 = 1
7386 endtry
7387 call assert_equal(1, caught_e128)
7388
7389 " function name includes a colon
7390 let caught_e884 = 0
7391 try
7392 func! b:test()
7393 echo "test"
7394 endfunc
7395 catch /E884:/
7396 let caught_e884 = 1
7397 endtry
7398 call assert_equal(1, caught_e884)
7399
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01007400 " function name followed by #
Bram Moolenaar08f41572020-04-20 16:50:00 +02007401 let caught_e128 = 0
7402 try
7403 func! test2() "#
7404 echo "test2"
7405 endfunc
7406 catch /E128:/
7407 let caught_e128 = 1
7408 endtry
7409 call assert_equal(1, caught_e128)
7410
7411 " function name starting with/without "g:", buffer-local funcref.
7412 function! g:Foo(n)
7413 return 'called Foo(' . a:n . ')'
7414 endfunction
7415 let b:my_func = function('Foo')
7416 call assert_equal('called Foo(1)', b:my_func(1))
7417 call assert_equal('called Foo(2)', g:Foo(2))
7418 call assert_equal('called Foo(3)', Foo(3))
7419 delfunc g:Foo
7420
7421 " script-local function used in Funcref must exist.
7422 let lines =<< trim END
7423 func s:Testje()
7424 return "foo"
7425 endfunc
7426 let Bar = function('s:Testje')
7427 call assert_equal(0, exists('s:Testje'))
7428 call assert_equal(1, exists('*s:Testje'))
7429 call assert_equal(1, exists('Bar'))
7430 call assert_equal(1, exists('*Bar'))
7431 END
Bram Moolenaar5b148ef2022-10-15 21:35:56 +01007432 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar08f41572020-04-20 16:50:00 +02007433 source Xscript
Bram Moolenaar08f41572020-04-20 16:50:00 +02007434endfunc
7435
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02007436" substring and variable name {{{1
Bram Moolenaar08f41572020-04-20 16:50:00 +02007437func Test_substring_var()
7438 let str = 'abcdef'
7439 let n = 3
7440 call assert_equal('def', str[n:])
7441 call assert_equal('abcd', str[:n])
7442 call assert_equal('d', str[n:n])
7443 unlet n
7444 let nn = 3
7445 call assert_equal('def', str[nn:])
7446 call assert_equal('abcd', str[:nn])
7447 call assert_equal('d', str[nn:nn])
7448 unlet nn
7449 let b:nn = 4
7450 call assert_equal('ef', str[b:nn:])
7451 call assert_equal('abcde', str[:b:nn])
7452 call assert_equal('e', str[b:nn:b:nn])
7453 unlet b:nn
7454endfunc
7455
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02007456" Test using s: with a typed command {{{1
7457func Test_typed_script_var()
7458 CheckRunVimInTerminal
7459
7460 let buf = RunVimInTerminal('', {'rows': 6})
7461
7462 " Deep nesting of if ... endif
7463 call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n")
7464 call TermWait(buf)
7465 call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))})
7466
7467 call StopVimInTerminal(buf)
7468endfunc
7469
Bram Moolenaar69e445522020-08-22 22:37:20 +02007470" Test for issue6776 {{{1
=?UTF-8?q?Dundar=20G=C3=B6c?=e41c1dd2022-02-26 11:46:13 +00007471func Test_ternary_expression()
Bram Moolenaar69e445522020-08-22 22:37:20 +02007472 try
7473 call eval('0 ? 0')
7474 catch
7475 endtry
7476 " previous failure should not cause next expression to fail
7477 call assert_equal(v:false, eval(string(v:false)))
7478
7479 try
7480 call eval('0 ? "burp')
7481 catch
7482 endtry
7483 " previous failure should not cause next expression to fail
7484 call assert_equal(v:false, eval(string(v:false)))
7485
7486 try
7487 call eval('1 ? 0 : "burp')
7488 catch
7489 endtry
7490 " previous failure should not cause next expression to fail
7491 call assert_equal(v:false, eval(string(v:false)))
7492endfunction
7493
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01007494func Test_for_over_string()
7495 let res = ''
7496 for c in 'aéc̀d'
7497 let res ..= c .. '-'
7498 endfor
7499 call assert_equal('a-é-c̀-d-', res)
7500
7501 let res = ''
7502 for c in ''
7503 let res ..= c .. '-'
7504 endfor
7505 call assert_equal('', res)
7506
7507 let res = ''
7508 for c in test_null_string()
7509 let res ..= c .. '-'
7510 endfor
7511 call assert_equal('', res)
7512endfunc
7513
Bram Moolenaar79481362022-06-27 20:15:10 +01007514" Test for deeply nested :source command {{{1
7515func Test_deeply_nested_source()
7516 let lines =<< trim END
7517
7518 so
7519 sil 0scr
7520 delete
7521 so
7522 0
7523 END
Bram Moolenaar5b148ef2022-10-15 21:35:56 +01007524 call writefile(["vim9 silent! @0 \n/"] + lines, 'Xnested.vim', 'D')
Bram Moolenaar79481362022-06-27 20:15:10 +01007525
7526 " this must not crash
7527 let cmd = GetVimCommand() .. " -e -s -S Xnested.vim -c qa!"
7528 call system(cmd)
Bram Moolenaar79481362022-06-27 20:15:10 +01007529endfunc
7530
Bram Moolenaar863e80b2017-06-04 20:30:00 +02007531"-------------------------------------------------------------------------------
Bram Moolenaarf49e2402015-12-30 15:59:25 +01007532" Modelines {{{1
Bram Moolenaar1f068232019-11-03 16:17:26 +01007533" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
Bram Moolenaarf49e2402015-12-30 15:59:25 +01007534"-------------------------------------------------------------------------------