1" Test various aspects of the Vim9 script language. 2 3source check.vim 4source term_util.vim 5source view_util.vim 6source vim9.vim 7source shared.vim 8source screendump.vim 9 10def Test_range_only() 11 new 12 setline(1, ['blah', 'Blah']) 13 :/Blah/ 14 assert_equal(2, getcurpos()[1]) 15 bwipe! 16 17 # without range commands use current line 18 new 19 setline(1, ['one', 'two', 'three']) 20 :2 21 print 22 assert_equal('two', Screenline(&lines)) 23 :3 24 list 25 assert_equal('three$', Screenline(&lines)) 26 27 # missing command does not print the line 28 var lines =<< trim END 29 vim9script 30 :1| 31 assert_equal('three$', Screenline(&lines)) 32 :| 33 assert_equal('three$', Screenline(&lines)) 34 END 35 CheckScriptSuccess(lines) 36 37 bwipe! 38 39 # won't generate anything 40 if false 41 :123 42 endif 43enddef 44 45let g:alist = [7] 46let g:astring = 'text' 47let g:anumber = 123 48 49def Test_delfunction() 50 # Check function is defined in script namespace 51 CheckScriptSuccess([ 52 'vim9script', 53 'func CheckMe()', 54 ' return 123', 55 'endfunc', 56 'assert_equal(123, s:CheckMe())', 57 ]) 58 59 # Check function in script namespace cannot be deleted 60 CheckScriptFailure([ 61 'vim9script', 62 'func DeleteMe1()', 63 'endfunc', 64 'delfunction DeleteMe1', 65 ], 'E1084:') 66 CheckScriptFailure([ 67 'vim9script', 68 'func DeleteMe2()', 69 'endfunc', 70 'def DoThat()', 71 ' delfunction DeleteMe2', 72 'enddef', 73 'DoThat()', 74 ], 'E1084:') 75 CheckScriptFailure([ 76 'vim9script', 77 'def DeleteMe3()', 78 'enddef', 79 'delfunction DeleteMe3', 80 ], 'E1084:') 81 CheckScriptFailure([ 82 'vim9script', 83 'def DeleteMe4()', 84 'enddef', 85 'def DoThat()', 86 ' delfunction DeleteMe4', 87 'enddef', 88 'DoThat()', 89 ], 'E1084:') 90 91 # Check that global :def function can be replaced and deleted 92 var lines =<< trim END 93 vim9script 94 def g:Global(): string 95 return "yes" 96 enddef 97 assert_equal("yes", g:Global()) 98 def! g:Global(): string 99 return "no" 100 enddef 101 assert_equal("no", g:Global()) 102 delfunc g:Global 103 assert_false(exists('*g:Global')) 104 END 105 CheckScriptSuccess(lines) 106 107 # Check that global function can be replaced by a :def function and deleted 108 lines =<< trim END 109 vim9script 110 func g:Global() 111 return "yes" 112 endfunc 113 assert_equal("yes", g:Global()) 114 def! g:Global(): string 115 return "no" 116 enddef 117 assert_equal("no", g:Global()) 118 delfunc g:Global 119 assert_false(exists('*g:Global')) 120 END 121 CheckScriptSuccess(lines) 122 123 # Check that global :def function can be replaced by a function and deleted 124 lines =<< trim END 125 vim9script 126 def g:Global(): string 127 return "yes" 128 enddef 129 assert_equal("yes", g:Global()) 130 func! g:Global() 131 return "no" 132 endfunc 133 assert_equal("no", g:Global()) 134 delfunc g:Global 135 assert_false(exists('*g:Global')) 136 END 137 CheckScriptSuccess(lines) 138enddef 139 140def Test_wrong_type() 141 CheckDefFailure(['var name: list<nothing>'], 'E1010:') 142 CheckDefFailure(['var name: list<list<nothing>>'], 'E1010:') 143 CheckDefFailure(['var name: dict<nothing>'], 'E1010:') 144 CheckDefFailure(['var name: dict<dict<nothing>>'], 'E1010:') 145 146 CheckDefFailure(['var name: dict<number'], 'E1009:') 147 CheckDefFailure(['var name: dict<list<number>'], 'E1009:') 148 149 CheckDefFailure(['var name: ally'], 'E1010:') 150 CheckDefFailure(['var name: bram'], 'E1010:') 151 CheckDefFailure(['var name: cathy'], 'E1010:') 152 CheckDefFailure(['var name: dom'], 'E1010:') 153 CheckDefFailure(['var name: freddy'], 'E1010:') 154 CheckDefFailure(['var name: john'], 'E1010:') 155 CheckDefFailure(['var name: larry'], 'E1010:') 156 CheckDefFailure(['var name: ned'], 'E1010:') 157 CheckDefFailure(['var name: pam'], 'E1010:') 158 CheckDefFailure(['var name: sam'], 'E1010:') 159 CheckDefFailure(['var name: vim'], 'E1010:') 160 161 CheckDefFailure(['var Ref: number', 'Ref()'], 'E1085:') 162 CheckDefFailure(['var Ref: string', 'var res = Ref()'], 'E1085:') 163enddef 164 165def Test_script_wrong_type() 166 var lines =<< trim END 167 vim9script 168 var s:dict: dict<string> 169 s:dict['a'] = ['x'] 170 END 171 CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got list<string>', 3) 172enddef 173 174def Test_const() 175 CheckDefFailure(['final name = 234', 'name = 99'], 'E1018:') 176 CheckDefFailure(['final one = 234', 'var one = 99'], 'E1017:') 177 CheckDefFailure(['final list = [1, 2]', 'var list = [3, 4]'], 'E1017:') 178 CheckDefFailure(['final two'], 'E1125:') 179 CheckDefFailure(['final &option'], 'E996:') 180 181 var lines =<< trim END 182 final list = [1, 2, 3] 183 list[0] = 4 184 list->assert_equal([4, 2, 3]) 185 const other = [5, 6, 7] 186 other->assert_equal([5, 6, 7]) 187 188 var varlist = [7, 8] 189 const constlist = [1, varlist, 3] 190 varlist[0] = 77 191 # TODO: does not work yet 192 # constlist[1][1] = 88 193 var cl = constlist[1] 194 cl[1] = 88 195 constlist->assert_equal([1, [77, 88], 3]) 196 197 var vardict = {five: 5, six: 6} 198 const constdict = {one: 1, two: vardict, three: 3} 199 vardict['five'] = 55 200 # TODO: does not work yet 201 # constdict['two']['six'] = 66 202 var cd = constdict['two'] 203 cd['six'] = 66 204 constdict->assert_equal({one: 1, two: {five: 55, six: 66}, three: 3}) 205 END 206 CheckDefAndScriptSuccess(lines) 207enddef 208 209def Test_const_bang() 210 var lines =<< trim END 211 const var = 234 212 var = 99 213 END 214 CheckDefExecFailure(lines, 'E1018:', 2) 215 CheckScriptFailure(['vim9script'] + lines, 'E46:', 3) 216 217 lines =<< trim END 218 const ll = [2, 3, 4] 219 ll[0] = 99 220 END 221 CheckDefExecFailure(lines, 'E1119:', 2) 222 CheckScriptFailure(['vim9script'] + lines, 'E741:', 3) 223 224 lines =<< trim END 225 const ll = [2, 3, 4] 226 ll[3] = 99 227 END 228 CheckDefExecFailure(lines, 'E1118:', 2) 229 CheckScriptFailure(['vim9script'] + lines, 'E684:', 3) 230 231 lines =<< trim END 232 const dd = {one: 1, two: 2} 233 dd["one"] = 99 234 END 235 CheckDefExecFailure(lines, 'E1121:', 2) 236 CheckScriptFailure(['vim9script'] + lines, 'E741:', 3) 237 238 lines =<< trim END 239 const dd = {one: 1, two: 2} 240 dd["three"] = 99 241 END 242 CheckDefExecFailure(lines, 'E1120:') 243 CheckScriptFailure(['vim9script'] + lines, 'E741:', 3) 244enddef 245 246def Test_range_no_colon() 247 CheckDefFailure(['%s/a/b/'], 'E1050:') 248 CheckDefFailure(['+ s/a/b/'], 'E1050:') 249 CheckDefFailure(['- s/a/b/'], 'E1050:') 250 CheckDefFailure(['. s/a/b/'], 'E1050:') 251enddef 252 253 254def Test_block() 255 var outer = 1 256 { 257 var inner = 2 258 assert_equal(1, outer) 259 assert_equal(2, inner) 260 } 261 assert_equal(1, outer) 262 263 {|echo 'yes'|} 264enddef 265 266def Test_block_failure() 267 CheckDefFailure(['{', 'var inner = 1', '}', 'echo inner'], 'E1001:') 268 CheckDefFailure(['}'], 'E1025:') 269 CheckDefFailure(['{', 'echo 1'], 'E1026:') 270enddef 271 272def Test_block_local_vars() 273 var lines =<< trim END 274 vim9script 275 v:testing = 1 276 if true 277 var text = ['hello'] 278 def SayHello(): list<string> 279 return text 280 enddef 281 def SetText(v: string) 282 text = [v] 283 enddef 284 endif 285 286 if true 287 var text = ['again'] 288 def SayAgain(): list<string> 289 return text 290 enddef 291 endif 292 293 # test that the "text" variables are not cleaned up 294 test_garbagecollect_now() 295 296 defcompile 297 298 assert_equal(['hello'], SayHello()) 299 assert_equal(['again'], SayAgain()) 300 301 SetText('foobar') 302 assert_equal(['foobar'], SayHello()) 303 304 call writefile(['ok'], 'Xdidit') 305 qall! 306 END 307 308 # need to execute this with a separate Vim instance to avoid the current 309 # context gets garbage collected. 310 writefile(lines, 'Xscript') 311 RunVim([], [], '-S Xscript') 312 assert_equal(['ok'], readfile('Xdidit')) 313 314 delete('Xscript') 315 delete('Xdidit') 316enddef 317 318def Test_block_local_vars_with_func() 319 var lines =<< trim END 320 vim9script 321 if true 322 var foo = 'foo' 323 if true 324 var bar = 'bar' 325 def Func(): list<string> 326 return [foo, bar] 327 enddef 328 endif 329 endif 330 # function is compiled here, after blocks have finished, can still access 331 # "foo" and "bar" 332 assert_equal(['foo', 'bar'], Func()) 333 END 334 CheckScriptSuccess(lines) 335enddef 336 337func g:NoSuchFunc() 338 echo 'none' 339endfunc 340 341def Test_try_catch_throw() 342 var l = [] 343 try # comment 344 add(l, '1') 345 throw 'wrong' 346 add(l, '2') 347 catch # comment 348 add(l, v:exception) 349 finally # comment 350 add(l, '3') 351 endtry # comment 352 assert_equal(['1', 'wrong', '3'], l) 353 354 l = [] 355 try 356 try 357 add(l, '1') 358 throw 'wrong' 359 add(l, '2') 360 catch /right/ 361 add(l, v:exception) 362 endtry 363 catch /wrong/ 364 add(l, 'caught') 365 fina 366 add(l, 'finally') 367 endtry 368 assert_equal(['1', 'caught', 'finally'], l) 369 370 var n: number 371 try 372 n = l[3] 373 catch /E684:/ 374 n = 99 375 endtry 376 assert_equal(99, n) 377 378 var done = 'no' 379 if 0 380 try | catch | endtry 381 else 382 done = 'yes' 383 endif 384 assert_equal('yes', done) 385 386 done = 'no' 387 if 1 388 done = 'yes' 389 else 390 try | catch | endtry 391 done = 'never' 392 endif 393 assert_equal('yes', done) 394 395 if 1 396 else 397 try | catch /pat/ | endtry 398 try | catch /pat/ 399 endtry 400 try 401 catch /pat/ | endtry 402 try 403 catch /pat/ 404 endtry 405 endif 406 407 try 408 # string slice returns a string, not a number 409 n = g:astring[3] 410 catch /E1012:/ 411 n = 77 412 endtry 413 assert_equal(77, n) 414 415 try 416 n = l[g:astring] 417 catch /E1012:/ 418 n = 88 419 endtry 420 assert_equal(88, n) 421 422 try 423 n = s:does_not_exist 424 catch /E121:/ 425 n = 111 426 endtry 427 assert_equal(111, n) 428 429 try 430 n = g:does_not_exist 431 catch /E121:/ 432 n = 121 433 endtry 434 assert_equal(121, n) 435 436 var d = {one: 1} 437 try 438 n = d[g:astring] 439 catch /E716:/ 440 n = 222 441 endtry 442 assert_equal(222, n) 443 444 try 445 n = -g:astring 446 catch /E39:/ 447 n = 233 448 endtry 449 assert_equal(233, n) 450 451 try 452 n = +g:astring 453 catch /E1030:/ 454 n = 244 455 endtry 456 assert_equal(244, n) 457 458 try 459 n = +g:alist 460 catch /E745:/ 461 n = 255 462 endtry 463 assert_equal(255, n) 464 465 var nd: dict<any> 466 try 467 nd = {[g:alist]: 1} 468 catch /E1105:/ 469 n = 266 470 endtry 471 assert_equal(266, n) 472 473 try 474 [n] = [1, 2, 3] 475 catch /E1093:/ 476 n = 277 477 endtry 478 assert_equal(277, n) 479 480 try 481 &ts = g:astring 482 catch /E1012:/ 483 n = 288 484 endtry 485 assert_equal(288, n) 486 487 try 488 &backspace = 'asdf' 489 catch /E474:/ 490 n = 299 491 endtry 492 assert_equal(299, n) 493 494 l = [1] 495 try 496 l[3] = 3 497 catch /E684:/ 498 n = 300 499 endtry 500 assert_equal(300, n) 501 502 try 503 unlet g:does_not_exist 504 catch /E108:/ 505 n = 322 506 endtry 507 assert_equal(322, n) 508 509 try 510 d = {text: 1, [g:astring]: 2} 511 catch /E721:/ 512 n = 333 513 endtry 514 assert_equal(333, n) 515 516 try 517 l = DeletedFunc() 518 catch /E933:/ 519 n = 344 520 endtry 521 assert_equal(344, n) 522 523 try 524 echo len(v:true) 525 catch /E701:/ 526 n = 355 527 endtry 528 assert_equal(355, n) 529 530 var P = function('g:NoSuchFunc') 531 delfunc g:NoSuchFunc 532 try 533 echo P() 534 catch /E117:/ 535 n = 366 536 endtry 537 assert_equal(366, n) 538 539 try 540 echo g:NoSuchFunc() 541 catch /E117:/ 542 n = 377 543 endtry 544 assert_equal(377, n) 545 546 try 547 echo g:alist + 4 548 catch /E745:/ 549 n = 388 550 endtry 551 assert_equal(388, n) 552 553 try 554 echo 4 + g:alist 555 catch /E745:/ 556 n = 399 557 endtry 558 assert_equal(399, n) 559 560 try 561 echo g:alist.member 562 catch /E715:/ 563 n = 400 564 endtry 565 assert_equal(400, n) 566 567 try 568 echo d.member 569 catch /E716:/ 570 n = 411 571 endtry 572 assert_equal(411, n) 573 574 var counter = 0 575 for i in range(4) 576 try 577 eval [][0] 578 catch 579 endtry 580 counter += 1 581 endfor 582 assert_equal(4, counter) 583 584 # return in finally after empty catch 585 def ReturnInFinally(): number 586 try 587 finally 588 return 4 589 endtry 590 return 2 591 enddef 592 assert_equal(4, ReturnInFinally()) 593enddef 594 595" :while at the very start of a function that :continue jumps to 596def TryContinueFunc() 597 while g:Count < 2 598 g:sequence ..= 't' 599 try 600 echoerr 'Test' 601 catch 602 g:Count += 1 603 g:sequence ..= 'c' 604 continue 605 endtry 606 g:sequence ..= 'e' 607 g:Count += 1 608 endwhile 609enddef 610 611def Test_continue_in_try_in_while() 612 g:Count = 0 613 g:sequence = '' 614 TryContinueFunc() 615 assert_equal('tctc', g:sequence) 616 unlet g:Count 617 unlet g:sequence 618enddef 619 620def Test_nocatch_return_in_try() 621 # return in try block returns normally 622 def ReturnInTry(): string 623 try 624 return '"some message"' 625 catch 626 endtry 627 return 'not reached' 628 enddef 629 exe 'echoerr ' .. ReturnInTry() 630enddef 631 632def Test_cnext_works_in_catch() 633 var lines =<< trim END 634 vim9script 635 au BufEnter * eval 0 636 writefile(['text'], 'Xfile1') 637 writefile(['text'], 'Xfile2') 638 var items = [ 639 {lnum: 1, filename: 'Xfile1', valid: true}, 640 {lnum: 1, filename: 'Xfile2', valid: true} 641 ] 642 setqflist([], ' ', {items: items}) 643 cwindow 644 645 def CnextOrCfirst() 646 # if cnext fails, cfirst is used 647 try 648 cnext 649 catch 650 cfirst 651 endtry 652 enddef 653 654 CnextOrCfirst() 655 CnextOrCfirst() 656 writefile([getqflist({idx: 0}).idx], 'Xresult') 657 qall 658 END 659 writefile(lines, 'XCatchCnext') 660 RunVim([], [], '--clean -S XCatchCnext') 661 assert_equal(['1'], readfile('Xresult')) 662 663 delete('Xfile1') 664 delete('Xfile2') 665 delete('XCatchCnext') 666 delete('Xresult') 667enddef 668 669def Test_throw_skipped() 670 if 0 671 throw dontgethere 672 endif 673enddef 674 675def Test_nocatch_throw_silenced() 676 var lines =<< trim END 677 vim9script 678 def Func() 679 throw 'error' 680 enddef 681 silent! Func() 682 END 683 writefile(lines, 'XthrowSilenced') 684 source XthrowSilenced 685 delete('XthrowSilenced') 686enddef 687 688def DeletedFunc(): list<any> 689 return ['delete me'] 690enddef 691defcompile 692delfunc DeletedFunc 693 694def ThrowFromDef() 695 throw "getout" # comment 696enddef 697 698func CatchInFunc() 699 try 700 call ThrowFromDef() 701 catch 702 let g:thrown_func = v:exception 703 endtry 704endfunc 705 706def CatchInDef() 707 try 708 ThrowFromDef() 709 catch 710 g:thrown_def = v:exception 711 endtry 712enddef 713 714def ReturnFinally(): string 715 try 716 return 'intry' 717 finall 718 g:in_finally = 'finally' 719 endtry 720 return 'end' 721enddef 722 723def Test_try_catch_nested() 724 CatchInFunc() 725 assert_equal('getout', g:thrown_func) 726 727 CatchInDef() 728 assert_equal('getout', g:thrown_def) 729 730 assert_equal('intry', ReturnFinally()) 731 assert_equal('finally', g:in_finally) 732enddef 733 734def TryOne(): number 735 try 736 return 0 737 catch 738 endtry 739 return 0 740enddef 741 742def TryTwo(n: number): string 743 try 744 var x = {} 745 catch 746 endtry 747 return 'text' 748enddef 749 750def Test_try_catch_twice() 751 assert_equal('text', TryOne()->TryTwo()) 752enddef 753 754def Test_try_catch_match() 755 var seq = 'a' 756 try 757 throw 'something' 758 catch /nothing/ 759 seq ..= 'x' 760 catch /some/ 761 seq ..= 'b' 762 catch /asdf/ 763 seq ..= 'x' 764 catch ?a\?sdf? 765 seq ..= 'y' 766 finally 767 seq ..= 'c' 768 endtry 769 assert_equal('abc', seq) 770enddef 771 772def Test_try_catch_fails() 773 CheckDefFailure(['catch'], 'E603:') 774 CheckDefFailure(['try', 'echo 0', 'catch', 'catch'], 'E1033:') 775 CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:') 776 CheckDefFailure(['finally'], 'E606:') 777 CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:') 778 CheckDefFailure(['endtry'], 'E602:') 779 CheckDefFailure(['while 1', 'endtry'], 'E170:') 780 CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:') 781 CheckDefFailure(['if 1', 'endtry'], 'E171:') 782 CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:') 783 784 CheckDefFailure(['throw'], 'E1143:') 785 CheckDefFailure(['throw xxx'], 'E1001:') 786enddef 787 788def Try_catch_skipped() 789 var l = [] 790 try 791 finally 792 endtry 793 794 if 1 795 else 796 try 797 endtry 798 endif 799enddef 800 801" The skipped try/endtry was updating the wrong instruction. 802def Test_try_catch_skipped() 803 var instr = execute('disassemble Try_catch_skipped') 804 assert_match("NEWLIST size 0\n", instr) 805enddef 806 807 808 809def Test_throw_vimscript() 810 # only checks line continuation 811 var lines =<< trim END 812 vim9script 813 try 814 throw 'one' 815 .. 'two' 816 catch 817 assert_equal('onetwo', v:exception) 818 endtry 819 END 820 CheckScriptSuccess(lines) 821 822 lines =<< trim END 823 vim9script 824 @r = '' 825 def Func() 826 throw @r 827 enddef 828 var result = '' 829 try 830 Func() 831 catch /E1129:/ 832 result = 'caught' 833 endtry 834 assert_equal('caught', result) 835 END 836 CheckScriptSuccess(lines) 837enddef 838 839def Test_error_in_nested_function() 840 # an error in a nested :function aborts executing in the calling :def function 841 var lines =<< trim END 842 vim9script 843 def Func() 844 Error() 845 g:test_var = 1 846 enddef 847 func Error() abort 848 eval [][0] 849 endfunc 850 Func() 851 END 852 g:test_var = 0 853 CheckScriptFailure(lines, 'E684:') 854 assert_equal(0, g:test_var) 855enddef 856 857def Test_cexpr_vimscript() 858 # only checks line continuation 859 set errorformat=File\ %f\ line\ %l 860 var lines =<< trim END 861 vim9script 862 cexpr 'File' 863 .. ' someFile' .. 864 ' line 19' 865 assert_equal(19, getqflist()[0].lnum) 866 END 867 CheckScriptSuccess(lines) 868 set errorformat& 869enddef 870 871def Test_statusline_syntax() 872 # legacy syntax is used for 'statusline' 873 var lines =<< trim END 874 vim9script 875 func g:Status() 876 return '%{"x" is# "x"}' 877 endfunc 878 set laststatus=2 statusline=%!Status() 879 redrawstatus 880 set laststatus statusline= 881 END 882 CheckScriptSuccess(lines) 883enddef 884 885def Test_list_vimscript() 886 # checks line continuation and comments 887 var lines =<< trim END 888 vim9script 889 var mylist = [ 890 'one', 891 # comment 892 'two', # empty line follows 893 894 'three', 895 ] 896 assert_equal(['one', 'two', 'three'], mylist) 897 END 898 CheckScriptSuccess(lines) 899 900 # check all lines from heredoc are kept 901 lines =<< trim END 902 # comment 1 903 two 904 # comment 3 905 906 five 907 # comment 6 908 END 909 assert_equal(['# comment 1', 'two', '# comment 3', '', 'five', '# comment 6'], lines) 910 911 lines =<< trim END 912 [{ 913 a: 0}]->string()->assert_equal("[{'a': 0}]") 914 END 915 CheckDefAndScriptSuccess(lines) 916enddef 917 918if has('channel') 919 let someJob = test_null_job() 920 921 def FuncWithError() 922 echomsg g:someJob 923 enddef 924 925 func Test_convert_emsg_to_exception() 926 try 927 call FuncWithError() 928 catch 929 call assert_match('Vim:E908:', v:exception) 930 endtry 931 endfunc 932endif 933 934let s:export_script_lines =<< trim END 935 vim9script 936 var name: string = 'bob' 937 def Concat(arg: string): string 938 return name .. arg 939 enddef 940 g:result = Concat('bie') 941 g:localname = name 942 943 export const CONST = 1234 944 export var exported = 9876 945 export var exp_name = 'John' 946 export def Exported(): string 947 return 'Exported' 948 enddef 949 export final theList = [1] 950END 951 952def Undo_export_script_lines() 953 unlet g:result 954 unlet g:localname 955enddef 956 957def Test_vim9_import_export() 958 var import_script_lines =<< trim END 959 vim9script 960 import {exported, Exported} from './Xexport.vim' 961 g:imported = exported 962 exported += 3 963 g:imported_added = exported 964 g:imported_func = Exported() 965 966 def GetExported(): string 967 var local_dict = {ref: Exported} 968 return local_dict.ref() 969 enddef 970 g:funcref_result = GetExported() 971 972 import {exp_name} from './Xexport.vim' 973 g:imported_name = exp_name 974 exp_name ..= ' Doe' 975 g:imported_name_appended = exp_name 976 g:imported_later = exported 977 978 import theList from './Xexport.vim' 979 theList->add(2) 980 assert_equal([1, 2], theList) 981 END 982 983 writefile(import_script_lines, 'Ximport.vim') 984 writefile(s:export_script_lines, 'Xexport.vim') 985 986 source Ximport.vim 987 988 assert_equal('bobbie', g:result) 989 assert_equal('bob', g:localname) 990 assert_equal(9876, g:imported) 991 assert_equal(9879, g:imported_added) 992 assert_equal(9879, g:imported_later) 993 assert_equal('Exported', g:imported_func) 994 assert_equal('Exported', g:funcref_result) 995 assert_equal('John', g:imported_name) 996 assert_equal('John Doe', g:imported_name_appended) 997 assert_false(exists('g:name')) 998 999 Undo_export_script_lines() 1000 unlet g:imported 1001 unlet g:imported_added 1002 unlet g:imported_later 1003 unlet g:imported_func 1004 unlet g:imported_name g:imported_name_appended 1005 delete('Ximport.vim') 1006 1007 # similar, with line breaks 1008 var import_line_break_script_lines =<< trim END 1009 vim9script 1010 import { 1011 exported, 1012 Exported, 1013 } 1014 from 1015 './Xexport.vim' 1016 g:imported = exported 1017 exported += 5 1018 g:imported_added = exported 1019 g:imported_func = Exported() 1020 END 1021 writefile(import_line_break_script_lines, 'Ximport_lbr.vim') 1022 source Ximport_lbr.vim 1023 1024 assert_equal(9876, g:imported) 1025 assert_equal(9881, g:imported_added) 1026 assert_equal('Exported', g:imported_func) 1027 1028 # exported script not sourced again 1029 assert_false(exists('g:result')) 1030 unlet g:imported 1031 unlet g:imported_added 1032 unlet g:imported_func 1033 delete('Ximport_lbr.vim') 1034 1035 # import inside :def function 1036 var import_in_def_lines =<< trim END 1037 vim9script 1038 def ImportInDef() 1039 import exported from './Xexport.vim' 1040 g:imported = exported 1041 exported += 7 1042 g:imported_added = exported 1043 enddef 1044 ImportInDef() 1045 END 1046 writefile(import_in_def_lines, 'Ximport2.vim') 1047 source Ximport2.vim 1048 # TODO: this should be 9879 1049 assert_equal(9876, g:imported) 1050 assert_equal(9883, g:imported_added) 1051 unlet g:imported 1052 unlet g:imported_added 1053 delete('Ximport2.vim') 1054 1055 var import_star_as_lines =<< trim END 1056 vim9script 1057 import * as Export from './Xexport.vim' 1058 def UseExport() 1059 g:imported_def = Export.exported 1060 enddef 1061 g:imported_script = Export.exported 1062 assert_equal(1, exists('Export.exported')) 1063 assert_equal(0, exists('Export.notexported')) 1064 UseExport() 1065 END 1066 writefile(import_star_as_lines, 'Ximport.vim') 1067 source Ximport.vim 1068 assert_equal(9883, g:imported_def) 1069 assert_equal(9883, g:imported_script) 1070 1071 var import_star_as_lines_no_dot =<< trim END 1072 vim9script 1073 import * as Export from './Xexport.vim' 1074 def Func() 1075 var dummy = 1 1076 var imported = Export + dummy 1077 enddef 1078 defcompile 1079 END 1080 writefile(import_star_as_lines_no_dot, 'Ximport.vim') 1081 assert_fails('source Ximport.vim', 'E1060:', '', 2, 'Func') 1082 1083 var import_star_as_lines_dot_space =<< trim END 1084 vim9script 1085 import * as Export from './Xexport.vim' 1086 def Func() 1087 var imported = Export . exported 1088 enddef 1089 defcompile 1090 END 1091 writefile(import_star_as_lines_dot_space, 'Ximport.vim') 1092 assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func') 1093 1094 var import_star_as_duplicated =<< trim END 1095 vim9script 1096 import * as Export from './Xexport.vim' 1097 var some = 'other' 1098 import * as Export from './Xexport.vim' 1099 defcompile 1100 END 1101 writefile(import_star_as_duplicated, 'Ximport.vim') 1102 assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim') 1103 1104 var import_star_as_lines_script_no_dot =<< trim END 1105 vim9script 1106 import * as Export from './Xexport.vim' 1107 g:imported_script = Export exported 1108 END 1109 writefile(import_star_as_lines_script_no_dot, 'Ximport.vim') 1110 assert_fails('source Ximport.vim', 'E1029:') 1111 1112 var import_star_as_lines_script_space_after_dot =<< trim END 1113 vim9script 1114 import * as Export from './Xexport.vim' 1115 g:imported_script = Export. exported 1116 END 1117 writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim') 1118 assert_fails('source Ximport.vim', 'E1074:') 1119 1120 var import_star_as_lines_missing_name =<< trim END 1121 vim9script 1122 import * as Export from './Xexport.vim' 1123 def Func() 1124 var imported = Export. 1125 enddef 1126 defcompile 1127 END 1128 writefile(import_star_as_lines_missing_name, 'Ximport.vim') 1129 assert_fails('source Ximport.vim', 'E1048:', '', 1, 'Func') 1130 1131 var import_star_as_lbr_lines =<< trim END 1132 vim9script 1133 import * 1134 as Export 1135 from 1136 './Xexport.vim' 1137 def UseExport() 1138 g:imported = Export.exported 1139 enddef 1140 UseExport() 1141 END 1142 writefile(import_star_as_lbr_lines, 'Ximport.vim') 1143 source Ximport.vim 1144 assert_equal(9883, g:imported) 1145 1146 var import_star_lines =<< trim END 1147 vim9script 1148 import * from './Xexport.vim' 1149 END 1150 writefile(import_star_lines, 'Ximport.vim') 1151 assert_fails('source Ximport.vim', 'E1045:', '', 2, 'Ximport.vim') 1152 1153 # try to import something that exists but is not exported 1154 var import_not_exported_lines =<< trim END 1155 vim9script 1156 import name from './Xexport.vim' 1157 END 1158 writefile(import_not_exported_lines, 'Ximport.vim') 1159 assert_fails('source Ximport.vim', 'E1049:', '', 2, 'Ximport.vim') 1160 1161 # try to import something that is already defined 1162 var import_already_defined =<< trim END 1163 vim9script 1164 var exported = 'something' 1165 import exported from './Xexport.vim' 1166 END 1167 writefile(import_already_defined, 'Ximport.vim') 1168 assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') 1169 1170 # try to import something that is already defined 1171 import_already_defined =<< trim END 1172 vim9script 1173 var exported = 'something' 1174 import * as exported from './Xexport.vim' 1175 END 1176 writefile(import_already_defined, 'Ximport.vim') 1177 assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') 1178 1179 # try to import something that is already defined 1180 import_already_defined =<< trim END 1181 vim9script 1182 var exported = 'something' 1183 import {exported} from './Xexport.vim' 1184 END 1185 writefile(import_already_defined, 'Ximport.vim') 1186 assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') 1187 1188 # try changing an imported const 1189 var import_assign_to_const =<< trim END 1190 vim9script 1191 import CONST from './Xexport.vim' 1192 def Assign() 1193 CONST = 987 1194 enddef 1195 defcompile 1196 END 1197 writefile(import_assign_to_const, 'Ximport.vim') 1198 assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign') 1199 1200 # try changing an imported final 1201 var import_assign_to_final =<< trim END 1202 vim9script 1203 import theList from './Xexport.vim' 1204 def Assign() 1205 theList = [2] 1206 enddef 1207 defcompile 1208 END 1209 writefile(import_assign_to_final, 'Ximport.vim') 1210 assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign') 1211 1212 # import a very long name, requires making a copy 1213 var import_long_name_lines =<< trim END 1214 vim9script 1215 import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim' 1216 END 1217 writefile(import_long_name_lines, 'Ximport.vim') 1218 assert_fails('source Ximport.vim', 'E1048:', '', 2, 'Ximport.vim') 1219 1220 var import_no_from_lines =<< trim END 1221 vim9script 1222 import name './Xexport.vim' 1223 END 1224 writefile(import_no_from_lines, 'Ximport.vim') 1225 assert_fails('source Ximport.vim', 'E1070:', '', 2, 'Ximport.vim') 1226 1227 var import_invalid_string_lines =<< trim END 1228 vim9script 1229 import name from Xexport.vim 1230 END 1231 writefile(import_invalid_string_lines, 'Ximport.vim') 1232 assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim') 1233 1234 var import_wrong_name_lines =<< trim END 1235 vim9script 1236 import name from './XnoExport.vim' 1237 END 1238 writefile(import_wrong_name_lines, 'Ximport.vim') 1239 assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim') 1240 1241 var import_missing_comma_lines =<< trim END 1242 vim9script 1243 import {exported name} from './Xexport.vim' 1244 END 1245 writefile(import_missing_comma_lines, 'Ximport3.vim') 1246 assert_fails('source Ximport3.vim', 'E1046:', '', 2, 'Ximport3.vim') 1247 1248 delete('Ximport.vim') 1249 delete('Ximport3.vim') 1250 delete('Xexport.vim') 1251 1252 # Check that in a Vim9 script 'cpo' is set to the Vim default. 1253 # Flags added or removed are also applied to the restored value. 1254 set cpo=abcd 1255 var lines =<< trim END 1256 vim9script 1257 g:cpo_in_vim9script = &cpo 1258 set cpo+=f 1259 set cpo-=c 1260 g:cpo_after_vim9script = &cpo 1261 END 1262 writefile(lines, 'Xvim9_script') 1263 source Xvim9_script 1264 assert_equal('fabd', &cpo) 1265 set cpo&vim 1266 assert_equal(&cpo, g:cpo_in_vim9script) 1267 var newcpo = substitute(&cpo, 'c', '', '') .. 'f' 1268 assert_equal(newcpo, g:cpo_after_vim9script) 1269 1270 delete('Xvim9_script') 1271enddef 1272 1273def Test_import_as() 1274 var export_lines =<< trim END 1275 vim9script 1276 export var one = 1 1277 export var yes = 'yes' 1278 END 1279 writefile(export_lines, 'XexportAs') 1280 1281 var import_lines =<< trim END 1282 vim9script 1283 var one = 'notused' 1284 var yes = 777 1285 import one as thatOne from './XexportAs' 1286 assert_equal(1, thatOne) 1287 import yes as yesYes from './XexportAs' 1288 assert_equal('yes', yesYes) 1289 END 1290 CheckScriptSuccess(import_lines) 1291 1292 import_lines =<< trim END 1293 vim9script 1294 import {one as thatOne, yes as yesYes} from './XexportAs' 1295 assert_equal(1, thatOne) 1296 assert_equal('yes', yesYes) 1297 assert_fails('echo one', 'E121:') 1298 assert_fails('echo yes', 'E121:') 1299 END 1300 CheckScriptSuccess(import_lines) 1301 1302 delete('XexportAs') 1303enddef 1304 1305func g:Trigger() 1306 source Ximport.vim 1307 return "echo 'yes'\<CR>" 1308endfunc 1309 1310def Test_import_export_expr_map() 1311 # check that :import and :export work when buffer is locked 1312 var export_lines =<< trim END 1313 vim9script 1314 export def That(): string 1315 return 'yes' 1316 enddef 1317 END 1318 writefile(export_lines, 'Xexport_that.vim') 1319 1320 var import_lines =<< trim END 1321 vim9script 1322 import That from './Xexport_that.vim' 1323 assert_equal('yes', That()) 1324 END 1325 writefile(import_lines, 'Ximport.vim') 1326 1327 nnoremap <expr> trigger g:Trigger() 1328 feedkeys('trigger', "xt") 1329 1330 delete('Xexport_that.vim') 1331 delete('Ximport.vim') 1332 nunmap trigger 1333enddef 1334 1335def Test_import_in_filetype() 1336 # check that :import works when the buffer is locked 1337 mkdir('ftplugin', 'p') 1338 var export_lines =<< trim END 1339 vim9script 1340 export var That = 'yes' 1341 END 1342 writefile(export_lines, 'ftplugin/Xexport_ft.vim') 1343 1344 var import_lines =<< trim END 1345 vim9script 1346 import That from './Xexport_ft.vim' 1347 assert_equal('yes', That) 1348 g:did_load_mytpe = 1 1349 END 1350 writefile(import_lines, 'ftplugin/qf.vim') 1351 1352 var save_rtp = &rtp 1353 &rtp = getcwd() .. ',' .. &rtp 1354 1355 filetype plugin on 1356 copen 1357 assert_equal(1, g:did_load_mytpe) 1358 1359 quit! 1360 delete('Xexport_ft.vim') 1361 delete('ftplugin', 'rf') 1362 &rtp = save_rtp 1363enddef 1364 1365def Test_use_import_in_mapping() 1366 var lines =<< trim END 1367 vim9script 1368 export def Funcx() 1369 g:result = 42 1370 enddef 1371 END 1372 writefile(lines, 'XsomeExport.vim') 1373 lines =<< trim END 1374 vim9script 1375 import Funcx from './XsomeExport.vim' 1376 nnoremap <F3> :call <sid>Funcx()<cr> 1377 END 1378 writefile(lines, 'Xmapscript.vim') 1379 1380 source Xmapscript.vim 1381 feedkeys("\<F3>", "xt") 1382 assert_equal(42, g:result) 1383 1384 unlet g:result 1385 delete('XsomeExport.vim') 1386 delete('Xmapscript.vim') 1387 nunmap <F3> 1388enddef 1389 1390def Test_vim9script_mix() 1391 var lines =<< trim END 1392 if has(g:feature) 1393 " legacy script 1394 let g:legacy = 1 1395 finish 1396 endif 1397 vim9script 1398 g:legacy = 0 1399 END 1400 g:feature = 'eval' 1401 g:legacy = -1 1402 CheckScriptSuccess(lines) 1403 assert_equal(1, g:legacy) 1404 1405 g:feature = 'noteval' 1406 g:legacy = -1 1407 CheckScriptSuccess(lines) 1408 assert_equal(0, g:legacy) 1409enddef 1410 1411def Test_vim9script_fails() 1412 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') 1413 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') 1414 CheckScriptFailure(['export var some = 123'], 'E1042:') 1415 CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:') 1416 CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:') 1417 CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') 1418 1419 CheckScriptFailure(['vim9script', 'var str: string', 'str = 1234'], 'E1012:') 1420 CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:') 1421 1422 assert_fails('vim9script', 'E1038:') 1423 assert_fails('export something', 'E1043:') 1424enddef 1425 1426func Test_import_fails_without_script() 1427 CheckRunVimInTerminal 1428 1429 " call indirectly to avoid compilation error for missing functions 1430 call Run_Test_import_fails_on_command_line() 1431endfunc 1432 1433def Run_Test_import_fails_on_command_line() 1434 var export =<< trim END 1435 vim9script 1436 export def Foo(): number 1437 return 0 1438 enddef 1439 END 1440 writefile(export, 'XexportCmd.vim') 1441 1442 var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', { 1443 rows: 6, wait_for_ruler: 0}) 1444 WaitForAssert(() => assert_match('^E1094:', term_getline(buf, 5))) 1445 1446 delete('XexportCmd.vim') 1447 StopVimInTerminal(buf) 1448enddef 1449 1450def Test_vim9script_reload_noclear() 1451 var lines =<< trim END 1452 vim9script 1453 export var exported = 'thexport' 1454 END 1455 writefile(lines, 'XExportReload') 1456 lines =<< trim END 1457 vim9script noclear 1458 g:loadCount += 1 1459 var s:reloaded = 'init' 1460 import exported from './XExportReload' 1461 1462 def Again(): string 1463 return 'again' 1464 enddef 1465 1466 if exists('s:loaded') | finish | endif 1467 var s:loaded = true 1468 1469 var s:notReloaded = 'yes' 1470 s:reloaded = 'first' 1471 def g:Values(): list<string> 1472 return [s:reloaded, s:notReloaded, Again(), Once(), exported] 1473 enddef 1474 1475 def Once(): string 1476 return 'once' 1477 enddef 1478 END 1479 writefile(lines, 'XReloaded') 1480 g:loadCount = 0 1481 source XReloaded 1482 assert_equal(1, g:loadCount) 1483 assert_equal(['first', 'yes', 'again', 'once', 'thexport'], g:Values()) 1484 source XReloaded 1485 assert_equal(2, g:loadCount) 1486 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1487 source XReloaded 1488 assert_equal(3, g:loadCount) 1489 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1490 1491 delete('XReloaded') 1492 delete('XExportReload') 1493 delfunc g:Values 1494 unlet g:loadCount 1495enddef 1496 1497def Test_vim9script_reload_import() 1498 var lines =<< trim END 1499 vim9script 1500 const var = '' 1501 var valone = 1234 1502 def MyFunc(arg: string) 1503 valone = 5678 1504 enddef 1505 END 1506 var morelines =<< trim END 1507 var valtwo = 222 1508 export def GetValtwo(): number 1509 return valtwo 1510 enddef 1511 END 1512 writefile(lines + morelines, 'Xreload.vim') 1513 source Xreload.vim 1514 source Xreload.vim 1515 source Xreload.vim 1516 1517 var testlines =<< trim END 1518 vim9script 1519 def TheFunc() 1520 import GetValtwo from './Xreload.vim' 1521 assert_equal(222, GetValtwo()) 1522 enddef 1523 TheFunc() 1524 END 1525 writefile(testlines, 'Ximport.vim') 1526 source Ximport.vim 1527 1528 # Test that when not using "morelines" GetValtwo() and valtwo are still 1529 # defined, because import doesn't reload a script. 1530 writefile(lines, 'Xreload.vim') 1531 source Ximport.vim 1532 1533 # cannot declare a var twice 1534 lines =<< trim END 1535 vim9script 1536 var valone = 1234 1537 var valone = 5678 1538 END 1539 writefile(lines, 'Xreload.vim') 1540 assert_fails('source Xreload.vim', 'E1041:', '', 3, 'Xreload.vim') 1541 1542 delete('Xreload.vim') 1543 delete('Ximport.vim') 1544enddef 1545 1546" if a script is reloaded with a script-local variable that changed its type, a 1547" compiled function using that variable must fail. 1548def Test_script_reload_change_type() 1549 var lines =<< trim END 1550 vim9script noclear 1551 var str = 'string' 1552 def g:GetStr(): string 1553 return str .. 'xxx' 1554 enddef 1555 END 1556 writefile(lines, 'Xreload.vim') 1557 source Xreload.vim 1558 echo g:GetStr() 1559 1560 lines =<< trim END 1561 vim9script noclear 1562 var str = 1234 1563 END 1564 writefile(lines, 'Xreload.vim') 1565 source Xreload.vim 1566 assert_fails('echo g:GetStr()', 'E1150:') 1567 1568 delfunc g:GetStr 1569 delete('Xreload.vim') 1570enddef 1571 1572" Define CallFunc so that the test can be compiled 1573command CallFunc echo 'nop' 1574 1575def Test_script_reload_from_function() 1576 var lines =<< trim END 1577 vim9script 1578 1579 if exists('g:loaded') 1580 finish 1581 endif 1582 g:loaded = 1 1583 delcommand CallFunc 1584 command CallFunc Func() 1585 def Func() 1586 so XreloadFunc.vim 1587 g:didTheFunc = 1 1588 enddef 1589 END 1590 writefile(lines, 'XreloadFunc.vim') 1591 source XreloadFunc.vim 1592 CallFunc 1593 assert_equal(1, g:didTheFunc) 1594 1595 delete('XreloadFunc.vim') 1596 delcommand CallFunc 1597 unlet g:loaded 1598 unlet g:didTheFunc 1599enddef 1600 1601def Test_script_var_shadows_function() 1602 var lines =<< trim END 1603 vim9script 1604 def Func(): number 1605 return 123 1606 enddef 1607 var Func = 1 1608 END 1609 CheckScriptFailure(lines, 'E1041:', 5) 1610enddef 1611 1612def s:RetSome(): string 1613 return 'some' 1614enddef 1615 1616" Not exported function that is referenced needs to be accessed by the 1617" script-local name. 1618def Test_vim9script_funcref() 1619 var sortlines =<< trim END 1620 vim9script 1621 def Compare(i1: number, i2: number): number 1622 return i2 - i1 1623 enddef 1624 1625 export def FastSort(): list<number> 1626 return range(5)->sort(Compare) 1627 enddef 1628 1629 export def GetString(arg: string): string 1630 return arg 1631 enddef 1632 END 1633 writefile(sortlines, 'Xsort.vim') 1634 1635 var lines =<< trim END 1636 vim9script 1637 import FastSort from './Xsort.vim' 1638 def Test() 1639 g:result = FastSort() 1640 enddef 1641 Test() 1642 1643 # using a function imported with "as" 1644 import * as anAlias from './Xsort.vim' 1645 assert_equal('yes', anAlias.GetString('yes')) 1646 1647 # using the function from a compiled function 1648 def TestMore(): string 1649 var s = s:anAlias.GetString('foo') 1650 return s .. anAlias.GetString('bar') 1651 enddef 1652 assert_equal('foobar', TestMore()) 1653 1654 # error when using a function that isn't exported 1655 assert_fails('anAlias.Compare(1, 2)', 'E1049:') 1656 END 1657 writefile(lines, 'Xscript.vim') 1658 1659 source Xscript.vim 1660 assert_equal([4, 3, 2, 1, 0], g:result) 1661 1662 unlet g:result 1663 delete('Xsort.vim') 1664 delete('Xscript.vim') 1665 1666 var Funcref = function('s:RetSome') 1667 assert_equal('some', Funcref()) 1668enddef 1669 1670" Check that when searching for "FilterFunc" it finds the import in the 1671" script where FastFilter() is called from, both as a string and as a direct 1672" function reference. 1673def Test_vim9script_funcref_other_script() 1674 var filterLines =<< trim END 1675 vim9script 1676 export def FilterFunc(idx: number, val: number): bool 1677 return idx % 2 == 1 1678 enddef 1679 export def FastFilter(): list<number> 1680 return range(10)->filter('FilterFunc') 1681 enddef 1682 export def FastFilterDirect(): list<number> 1683 return range(10)->filter(FilterFunc) 1684 enddef 1685 END 1686 writefile(filterLines, 'Xfilter.vim') 1687 1688 var lines =<< trim END 1689 vim9script 1690 import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim' 1691 def Test() 1692 var x: list<number> = FastFilter() 1693 enddef 1694 Test() 1695 def TestDirect() 1696 var x: list<number> = FastFilterDirect() 1697 enddef 1698 TestDirect() 1699 END 1700 CheckScriptSuccess(lines) 1701 delete('Xfilter.vim') 1702enddef 1703 1704def Test_vim9script_reload_delfunc() 1705 var first_lines =<< trim END 1706 vim9script 1707 def FuncYes(): string 1708 return 'yes' 1709 enddef 1710 END 1711 var withno_lines =<< trim END 1712 def FuncNo(): string 1713 return 'no' 1714 enddef 1715 def g:DoCheck(no_exists: bool) 1716 assert_equal('yes', FuncYes()) 1717 assert_equal('no', FuncNo()) 1718 enddef 1719 END 1720 var nono_lines =<< trim END 1721 def g:DoCheck(no_exists: bool) 1722 assert_equal('yes', FuncYes()) 1723 assert_fails('FuncNo()', 'E117:', '', 2, 'DoCheck') 1724 enddef 1725 END 1726 1727 # FuncNo() is defined 1728 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1729 source Xreloaded.vim 1730 g:DoCheck(true) 1731 1732 # FuncNo() is not redefined 1733 writefile(first_lines + nono_lines, 'Xreloaded.vim') 1734 source Xreloaded.vim 1735 g:DoCheck(false) 1736 1737 # FuncNo() is back 1738 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1739 source Xreloaded.vim 1740 g:DoCheck(false) 1741 1742 delete('Xreloaded.vim') 1743enddef 1744 1745def Test_vim9script_reload_delvar() 1746 # write the script with a script-local variable 1747 var lines =<< trim END 1748 vim9script 1749 var name = 'string' 1750 END 1751 writefile(lines, 'XreloadVar.vim') 1752 source XreloadVar.vim 1753 1754 # now write the script using the same variable locally - works 1755 lines =<< trim END 1756 vim9script 1757 def Func() 1758 var name = 'string' 1759 enddef 1760 END 1761 writefile(lines, 'XreloadVar.vim') 1762 source XreloadVar.vim 1763 1764 delete('XreloadVar.vim') 1765enddef 1766 1767def Test_import_absolute() 1768 var import_lines = [ 1769 'vim9script', 1770 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 1771 'def UseExported()', 1772 ' g:imported_abs = exported', 1773 ' exported = 8888', 1774 ' g:imported_after = exported', 1775 'enddef', 1776 'UseExported()', 1777 'g:import_disassembled = execute("disass UseExported")', 1778 ] 1779 writefile(import_lines, 'Ximport_abs.vim') 1780 writefile(s:export_script_lines, 'Xexport_abs.vim') 1781 1782 source Ximport_abs.vim 1783 1784 assert_equal(9876, g:imported_abs) 1785 assert_equal(8888, g:imported_after) 1786 assert_match('<SNR>\d\+_UseExported\_s*' .. 1787 'g:imported_abs = exported\_s*' .. 1788 '0 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 1789 '1 STOREG g:imported_abs\_s*' .. 1790 'exported = 8888\_s*' .. 1791 '2 PUSHNR 8888\_s*' .. 1792 '3 STORESCRIPT exported-2 in .*Xexport_abs.vim\_s*' .. 1793 'g:imported_after = exported\_s*' .. 1794 '4 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 1795 '5 STOREG g:imported_after', 1796 g:import_disassembled) 1797 1798 Undo_export_script_lines() 1799 unlet g:imported_abs 1800 unlet g:import_disassembled 1801 1802 delete('Ximport_abs.vim') 1803 delete('Xexport_abs.vim') 1804enddef 1805 1806def Test_import_rtp() 1807 var import_lines = [ 1808 'vim9script', 1809 'import exported from "Xexport_rtp.vim"', 1810 'g:imported_rtp = exported', 1811 ] 1812 writefile(import_lines, 'Ximport_rtp.vim') 1813 mkdir('import') 1814 writefile(s:export_script_lines, 'import/Xexport_rtp.vim') 1815 1816 var save_rtp = &rtp 1817 &rtp = getcwd() 1818 source Ximport_rtp.vim 1819 &rtp = save_rtp 1820 1821 assert_equal(9876, g:imported_rtp) 1822 1823 Undo_export_script_lines() 1824 unlet g:imported_rtp 1825 delete('Ximport_rtp.vim') 1826 delete('import', 'rf') 1827enddef 1828 1829def Test_import_compile_error() 1830 var export_lines = [ 1831 'vim9script', 1832 'export def ExpFunc(): string', 1833 ' return notDefined', 1834 'enddef', 1835 ] 1836 writefile(export_lines, 'Xexported.vim') 1837 1838 var import_lines = [ 1839 'vim9script', 1840 'import ExpFunc from "./Xexported.vim"', 1841 'def ImpFunc()', 1842 ' echo ExpFunc()', 1843 'enddef', 1844 'defcompile', 1845 ] 1846 writefile(import_lines, 'Ximport.vim') 1847 1848 try 1849 source Ximport.vim 1850 catch /E1001/ 1851 # Error should be fore the Xexported.vim file. 1852 assert_match('E1001: Variable not found: notDefined', v:exception) 1853 assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint) 1854 endtry 1855 1856 delete('Xexported.vim') 1857 delete('Ximport.vim') 1858enddef 1859 1860def Test_func_redefine_error() 1861 var lines = [ 1862 'vim9script', 1863 'def Func()', 1864 ' eval [][0]', 1865 'enddef', 1866 'Func()', 1867 ] 1868 writefile(lines, 'Xtestscript.vim') 1869 1870 for count in range(3) 1871 try 1872 source Xtestscript.vim 1873 catch /E684/ 1874 # function name should contain <SNR> every time 1875 assert_match('E684: list index out of range', v:exception) 1876 assert_match('function <SNR>\d\+_Func, line 1', v:throwpoint) 1877 endtry 1878 endfor 1879 1880 delete('Xtestscript.vim') 1881enddef 1882 1883def Test_func_overrules_import_fails() 1884 var export_lines =<< trim END 1885 vim9script 1886 export def Func() 1887 echo 'imported' 1888 enddef 1889 END 1890 writefile(export_lines, 'XexportedFunc.vim') 1891 1892 var lines =<< trim END 1893 vim9script 1894 import Func from './XexportedFunc.vim' 1895 def Func() 1896 echo 'local to function' 1897 enddef 1898 END 1899 CheckScriptFailure(lines, 'E1073:') 1900 1901 lines =<< trim END 1902 vim9script 1903 import Func from './XexportedFunc.vim' 1904 def Outer() 1905 def Func() 1906 echo 'local to function' 1907 enddef 1908 enddef 1909 defcompile 1910 END 1911 CheckScriptFailure(lines, 'E1073:') 1912 1913 delete('XexportedFunc.vim') 1914enddef 1915 1916def Test_func_redefine_fails() 1917 var lines =<< trim END 1918 vim9script 1919 def Func() 1920 echo 'one' 1921 enddef 1922 def Func() 1923 echo 'two' 1924 enddef 1925 END 1926 CheckScriptFailure(lines, 'E1073:') 1927 1928 lines =<< trim END 1929 vim9script 1930 def Foo(): string 1931 return 'foo' 1932 enddef 1933 def Func() 1934 var Foo = {-> 'lambda'} 1935 enddef 1936 defcompile 1937 END 1938 CheckScriptFailure(lines, 'E1073:') 1939enddef 1940 1941def Test_fixed_size_list() 1942 # will be allocated as one piece of memory, check that changes work 1943 var l = [1, 2, 3, 4] 1944 l->remove(0) 1945 l->add(5) 1946 l->insert(99, 1) 1947 assert_equal([2, 99, 3, 4, 5], l) 1948enddef 1949 1950def Test_no_insert_xit() 1951 CheckDefExecFailure(['a = 1'], 'E1100:') 1952 CheckDefExecFailure(['c = 1'], 'E1100:') 1953 CheckDefExecFailure(['i = 1'], 'E1100:') 1954 CheckDefExecFailure(['t = 1'], 'E1100:') 1955 CheckDefExecFailure(['x = 1'], 'E1100:') 1956 1957 CheckScriptFailure(['vim9script', 'a = 1'], 'E488:') 1958 CheckScriptFailure(['vim9script', 'a'], 'E1100:') 1959 CheckScriptFailure(['vim9script', 'c = 1'], 'E488:') 1960 CheckScriptFailure(['vim9script', 'c'], 'E1100:') 1961 CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') 1962 CheckScriptFailure(['vim9script', 'i'], 'E1100:') 1963 CheckScriptFailure(['vim9script', 'o = 1'], 'E1100:') 1964 CheckScriptFailure(['vim9script', 'o'], 'E1100:') 1965 CheckScriptFailure(['vim9script', 't'], 'E1100:') 1966 CheckScriptFailure(['vim9script', 't = 1'], 'E1100:') 1967 CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') 1968enddef 1969 1970def IfElse(what: number): string 1971 var res = '' 1972 if what == 1 1973 res = "one" 1974 elseif what == 2 1975 res = "two" 1976 else 1977 res = "three" 1978 endif 1979 return res 1980enddef 1981 1982def Test_if_elseif_else() 1983 assert_equal('one', IfElse(1)) 1984 assert_equal('two', IfElse(2)) 1985 assert_equal('three', IfElse(3)) 1986enddef 1987 1988def Test_if_elseif_else_fails() 1989 CheckDefFailure(['elseif true'], 'E582:') 1990 CheckDefFailure(['else'], 'E581:') 1991 CheckDefFailure(['endif'], 'E580:') 1992 CheckDefFailure(['if g:abool', 'elseif xxx'], 'E1001:') 1993 CheckDefFailure(['if true', 'echo 1'], 'E171:') 1994 1995 var lines =<< trim END 1996 var s = '' 1997 if s = '' 1998 endif 1999 END 2000 CheckDefFailure(lines, 'E488:') 2001 2002 lines =<< trim END 2003 var s = '' 2004 if s == '' 2005 elseif s = '' 2006 endif 2007 END 2008 CheckDefFailure(lines, 'E488:') 2009enddef 2010 2011let g:bool_true = v:true 2012let g:bool_false = v:false 2013 2014def Test_if_const_expr() 2015 var res = false 2016 if true ? true : false 2017 res = true 2018 endif 2019 assert_equal(true, res) 2020 2021 g:glob = 2 2022 if false 2023 execute('g:glob = 3') 2024 endif 2025 assert_equal(2, g:glob) 2026 if true 2027 execute('g:glob = 3') 2028 endif 2029 assert_equal(3, g:glob) 2030 2031 res = false 2032 if g:bool_true ? true : false 2033 res = true 2034 endif 2035 assert_equal(true, res) 2036 2037 res = false 2038 if true ? g:bool_true : false 2039 res = true 2040 endif 2041 assert_equal(true, res) 2042 2043 res = false 2044 if true ? true : g:bool_false 2045 res = true 2046 endif 2047 assert_equal(true, res) 2048 2049 res = false 2050 if true ? false : true 2051 res = true 2052 endif 2053 assert_equal(false, res) 2054 2055 res = false 2056 if false ? false : true 2057 res = true 2058 endif 2059 assert_equal(true, res) 2060 2061 res = false 2062 if false ? true : false 2063 res = true 2064 endif 2065 assert_equal(false, res) 2066 2067 res = false 2068 if has('xyz') ? true : false 2069 res = true 2070 endif 2071 assert_equal(false, res) 2072 2073 res = false 2074 if true && true 2075 res = true 2076 endif 2077 assert_equal(true, res) 2078 2079 res = false 2080 if true && false 2081 res = true 2082 endif 2083 assert_equal(false, res) 2084 2085 res = false 2086 if g:bool_true && false 2087 res = true 2088 endif 2089 assert_equal(false, res) 2090 2091 res = false 2092 if true && g:bool_false 2093 res = true 2094 endif 2095 assert_equal(false, res) 2096 2097 res = false 2098 if false && false 2099 res = true 2100 endif 2101 assert_equal(false, res) 2102 2103 res = false 2104 if true || false 2105 res = true 2106 endif 2107 assert_equal(true, res) 2108 2109 res = false 2110 if g:bool_true || false 2111 res = true 2112 endif 2113 assert_equal(true, res) 2114 2115 res = false 2116 if true || g:bool_false 2117 res = true 2118 endif 2119 assert_equal(true, res) 2120 2121 res = false 2122 if false || false 2123 res = true 2124 endif 2125 assert_equal(false, res) 2126 2127 # with constant "false" expression may be invalid so long as the syntax is OK 2128 if false | eval 0 | endif 2129 if false | eval burp + 234 | endif 2130 if false | echo burp 234 'asd' | endif 2131 if false 2132 burp 2133 endif 2134enddef 2135 2136def Test_if_const_expr_fails() 2137 CheckDefFailure(['if "aaa" == "bbb'], 'E114:') 2138 CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:') 2139 CheckDefFailure(["if has('aaa'"], 'E110:') 2140 CheckDefFailure(["if has('aaa') ? true false"], 'E109:') 2141enddef 2142 2143def RunNested(i: number): number 2144 var x: number = 0 2145 if i % 2 2146 if 1 2147 # comment 2148 else 2149 # comment 2150 endif 2151 x += 1 2152 else 2153 x += 1000 2154 endif 2155 return x 2156enddef 2157 2158def Test_nested_if() 2159 assert_equal(1, RunNested(1)) 2160 assert_equal(1000, RunNested(2)) 2161enddef 2162 2163def Test_execute_cmd() 2164 # missing argument is ignored 2165 execute 2166 execute # comment 2167 2168 new 2169 setline(1, 'default') 2170 execute 'setline(1, "execute-string")' 2171 assert_equal('execute-string', getline(1)) 2172 2173 execute "setline(1, 'execute-string')" 2174 assert_equal('execute-string', getline(1)) 2175 2176 var cmd1 = 'setline(1,' 2177 var cmd2 = '"execute-var")' 2178 execute cmd1 cmd2 # comment 2179 assert_equal('execute-var', getline(1)) 2180 2181 execute cmd1 cmd2 '|setline(1, "execute-var-string")' 2182 assert_equal('execute-var-string', getline(1)) 2183 2184 var cmd_first = 'call ' 2185 var cmd_last = 'setline(1, "execute-var-var")' 2186 execute cmd_first .. cmd_last 2187 assert_equal('execute-var-var', getline(1)) 2188 bwipe! 2189 2190 var n = true 2191 execute 'echomsg' (n ? '"true"' : '"no"') 2192 assert_match('^true$', Screenline(&lines)) 2193 2194 echomsg [1, 2, 3] {a: 1, b: 2} 2195 assert_match('^\[1, 2, 3\] {''a'': 1, ''b'': 2}$', Screenline(&lines)) 2196 2197 CheckDefFailure(['execute xxx'], 'E1001:', 1) 2198 CheckDefExecFailure(['execute "tabnext " .. 8'], 'E475:', 1) 2199 CheckDefFailure(['execute "cmd"# comment'], 'E488:', 1) 2200enddef 2201 2202def Test_execute_cmd_vimscript() 2203 # only checks line continuation 2204 var lines =<< trim END 2205 vim9script 2206 execute 'g:someVar' 2207 .. ' = ' .. 2208 '28' 2209 assert_equal(28, g:someVar) 2210 unlet g:someVar 2211 END 2212 CheckScriptSuccess(lines) 2213enddef 2214 2215def Test_echo_cmd() 2216 echo 'some' # comment 2217 echon 'thing' 2218 assert_match('^something$', Screenline(&lines)) 2219 2220 echo "some" # comment 2221 echon "thing" 2222 assert_match('^something$', Screenline(&lines)) 2223 2224 var str1 = 'some' 2225 var str2 = 'more' 2226 echo str1 str2 2227 assert_match('^some more$', Screenline(&lines)) 2228 2229 CheckDefFailure(['echo "xxx"# comment'], 'E488:') 2230enddef 2231 2232def Test_echomsg_cmd() 2233 echomsg 'some' 'more' # comment 2234 assert_match('^some more$', Screenline(&lines)) 2235 echo 'clear' 2236 :1messages 2237 assert_match('^some more$', Screenline(&lines)) 2238 2239 CheckDefFailure(['echomsg "xxx"# comment'], 'E488:') 2240enddef 2241 2242def Test_echomsg_cmd_vimscript() 2243 # only checks line continuation 2244 var lines =<< trim END 2245 vim9script 2246 echomsg 'here' 2247 .. ' is ' .. 2248 'a message' 2249 assert_match('^here is a message$', Screenline(&lines)) 2250 END 2251 CheckScriptSuccess(lines) 2252enddef 2253 2254def Test_echoerr_cmd() 2255 try 2256 echoerr 'something' 'wrong' # comment 2257 catch 2258 assert_match('something wrong', v:exception) 2259 endtry 2260enddef 2261 2262def Test_echoerr_cmd_vimscript() 2263 # only checks line continuation 2264 var lines =<< trim END 2265 vim9script 2266 try 2267 echoerr 'this' 2268 .. ' is ' .. 2269 'wrong' 2270 catch 2271 assert_match('this is wrong', v:exception) 2272 endtry 2273 END 2274 CheckScriptSuccess(lines) 2275enddef 2276 2277def Test_for_outside_of_function() 2278 var lines =<< trim END 2279 vim9script 2280 new 2281 for var in range(0, 3) 2282 append(line('$'), var) 2283 endfor 2284 assert_equal(['', '0', '1', '2', '3'], getline(1, '$')) 2285 bwipe! 2286 2287 var result = '' 2288 for i in [1, 2, 3] 2289 var loop = ' loop ' .. i 2290 result ..= loop 2291 endfor 2292 assert_equal(' loop 1 loop 2 loop 3', result) 2293 END 2294 writefile(lines, 'Xvim9for.vim') 2295 source Xvim9for.vim 2296 delete('Xvim9for.vim') 2297enddef 2298 2299def Test_for_loop() 2300 var lines =<< trim END 2301 var result = '' 2302 for cnt in range(7) 2303 if cnt == 4 2304 break 2305 endif 2306 if cnt == 2 2307 continue 2308 endif 2309 result ..= cnt .. '_' 2310 endfor 2311 assert_equal('0_1_3_', result) 2312 2313 var concat = '' 2314 for str in eval('["one", "two"]') 2315 concat ..= str 2316 endfor 2317 assert_equal('onetwo', concat) 2318 2319 var total = 0 2320 for nr in 2321 [1, 2, 3] 2322 total += nr 2323 endfor 2324 assert_equal(6, total) 2325 2326 total = 0 2327 for nr 2328 in [1, 2, 3] 2329 total += nr 2330 endfor 2331 assert_equal(6, total) 2332 2333 total = 0 2334 for nr 2335 in 2336 [1, 2, 3] 2337 total += nr 2338 endfor 2339 assert_equal(6, total) 2340 2341 # with type 2342 total = 0 2343 for n: number in [1, 2, 3] 2344 total += n 2345 endfor 2346 assert_equal(6, total) 2347 2348 var chars = '' 2349 for s: string in 'foobar' 2350 chars ..= s 2351 endfor 2352 assert_equal('foobar', chars) 2353 2354 # unpack with type 2355 var res = '' 2356 for [n: number, s: string] in [[1, 'a'], [2, 'b']] 2357 res ..= n .. s 2358 endfor 2359 assert_equal('1a2b', res) 2360 2361 # loop over string 2362 res = '' 2363 for c in 'aéc̀d' 2364 res ..= c .. '-' 2365 endfor 2366 assert_equal('a-é-c̀-d-', res) 2367 2368 res = '' 2369 for c in '' 2370 res ..= c .. '-' 2371 endfor 2372 assert_equal('', res) 2373 2374 res = '' 2375 for c in test_null_string() 2376 res ..= c .. '-' 2377 endfor 2378 assert_equal('', res) 2379 2380 var foo: list<dict<any>> = [ 2381 {a: 'Cat'} 2382 ] 2383 for dd in foo 2384 dd.counter = 12 2385 endfor 2386 assert_equal([{a: 'Cat', counter: 12}], foo) 2387 END 2388 CheckDefAndScriptSuccess(lines) 2389enddef 2390 2391def Test_for_loop_fails() 2392 CheckDefFailure(['for '], 'E1097:') 2393 CheckDefFailure(['for x'], 'E1097:') 2394 CheckDefFailure(['for x in'], 'E1097:') 2395 CheckDefFailure(['for # in range(5)'], 'E690:') 2396 CheckDefFailure(['for i In range(5)'], 'E690:') 2397 CheckDefFailure(['var x = 5', 'for x in range(5)'], 'E1017:') 2398 CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:') 2399 delfunc! g:Func 2400 CheckDefFailure(['for i in xxx'], 'E1001:') 2401 CheckDefFailure(['endfor'], 'E588:') 2402 CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:') 2403 2404 # wrong type detected at compile time 2405 CheckDefFailure(['for i in {a: 1}', 'echo 3', 'endfor'], 'E1177: For loop on dict not supported') 2406 2407 # wrong type detected at runtime 2408 g:adict = {a: 1} 2409 CheckDefExecFailure(['for i in g:adict', 'echo 3', 'endfor'], 'E1177: For loop on dict not supported') 2410 unlet g:adict 2411 2412 var lines =<< trim END 2413 var d: list<dict<any>> = [{a: 0}] 2414 for e in d 2415 e = {a: 0, b: ''} 2416 endfor 2417 END 2418 CheckDefAndScriptFailure2(lines, 'E1018:', 'E46:', 3) 2419 2420 lines =<< trim END 2421 for nr: number in ['foo'] 2422 endfor 2423 END 2424 CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got string', 1) 2425enddef 2426 2427def Test_for_loop_script_var() 2428 # cannot use s:var in a :def function 2429 CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E1101:') 2430 2431 # can use s:var in Vim9 script, with or without s: 2432 var lines =<< trim END 2433 vim9script 2434 var total = 0 2435 for s:var in [1, 2, 3] 2436 total += s:var 2437 endfor 2438 assert_equal(6, total) 2439 2440 total = 0 2441 for var in [1, 2, 3] 2442 total += var 2443 endfor 2444 assert_equal(6, total) 2445 END 2446enddef 2447 2448def Test_for_loop_unpack() 2449 var lines =<< trim END 2450 var result = [] 2451 for [v1, v2] in [[1, 2], [3, 4]] 2452 result->add(v1) 2453 result->add(v2) 2454 endfor 2455 assert_equal([1, 2, 3, 4], result) 2456 2457 result = [] 2458 for [v1, v2; v3] in [[1, 2], [3, 4, 5, 6]] 2459 result->add(v1) 2460 result->add(v2) 2461 result->add(v3) 2462 endfor 2463 assert_equal([1, 2, [], 3, 4, [5, 6]], result) 2464 2465 result = [] 2466 for [&ts, &sw] in [[1, 2], [3, 4]] 2467 result->add(&ts) 2468 result->add(&sw) 2469 endfor 2470 assert_equal([1, 2, 3, 4], result) 2471 2472 var slist: list<string> 2473 for [$LOOPVAR, @r, v:errmsg] in [['a', 'b', 'c'], ['d', 'e', 'f']] 2474 slist->add($LOOPVAR) 2475 slist->add(@r) 2476 slist->add(v:errmsg) 2477 endfor 2478 assert_equal(['a', 'b', 'c', 'd', 'e', 'f'], slist) 2479 2480 slist = [] 2481 for [g:globalvar, b:bufvar, w:winvar, t:tabvar] in [['global', 'buf', 'win', 'tab'], ['1', '2', '3', '4']] 2482 slist->add(g:globalvar) 2483 slist->add(b:bufvar) 2484 slist->add(w:winvar) 2485 slist->add(t:tabvar) 2486 endfor 2487 assert_equal(['global', 'buf', 'win', 'tab', '1', '2', '3', '4'], slist) 2488 unlet! g:globalvar b:bufvar w:winvar t:tabvar 2489 END 2490 CheckDefAndScriptSuccess(lines) 2491 2492 lines =<< trim END 2493 for [v1, v2] in [[1, 2, 3], [3, 4]] 2494 echo v1 v2 2495 endfor 2496 END 2497 CheckDefExecFailure(lines, 'E710:', 1) 2498 2499 lines =<< trim END 2500 for [v1, v2] in [[1], [3, 4]] 2501 echo v1 v2 2502 endfor 2503 END 2504 CheckDefExecFailure(lines, 'E711:', 1) 2505 2506 lines =<< trim END 2507 for [v1, v1] in [[1, 2], [3, 4]] 2508 echo v1 2509 endfor 2510 END 2511 CheckDefExecFailure(lines, 'E1017:', 1) 2512enddef 2513 2514def Test_for_loop_with_try_continue() 2515 var lines =<< trim END 2516 var looped = 0 2517 var cleanup = 0 2518 for i in range(3) 2519 looped += 1 2520 try 2521 eval [][0] 2522 catch 2523 continue 2524 finally 2525 cleanup += 1 2526 endtry 2527 endfor 2528 assert_equal(3, looped) 2529 assert_equal(3, cleanup) 2530 END 2531 CheckDefAndScriptSuccess(lines) 2532enddef 2533 2534def Test_while_loop() 2535 var result = '' 2536 var cnt = 0 2537 while cnt < 555 2538 if cnt == 3 2539 break 2540 endif 2541 cnt += 1 2542 if cnt == 2 2543 continue 2544 endif 2545 result ..= cnt .. '_' 2546 endwhile 2547 assert_equal('1_3_', result) 2548 2549 var s = '' 2550 while s == 'x' # {comment} 2551 endwhile 2552enddef 2553 2554def Test_while_loop_fails() 2555 CheckDefFailure(['while xxx'], 'E1001:') 2556 CheckDefFailure(['endwhile'], 'E588:') 2557 CheckDefFailure(['continue'], 'E586:') 2558 CheckDefFailure(['if true', 'continue'], 'E586:') 2559 CheckDefFailure(['break'], 'E587:') 2560 CheckDefFailure(['if true', 'break'], 'E587:') 2561 CheckDefFailure(['while 1', 'echo 3'], 'E170:') 2562 2563 var lines =<< trim END 2564 var s = '' 2565 while s = '' 2566 endwhile 2567 END 2568 CheckDefFailure(lines, 'E488:') 2569enddef 2570 2571def Test_interrupt_loop() 2572 var caught = false 2573 var x = 0 2574 try 2575 while 1 2576 x += 1 2577 if x == 100 2578 feedkeys("\<C-C>", 'Lt') 2579 endif 2580 endwhile 2581 catch 2582 caught = true 2583 assert_equal(100, x) 2584 endtry 2585 assert_true(caught, 'should have caught an exception') 2586 # consume the CTRL-C 2587 getchar(0) 2588enddef 2589 2590def Test_automatic_line_continuation() 2591 var mylist = [ 2592 'one', 2593 'two', 2594 'three', 2595 ] # comment 2596 assert_equal(['one', 'two', 'three'], mylist) 2597 2598 var mydict = { 2599 ['one']: 1, 2600 ['two']: 2, 2601 ['three']: 2602 3, 2603 } # comment 2604 assert_equal({one: 1, two: 2, three: 3}, mydict) 2605 mydict = { 2606 one: 1, # comment 2607 two: # comment 2608 2, # comment 2609 three: 3 # comment 2610 } 2611 assert_equal({one: 1, two: 2, three: 3}, mydict) 2612 mydict = { 2613 one: 1, 2614 two: 2615 2, 2616 three: 3 2617 } 2618 assert_equal({one: 1, two: 2, three: 3}, mydict) 2619 2620 assert_equal( 2621 ['one', 'two', 'three'], 2622 split('one two three') 2623 ) 2624enddef 2625 2626def Test_vim9_comment() 2627 CheckScriptSuccess([ 2628 'vim9script', 2629 '# something', 2630 '#something', 2631 '#{something', 2632 ]) 2633 2634 split Xfile 2635 CheckScriptSuccess([ 2636 'vim9script', 2637 'edit #something', 2638 ]) 2639 CheckScriptSuccess([ 2640 'vim9script', 2641 'edit #{something', 2642 ]) 2643 close 2644 2645 CheckScriptFailure([ 2646 'vim9script', 2647 ':# something', 2648 ], 'E488:') 2649 CheckScriptFailure([ 2650 '# something', 2651 ], 'E488:') 2652 CheckScriptFailure([ 2653 ':# something', 2654 ], 'E488:') 2655 2656 { # block start 2657 } # block end 2658 CheckDefFailure([ 2659 '{# comment', 2660 ], 'E488:') 2661 CheckDefFailure([ 2662 '{', 2663 '}# comment', 2664 ], 'E488:') 2665 2666 echo "yes" # comment 2667 CheckDefFailure([ 2668 'echo "yes"# comment', 2669 ], 'E488:') 2670 CheckScriptSuccess([ 2671 'vim9script', 2672 'echo "yes" # something', 2673 ]) 2674 CheckScriptFailure([ 2675 'vim9script', 2676 'echo "yes"# something', 2677 ], 'E121:') 2678 CheckScriptFailure([ 2679 'vim9script', 2680 'echo# something', 2681 ], 'E1144:') 2682 CheckScriptFailure([ 2683 'echo "yes" # something', 2684 ], 'E121:') 2685 2686 exe "echo" # comment 2687 CheckDefFailure([ 2688 'exe "echo"# comment', 2689 ], 'E488:') 2690 CheckScriptSuccess([ 2691 'vim9script', 2692 'exe "echo" # something', 2693 ]) 2694 CheckScriptFailure([ 2695 'vim9script', 2696 'exe "echo"# something', 2697 ], 'E121:') 2698 CheckScriptFailure([ 2699 'vim9script', 2700 'exe# something', 2701 ], 'E1144:') 2702 CheckScriptFailure([ 2703 'exe "echo" # something', 2704 ], 'E121:') 2705 2706 CheckDefFailure([ 2707 'try# comment', 2708 ' echo "yes"', 2709 'catch', 2710 'endtry', 2711 ], 'E1144:') 2712 CheckScriptFailure([ 2713 'vim9script', 2714 'try# comment', 2715 'echo "yes"', 2716 ], 'E1144:') 2717 CheckDefFailure([ 2718 'try', 2719 ' throw#comment', 2720 'catch', 2721 'endtry', 2722 ], 'E1144:') 2723 CheckDefFailure([ 2724 'try', 2725 ' throw "yes"#comment', 2726 'catch', 2727 'endtry', 2728 ], 'E488:') 2729 CheckDefFailure([ 2730 'try', 2731 ' echo "yes"', 2732 'catch# comment', 2733 'endtry', 2734 ], 'E1144:') 2735 CheckScriptFailure([ 2736 'vim9script', 2737 'try', 2738 ' echo "yes"', 2739 'catch# comment', 2740 'endtry', 2741 ], 'E1144:') 2742 CheckDefFailure([ 2743 'try', 2744 ' echo "yes"', 2745 'catch /pat/# comment', 2746 'endtry', 2747 ], 'E488:') 2748 CheckDefFailure([ 2749 'try', 2750 'echo "yes"', 2751 'catch', 2752 'endtry# comment', 2753 ], 'E1144:') 2754 CheckScriptFailure([ 2755 'vim9script', 2756 'try', 2757 ' echo "yes"', 2758 'catch', 2759 'endtry# comment', 2760 ], 'E1144:') 2761 2762 CheckScriptSuccess([ 2763 'vim9script', 2764 'hi # comment', 2765 ]) 2766 CheckScriptFailure([ 2767 'vim9script', 2768 'hi# comment', 2769 ], 'E1144:') 2770 CheckScriptSuccess([ 2771 'vim9script', 2772 'hi Search # comment', 2773 ]) 2774 CheckScriptFailure([ 2775 'vim9script', 2776 'hi Search# comment', 2777 ], 'E416:') 2778 CheckScriptSuccess([ 2779 'vim9script', 2780 'hi link This Search # comment', 2781 ]) 2782 CheckScriptFailure([ 2783 'vim9script', 2784 'hi link This That# comment', 2785 ], 'E413:') 2786 CheckScriptSuccess([ 2787 'vim9script', 2788 'hi clear This # comment', 2789 'hi clear # comment', 2790 ]) 2791 # not tested, because it doesn't give an error but a warning: 2792 # hi clear This# comment', 2793 CheckScriptFailure([ 2794 'vim9script', 2795 'hi clear# comment', 2796 ], 'E416:') 2797 2798 CheckScriptSuccess([ 2799 'vim9script', 2800 'hi Group term=bold', 2801 'match Group /todo/ # comment', 2802 ]) 2803 CheckScriptFailure([ 2804 'vim9script', 2805 'hi Group term=bold', 2806 'match Group /todo/# comment', 2807 ], 'E488:') 2808 CheckScriptSuccess([ 2809 'vim9script', 2810 'match # comment', 2811 ]) 2812 CheckScriptFailure([ 2813 'vim9script', 2814 'match# comment', 2815 ], 'E1144:') 2816 CheckScriptSuccess([ 2817 'vim9script', 2818 'match none # comment', 2819 ]) 2820 CheckScriptFailure([ 2821 'vim9script', 2822 'match none# comment', 2823 ], 'E475:') 2824 2825 CheckScriptSuccess([ 2826 'vim9script', 2827 'menutrans clear # comment', 2828 ]) 2829 CheckScriptFailure([ 2830 'vim9script', 2831 'menutrans clear# comment text', 2832 ], 'E474:') 2833 2834 CheckScriptSuccess([ 2835 'vim9script', 2836 'syntax clear # comment', 2837 ]) 2838 CheckScriptFailure([ 2839 'vim9script', 2840 'syntax clear# comment text', 2841 ], 'E28:') 2842 CheckScriptSuccess([ 2843 'vim9script', 2844 'syntax keyword Word some', 2845 'syntax clear Word # comment', 2846 ]) 2847 CheckScriptFailure([ 2848 'vim9script', 2849 'syntax keyword Word some', 2850 'syntax clear Word# comment text', 2851 ], 'E28:') 2852 2853 CheckScriptSuccess([ 2854 'vim9script', 2855 'syntax list # comment', 2856 ]) 2857 CheckScriptFailure([ 2858 'vim9script', 2859 'syntax list# comment text', 2860 ], 'E28:') 2861 2862 CheckScriptSuccess([ 2863 'vim9script', 2864 'syntax match Word /pat/ oneline # comment', 2865 ]) 2866 CheckScriptFailure([ 2867 'vim9script', 2868 'syntax match Word /pat/ oneline# comment', 2869 ], 'E475:') 2870 2871 CheckScriptSuccess([ 2872 'vim9script', 2873 'syntax keyword Word word # comm[ent', 2874 ]) 2875 CheckScriptFailure([ 2876 'vim9script', 2877 'syntax keyword Word word# comm[ent', 2878 ], 'E789:') 2879 2880 CheckScriptSuccess([ 2881 'vim9script', 2882 'syntax match Word /pat/ # comment', 2883 ]) 2884 CheckScriptFailure([ 2885 'vim9script', 2886 'syntax match Word /pat/# comment', 2887 ], 'E402:') 2888 2889 CheckScriptSuccess([ 2890 'vim9script', 2891 'syntax match Word /pat/ contains=Something # comment', 2892 ]) 2893 CheckScriptFailure([ 2894 'vim9script', 2895 'syntax match Word /pat/ contains=Something# comment', 2896 ], 'E475:') 2897 CheckScriptFailure([ 2898 'vim9script', 2899 'syntax match Word /pat/ contains= # comment', 2900 ], 'E406:') 2901 CheckScriptFailure([ 2902 'vim9script', 2903 'syntax match Word /pat/ contains=# comment', 2904 ], 'E475:') 2905 2906 CheckScriptSuccess([ 2907 'vim9script', 2908 'syntax region Word start=/pat/ end=/pat/ # comment', 2909 ]) 2910 CheckScriptFailure([ 2911 'vim9script', 2912 'syntax region Word start=/pat/ end=/pat/# comment', 2913 ], 'E402:') 2914 2915 CheckScriptSuccess([ 2916 'vim9script', 2917 'syntax sync # comment', 2918 ]) 2919 CheckScriptFailure([ 2920 'vim9script', 2921 'syntax sync# comment', 2922 ], 'E404:') 2923 CheckScriptSuccess([ 2924 'vim9script', 2925 'syntax sync ccomment # comment', 2926 ]) 2927 CheckScriptFailure([ 2928 'vim9script', 2929 'syntax sync ccomment# comment', 2930 ], 'E404:') 2931 2932 CheckScriptSuccess([ 2933 'vim9script', 2934 'syntax cluster Some contains=Word # comment', 2935 ]) 2936 CheckScriptFailure([ 2937 'vim9script', 2938 'syntax cluster Some contains=Word# comment', 2939 ], 'E475:') 2940 2941 CheckScriptSuccess([ 2942 'vim9script', 2943 'command Echo echo # comment', 2944 'command Echo # comment', 2945 'delcommand Echo', 2946 ]) 2947 CheckScriptFailure([ 2948 'vim9script', 2949 'command Echo echo# comment', 2950 'Echo', 2951 ], 'E1144:') 2952 delcommand Echo 2953 2954 var curdir = getcwd() 2955 CheckScriptSuccess([ 2956 'command Echo cd " comment', 2957 'Echo', 2958 'delcommand Echo', 2959 ]) 2960 CheckScriptSuccess([ 2961 'vim9script', 2962 'command Echo cd # comment', 2963 'Echo', 2964 'delcommand Echo', 2965 ]) 2966 CheckScriptFailure([ 2967 'vim9script', 2968 'command Echo cd " comment', 2969 'Echo', 2970 ], 'E344:') 2971 delcommand Echo 2972 chdir(curdir) 2973 2974 CheckScriptFailure([ 2975 'vim9script', 2976 'command Echo# comment', 2977 ], 'E182:') 2978 CheckScriptFailure([ 2979 'vim9script', 2980 'command Echo echo', 2981 'command Echo# comment', 2982 ], 'E182:') 2983 delcommand Echo 2984 2985 CheckScriptSuccess([ 2986 'vim9script', 2987 'function # comment', 2988 ]) 2989 CheckScriptFailure([ 2990 'vim9script', 2991 'function " comment', 2992 ], 'E129:') 2993 CheckScriptFailure([ 2994 'vim9script', 2995 'function# comment', 2996 ], 'E1144:') 2997 CheckScriptSuccess([ 2998 'vim9script', 2999 'function CheckScriptSuccess # comment', 3000 ]) 3001 CheckScriptFailure([ 3002 'vim9script', 3003 'function CheckScriptSuccess# comment', 3004 ], 'E488:') 3005 3006 CheckScriptSuccess([ 3007 'vim9script', 3008 'func g:DeleteMeA()', 3009 'endfunc', 3010 'delfunction g:DeleteMeA # comment', 3011 ]) 3012 CheckScriptFailure([ 3013 'vim9script', 3014 'func g:DeleteMeB()', 3015 'endfunc', 3016 'delfunction g:DeleteMeB# comment', 3017 ], 'E488:') 3018 3019 CheckScriptSuccess([ 3020 'vim9script', 3021 'call execute("ls") # comment', 3022 ]) 3023 CheckScriptFailure([ 3024 'vim9script', 3025 'call execute("ls")# comment', 3026 ], 'E488:') 3027 3028 CheckScriptFailure([ 3029 'def Test() " comment', 3030 'enddef', 3031 ], 'E488:') 3032 CheckScriptFailure([ 3033 'vim9script', 3034 'def Test() " comment', 3035 'enddef', 3036 ], 'E488:') 3037 3038 CheckScriptSuccess([ 3039 'func Test() " comment', 3040 'endfunc', 3041 'delfunc Test', 3042 ]) 3043 CheckScriptSuccess([ 3044 'vim9script', 3045 'func Test() " comment', 3046 'endfunc', 3047 ]) 3048 3049 CheckScriptSuccess([ 3050 'def Test() # comment', 3051 'enddef', 3052 ]) 3053 CheckScriptFailure([ 3054 'func Test() # comment', 3055 'endfunc', 3056 ], 'E488:') 3057enddef 3058 3059def Test_vim9_comment_gui() 3060 CheckCanRunGui 3061 3062 CheckScriptFailure([ 3063 'vim9script', 3064 'gui#comment' 3065 ], 'E1144:') 3066 CheckScriptFailure([ 3067 'vim9script', 3068 'gui -f#comment' 3069 ], 'E499:') 3070enddef 3071 3072def Test_vim9_comment_not_compiled() 3073 au TabEnter *.vim g:entered = 1 3074 au TabEnter *.x g:entered = 2 3075 3076 edit test.vim 3077 doautocmd TabEnter #comment 3078 assert_equal(1, g:entered) 3079 3080 doautocmd TabEnter f.x 3081 assert_equal(2, g:entered) 3082 3083 g:entered = 0 3084 doautocmd TabEnter f.x #comment 3085 assert_equal(2, g:entered) 3086 3087 assert_fails('doautocmd Syntax#comment', 'E216:') 3088 3089 au! TabEnter 3090 unlet g:entered 3091 3092 CheckScriptSuccess([ 3093 'vim9script', 3094 'g:var = 123', 3095 'b:var = 456', 3096 'w:var = 777', 3097 't:var = 888', 3098 'unlet g:var w:var # something', 3099 ]) 3100 3101 CheckScriptFailure([ 3102 'vim9script', 3103 'let var = 123', 3104 ], 'E1126: Cannot use :let in Vim9 script') 3105 3106 CheckScriptFailure([ 3107 'vim9script', 3108 'var g:var = 123', 3109 ], 'E1016: Cannot declare a global variable:') 3110 3111 CheckScriptFailure([ 3112 'vim9script', 3113 'var b:var = 123', 3114 ], 'E1016: Cannot declare a buffer variable:') 3115 3116 CheckScriptFailure([ 3117 'vim9script', 3118 'var w:var = 123', 3119 ], 'E1016: Cannot declare a window variable:') 3120 3121 CheckScriptFailure([ 3122 'vim9script', 3123 'var t:var = 123', 3124 ], 'E1016: Cannot declare a tab variable:') 3125 3126 CheckScriptFailure([ 3127 'vim9script', 3128 'var v:version = 123', 3129 ], 'E1016: Cannot declare a v: variable:') 3130 3131 CheckScriptFailure([ 3132 'vim9script', 3133 'var $VARIABLE = "text"', 3134 ], 'E1016: Cannot declare an environment variable:') 3135 3136 CheckScriptFailure([ 3137 'vim9script', 3138 'g:var = 123', 3139 'unlet g:var# comment1', 3140 ], 'E108:') 3141 3142 CheckScriptFailure([ 3143 'let g:var = 123', 3144 'unlet g:var # something', 3145 ], 'E488:') 3146 3147 CheckScriptSuccess([ 3148 'vim9script', 3149 'if 1 # comment2', 3150 ' echo "yes"', 3151 'elseif 2 #comment', 3152 ' echo "no"', 3153 'endif', 3154 ]) 3155 3156 CheckScriptFailure([ 3157 'vim9script', 3158 'if 1# comment3', 3159 ' echo "yes"', 3160 'endif', 3161 ], 'E15:') 3162 3163 CheckScriptFailure([ 3164 'vim9script', 3165 'if 0 # comment4', 3166 ' echo "yes"', 3167 'elseif 2#comment', 3168 ' echo "no"', 3169 'endif', 3170 ], 'E15:') 3171 3172 CheckScriptSuccess([ 3173 'vim9script', 3174 'var v = 1 # comment5', 3175 ]) 3176 3177 CheckScriptFailure([ 3178 'vim9script', 3179 'var v = 1# comment6', 3180 ], 'E15:') 3181 3182 CheckScriptSuccess([ 3183 'vim9script', 3184 'new' 3185 'setline(1, ["# define pat", "last"])', 3186 ':$', 3187 'dsearch /pat/ #comment', 3188 'bwipe!', 3189 ]) 3190 3191 CheckScriptFailure([ 3192 'vim9script', 3193 'new' 3194 'setline(1, ["# define pat", "last"])', 3195 ':$', 3196 'dsearch /pat/#comment', 3197 'bwipe!', 3198 ], 'E488:') 3199 3200 CheckScriptFailure([ 3201 'vim9script', 3202 'func! SomeFunc()', 3203 ], 'E477:') 3204enddef 3205 3206def Test_finish() 3207 var lines =<< trim END 3208 vim9script 3209 g:res = 'one' 3210 if v:false | finish | endif 3211 g:res = 'two' 3212 finish 3213 g:res = 'three' 3214 END 3215 writefile(lines, 'Xfinished') 3216 source Xfinished 3217 assert_equal('two', g:res) 3218 3219 unlet g:res 3220 delete('Xfinished') 3221enddef 3222 3223def Test_forward_declaration() 3224 var lines =<< trim END 3225 vim9script 3226 def GetValue(): string 3227 return theVal 3228 enddef 3229 var theVal = 'something' 3230 g:initVal = GetValue() 3231 theVal = 'else' 3232 g:laterVal = GetValue() 3233 END 3234 writefile(lines, 'Xforward') 3235 source Xforward 3236 assert_equal('something', g:initVal) 3237 assert_equal('else', g:laterVal) 3238 3239 unlet g:initVal 3240 unlet g:laterVal 3241 delete('Xforward') 3242enddef 3243 3244def Test_source_vim9_from_legacy() 3245 var vim9_lines =<< trim END 3246 vim9script 3247 var local = 'local' 3248 g:global = 'global' 3249 export var exported = 'exported' 3250 export def GetText(): string 3251 return 'text' 3252 enddef 3253 END 3254 writefile(vim9_lines, 'Xvim9_script.vim') 3255 3256 var legacy_lines =<< trim END 3257 source Xvim9_script.vim 3258 3259 call assert_false(exists('local')) 3260 call assert_false(exists('exported')) 3261 call assert_false(exists('s:exported')) 3262 call assert_equal('global', global) 3263 call assert_equal('global', g:global) 3264 3265 " imported variable becomes script-local 3266 import exported from './Xvim9_script.vim' 3267 call assert_equal('exported', s:exported) 3268 call assert_false(exists('exported')) 3269 3270 " imported function becomes script-local 3271 import GetText from './Xvim9_script.vim' 3272 call assert_equal('text', s:GetText()) 3273 call assert_false(exists('*GetText')) 3274 END 3275 writefile(legacy_lines, 'Xlegacy_script.vim') 3276 3277 source Xlegacy_script.vim 3278 assert_equal('global', g:global) 3279 unlet g:global 3280 3281 delete('Xlegacy_script.vim') 3282 delete('Xvim9_script.vim') 3283enddef 3284 3285def Test_declare_script_in_func() 3286 var lines =<< trim END 3287 vim9script 3288 func Declare() 3289 let s:local = 123 3290 endfunc 3291 Declare() 3292 assert_equal(123, local) 3293 3294 var error: string 3295 try 3296 local = 'asdf' 3297 catch 3298 error = v:exception 3299 endtry 3300 assert_match('E1012: Type mismatch; expected number but got string', error) 3301 3302 lockvar local 3303 try 3304 local = 999 3305 catch 3306 error = v:exception 3307 endtry 3308 assert_match('E741: Value is locked: local', error) 3309 END 3310 CheckScriptSuccess(lines) 3311enddef 3312 3313 3314func Test_vim9script_not_global() 3315 " check that items defined in Vim9 script are script-local, not global 3316 let vim9lines =<< trim END 3317 vim9script 3318 var name = 'local' 3319 func TheFunc() 3320 echo 'local' 3321 endfunc 3322 def DefFunc() 3323 echo 'local' 3324 enddef 3325 END 3326 call writefile(vim9lines, 'Xvim9script.vim') 3327 source Xvim9script.vim 3328 try 3329 echo g:var 3330 assert_report('did not fail') 3331 catch /E121:/ 3332 " caught 3333 endtry 3334 try 3335 call TheFunc() 3336 assert_report('did not fail') 3337 catch /E117:/ 3338 " caught 3339 endtry 3340 try 3341 call DefFunc() 3342 assert_report('did not fail') 3343 catch /E117:/ 3344 " caught 3345 endtry 3346 3347 call delete('Xvim9script.vim') 3348endfunc 3349 3350def Test_vim9_copen() 3351 # this was giving an error for setting w:quickfix_title 3352 copen 3353 quit 3354enddef 3355 3356" test using an auto-loaded function and variable 3357def Test_vim9_autoload() 3358 var lines =<< trim END 3359 vim9script 3360 def some#gettest(): string 3361 return 'test' 3362 enddef 3363 g:some#name = 'name' 3364 3365 def some#varargs(a1: string, ...l: list<string>): string 3366 return a1 .. l[0] .. l[1] 3367 enddef 3368 END 3369 3370 mkdir('Xdir/autoload', 'p') 3371 writefile(lines, 'Xdir/autoload/some.vim') 3372 var save_rtp = &rtp 3373 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3374 3375 assert_equal('test', g:some#gettest()) 3376 assert_equal('name', g:some#name) 3377 g:some#other = 'other' 3378 assert_equal('other', g:some#other) 3379 3380 assert_equal('abc', some#varargs('a', 'b', 'c')) 3381 3382 # upper case script name works 3383 lines =<< trim END 3384 vim9script 3385 def Other#getOther(): string 3386 return 'other' 3387 enddef 3388 END 3389 writefile(lines, 'Xdir/autoload/Other.vim') 3390 assert_equal('other', g:Other#getOther()) 3391 3392 delete('Xdir', 'rf') 3393 &rtp = save_rtp 3394enddef 3395 3396" test using a vim9script that is auto-loaded from an autocmd 3397def Test_vim9_aucmd_autoload() 3398 var lines =<< trim END 3399 vim9script 3400 def foo#test() 3401 echomsg getreg('"') 3402 enddef 3403 END 3404 3405 mkdir('Xdir/autoload', 'p') 3406 writefile(lines, 'Xdir/autoload/foo.vim') 3407 var save_rtp = &rtp 3408 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3409 augroup test 3410 autocmd TextYankPost * call foo#test() 3411 augroup END 3412 3413 normal Y 3414 3415 augroup test 3416 autocmd! 3417 augroup END 3418 delete('Xdir', 'rf') 3419 &rtp = save_rtp 3420enddef 3421 3422" This was causing a crash because suppress_errthrow wasn't reset. 3423def Test_vim9_autoload_error() 3424 var lines =<< trim END 3425 vim9script 3426 def crash#func() 3427 try 3428 for x in List() 3429 endfor 3430 catch 3431 endtry 3432 g:ok = true 3433 enddef 3434 fu List() 3435 invalid 3436 endfu 3437 try 3438 alsoinvalid 3439 catch /wontmatch/ 3440 endtry 3441 END 3442 call mkdir('Xruntime/autoload', 'p') 3443 call writefile(lines, 'Xruntime/autoload/crash.vim') 3444 3445 # run in a separate Vim to avoid the side effects of assert_fails() 3446 lines =<< trim END 3447 exe 'set rtp^=' .. getcwd() .. '/Xruntime' 3448 call crash#func() 3449 call writefile(['ok'], 'Xdidit') 3450 qall! 3451 END 3452 writefile(lines, 'Xscript') 3453 RunVim([], [], '-S Xscript') 3454 assert_equal(['ok'], readfile('Xdidit')) 3455 3456 delete('Xdidit') 3457 delete('Xscript') 3458 delete('Xruntime', 'rf') 3459 3460 lines =<< trim END 3461 vim9script 3462 var foo#bar = 'asdf' 3463 END 3464 CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2) 3465enddef 3466 3467def Test_script_var_in_autocmd() 3468 # using a script variable from an autocommand, defined in a :def function in a 3469 # legacy Vim script, cannot check the variable type. 3470 var lines =<< trim END 3471 let s:counter = 1 3472 def s:Func() 3473 au! CursorHold 3474 au CursorHold * s:counter += 1 3475 enddef 3476 call s:Func() 3477 doau CursorHold 3478 call assert_equal(2, s:counter) 3479 au! CursorHold 3480 END 3481 CheckScriptSuccess(lines) 3482enddef 3483 3484def Test_cmdline_win() 3485 # if the Vim syntax highlighting uses Vim9 constructs they can be used from 3486 # the command line window. 3487 mkdir('rtp/syntax', 'p') 3488 var export_lines =<< trim END 3489 vim9script 3490 export var That = 'yes' 3491 END 3492 writefile(export_lines, 'rtp/syntax/Xexport.vim') 3493 var import_lines =<< trim END 3494 vim9script 3495 import That from './Xexport.vim' 3496 END 3497 writefile(import_lines, 'rtp/syntax/vim.vim') 3498 var save_rtp = &rtp 3499 &rtp = getcwd() .. '/rtp' .. ',' .. &rtp 3500 syntax on 3501 augroup CmdWin 3502 autocmd CmdwinEnter * g:got_there = 'yes' 3503 augroup END 3504 # this will open and also close the cmdline window 3505 feedkeys('q:', 'xt') 3506 assert_equal('yes', g:got_there) 3507 3508 augroup CmdWin 3509 au! 3510 augroup END 3511 &rtp = save_rtp 3512 delete('rtp', 'rf') 3513enddef 3514 3515def Test_invalid_sid() 3516 assert_fails('func <SNR>1234_func', 'E123:') 3517 3518 if RunVim([], ['wq! Xdidit'], '+"func <SNR>1_func"') 3519 assert_equal([], readfile('Xdidit')) 3520 endif 3521 delete('Xdidit') 3522enddef 3523 3524def Test_restoring_cpo() 3525 writefile(['vim9script', 'set nocp'], 'Xsourced') 3526 writefile(['call writefile(["done"], "Xdone")', 'quit!'], 'Xclose') 3527 if RunVim([], [], '-u NONE +"set cpo+=a" -S Xsourced -S Xclose') 3528 assert_equal(['done'], readfile('Xdone')) 3529 endif 3530 delete('Xsourced') 3531 delete('Xclose') 3532 delete('Xdone') 3533 3534 writefile(['vim9script'], 'XanotherScript') 3535 set cpo=aABceFsMny> 3536 edit XanotherScript 3537 so % 3538 assert_equal('aABceFsMny>', &cpo) 3539 :1del 3540 w 3541 so % 3542 assert_equal('aABceFsMny>', &cpo) 3543 3544 delete('XanotherScript') 3545 set cpo&vim 3546enddef 3547 3548" Use :function so we can use Check commands 3549func Test_no_redraw_when_restoring_cpo() 3550 CheckScreendump 3551 CheckFeature timers 3552 3553 let lines =<< trim END 3554 vim9script 3555 def script#func() 3556 enddef 3557 END 3558 call mkdir('Xdir/autoload', 'p') 3559 call writefile(lines, 'Xdir/autoload/script.vim') 3560 3561 let lines =<< trim END 3562 vim9script 3563 set cpo+=M 3564 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3565 au CmdlineEnter : ++once timer_start(0, (_) => script#func()) 3566 setline(1, 'some text') 3567 END 3568 call writefile(lines, 'XTest_redraw_cpo') 3569 let buf = RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6}) 3570 call term_sendkeys(buf, "V:") 3571 call VerifyScreenDump(buf, 'Test_vim9_no_redraw', {}) 3572 3573 " clean up 3574 call term_sendkeys(buf, "\<Esc>u") 3575 call StopVimInTerminal(buf) 3576 call delete('XTest_redraw_cpo') 3577 call delete('Xdir', 'rf') 3578endfunc 3579 3580 3581def Test_unset_any_variable() 3582 var lines =<< trim END 3583 var name: any 3584 assert_equal(0, name) 3585 END 3586 CheckDefAndScriptSuccess(lines) 3587enddef 3588 3589func Test_define_func_at_command_line() 3590 CheckRunVimInTerminal 3591 3592 " call indirectly to avoid compilation error for missing functions 3593 call Run_Test_define_func_at_command_line() 3594endfunc 3595 3596def Run_Test_define_func_at_command_line() 3597 # run in a separate Vim instance to avoid the script context 3598 var lines =<< trim END 3599 func CheckAndQuit() 3600 call assert_fails('call Afunc()', 'E117: Unknown function: Bfunc') 3601 call writefile(['errors: ' .. string(v:errors)], 'Xdidcmd') 3602 endfunc 3603 END 3604 writefile([''], 'Xdidcmd') 3605 writefile(lines, 'XcallFunc') 3606 var buf = RunVimInTerminal('-S XcallFunc', {rows: 6}) 3607 # define Afunc() on the command line 3608 term_sendkeys(buf, ":def Afunc()\<CR>Bfunc()\<CR>enddef\<CR>") 3609 term_sendkeys(buf, ":call CheckAndQuit()\<CR>") 3610 WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd'))) 3611 3612 call StopVimInTerminal(buf) 3613 delete('XcallFunc') 3614 delete('Xdidcmd') 3615enddef 3616 3617def Test_script_var_scope() 3618 var lines =<< trim END 3619 vim9script 3620 if true 3621 if true 3622 var one = 'one' 3623 echo one 3624 endif 3625 echo one 3626 endif 3627 END 3628 CheckScriptFailure(lines, 'E121:', 7) 3629 3630 lines =<< trim END 3631 vim9script 3632 if true 3633 if false 3634 var one = 'one' 3635 echo one 3636 else 3637 var one = 'one' 3638 echo one 3639 endif 3640 echo one 3641 endif 3642 END 3643 CheckScriptFailure(lines, 'E121:', 10) 3644 3645 lines =<< trim END 3646 vim9script 3647 while true 3648 var one = 'one' 3649 echo one 3650 break 3651 endwhile 3652 echo one 3653 END 3654 CheckScriptFailure(lines, 'E121:', 7) 3655 3656 lines =<< trim END 3657 vim9script 3658 for i in range(1) 3659 var one = 'one' 3660 echo one 3661 endfor 3662 echo one 3663 END 3664 CheckScriptFailure(lines, 'E121:', 6) 3665 3666 lines =<< trim END 3667 vim9script 3668 { 3669 var one = 'one' 3670 assert_equal('one', one) 3671 } 3672 assert_false(exists('one')) 3673 assert_false(exists('s:one')) 3674 END 3675 CheckScriptSuccess(lines) 3676 3677 lines =<< trim END 3678 vim9script 3679 { 3680 var one = 'one' 3681 echo one 3682 } 3683 echo one 3684 END 3685 CheckScriptFailure(lines, 'E121:', 6) 3686enddef 3687 3688def Test_catch_exception_in_callback() 3689 var lines =<< trim END 3690 vim9script 3691 def Callback(...l: list<any>) 3692 try 3693 var x: string 3694 var y: string 3695 # this error should be caught with CHECKLEN 3696 [x, y] = [''] 3697 catch 3698 g:caught = 'yes' 3699 endtry 3700 enddef 3701 popup_menu('popup', {callback: Callback}) 3702 feedkeys("\r", 'xt') 3703 END 3704 CheckScriptSuccess(lines) 3705 3706 unlet g:caught 3707enddef 3708 3709def Test_no_unknown_error_after_error() 3710 if !has('unix') || !has('job') 3711 throw 'Skipped: not unix of missing +job feature' 3712 endif 3713 var lines =<< trim END 3714 vim9script 3715 var source: list<number> 3716 def Out_cb(...l: list<any>) 3717 eval [][0] 3718 enddef 3719 def Exit_cb(...l: list<any>) 3720 sleep 1m 3721 source += l 3722 enddef 3723 var myjob = job_start('echo burp', {out_cb: Out_cb, exit_cb: Exit_cb, mode: 'raw'}) 3724 while job_status(myjob) == 'run' 3725 sleep 10m 3726 endwhile 3727 # wait for Exit_cb() to be called 3728 sleep 200m 3729 END 3730 writefile(lines, 'Xdef') 3731 assert_fails('so Xdef', ['E684:', 'E1012:']) 3732 delete('Xdef') 3733enddef 3734 3735def InvokeNormal() 3736 exe "norm! :m+1\r" 3737enddef 3738 3739def Test_invoke_normal_in_visual_mode() 3740 xnoremap <F3> <Cmd>call <SID>InvokeNormal()<CR> 3741 new 3742 setline(1, ['aaa', 'bbb']) 3743 feedkeys("V\<F3>", 'xt') 3744 assert_equal(['bbb', 'aaa'], getline(1, 2)) 3745 xunmap <F3> 3746enddef 3747 3748def Test_white_space_after_command() 3749 var lines =<< trim END 3750 exit_cb: Func}) 3751 END 3752 CheckDefAndScriptFailure(lines, 'E1144:', 1) 3753 3754 lines =<< trim END 3755 e# 3756 END 3757 CheckDefAndScriptFailure(lines, 'E1144:', 1) 3758enddef 3759 3760def Test_script_var_gone_when_sourced_twice() 3761 var lines =<< trim END 3762 vim9script 3763 if exists('g:guard') 3764 finish 3765 endif 3766 g:guard = 1 3767 var name = 'thename' 3768 def g:GetName(): string 3769 return name 3770 enddef 3771 def g:SetName(arg: string) 3772 name = arg 3773 enddef 3774 END 3775 writefile(lines, 'XscriptTwice.vim') 3776 so XscriptTwice.vim 3777 assert_equal('thename', g:GetName()) 3778 g:SetName('newname') 3779 assert_equal('newname', g:GetName()) 3780 so XscriptTwice.vim 3781 assert_fails('call g:GetName()', 'E1149:') 3782 assert_fails('call g:SetName("x")', 'E1149:') 3783 3784 delfunc g:GetName 3785 delfunc g:SetName 3786 delete('XscriptTwice.vim') 3787 unlet g:guard 3788enddef 3789 3790def Test_import_gone_when_sourced_twice() 3791 var exportlines =<< trim END 3792 vim9script 3793 if exists('g:guard') 3794 finish 3795 endif 3796 g:guard = 1 3797 export var name = 'someName' 3798 END 3799 writefile(exportlines, 'XexportScript.vim') 3800 3801 var lines =<< trim END 3802 vim9script 3803 import name from './XexportScript.vim' 3804 def g:GetName(): string 3805 return name 3806 enddef 3807 END 3808 writefile(lines, 'XscriptImport.vim') 3809 so XscriptImport.vim 3810 assert_equal('someName', g:GetName()) 3811 3812 so XexportScript.vim 3813 assert_fails('call g:GetName()', 'E1149:') 3814 3815 delfunc g:GetName 3816 delete('XexportScript.vim') 3817 delete('XscriptImport.vim') 3818 unlet g:guard 3819enddef 3820 3821def Test_unsupported_commands() 3822 var lines =<< trim END 3823 ka 3824 END 3825 CheckDefAndScriptFailure(lines, 'E1100:') 3826 3827 lines =<< trim END 3828 :1ka 3829 END 3830 CheckDefAndScriptFailure(lines, 'E481:') 3831 3832 lines =<< trim END 3833 t 3834 END 3835 CheckDefFailure(lines, 'E1100:') 3836 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 3837 3838 lines =<< trim END 3839 x 3840 END 3841 CheckDefFailure(lines, 'E1100:') 3842 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 3843 3844 lines =<< trim END 3845 xit 3846 END 3847 CheckDefFailure(lines, 'E1100:') 3848 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 3849enddef 3850 3851def Test_mapping_line_number() 3852 var lines =<< trim END 3853 vim9script 3854 def g:FuncA() 3855 # Some comment 3856 FuncB(0) 3857 enddef 3858 # Some comment 3859 def FuncB( 3860 # Some comment 3861 n: number 3862 ) 3863 exe 'nno ' 3864 # Some comment 3865 .. '<F3> a' 3866 .. 'b' 3867 .. 'c' 3868 enddef 3869 END 3870 CheckScriptSuccess(lines) 3871 var res = execute('verbose nmap <F3>') 3872 assert_match('No mapping found', res) 3873 3874 g:FuncA() 3875 res = execute('verbose nmap <F3>') 3876 assert_match(' <F3> .* abc.*Last set from .*XScriptSuccess\d\+ line 11', res) 3877 3878 nunmap <F3> 3879 delfunc g:FuncA 3880enddef 3881 3882" Keep this last, it messes up highlighting. 3883def Test_substitute_cmd() 3884 new 3885 setline(1, 'something') 3886 :substitute(some(other( 3887 assert_equal('otherthing', getline(1)) 3888 bwipe! 3889 3890 # also when the context is Vim9 script 3891 var lines =<< trim END 3892 vim9script 3893 new 3894 setline(1, 'something') 3895 :substitute(some(other( 3896 assert_equal('otherthing', getline(1)) 3897 bwipe! 3898 END 3899 writefile(lines, 'Xvim9lines') 3900 source Xvim9lines 3901 3902 delete('Xvim9lines') 3903enddef 3904 3905" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 3906