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