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_abort_after_error() 858 var lines =<< trim END 859 vim9script 860 while true 861 echo notfound 862 endwhile 863 g:gotthere = true 864 END 865 g:gotthere = false 866 CheckScriptFailure(lines, 'E121:') 867 assert_false(g:gotthere) 868 unlet g:gotthere 869enddef 870 871def Test_cexpr_vimscript() 872 # only checks line continuation 873 set errorformat=File\ %f\ line\ %l 874 var lines =<< trim END 875 vim9script 876 cexpr 'File' 877 .. ' someFile' .. 878 ' line 19' 879 assert_equal(19, getqflist()[0].lnum) 880 END 881 CheckScriptSuccess(lines) 882 set errorformat& 883enddef 884 885def Test_statusline_syntax() 886 # legacy syntax is used for 'statusline' 887 var lines =<< trim END 888 vim9script 889 func g:Status() 890 return '%{"x" is# "x"}' 891 endfunc 892 set laststatus=2 statusline=%!Status() 893 redrawstatus 894 set laststatus statusline= 895 END 896 CheckScriptSuccess(lines) 897enddef 898 899def Test_list_vimscript() 900 # checks line continuation and comments 901 var lines =<< trim END 902 vim9script 903 var mylist = [ 904 'one', 905 # comment 906 'two', # empty line follows 907 908 'three', 909 ] 910 assert_equal(['one', 'two', 'three'], mylist) 911 END 912 CheckScriptSuccess(lines) 913 914 # check all lines from heredoc are kept 915 lines =<< trim END 916 # comment 1 917 two 918 # comment 3 919 920 five 921 # comment 6 922 END 923 assert_equal(['# comment 1', 'two', '# comment 3', '', 'five', '# comment 6'], lines) 924 925 lines =<< trim END 926 [{ 927 a: 0}]->string()->assert_equal("[{'a': 0}]") 928 END 929 CheckDefAndScriptSuccess(lines) 930enddef 931 932if has('channel') 933 let someJob = test_null_job() 934 935 def FuncWithError() 936 echomsg g:someJob 937 enddef 938 939 func Test_convert_emsg_to_exception() 940 try 941 call FuncWithError() 942 catch 943 call assert_match('Vim:E908:', v:exception) 944 endtry 945 endfunc 946endif 947 948let s:export_script_lines =<< trim END 949 vim9script 950 var name: string = 'bob' 951 def Concat(arg: string): string 952 return name .. arg 953 enddef 954 g:result = Concat('bie') 955 g:localname = name 956 957 export const CONST = 1234 958 export var exported = 9876 959 export var exp_name = 'John' 960 export def Exported(): string 961 return 'Exported' 962 enddef 963 export final theList = [1] 964END 965 966def Undo_export_script_lines() 967 unlet g:result 968 unlet g:localname 969enddef 970 971def Test_vim9_import_export() 972 var import_script_lines =<< trim END 973 vim9script 974 import {exported, Exported} from './Xexport.vim' 975 g:imported = exported 976 exported += 3 977 g:imported_added = exported 978 g:imported_func = Exported() 979 980 def GetExported(): string 981 var local_dict = {ref: Exported} 982 return local_dict.ref() 983 enddef 984 g:funcref_result = GetExported() 985 986 import {exp_name} from './Xexport.vim' 987 g:imported_name = exp_name 988 exp_name ..= ' Doe' 989 g:imported_name_appended = exp_name 990 g:imported_later = exported 991 992 import theList from './Xexport.vim' 993 theList->add(2) 994 assert_equal([1, 2], theList) 995 END 996 997 writefile(import_script_lines, 'Ximport.vim') 998 writefile(s:export_script_lines, 'Xexport.vim') 999 1000 source Ximport.vim 1001 1002 assert_equal('bobbie', g:result) 1003 assert_equal('bob', g:localname) 1004 assert_equal(9876, g:imported) 1005 assert_equal(9879, g:imported_added) 1006 assert_equal(9879, g:imported_later) 1007 assert_equal('Exported', g:imported_func) 1008 assert_equal('Exported', g:funcref_result) 1009 assert_equal('John', g:imported_name) 1010 assert_equal('John Doe', g:imported_name_appended) 1011 assert_false(exists('g:name')) 1012 1013 Undo_export_script_lines() 1014 unlet g:imported 1015 unlet g:imported_added 1016 unlet g:imported_later 1017 unlet g:imported_func 1018 unlet g:imported_name g:imported_name_appended 1019 delete('Ximport.vim') 1020 1021 # similar, with line breaks 1022 var import_line_break_script_lines =<< trim END 1023 vim9script 1024 import { 1025 exported, 1026 Exported, 1027 } 1028 from 1029 './Xexport.vim' 1030 g:imported = exported 1031 exported += 5 1032 g:imported_added = exported 1033 g:imported_func = Exported() 1034 END 1035 writefile(import_line_break_script_lines, 'Ximport_lbr.vim') 1036 source Ximport_lbr.vim 1037 1038 assert_equal(9876, g:imported) 1039 assert_equal(9881, g:imported_added) 1040 assert_equal('Exported', g:imported_func) 1041 1042 # exported script not sourced again 1043 assert_false(exists('g:result')) 1044 unlet g:imported 1045 unlet g:imported_added 1046 unlet g:imported_func 1047 delete('Ximport_lbr.vim') 1048 1049 # import inside :def function 1050 var import_in_def_lines =<< trim END 1051 vim9script 1052 def ImportInDef() 1053 import exported from './Xexport.vim' 1054 g:imported = exported 1055 exported += 7 1056 g:imported_added = exported 1057 enddef 1058 ImportInDef() 1059 END 1060 writefile(import_in_def_lines, 'Ximport2.vim') 1061 source Ximport2.vim 1062 # TODO: this should be 9879 1063 assert_equal(9876, g:imported) 1064 assert_equal(9883, g:imported_added) 1065 unlet g:imported 1066 unlet g:imported_added 1067 delete('Ximport2.vim') 1068 1069 var import_star_as_lines =<< trim END 1070 vim9script 1071 import * as Export from './Xexport.vim' 1072 def UseExport() 1073 g:imported_def = Export.exported 1074 enddef 1075 g:imported_script = Export.exported 1076 assert_equal(1, exists('Export.exported')) 1077 assert_equal(0, exists('Export.notexported')) 1078 UseExport() 1079 END 1080 writefile(import_star_as_lines, 'Ximport.vim') 1081 source Ximport.vim 1082 assert_equal(9883, g:imported_def) 1083 assert_equal(9883, g:imported_script) 1084 1085 var import_star_as_lines_no_dot =<< trim END 1086 vim9script 1087 import * as Export from './Xexport.vim' 1088 def Func() 1089 var dummy = 1 1090 var imported = Export + dummy 1091 enddef 1092 defcompile 1093 END 1094 writefile(import_star_as_lines_no_dot, 'Ximport.vim') 1095 assert_fails('source Ximport.vim', 'E1060:', '', 2, 'Func') 1096 1097 var import_star_as_lines_dot_space =<< trim END 1098 vim9script 1099 import * as Export from './Xexport.vim' 1100 def Func() 1101 var imported = Export . exported 1102 enddef 1103 defcompile 1104 END 1105 writefile(import_star_as_lines_dot_space, 'Ximport.vim') 1106 assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func') 1107 1108 var import_star_as_duplicated =<< trim END 1109 vim9script 1110 import * as Export from './Xexport.vim' 1111 var some = 'other' 1112 import * as Export from './Xexport.vim' 1113 defcompile 1114 END 1115 writefile(import_star_as_duplicated, 'Ximport.vim') 1116 assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim') 1117 1118 var import_star_as_lines_script_no_dot =<< trim END 1119 vim9script 1120 import * as Export from './Xexport.vim' 1121 g:imported_script = Export exported 1122 END 1123 writefile(import_star_as_lines_script_no_dot, 'Ximport.vim') 1124 assert_fails('source Ximport.vim', 'E1029:') 1125 1126 var import_star_as_lines_script_space_after_dot =<< trim END 1127 vim9script 1128 import * as Export from './Xexport.vim' 1129 g:imported_script = Export. exported 1130 END 1131 writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim') 1132 assert_fails('source Ximport.vim', 'E1074:') 1133 1134 var import_star_as_lines_missing_name =<< trim END 1135 vim9script 1136 import * as Export from './Xexport.vim' 1137 def Func() 1138 var imported = Export. 1139 enddef 1140 defcompile 1141 END 1142 writefile(import_star_as_lines_missing_name, 'Ximport.vim') 1143 assert_fails('source Ximport.vim', 'E1048:', '', 1, 'Func') 1144 1145 var import_star_as_lbr_lines =<< trim END 1146 vim9script 1147 import * 1148 as Export 1149 from 1150 './Xexport.vim' 1151 def UseExport() 1152 g:imported = Export.exported 1153 enddef 1154 UseExport() 1155 END 1156 writefile(import_star_as_lbr_lines, 'Ximport.vim') 1157 source Ximport.vim 1158 assert_equal(9883, g:imported) 1159 1160 var import_star_lines =<< trim END 1161 vim9script 1162 import * from './Xexport.vim' 1163 END 1164 writefile(import_star_lines, 'Ximport.vim') 1165 assert_fails('source Ximport.vim', 'E1045:', '', 2, 'Ximport.vim') 1166 1167 # try to import something that exists but is not exported 1168 var import_not_exported_lines =<< trim END 1169 vim9script 1170 import name from './Xexport.vim' 1171 END 1172 writefile(import_not_exported_lines, 'Ximport.vim') 1173 assert_fails('source Ximport.vim', 'E1049:', '', 2, 'Ximport.vim') 1174 1175 # try to import something that is already defined 1176 var import_already_defined =<< trim END 1177 vim9script 1178 var exported = 'something' 1179 import exported from './Xexport.vim' 1180 END 1181 writefile(import_already_defined, 'Ximport.vim') 1182 assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') 1183 1184 # try to import something that is already defined 1185 import_already_defined =<< trim END 1186 vim9script 1187 var exported = 'something' 1188 import * as exported from './Xexport.vim' 1189 END 1190 writefile(import_already_defined, 'Ximport.vim') 1191 assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') 1192 1193 # try to import something that is already defined 1194 import_already_defined =<< trim END 1195 vim9script 1196 var exported = 'something' 1197 import {exported} from './Xexport.vim' 1198 END 1199 writefile(import_already_defined, 'Ximport.vim') 1200 assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') 1201 1202 # try changing an imported const 1203 var import_assign_to_const =<< trim END 1204 vim9script 1205 import CONST from './Xexport.vim' 1206 def Assign() 1207 CONST = 987 1208 enddef 1209 defcompile 1210 END 1211 writefile(import_assign_to_const, 'Ximport.vim') 1212 assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign') 1213 1214 # try changing an imported final 1215 var import_assign_to_final =<< trim END 1216 vim9script 1217 import theList from './Xexport.vim' 1218 def Assign() 1219 theList = [2] 1220 enddef 1221 defcompile 1222 END 1223 writefile(import_assign_to_final, 'Ximport.vim') 1224 assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign') 1225 1226 # import a very long name, requires making a copy 1227 var import_long_name_lines =<< trim END 1228 vim9script 1229 import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim' 1230 END 1231 writefile(import_long_name_lines, 'Ximport.vim') 1232 assert_fails('source Ximport.vim', 'E1048:', '', 2, 'Ximport.vim') 1233 1234 var import_no_from_lines =<< trim END 1235 vim9script 1236 import name './Xexport.vim' 1237 END 1238 writefile(import_no_from_lines, 'Ximport.vim') 1239 assert_fails('source Ximport.vim', 'E1070:', '', 2, 'Ximport.vim') 1240 1241 var import_invalid_string_lines =<< trim END 1242 vim9script 1243 import name from Xexport.vim 1244 END 1245 writefile(import_invalid_string_lines, 'Ximport.vim') 1246 assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim') 1247 1248 var import_wrong_name_lines =<< trim END 1249 vim9script 1250 import name from './XnoExport.vim' 1251 END 1252 writefile(import_wrong_name_lines, 'Ximport.vim') 1253 assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim') 1254 1255 var import_missing_comma_lines =<< trim END 1256 vim9script 1257 import {exported name} from './Xexport.vim' 1258 END 1259 writefile(import_missing_comma_lines, 'Ximport3.vim') 1260 assert_fails('source Ximport3.vim', 'E1046:', '', 2, 'Ximport3.vim') 1261 1262 delete('Ximport.vim') 1263 delete('Ximport3.vim') 1264 delete('Xexport.vim') 1265 1266 # Check that in a Vim9 script 'cpo' is set to the Vim default. 1267 # Flags added or removed are also applied to the restored value. 1268 set cpo=abcd 1269 var lines =<< trim END 1270 vim9script 1271 g:cpo_in_vim9script = &cpo 1272 set cpo+=f 1273 set cpo-=c 1274 g:cpo_after_vim9script = &cpo 1275 END 1276 writefile(lines, 'Xvim9_script') 1277 source Xvim9_script 1278 assert_equal('fabd', &cpo) 1279 set cpo&vim 1280 assert_equal(&cpo, g:cpo_in_vim9script) 1281 var newcpo = substitute(&cpo, 'c', '', '') .. 'f' 1282 assert_equal(newcpo, g:cpo_after_vim9script) 1283 1284 delete('Xvim9_script') 1285enddef 1286 1287def Test_import_as() 1288 var export_lines =<< trim END 1289 vim9script 1290 export var one = 1 1291 export var yes = 'yes' 1292 END 1293 writefile(export_lines, 'XexportAs') 1294 1295 var import_lines =<< trim END 1296 vim9script 1297 var one = 'notused' 1298 var yes = 777 1299 import one as thatOne from './XexportAs' 1300 assert_equal(1, thatOne) 1301 import yes as yesYes from './XexportAs' 1302 assert_equal('yes', yesYes) 1303 END 1304 CheckScriptSuccess(import_lines) 1305 1306 import_lines =<< trim END 1307 vim9script 1308 import {one as thatOne, yes as yesYes} from './XexportAs' 1309 assert_equal(1, thatOne) 1310 assert_equal('yes', yesYes) 1311 assert_fails('echo one', 'E121:') 1312 assert_fails('echo yes', 'E121:') 1313 END 1314 CheckScriptSuccess(import_lines) 1315 1316 delete('XexportAs') 1317enddef 1318 1319func g:Trigger() 1320 source Ximport.vim 1321 return "echo 'yes'\<CR>" 1322endfunc 1323 1324def Test_import_export_expr_map() 1325 # check that :import and :export work when buffer is locked 1326 var export_lines =<< trim END 1327 vim9script 1328 export def That(): string 1329 return 'yes' 1330 enddef 1331 END 1332 writefile(export_lines, 'Xexport_that.vim') 1333 1334 var import_lines =<< trim END 1335 vim9script 1336 import That from './Xexport_that.vim' 1337 assert_equal('yes', That()) 1338 END 1339 writefile(import_lines, 'Ximport.vim') 1340 1341 nnoremap <expr> trigger g:Trigger() 1342 feedkeys('trigger', "xt") 1343 1344 delete('Xexport_that.vim') 1345 delete('Ximport.vim') 1346 nunmap trigger 1347enddef 1348 1349def Test_import_in_filetype() 1350 # check that :import works when the buffer is locked 1351 mkdir('ftplugin', 'p') 1352 var export_lines =<< trim END 1353 vim9script 1354 export var That = 'yes' 1355 END 1356 writefile(export_lines, 'ftplugin/Xexport_ft.vim') 1357 1358 var import_lines =<< trim END 1359 vim9script 1360 import That from './Xexport_ft.vim' 1361 assert_equal('yes', That) 1362 g:did_load_mytpe = 1 1363 END 1364 writefile(import_lines, 'ftplugin/qf.vim') 1365 1366 var save_rtp = &rtp 1367 &rtp = getcwd() .. ',' .. &rtp 1368 1369 filetype plugin on 1370 copen 1371 assert_equal(1, g:did_load_mytpe) 1372 1373 quit! 1374 delete('Xexport_ft.vim') 1375 delete('ftplugin', 'rf') 1376 &rtp = save_rtp 1377enddef 1378 1379def Test_use_import_in_mapping() 1380 var lines =<< trim END 1381 vim9script 1382 export def Funcx() 1383 g:result = 42 1384 enddef 1385 END 1386 writefile(lines, 'XsomeExport.vim') 1387 lines =<< trim END 1388 vim9script 1389 import Funcx from './XsomeExport.vim' 1390 nnoremap <F3> :call <sid>Funcx()<cr> 1391 END 1392 writefile(lines, 'Xmapscript.vim') 1393 1394 source Xmapscript.vim 1395 feedkeys("\<F3>", "xt") 1396 assert_equal(42, g:result) 1397 1398 unlet g:result 1399 delete('XsomeExport.vim') 1400 delete('Xmapscript.vim') 1401 nunmap <F3> 1402enddef 1403 1404def Test_vim9script_mix() 1405 var lines =<< trim END 1406 if has(g:feature) 1407 " legacy script 1408 let g:legacy = 1 1409 finish 1410 endif 1411 vim9script 1412 g:legacy = 0 1413 END 1414 g:feature = 'eval' 1415 g:legacy = -1 1416 CheckScriptSuccess(lines) 1417 assert_equal(1, g:legacy) 1418 1419 g:feature = 'noteval' 1420 g:legacy = -1 1421 CheckScriptSuccess(lines) 1422 assert_equal(0, g:legacy) 1423enddef 1424 1425def Test_vim9script_fails() 1426 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') 1427 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') 1428 CheckScriptFailure(['export var some = 123'], 'E1042:') 1429 CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:') 1430 CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:') 1431 CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') 1432 1433 CheckScriptFailure(['vim9script', 'var str: string', 'str = 1234'], 'E1012:') 1434 CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:') 1435 1436 assert_fails('vim9script', 'E1038:') 1437 assert_fails('export something', 'E1043:') 1438enddef 1439 1440func Test_import_fails_without_script() 1441 CheckRunVimInTerminal 1442 1443 " call indirectly to avoid compilation error for missing functions 1444 call Run_Test_import_fails_on_command_line() 1445endfunc 1446 1447def Run_Test_import_fails_on_command_line() 1448 var export =<< trim END 1449 vim9script 1450 export def Foo(): number 1451 return 0 1452 enddef 1453 END 1454 writefile(export, 'XexportCmd.vim') 1455 1456 var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', { 1457 rows: 6, wait_for_ruler: 0}) 1458 WaitForAssert(() => assert_match('^E1094:', term_getline(buf, 5))) 1459 1460 delete('XexportCmd.vim') 1461 StopVimInTerminal(buf) 1462enddef 1463 1464def Test_vim9script_reload_noclear() 1465 var lines =<< trim END 1466 vim9script 1467 export var exported = 'thexport' 1468 END 1469 writefile(lines, 'XExportReload') 1470 lines =<< trim END 1471 vim9script noclear 1472 g:loadCount += 1 1473 var s:reloaded = 'init' 1474 import exported from './XExportReload' 1475 1476 def Again(): string 1477 return 'again' 1478 enddef 1479 1480 if exists('s:loaded') | finish | endif 1481 var s:loaded = true 1482 1483 var s:notReloaded = 'yes' 1484 s:reloaded = 'first' 1485 def g:Values(): list<string> 1486 return [s:reloaded, s:notReloaded, Again(), Once(), exported] 1487 enddef 1488 1489 def Once(): string 1490 return 'once' 1491 enddef 1492 END 1493 writefile(lines, 'XReloaded') 1494 g:loadCount = 0 1495 source XReloaded 1496 assert_equal(1, g:loadCount) 1497 assert_equal(['first', 'yes', 'again', 'once', 'thexport'], g:Values()) 1498 source XReloaded 1499 assert_equal(2, g:loadCount) 1500 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1501 source XReloaded 1502 assert_equal(3, g:loadCount) 1503 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1504 1505 delete('XReloaded') 1506 delete('XExportReload') 1507 delfunc g:Values 1508 unlet g:loadCount 1509enddef 1510 1511def Test_vim9script_reload_import() 1512 var lines =<< trim END 1513 vim9script 1514 const var = '' 1515 var valone = 1234 1516 def MyFunc(arg: string) 1517 valone = 5678 1518 enddef 1519 END 1520 var morelines =<< trim END 1521 var valtwo = 222 1522 export def GetValtwo(): number 1523 return valtwo 1524 enddef 1525 END 1526 writefile(lines + morelines, 'Xreload.vim') 1527 source Xreload.vim 1528 source Xreload.vim 1529 source Xreload.vim 1530 1531 var testlines =<< trim END 1532 vim9script 1533 def TheFunc() 1534 import GetValtwo from './Xreload.vim' 1535 assert_equal(222, GetValtwo()) 1536 enddef 1537 TheFunc() 1538 END 1539 writefile(testlines, 'Ximport.vim') 1540 source Ximport.vim 1541 1542 # Test that when not using "morelines" GetValtwo() and valtwo are still 1543 # defined, because import doesn't reload a script. 1544 writefile(lines, 'Xreload.vim') 1545 source Ximport.vim 1546 1547 # cannot declare a var twice 1548 lines =<< trim END 1549 vim9script 1550 var valone = 1234 1551 var valone = 5678 1552 END 1553 writefile(lines, 'Xreload.vim') 1554 assert_fails('source Xreload.vim', 'E1041:', '', 3, 'Xreload.vim') 1555 1556 delete('Xreload.vim') 1557 delete('Ximport.vim') 1558enddef 1559 1560" if a script is reloaded with a script-local variable that changed its type, a 1561" compiled function using that variable must fail. 1562def Test_script_reload_change_type() 1563 var lines =<< trim END 1564 vim9script noclear 1565 var str = 'string' 1566 def g:GetStr(): string 1567 return str .. 'xxx' 1568 enddef 1569 END 1570 writefile(lines, 'Xreload.vim') 1571 source Xreload.vim 1572 echo g:GetStr() 1573 1574 lines =<< trim END 1575 vim9script noclear 1576 var str = 1234 1577 END 1578 writefile(lines, 'Xreload.vim') 1579 source Xreload.vim 1580 assert_fails('echo g:GetStr()', 'E1150:') 1581 1582 delfunc g:GetStr 1583 delete('Xreload.vim') 1584enddef 1585 1586" Define CallFunc so that the test can be compiled 1587command CallFunc echo 'nop' 1588 1589def Test_script_reload_from_function() 1590 var lines =<< trim END 1591 vim9script 1592 1593 if exists('g:loaded') 1594 finish 1595 endif 1596 g:loaded = 1 1597 delcommand CallFunc 1598 command CallFunc Func() 1599 def Func() 1600 so XreloadFunc.vim 1601 g:didTheFunc = 1 1602 enddef 1603 END 1604 writefile(lines, 'XreloadFunc.vim') 1605 source XreloadFunc.vim 1606 CallFunc 1607 assert_equal(1, g:didTheFunc) 1608 1609 delete('XreloadFunc.vim') 1610 delcommand CallFunc 1611 unlet g:loaded 1612 unlet g:didTheFunc 1613enddef 1614 1615def Test_script_var_shadows_function() 1616 var lines =<< trim END 1617 vim9script 1618 def Func(): number 1619 return 123 1620 enddef 1621 var Func = 1 1622 END 1623 CheckScriptFailure(lines, 'E1041:', 5) 1624enddef 1625 1626def s:RetSome(): string 1627 return 'some' 1628enddef 1629 1630" Not exported function that is referenced needs to be accessed by the 1631" script-local name. 1632def Test_vim9script_funcref() 1633 var sortlines =<< trim END 1634 vim9script 1635 def Compare(i1: number, i2: number): number 1636 return i2 - i1 1637 enddef 1638 1639 export def FastSort(): list<number> 1640 return range(5)->sort(Compare) 1641 enddef 1642 1643 export def GetString(arg: string): string 1644 return arg 1645 enddef 1646 END 1647 writefile(sortlines, 'Xsort.vim') 1648 1649 var lines =<< trim END 1650 vim9script 1651 import FastSort from './Xsort.vim' 1652 def Test() 1653 g:result = FastSort() 1654 enddef 1655 Test() 1656 1657 # using a function imported with "as" 1658 import * as anAlias from './Xsort.vim' 1659 assert_equal('yes', anAlias.GetString('yes')) 1660 1661 # using the function from a compiled function 1662 def TestMore(): string 1663 var s = s:anAlias.GetString('foo') 1664 return s .. anAlias.GetString('bar') 1665 enddef 1666 assert_equal('foobar', TestMore()) 1667 1668 # error when using a function that isn't exported 1669 assert_fails('anAlias.Compare(1, 2)', 'E1049:') 1670 END 1671 writefile(lines, 'Xscript.vim') 1672 1673 source Xscript.vim 1674 assert_equal([4, 3, 2, 1, 0], g:result) 1675 1676 unlet g:result 1677 delete('Xsort.vim') 1678 delete('Xscript.vim') 1679 1680 var Funcref = function('s:RetSome') 1681 assert_equal('some', Funcref()) 1682enddef 1683 1684" Check that when searching for "FilterFunc" it finds the import in the 1685" script where FastFilter() is called from, both as a string and as a direct 1686" function reference. 1687def Test_vim9script_funcref_other_script() 1688 var filterLines =<< trim END 1689 vim9script 1690 export def FilterFunc(idx: number, val: number): bool 1691 return idx % 2 == 1 1692 enddef 1693 export def FastFilter(): list<number> 1694 return range(10)->filter('FilterFunc') 1695 enddef 1696 export def FastFilterDirect(): list<number> 1697 return range(10)->filter(FilterFunc) 1698 enddef 1699 END 1700 writefile(filterLines, 'Xfilter.vim') 1701 1702 var lines =<< trim END 1703 vim9script 1704 import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim' 1705 def Test() 1706 var x: list<number> = FastFilter() 1707 enddef 1708 Test() 1709 def TestDirect() 1710 var x: list<number> = FastFilterDirect() 1711 enddef 1712 TestDirect() 1713 END 1714 CheckScriptSuccess(lines) 1715 delete('Xfilter.vim') 1716enddef 1717 1718def Test_vim9script_reload_delfunc() 1719 var first_lines =<< trim END 1720 vim9script 1721 def FuncYes(): string 1722 return 'yes' 1723 enddef 1724 END 1725 var withno_lines =<< trim END 1726 def FuncNo(): string 1727 return 'no' 1728 enddef 1729 def g:DoCheck(no_exists: bool) 1730 assert_equal('yes', FuncYes()) 1731 assert_equal('no', FuncNo()) 1732 enddef 1733 END 1734 var nono_lines =<< trim END 1735 def g:DoCheck(no_exists: bool) 1736 assert_equal('yes', FuncYes()) 1737 assert_fails('FuncNo()', 'E117:', '', 2, 'DoCheck') 1738 enddef 1739 END 1740 1741 # FuncNo() is defined 1742 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1743 source Xreloaded.vim 1744 g:DoCheck(true) 1745 1746 # FuncNo() is not redefined 1747 writefile(first_lines + nono_lines, 'Xreloaded.vim') 1748 source Xreloaded.vim 1749 g:DoCheck(false) 1750 1751 # FuncNo() is back 1752 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1753 source Xreloaded.vim 1754 g:DoCheck(false) 1755 1756 delete('Xreloaded.vim') 1757enddef 1758 1759def Test_vim9script_reload_delvar() 1760 # write the script with a script-local variable 1761 var lines =<< trim END 1762 vim9script 1763 var name = 'string' 1764 END 1765 writefile(lines, 'XreloadVar.vim') 1766 source XreloadVar.vim 1767 1768 # now write the script using the same variable locally - works 1769 lines =<< trim END 1770 vim9script 1771 def Func() 1772 var name = 'string' 1773 enddef 1774 END 1775 writefile(lines, 'XreloadVar.vim') 1776 source XreloadVar.vim 1777 1778 delete('XreloadVar.vim') 1779enddef 1780 1781def Test_import_absolute() 1782 var import_lines = [ 1783 'vim9script', 1784 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 1785 'def UseExported()', 1786 ' g:imported_abs = exported', 1787 ' exported = 8888', 1788 ' g:imported_after = exported', 1789 'enddef', 1790 'UseExported()', 1791 'g:import_disassembled = execute("disass UseExported")', 1792 ] 1793 writefile(import_lines, 'Ximport_abs.vim') 1794 writefile(s:export_script_lines, 'Xexport_abs.vim') 1795 1796 source Ximport_abs.vim 1797 1798 assert_equal(9876, g:imported_abs) 1799 assert_equal(8888, g:imported_after) 1800 assert_match('<SNR>\d\+_UseExported\_s*' .. 1801 'g:imported_abs = exported\_s*' .. 1802 '0 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 1803 '1 STOREG g:imported_abs\_s*' .. 1804 'exported = 8888\_s*' .. 1805 '2 PUSHNR 8888\_s*' .. 1806 '3 STORESCRIPT exported-2 in .*Xexport_abs.vim\_s*' .. 1807 'g:imported_after = exported\_s*' .. 1808 '4 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 1809 '5 STOREG g:imported_after', 1810 g:import_disassembled) 1811 1812 Undo_export_script_lines() 1813 unlet g:imported_abs 1814 unlet g:import_disassembled 1815 1816 delete('Ximport_abs.vim') 1817 delete('Xexport_abs.vim') 1818enddef 1819 1820def Test_import_rtp() 1821 var import_lines = [ 1822 'vim9script', 1823 'import exported from "Xexport_rtp.vim"', 1824 'g:imported_rtp = exported', 1825 ] 1826 writefile(import_lines, 'Ximport_rtp.vim') 1827 mkdir('import') 1828 writefile(s:export_script_lines, 'import/Xexport_rtp.vim') 1829 1830 var save_rtp = &rtp 1831 &rtp = getcwd() 1832 source Ximport_rtp.vim 1833 &rtp = save_rtp 1834 1835 assert_equal(9876, g:imported_rtp) 1836 1837 Undo_export_script_lines() 1838 unlet g:imported_rtp 1839 delete('Ximport_rtp.vim') 1840 delete('import', 'rf') 1841enddef 1842 1843def Test_import_compile_error() 1844 var export_lines = [ 1845 'vim9script', 1846 'export def ExpFunc(): string', 1847 ' return notDefined', 1848 'enddef', 1849 ] 1850 writefile(export_lines, 'Xexported.vim') 1851 1852 var import_lines = [ 1853 'vim9script', 1854 'import ExpFunc from "./Xexported.vim"', 1855 'def ImpFunc()', 1856 ' echo ExpFunc()', 1857 'enddef', 1858 'defcompile', 1859 ] 1860 writefile(import_lines, 'Ximport.vim') 1861 1862 try 1863 source Ximport.vim 1864 catch /E1001/ 1865 # Error should be fore the Xexported.vim file. 1866 assert_match('E1001: Variable not found: notDefined', v:exception) 1867 assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint) 1868 endtry 1869 1870 delete('Xexported.vim') 1871 delete('Ximport.vim') 1872enddef 1873 1874def Test_func_redefine_error() 1875 var lines = [ 1876 'vim9script', 1877 'def Func()', 1878 ' eval [][0]', 1879 'enddef', 1880 'Func()', 1881 ] 1882 writefile(lines, 'Xtestscript.vim') 1883 1884 for count in range(3) 1885 try 1886 source Xtestscript.vim 1887 catch /E684/ 1888 # function name should contain <SNR> every time 1889 assert_match('E684: list index out of range', v:exception) 1890 assert_match('function <SNR>\d\+_Func, line 1', v:throwpoint) 1891 endtry 1892 endfor 1893 1894 delete('Xtestscript.vim') 1895enddef 1896 1897def Test_func_overrules_import_fails() 1898 var export_lines =<< trim END 1899 vim9script 1900 export def Func() 1901 echo 'imported' 1902 enddef 1903 END 1904 writefile(export_lines, 'XexportedFunc.vim') 1905 1906 var lines =<< trim END 1907 vim9script 1908 import Func from './XexportedFunc.vim' 1909 def Func() 1910 echo 'local to function' 1911 enddef 1912 END 1913 CheckScriptFailure(lines, 'E1073:') 1914 1915 lines =<< trim END 1916 vim9script 1917 import Func from './XexportedFunc.vim' 1918 def Outer() 1919 def Func() 1920 echo 'local to function' 1921 enddef 1922 enddef 1923 defcompile 1924 END 1925 CheckScriptFailure(lines, 'E1073:') 1926 1927 delete('XexportedFunc.vim') 1928enddef 1929 1930def Test_func_redefine_fails() 1931 var lines =<< trim END 1932 vim9script 1933 def Func() 1934 echo 'one' 1935 enddef 1936 def Func() 1937 echo 'two' 1938 enddef 1939 END 1940 CheckScriptFailure(lines, 'E1073:') 1941 1942 lines =<< trim END 1943 vim9script 1944 def Foo(): string 1945 return 'foo' 1946 enddef 1947 def Func() 1948 var Foo = {-> 'lambda'} 1949 enddef 1950 defcompile 1951 END 1952 CheckScriptFailure(lines, 'E1073:') 1953enddef 1954 1955def Test_fixed_size_list() 1956 # will be allocated as one piece of memory, check that changes work 1957 var l = [1, 2, 3, 4] 1958 l->remove(0) 1959 l->add(5) 1960 l->insert(99, 1) 1961 assert_equal([2, 99, 3, 4, 5], l) 1962enddef 1963 1964def Test_no_insert_xit() 1965 CheckDefExecFailure(['a = 1'], 'E1100:') 1966 CheckDefExecFailure(['c = 1'], 'E1100:') 1967 CheckDefExecFailure(['i = 1'], 'E1100:') 1968 CheckDefExecFailure(['t = 1'], 'E1100:') 1969 CheckDefExecFailure(['x = 1'], 'E1100:') 1970 1971 CheckScriptFailure(['vim9script', 'a = 1'], 'E488:') 1972 CheckScriptFailure(['vim9script', 'a'], 'E1100:') 1973 CheckScriptFailure(['vim9script', 'c = 1'], 'E488:') 1974 CheckScriptFailure(['vim9script', 'c'], 'E1100:') 1975 CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') 1976 CheckScriptFailure(['vim9script', 'i'], 'E1100:') 1977 CheckScriptFailure(['vim9script', 'o = 1'], 'E1100:') 1978 CheckScriptFailure(['vim9script', 'o'], 'E1100:') 1979 CheckScriptFailure(['vim9script', 't'], 'E1100:') 1980 CheckScriptFailure(['vim9script', 't = 1'], 'E1100:') 1981 CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') 1982enddef 1983 1984def IfElse(what: number): string 1985 var res = '' 1986 if what == 1 1987 res = "one" 1988 elseif what == 2 1989 res = "two" 1990 else 1991 res = "three" 1992 endif 1993 return res 1994enddef 1995 1996def Test_if_elseif_else() 1997 assert_equal('one', IfElse(1)) 1998 assert_equal('two', IfElse(2)) 1999 assert_equal('three', IfElse(3)) 2000enddef 2001 2002def Test_if_elseif_else_fails() 2003 CheckDefFailure(['elseif true'], 'E582:') 2004 CheckDefFailure(['else'], 'E581:') 2005 CheckDefFailure(['endif'], 'E580:') 2006 CheckDefFailure(['if g:abool', 'elseif xxx'], 'E1001:') 2007 CheckDefFailure(['if true', 'echo 1'], 'E171:') 2008 2009 var lines =<< trim END 2010 var s = '' 2011 if s = '' 2012 endif 2013 END 2014 CheckDefFailure(lines, 'E488:') 2015 2016 lines =<< trim END 2017 var s = '' 2018 if s == '' 2019 elseif s = '' 2020 endif 2021 END 2022 CheckDefFailure(lines, 'E488:') 2023enddef 2024 2025let g:bool_true = v:true 2026let g:bool_false = v:false 2027 2028def Test_if_const_expr() 2029 var res = false 2030 if true ? true : false 2031 res = true 2032 endif 2033 assert_equal(true, res) 2034 2035 g:glob = 2 2036 if false 2037 execute('g:glob = 3') 2038 endif 2039 assert_equal(2, g:glob) 2040 if true 2041 execute('g:glob = 3') 2042 endif 2043 assert_equal(3, g:glob) 2044 2045 res = false 2046 if g:bool_true ? true : false 2047 res = true 2048 endif 2049 assert_equal(true, res) 2050 2051 res = false 2052 if true ? g:bool_true : false 2053 res = true 2054 endif 2055 assert_equal(true, res) 2056 2057 res = false 2058 if true ? true : g:bool_false 2059 res = true 2060 endif 2061 assert_equal(true, res) 2062 2063 res = false 2064 if true ? false : true 2065 res = true 2066 endif 2067 assert_equal(false, res) 2068 2069 res = false 2070 if false ? false : true 2071 res = true 2072 endif 2073 assert_equal(true, res) 2074 2075 res = false 2076 if false ? true : false 2077 res = true 2078 endif 2079 assert_equal(false, res) 2080 2081 res = false 2082 if has('xyz') ? true : false 2083 res = true 2084 endif 2085 assert_equal(false, res) 2086 2087 res = false 2088 if true && true 2089 res = true 2090 endif 2091 assert_equal(true, res) 2092 2093 res = false 2094 if true && false 2095 res = true 2096 endif 2097 assert_equal(false, res) 2098 2099 res = false 2100 if g:bool_true && false 2101 res = true 2102 endif 2103 assert_equal(false, res) 2104 2105 res = false 2106 if true && g:bool_false 2107 res = true 2108 endif 2109 assert_equal(false, res) 2110 2111 res = false 2112 if false && false 2113 res = true 2114 endif 2115 assert_equal(false, res) 2116 2117 res = false 2118 if true || false 2119 res = true 2120 endif 2121 assert_equal(true, res) 2122 2123 res = false 2124 if g:bool_true || false 2125 res = true 2126 endif 2127 assert_equal(true, res) 2128 2129 res = false 2130 if true || g:bool_false 2131 res = true 2132 endif 2133 assert_equal(true, res) 2134 2135 res = false 2136 if false || false 2137 res = true 2138 endif 2139 assert_equal(false, res) 2140 2141 # with constant "false" expression may be invalid so long as the syntax is OK 2142 if false | eval 0 | endif 2143 if false | eval burp + 234 | endif 2144 if false | echo burp 234 'asd' | endif 2145 if false 2146 burp 2147 endif 2148enddef 2149 2150def Test_if_const_expr_fails() 2151 CheckDefFailure(['if "aaa" == "bbb'], 'E114:') 2152 CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:') 2153 CheckDefFailure(["if has('aaa'"], 'E110:') 2154 CheckDefFailure(["if has('aaa') ? true false"], 'E109:') 2155enddef 2156 2157def RunNested(i: number): number 2158 var x: number = 0 2159 if i % 2 2160 if 1 2161 # comment 2162 else 2163 # comment 2164 endif 2165 x += 1 2166 else 2167 x += 1000 2168 endif 2169 return x 2170enddef 2171 2172def Test_nested_if() 2173 assert_equal(1, RunNested(1)) 2174 assert_equal(1000, RunNested(2)) 2175enddef 2176 2177def Test_execute_cmd() 2178 # missing argument is ignored 2179 execute 2180 execute # comment 2181 2182 new 2183 setline(1, 'default') 2184 execute 'setline(1, "execute-string")' 2185 assert_equal('execute-string', getline(1)) 2186 2187 execute "setline(1, 'execute-string')" 2188 assert_equal('execute-string', getline(1)) 2189 2190 var cmd1 = 'setline(1,' 2191 var cmd2 = '"execute-var")' 2192 execute cmd1 cmd2 # comment 2193 assert_equal('execute-var', getline(1)) 2194 2195 execute cmd1 cmd2 '|setline(1, "execute-var-string")' 2196 assert_equal('execute-var-string', getline(1)) 2197 2198 var cmd_first = 'call ' 2199 var cmd_last = 'setline(1, "execute-var-var")' 2200 execute cmd_first .. cmd_last 2201 assert_equal('execute-var-var', getline(1)) 2202 bwipe! 2203 2204 var n = true 2205 execute 'echomsg' (n ? '"true"' : '"no"') 2206 assert_match('^true$', Screenline(&lines)) 2207 2208 echomsg [1, 2, 3] {a: 1, b: 2} 2209 assert_match('^\[1, 2, 3\] {''a'': 1, ''b'': 2}$', Screenline(&lines)) 2210 2211 CheckDefFailure(['execute xxx'], 'E1001:', 1) 2212 CheckDefExecFailure(['execute "tabnext " .. 8'], 'E475:', 1) 2213 CheckDefFailure(['execute "cmd"# comment'], 'E488:', 1) 2214enddef 2215 2216def Test_execute_cmd_vimscript() 2217 # only checks line continuation 2218 var lines =<< trim END 2219 vim9script 2220 execute 'g:someVar' 2221 .. ' = ' .. 2222 '28' 2223 assert_equal(28, g:someVar) 2224 unlet g:someVar 2225 END 2226 CheckScriptSuccess(lines) 2227enddef 2228 2229def Test_echo_cmd() 2230 echo 'some' # comment 2231 echon 'thing' 2232 assert_match('^something$', Screenline(&lines)) 2233 2234 echo "some" # comment 2235 echon "thing" 2236 assert_match('^something$', Screenline(&lines)) 2237 2238 var str1 = 'some' 2239 var str2 = 'more' 2240 echo str1 str2 2241 assert_match('^some more$', Screenline(&lines)) 2242 2243 CheckDefFailure(['echo "xxx"# comment'], 'E488:') 2244enddef 2245 2246def Test_echomsg_cmd() 2247 echomsg 'some' 'more' # comment 2248 assert_match('^some more$', Screenline(&lines)) 2249 echo 'clear' 2250 :1messages 2251 assert_match('^some more$', Screenline(&lines)) 2252 2253 CheckDefFailure(['echomsg "xxx"# comment'], 'E488:') 2254enddef 2255 2256def Test_echomsg_cmd_vimscript() 2257 # only checks line continuation 2258 var lines =<< trim END 2259 vim9script 2260 echomsg 'here' 2261 .. ' is ' .. 2262 'a message' 2263 assert_match('^here is a message$', Screenline(&lines)) 2264 END 2265 CheckScriptSuccess(lines) 2266enddef 2267 2268def Test_echoerr_cmd() 2269 try 2270 echoerr 'something' 'wrong' # comment 2271 catch 2272 assert_match('something wrong', v:exception) 2273 endtry 2274enddef 2275 2276def Test_echoerr_cmd_vimscript() 2277 # only checks line continuation 2278 var lines =<< trim END 2279 vim9script 2280 try 2281 echoerr 'this' 2282 .. ' is ' .. 2283 'wrong' 2284 catch 2285 assert_match('this is wrong', v:exception) 2286 endtry 2287 END 2288 CheckScriptSuccess(lines) 2289enddef 2290 2291def Test_for_outside_of_function() 2292 var lines =<< trim END 2293 vim9script 2294 new 2295 for var in range(0, 3) 2296 append(line('$'), var) 2297 endfor 2298 assert_equal(['', '0', '1', '2', '3'], getline(1, '$')) 2299 bwipe! 2300 2301 var result = '' 2302 for i in [1, 2, 3] 2303 var loop = ' loop ' .. i 2304 result ..= loop 2305 endfor 2306 assert_equal(' loop 1 loop 2 loop 3', result) 2307 END 2308 writefile(lines, 'Xvim9for.vim') 2309 source Xvim9for.vim 2310 delete('Xvim9for.vim') 2311enddef 2312 2313def Test_for_loop() 2314 var lines =<< trim END 2315 var result = '' 2316 for cnt in range(7) 2317 if cnt == 4 2318 break 2319 endif 2320 if cnt == 2 2321 continue 2322 endif 2323 result ..= cnt .. '_' 2324 endfor 2325 assert_equal('0_1_3_', result) 2326 2327 var concat = '' 2328 for str in eval('["one", "two"]') 2329 concat ..= str 2330 endfor 2331 assert_equal('onetwo', concat) 2332 2333 var total = 0 2334 for nr in 2335 [1, 2, 3] 2336 total += nr 2337 endfor 2338 assert_equal(6, total) 2339 2340 total = 0 2341 for nr 2342 in [1, 2, 3] 2343 total += nr 2344 endfor 2345 assert_equal(6, total) 2346 2347 total = 0 2348 for nr 2349 in 2350 [1, 2, 3] 2351 total += nr 2352 endfor 2353 assert_equal(6, total) 2354 2355 # with type 2356 total = 0 2357 for n: number in [1, 2, 3] 2358 total += n 2359 endfor 2360 assert_equal(6, total) 2361 2362 var chars = '' 2363 for s: string in 'foobar' 2364 chars ..= s 2365 endfor 2366 assert_equal('foobar', chars) 2367 2368 # unpack with type 2369 var res = '' 2370 for [n: number, s: string] in [[1, 'a'], [2, 'b']] 2371 res ..= n .. s 2372 endfor 2373 assert_equal('1a2b', res) 2374 2375 # loop over string 2376 res = '' 2377 for c in 'aéc̀d' 2378 res ..= c .. '-' 2379 endfor 2380 assert_equal('a-é-c̀-d-', res) 2381 2382 res = '' 2383 for c in '' 2384 res ..= c .. '-' 2385 endfor 2386 assert_equal('', res) 2387 2388 res = '' 2389 for c in test_null_string() 2390 res ..= c .. '-' 2391 endfor 2392 assert_equal('', res) 2393 2394 var foo: list<dict<any>> = [ 2395 {a: 'Cat'} 2396 ] 2397 for dd in foo 2398 dd.counter = 12 2399 endfor 2400 assert_equal([{a: 'Cat', counter: 12}], foo) 2401 END 2402 CheckDefAndScriptSuccess(lines) 2403enddef 2404 2405def Test_for_loop_fails() 2406 CheckDefFailure(['for '], 'E1097:') 2407 CheckDefFailure(['for x'], 'E1097:') 2408 CheckDefFailure(['for x in'], 'E1097:') 2409 CheckDefFailure(['for # in range(5)'], 'E690:') 2410 CheckDefFailure(['for i In range(5)'], 'E690:') 2411 CheckDefFailure(['var x = 5', 'for x in range(5)'], 'E1017:') 2412 CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:') 2413 delfunc! g:Func 2414 CheckDefFailure(['for i in xxx'], 'E1001:') 2415 CheckDefFailure(['endfor'], 'E588:') 2416 CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:') 2417 2418 # wrong type detected at compile time 2419 CheckDefFailure(['for i in {a: 1}', 'echo 3', 'endfor'], 'E1177: For loop on dict not supported') 2420 2421 # wrong type detected at runtime 2422 g:adict = {a: 1} 2423 CheckDefExecFailure(['for i in g:adict', 'echo 3', 'endfor'], 'E1177: For loop on dict not supported') 2424 unlet g:adict 2425 2426 var lines =<< trim END 2427 var d: list<dict<any>> = [{a: 0}] 2428 for e in d 2429 e = {a: 0, b: ''} 2430 endfor 2431 END 2432 CheckDefAndScriptFailure2(lines, 'E1018:', 'E46:', 3) 2433 2434 lines =<< trim END 2435 for nr: number in ['foo'] 2436 endfor 2437 END 2438 CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got string', 1) 2439enddef 2440 2441def Test_for_loop_script_var() 2442 # cannot use s:var in a :def function 2443 CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E1101:') 2444 2445 # can use s:var in Vim9 script, with or without s: 2446 var lines =<< trim END 2447 vim9script 2448 var total = 0 2449 for s:var in [1, 2, 3] 2450 total += s:var 2451 endfor 2452 assert_equal(6, total) 2453 2454 total = 0 2455 for var in [1, 2, 3] 2456 total += var 2457 endfor 2458 assert_equal(6, total) 2459 END 2460enddef 2461 2462def Test_for_loop_unpack() 2463 var lines =<< trim END 2464 var result = [] 2465 for [v1, v2] in [[1, 2], [3, 4]] 2466 result->add(v1) 2467 result->add(v2) 2468 endfor 2469 assert_equal([1, 2, 3, 4], result) 2470 2471 result = [] 2472 for [v1, v2; v3] in [[1, 2], [3, 4, 5, 6]] 2473 result->add(v1) 2474 result->add(v2) 2475 result->add(v3) 2476 endfor 2477 assert_equal([1, 2, [], 3, 4, [5, 6]], result) 2478 2479 result = [] 2480 for [&ts, &sw] in [[1, 2], [3, 4]] 2481 result->add(&ts) 2482 result->add(&sw) 2483 endfor 2484 assert_equal([1, 2, 3, 4], result) 2485 2486 var slist: list<string> 2487 for [$LOOPVAR, @r, v:errmsg] in [['a', 'b', 'c'], ['d', 'e', 'f']] 2488 slist->add($LOOPVAR) 2489 slist->add(@r) 2490 slist->add(v:errmsg) 2491 endfor 2492 assert_equal(['a', 'b', 'c', 'd', 'e', 'f'], slist) 2493 2494 slist = [] 2495 for [g:globalvar, b:bufvar, w:winvar, t:tabvar] in [['global', 'buf', 'win', 'tab'], ['1', '2', '3', '4']] 2496 slist->add(g:globalvar) 2497 slist->add(b:bufvar) 2498 slist->add(w:winvar) 2499 slist->add(t:tabvar) 2500 endfor 2501 assert_equal(['global', 'buf', 'win', 'tab', '1', '2', '3', '4'], slist) 2502 unlet! g:globalvar b:bufvar w:winvar t:tabvar 2503 2504 var res = [] 2505 for [_, n, _] in [[1, 2, 3], [4, 5, 6]] 2506 res->add(n) 2507 endfor 2508 assert_equal([2, 5], res) 2509 END 2510 CheckDefAndScriptSuccess(lines) 2511 2512 lines =<< trim END 2513 for [v1, v2] in [[1, 2, 3], [3, 4]] 2514 echo v1 v2 2515 endfor 2516 END 2517 CheckDefExecFailure(lines, 'E710:', 1) 2518 2519 lines =<< trim END 2520 for [v1, v2] in [[1], [3, 4]] 2521 echo v1 v2 2522 endfor 2523 END 2524 CheckDefExecFailure(lines, 'E711:', 1) 2525 2526 lines =<< trim END 2527 for [v1, v1] in [[1, 2], [3, 4]] 2528 echo v1 2529 endfor 2530 END 2531 CheckDefExecFailure(lines, 'E1017:', 1) 2532enddef 2533 2534def Test_for_loop_with_try_continue() 2535 var lines =<< trim END 2536 var looped = 0 2537 var cleanup = 0 2538 for i in range(3) 2539 looped += 1 2540 try 2541 eval [][0] 2542 catch 2543 continue 2544 finally 2545 cleanup += 1 2546 endtry 2547 endfor 2548 assert_equal(3, looped) 2549 assert_equal(3, cleanup) 2550 END 2551 CheckDefAndScriptSuccess(lines) 2552enddef 2553 2554def Test_while_loop() 2555 var result = '' 2556 var cnt = 0 2557 while cnt < 555 2558 if cnt == 3 2559 break 2560 endif 2561 cnt += 1 2562 if cnt == 2 2563 continue 2564 endif 2565 result ..= cnt .. '_' 2566 endwhile 2567 assert_equal('1_3_', result) 2568 2569 var s = '' 2570 while s == 'x' # {comment} 2571 endwhile 2572enddef 2573 2574def Test_while_loop_fails() 2575 CheckDefFailure(['while xxx'], 'E1001:') 2576 CheckDefFailure(['endwhile'], 'E588:') 2577 CheckDefFailure(['continue'], 'E586:') 2578 CheckDefFailure(['if true', 'continue'], 'E586:') 2579 CheckDefFailure(['break'], 'E587:') 2580 CheckDefFailure(['if true', 'break'], 'E587:') 2581 CheckDefFailure(['while 1', 'echo 3'], 'E170:') 2582 2583 var lines =<< trim END 2584 var s = '' 2585 while s = '' 2586 endwhile 2587 END 2588 CheckDefFailure(lines, 'E488:') 2589enddef 2590 2591def Test_interrupt_loop() 2592 var caught = false 2593 var x = 0 2594 try 2595 while 1 2596 x += 1 2597 if x == 100 2598 feedkeys("\<C-C>", 'Lt') 2599 endif 2600 endwhile 2601 catch 2602 caught = true 2603 assert_equal(100, x) 2604 endtry 2605 assert_true(caught, 'should have caught an exception') 2606 # consume the CTRL-C 2607 getchar(0) 2608enddef 2609 2610def Test_automatic_line_continuation() 2611 var mylist = [ 2612 'one', 2613 'two', 2614 'three', 2615 ] # comment 2616 assert_equal(['one', 'two', 'three'], mylist) 2617 2618 var mydict = { 2619 ['one']: 1, 2620 ['two']: 2, 2621 ['three']: 2622 3, 2623 } # comment 2624 assert_equal({one: 1, two: 2, three: 3}, mydict) 2625 mydict = { 2626 one: 1, # comment 2627 two: # comment 2628 2, # comment 2629 three: 3 # comment 2630 } 2631 assert_equal({one: 1, two: 2, three: 3}, mydict) 2632 mydict = { 2633 one: 1, 2634 two: 2635 2, 2636 three: 3 2637 } 2638 assert_equal({one: 1, two: 2, three: 3}, mydict) 2639 2640 assert_equal( 2641 ['one', 'two', 'three'], 2642 split('one two three') 2643 ) 2644enddef 2645 2646def Test_vim9_comment() 2647 CheckScriptSuccess([ 2648 'vim9script', 2649 '# something', 2650 '#something', 2651 '#{something', 2652 ]) 2653 2654 split Xfile 2655 CheckScriptSuccess([ 2656 'vim9script', 2657 'edit #something', 2658 ]) 2659 CheckScriptSuccess([ 2660 'vim9script', 2661 'edit #{something', 2662 ]) 2663 close 2664 2665 CheckScriptFailure([ 2666 'vim9script', 2667 ':# something', 2668 ], 'E488:') 2669 CheckScriptFailure([ 2670 '# something', 2671 ], 'E488:') 2672 CheckScriptFailure([ 2673 ':# something', 2674 ], 'E488:') 2675 2676 { # block start 2677 } # block end 2678 CheckDefFailure([ 2679 '{# comment', 2680 ], 'E488:') 2681 CheckDefFailure([ 2682 '{', 2683 '}# comment', 2684 ], 'E488:') 2685 2686 echo "yes" # comment 2687 CheckDefFailure([ 2688 'echo "yes"# comment', 2689 ], 'E488:') 2690 CheckScriptSuccess([ 2691 'vim9script', 2692 'echo "yes" # something', 2693 ]) 2694 CheckScriptFailure([ 2695 'vim9script', 2696 'echo "yes"# something', 2697 ], 'E121:') 2698 CheckScriptFailure([ 2699 'vim9script', 2700 'echo# something', 2701 ], 'E1144:') 2702 CheckScriptFailure([ 2703 'echo "yes" # something', 2704 ], 'E121:') 2705 2706 exe "echo" # comment 2707 CheckDefFailure([ 2708 'exe "echo"# comment', 2709 ], 'E488:') 2710 CheckScriptSuccess([ 2711 'vim9script', 2712 'exe "echo" # something', 2713 ]) 2714 CheckScriptFailure([ 2715 'vim9script', 2716 'exe "echo"# something', 2717 ], 'E121:') 2718 CheckScriptFailure([ 2719 'vim9script', 2720 'exe# something', 2721 ], 'E1144:') 2722 CheckScriptFailure([ 2723 'exe "echo" # something', 2724 ], 'E121:') 2725 2726 CheckDefFailure([ 2727 'try# comment', 2728 ' echo "yes"', 2729 'catch', 2730 'endtry', 2731 ], 'E1144:') 2732 CheckScriptFailure([ 2733 'vim9script', 2734 'try# comment', 2735 'echo "yes"', 2736 ], 'E1144:') 2737 CheckDefFailure([ 2738 'try', 2739 ' throw#comment', 2740 'catch', 2741 'endtry', 2742 ], 'E1144:') 2743 CheckDefFailure([ 2744 'try', 2745 ' throw "yes"#comment', 2746 'catch', 2747 'endtry', 2748 ], 'E488:') 2749 CheckDefFailure([ 2750 'try', 2751 ' echo "yes"', 2752 'catch# comment', 2753 'endtry', 2754 ], 'E1144:') 2755 CheckScriptFailure([ 2756 'vim9script', 2757 'try', 2758 ' echo "yes"', 2759 'catch# comment', 2760 'endtry', 2761 ], 'E1144:') 2762 CheckDefFailure([ 2763 'try', 2764 ' echo "yes"', 2765 'catch /pat/# comment', 2766 'endtry', 2767 ], 'E488:') 2768 CheckDefFailure([ 2769 'try', 2770 'echo "yes"', 2771 'catch', 2772 'endtry# comment', 2773 ], 'E1144:') 2774 CheckScriptFailure([ 2775 'vim9script', 2776 'try', 2777 ' echo "yes"', 2778 'catch', 2779 'endtry# comment', 2780 ], 'E1144:') 2781 2782 CheckScriptSuccess([ 2783 'vim9script', 2784 'hi # comment', 2785 ]) 2786 CheckScriptFailure([ 2787 'vim9script', 2788 'hi# comment', 2789 ], 'E1144:') 2790 CheckScriptSuccess([ 2791 'vim9script', 2792 'hi Search # comment', 2793 ]) 2794 CheckScriptFailure([ 2795 'vim9script', 2796 'hi Search# comment', 2797 ], 'E416:') 2798 CheckScriptSuccess([ 2799 'vim9script', 2800 'hi link This Search # comment', 2801 ]) 2802 CheckScriptFailure([ 2803 'vim9script', 2804 'hi link This That# comment', 2805 ], 'E413:') 2806 CheckScriptSuccess([ 2807 'vim9script', 2808 'hi clear This # comment', 2809 'hi clear # comment', 2810 ]) 2811 # not tested, because it doesn't give an error but a warning: 2812 # hi clear This# comment', 2813 CheckScriptFailure([ 2814 'vim9script', 2815 'hi clear# comment', 2816 ], 'E416:') 2817 2818 CheckScriptSuccess([ 2819 'vim9script', 2820 'hi Group term=bold', 2821 'match Group /todo/ # comment', 2822 ]) 2823 CheckScriptFailure([ 2824 'vim9script', 2825 'hi Group term=bold', 2826 'match Group /todo/# comment', 2827 ], 'E488:') 2828 CheckScriptSuccess([ 2829 'vim9script', 2830 'match # comment', 2831 ]) 2832 CheckScriptFailure([ 2833 'vim9script', 2834 'match# comment', 2835 ], 'E1144:') 2836 CheckScriptSuccess([ 2837 'vim9script', 2838 'match none # comment', 2839 ]) 2840 CheckScriptFailure([ 2841 'vim9script', 2842 'match none# comment', 2843 ], 'E475:') 2844 2845 CheckScriptSuccess([ 2846 'vim9script', 2847 'menutrans clear # comment', 2848 ]) 2849 CheckScriptFailure([ 2850 'vim9script', 2851 'menutrans clear# comment text', 2852 ], 'E474:') 2853 2854 CheckScriptSuccess([ 2855 'vim9script', 2856 'syntax clear # comment', 2857 ]) 2858 CheckScriptFailure([ 2859 'vim9script', 2860 'syntax clear# comment text', 2861 ], 'E28:') 2862 CheckScriptSuccess([ 2863 'vim9script', 2864 'syntax keyword Word some', 2865 'syntax clear Word # comment', 2866 ]) 2867 CheckScriptFailure([ 2868 'vim9script', 2869 'syntax keyword Word some', 2870 'syntax clear Word# comment text', 2871 ], 'E28:') 2872 2873 CheckScriptSuccess([ 2874 'vim9script', 2875 'syntax list # comment', 2876 ]) 2877 CheckScriptFailure([ 2878 'vim9script', 2879 'syntax list# comment text', 2880 ], 'E28:') 2881 2882 CheckScriptSuccess([ 2883 'vim9script', 2884 'syntax match Word /pat/ oneline # comment', 2885 ]) 2886 CheckScriptFailure([ 2887 'vim9script', 2888 'syntax match Word /pat/ oneline# comment', 2889 ], 'E475:') 2890 2891 CheckScriptSuccess([ 2892 'vim9script', 2893 'syntax keyword Word word # comm[ent', 2894 ]) 2895 CheckScriptFailure([ 2896 'vim9script', 2897 'syntax keyword Word word# comm[ent', 2898 ], 'E789:') 2899 2900 CheckScriptSuccess([ 2901 'vim9script', 2902 'syntax match Word /pat/ # comment', 2903 ]) 2904 CheckScriptFailure([ 2905 'vim9script', 2906 'syntax match Word /pat/# comment', 2907 ], 'E402:') 2908 2909 CheckScriptSuccess([ 2910 'vim9script', 2911 'syntax match Word /pat/ contains=Something # comment', 2912 ]) 2913 CheckScriptFailure([ 2914 'vim9script', 2915 'syntax match Word /pat/ contains=Something# comment', 2916 ], 'E475:') 2917 CheckScriptFailure([ 2918 'vim9script', 2919 'syntax match Word /pat/ contains= # comment', 2920 ], 'E406:') 2921 CheckScriptFailure([ 2922 'vim9script', 2923 'syntax match Word /pat/ contains=# comment', 2924 ], 'E475:') 2925 2926 CheckScriptSuccess([ 2927 'vim9script', 2928 'syntax region Word start=/pat/ end=/pat/ # comment', 2929 ]) 2930 CheckScriptFailure([ 2931 'vim9script', 2932 'syntax region Word start=/pat/ end=/pat/# comment', 2933 ], 'E402:') 2934 2935 CheckScriptSuccess([ 2936 'vim9script', 2937 'syntax sync # comment', 2938 ]) 2939 CheckScriptFailure([ 2940 'vim9script', 2941 'syntax sync# comment', 2942 ], 'E404:') 2943 CheckScriptSuccess([ 2944 'vim9script', 2945 'syntax sync ccomment # comment', 2946 ]) 2947 CheckScriptFailure([ 2948 'vim9script', 2949 'syntax sync ccomment# comment', 2950 ], 'E404:') 2951 2952 CheckScriptSuccess([ 2953 'vim9script', 2954 'syntax cluster Some contains=Word # comment', 2955 ]) 2956 CheckScriptFailure([ 2957 'vim9script', 2958 'syntax cluster Some contains=Word# comment', 2959 ], 'E475:') 2960 2961 CheckScriptSuccess([ 2962 'vim9script', 2963 'command Echo echo # comment', 2964 'command Echo # comment', 2965 'delcommand Echo', 2966 ]) 2967 CheckScriptFailure([ 2968 'vim9script', 2969 'command Echo echo# comment', 2970 'Echo', 2971 ], 'E1144:') 2972 delcommand Echo 2973 2974 var curdir = getcwd() 2975 CheckScriptSuccess([ 2976 'command Echo cd " comment', 2977 'Echo', 2978 'delcommand Echo', 2979 ]) 2980 CheckScriptSuccess([ 2981 'vim9script', 2982 'command Echo cd # comment', 2983 'Echo', 2984 'delcommand Echo', 2985 ]) 2986 CheckScriptFailure([ 2987 'vim9script', 2988 'command Echo cd " comment', 2989 'Echo', 2990 ], 'E344:') 2991 delcommand Echo 2992 chdir(curdir) 2993 2994 CheckScriptFailure([ 2995 'vim9script', 2996 'command Echo# comment', 2997 ], 'E182:') 2998 CheckScriptFailure([ 2999 'vim9script', 3000 'command Echo echo', 3001 'command Echo# comment', 3002 ], 'E182:') 3003 delcommand Echo 3004 3005 CheckScriptSuccess([ 3006 'vim9script', 3007 'function # comment', 3008 ]) 3009 CheckScriptFailure([ 3010 'vim9script', 3011 'function " comment', 3012 ], 'E129:') 3013 CheckScriptFailure([ 3014 'vim9script', 3015 'function# comment', 3016 ], 'E1144:') 3017 CheckScriptSuccess([ 3018 'vim9script', 3019 'function CheckScriptSuccess # comment', 3020 ]) 3021 CheckScriptFailure([ 3022 'vim9script', 3023 'function CheckScriptSuccess# comment', 3024 ], 'E488:') 3025 3026 CheckScriptSuccess([ 3027 'vim9script', 3028 'func g:DeleteMeA()', 3029 'endfunc', 3030 'delfunction g:DeleteMeA # comment', 3031 ]) 3032 CheckScriptFailure([ 3033 'vim9script', 3034 'func g:DeleteMeB()', 3035 'endfunc', 3036 'delfunction g:DeleteMeB# comment', 3037 ], 'E488:') 3038 3039 CheckScriptSuccess([ 3040 'vim9script', 3041 'call execute("ls") # comment', 3042 ]) 3043 CheckScriptFailure([ 3044 'vim9script', 3045 'call execute("ls")# comment', 3046 ], 'E488:') 3047 3048 CheckScriptFailure([ 3049 'def Test() " comment', 3050 'enddef', 3051 ], 'E488:') 3052 CheckScriptFailure([ 3053 'vim9script', 3054 'def Test() " comment', 3055 'enddef', 3056 ], 'E488:') 3057 3058 CheckScriptSuccess([ 3059 'func Test() " comment', 3060 'endfunc', 3061 'delfunc Test', 3062 ]) 3063 CheckScriptSuccess([ 3064 'vim9script', 3065 'func Test() " comment', 3066 'endfunc', 3067 ]) 3068 3069 CheckScriptSuccess([ 3070 'def Test() # comment', 3071 'enddef', 3072 ]) 3073 CheckScriptFailure([ 3074 'func Test() # comment', 3075 'endfunc', 3076 ], 'E488:') 3077 3078 var lines =<< trim END 3079 vim9script 3080 syn region Text 3081 \ start='foo' 3082 #\ comment 3083 \ end='bar' 3084 syn region Text start='foo' 3085 #\ comment 3086 \ end='bar' 3087 END 3088 CheckScriptSuccess(lines) 3089 3090 lines =<< trim END 3091 vim9script 3092 syn region Text 3093 \ start='foo' 3094 "\ comment 3095 \ end='bar' 3096 END 3097 CheckScriptFailure(lines, 'E399:') 3098enddef 3099 3100def Test_vim9_comment_gui() 3101 CheckCanRunGui 3102 3103 CheckScriptFailure([ 3104 'vim9script', 3105 'gui#comment' 3106 ], 'E1144:') 3107 CheckScriptFailure([ 3108 'vim9script', 3109 'gui -f#comment' 3110 ], 'E499:') 3111enddef 3112 3113def Test_vim9_comment_not_compiled() 3114 au TabEnter *.vim g:entered = 1 3115 au TabEnter *.x g:entered = 2 3116 3117 edit test.vim 3118 doautocmd TabEnter #comment 3119 assert_equal(1, g:entered) 3120 3121 doautocmd TabEnter f.x 3122 assert_equal(2, g:entered) 3123 3124 g:entered = 0 3125 doautocmd TabEnter f.x #comment 3126 assert_equal(2, g:entered) 3127 3128 assert_fails('doautocmd Syntax#comment', 'E216:') 3129 3130 au! TabEnter 3131 unlet g:entered 3132 3133 CheckScriptSuccess([ 3134 'vim9script', 3135 'g:var = 123', 3136 'b:var = 456', 3137 'w:var = 777', 3138 't:var = 888', 3139 'unlet g:var w:var # something', 3140 ]) 3141 3142 CheckScriptFailure([ 3143 'vim9script', 3144 'let var = 123', 3145 ], 'E1126: Cannot use :let in Vim9 script') 3146 3147 CheckScriptFailure([ 3148 'vim9script', 3149 'var g:var = 123', 3150 ], 'E1016: Cannot declare a global variable:') 3151 3152 CheckScriptFailure([ 3153 'vim9script', 3154 'var b:var = 123', 3155 ], 'E1016: Cannot declare a buffer variable:') 3156 3157 CheckScriptFailure([ 3158 'vim9script', 3159 'var w:var = 123', 3160 ], 'E1016: Cannot declare a window variable:') 3161 3162 CheckScriptFailure([ 3163 'vim9script', 3164 'var t:var = 123', 3165 ], 'E1016: Cannot declare a tab variable:') 3166 3167 CheckScriptFailure([ 3168 'vim9script', 3169 'var v:version = 123', 3170 ], 'E1016: Cannot declare a v: variable:') 3171 3172 CheckScriptFailure([ 3173 'vim9script', 3174 'var $VARIABLE = "text"', 3175 ], 'E1016: Cannot declare an environment variable:') 3176 3177 CheckScriptFailure([ 3178 'vim9script', 3179 'g:var = 123', 3180 'unlet g:var# comment1', 3181 ], 'E108:') 3182 3183 CheckScriptFailure([ 3184 'let g:var = 123', 3185 'unlet g:var # something', 3186 ], 'E488:') 3187 3188 CheckScriptSuccess([ 3189 'vim9script', 3190 'if 1 # comment2', 3191 ' echo "yes"', 3192 'elseif 2 #comment', 3193 ' echo "no"', 3194 'endif', 3195 ]) 3196 3197 CheckScriptFailure([ 3198 'vim9script', 3199 'if 1# comment3', 3200 ' echo "yes"', 3201 'endif', 3202 ], 'E15:') 3203 3204 CheckScriptFailure([ 3205 'vim9script', 3206 'if 0 # comment4', 3207 ' echo "yes"', 3208 'elseif 2#comment', 3209 ' echo "no"', 3210 'endif', 3211 ], 'E15:') 3212 3213 CheckScriptSuccess([ 3214 'vim9script', 3215 'var v = 1 # comment5', 3216 ]) 3217 3218 CheckScriptFailure([ 3219 'vim9script', 3220 'var v = 1# comment6', 3221 ], 'E15:') 3222 3223 CheckScriptSuccess([ 3224 'vim9script', 3225 'new' 3226 'setline(1, ["# define pat", "last"])', 3227 ':$', 3228 'dsearch /pat/ #comment', 3229 'bwipe!', 3230 ]) 3231 3232 CheckScriptFailure([ 3233 'vim9script', 3234 'new' 3235 'setline(1, ["# define pat", "last"])', 3236 ':$', 3237 'dsearch /pat/#comment', 3238 'bwipe!', 3239 ], 'E488:') 3240 3241 CheckScriptFailure([ 3242 'vim9script', 3243 'func! SomeFunc()', 3244 ], 'E477:') 3245enddef 3246 3247def Test_finish() 3248 var lines =<< trim END 3249 vim9script 3250 g:res = 'one' 3251 if v:false | finish | endif 3252 g:res = 'two' 3253 finish 3254 g:res = 'three' 3255 END 3256 writefile(lines, 'Xfinished') 3257 source Xfinished 3258 assert_equal('two', g:res) 3259 3260 unlet g:res 3261 delete('Xfinished') 3262enddef 3263 3264def Test_forward_declaration() 3265 var lines =<< trim END 3266 vim9script 3267 def GetValue(): string 3268 return theVal 3269 enddef 3270 var theVal = 'something' 3271 g:initVal = GetValue() 3272 theVal = 'else' 3273 g:laterVal = GetValue() 3274 END 3275 writefile(lines, 'Xforward') 3276 source Xforward 3277 assert_equal('something', g:initVal) 3278 assert_equal('else', g:laterVal) 3279 3280 unlet g:initVal 3281 unlet g:laterVal 3282 delete('Xforward') 3283enddef 3284 3285def Test_source_vim9_from_legacy() 3286 var vim9_lines =<< trim END 3287 vim9script 3288 var local = 'local' 3289 g:global = 'global' 3290 export var exported = 'exported' 3291 export def GetText(): string 3292 return 'text' 3293 enddef 3294 END 3295 writefile(vim9_lines, 'Xvim9_script.vim') 3296 3297 var legacy_lines =<< trim END 3298 source Xvim9_script.vim 3299 3300 call assert_false(exists('local')) 3301 call assert_false(exists('exported')) 3302 call assert_false(exists('s:exported')) 3303 call assert_equal('global', global) 3304 call assert_equal('global', g:global) 3305 3306 " imported variable becomes script-local 3307 import exported from './Xvim9_script.vim' 3308 call assert_equal('exported', s:exported) 3309 call assert_false(exists('exported')) 3310 3311 " imported function becomes script-local 3312 import GetText from './Xvim9_script.vim' 3313 call assert_equal('text', s:GetText()) 3314 call assert_false(exists('*GetText')) 3315 END 3316 writefile(legacy_lines, 'Xlegacy_script.vim') 3317 3318 source Xlegacy_script.vim 3319 assert_equal('global', g:global) 3320 unlet g:global 3321 3322 delete('Xlegacy_script.vim') 3323 delete('Xvim9_script.vim') 3324enddef 3325 3326def Test_declare_script_in_func() 3327 var lines =<< trim END 3328 vim9script 3329 func Declare() 3330 let s:local = 123 3331 endfunc 3332 Declare() 3333 assert_equal(123, local) 3334 3335 var error: string 3336 try 3337 local = 'asdf' 3338 catch 3339 error = v:exception 3340 endtry 3341 assert_match('E1012: Type mismatch; expected number but got string', error) 3342 3343 lockvar local 3344 try 3345 local = 999 3346 catch 3347 error = v:exception 3348 endtry 3349 assert_match('E741: Value is locked: local', error) 3350 END 3351 CheckScriptSuccess(lines) 3352enddef 3353 3354 3355func Test_vim9script_not_global() 3356 " check that items defined in Vim9 script are script-local, not global 3357 let vim9lines =<< trim END 3358 vim9script 3359 var name = 'local' 3360 func TheFunc() 3361 echo 'local' 3362 endfunc 3363 def DefFunc() 3364 echo 'local' 3365 enddef 3366 END 3367 call writefile(vim9lines, 'Xvim9script.vim') 3368 source Xvim9script.vim 3369 try 3370 echo g:var 3371 assert_report('did not fail') 3372 catch /E121:/ 3373 " caught 3374 endtry 3375 try 3376 call TheFunc() 3377 assert_report('did not fail') 3378 catch /E117:/ 3379 " caught 3380 endtry 3381 try 3382 call DefFunc() 3383 assert_report('did not fail') 3384 catch /E117:/ 3385 " caught 3386 endtry 3387 3388 call delete('Xvim9script.vim') 3389endfunc 3390 3391def Test_vim9_copen() 3392 # this was giving an error for setting w:quickfix_title 3393 copen 3394 quit 3395enddef 3396 3397" test using an auto-loaded function and variable 3398def Test_vim9_autoload() 3399 var lines =<< trim END 3400 vim9script 3401 def some#gettest(): string 3402 return 'test' 3403 enddef 3404 g:some#name = 'name' 3405 g:some#dict = {key: 'value'} 3406 3407 def some#varargs(a1: string, ...l: list<string>): string 3408 return a1 .. l[0] .. l[1] 3409 enddef 3410 END 3411 3412 mkdir('Xdir/autoload', 'p') 3413 writefile(lines, 'Xdir/autoload/some.vim') 3414 var save_rtp = &rtp 3415 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3416 3417 assert_equal('test', g:some#gettest()) 3418 assert_equal('name', g:some#name) 3419 assert_equal('value', g:some#dict.key) 3420 g:some#other = 'other' 3421 assert_equal('other', g:some#other) 3422 3423 assert_equal('abc', some#varargs('a', 'b', 'c')) 3424 3425 # upper case script name works 3426 lines =<< trim END 3427 vim9script 3428 def Other#getOther(): string 3429 return 'other' 3430 enddef 3431 END 3432 writefile(lines, 'Xdir/autoload/Other.vim') 3433 assert_equal('other', g:Other#getOther()) 3434 3435 delete('Xdir', 'rf') 3436 &rtp = save_rtp 3437enddef 3438 3439" test using a vim9script that is auto-loaded from an autocmd 3440def Test_vim9_aucmd_autoload() 3441 var lines =<< trim END 3442 vim9script 3443 def foo#test() 3444 echomsg getreg('"') 3445 enddef 3446 END 3447 3448 mkdir('Xdir/autoload', 'p') 3449 writefile(lines, 'Xdir/autoload/foo.vim') 3450 var save_rtp = &rtp 3451 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3452 augroup test 3453 autocmd TextYankPost * call foo#test() 3454 augroup END 3455 3456 normal Y 3457 3458 augroup test 3459 autocmd! 3460 augroup END 3461 delete('Xdir', 'rf') 3462 &rtp = save_rtp 3463enddef 3464 3465" This was causing a crash because suppress_errthrow wasn't reset. 3466def Test_vim9_autoload_error() 3467 var lines =<< trim END 3468 vim9script 3469 def crash#func() 3470 try 3471 for x in List() 3472 endfor 3473 catch 3474 endtry 3475 g:ok = true 3476 enddef 3477 fu List() 3478 invalid 3479 endfu 3480 try 3481 alsoinvalid 3482 catch /wontmatch/ 3483 endtry 3484 END 3485 call mkdir('Xruntime/autoload', 'p') 3486 call writefile(lines, 'Xruntime/autoload/crash.vim') 3487 3488 # run in a separate Vim to avoid the side effects of assert_fails() 3489 lines =<< trim END 3490 exe 'set rtp^=' .. getcwd() .. '/Xruntime' 3491 call crash#func() 3492 call writefile(['ok'], 'Xdidit') 3493 qall! 3494 END 3495 writefile(lines, 'Xscript') 3496 RunVim([], [], '-S Xscript') 3497 assert_equal(['ok'], readfile('Xdidit')) 3498 3499 delete('Xdidit') 3500 delete('Xscript') 3501 delete('Xruntime', 'rf') 3502 3503 lines =<< trim END 3504 vim9script 3505 var foo#bar = 'asdf' 3506 END 3507 CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2) 3508enddef 3509 3510def Test_script_var_in_autocmd() 3511 # using a script variable from an autocommand, defined in a :def function in a 3512 # legacy Vim script, cannot check the variable type. 3513 var lines =<< trim END 3514 let s:counter = 1 3515 def s:Func() 3516 au! CursorHold 3517 au CursorHold * s:counter += 1 3518 enddef 3519 call s:Func() 3520 doau CursorHold 3521 call assert_equal(2, s:counter) 3522 au! CursorHold 3523 END 3524 CheckScriptSuccess(lines) 3525enddef 3526 3527def Test_cmdline_win() 3528 # if the Vim syntax highlighting uses Vim9 constructs they can be used from 3529 # the command line window. 3530 mkdir('rtp/syntax', 'p') 3531 var export_lines =<< trim END 3532 vim9script 3533 export var That = 'yes' 3534 END 3535 writefile(export_lines, 'rtp/syntax/Xexport.vim') 3536 var import_lines =<< trim END 3537 vim9script 3538 import That from './Xexport.vim' 3539 END 3540 writefile(import_lines, 'rtp/syntax/vim.vim') 3541 var save_rtp = &rtp 3542 &rtp = getcwd() .. '/rtp' .. ',' .. &rtp 3543 syntax on 3544 augroup CmdWin 3545 autocmd CmdwinEnter * g:got_there = 'yes' 3546 augroup END 3547 # this will open and also close the cmdline window 3548 feedkeys('q:', 'xt') 3549 assert_equal('yes', g:got_there) 3550 3551 augroup CmdWin 3552 au! 3553 augroup END 3554 &rtp = save_rtp 3555 delete('rtp', 'rf') 3556enddef 3557 3558def Test_invalid_sid() 3559 assert_fails('func <SNR>1234_func', 'E123:') 3560 3561 if RunVim([], ['wq! Xdidit'], '+"func <SNR>1_func"') 3562 assert_equal([], readfile('Xdidit')) 3563 endif 3564 delete('Xdidit') 3565enddef 3566 3567def Test_restoring_cpo() 3568 writefile(['vim9script', 'set nocp'], 'Xsourced') 3569 writefile(['call writefile(["done"], "Xdone")', 'quit!'], 'Xclose') 3570 if RunVim([], [], '-u NONE +"set cpo+=a" -S Xsourced -S Xclose') 3571 assert_equal(['done'], readfile('Xdone')) 3572 endif 3573 delete('Xsourced') 3574 delete('Xclose') 3575 delete('Xdone') 3576 3577 writefile(['vim9script'], 'XanotherScript') 3578 set cpo=aABceFsMny> 3579 edit XanotherScript 3580 so % 3581 assert_equal('aABceFsMny>', &cpo) 3582 :1del 3583 w 3584 so % 3585 assert_equal('aABceFsMny>', &cpo) 3586 3587 delete('XanotherScript') 3588 set cpo&vim 3589enddef 3590 3591" Use :function so we can use Check commands 3592func Test_no_redraw_when_restoring_cpo() 3593 CheckScreendump 3594 CheckFeature timers 3595 3596 let lines =<< trim END 3597 vim9script 3598 def script#func() 3599 enddef 3600 END 3601 call mkdir('Xdir/autoload', 'p') 3602 call writefile(lines, 'Xdir/autoload/script.vim') 3603 3604 let lines =<< trim END 3605 vim9script 3606 set cpo+=M 3607 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3608 au CmdlineEnter : ++once timer_start(0, (_) => script#func()) 3609 setline(1, 'some text') 3610 END 3611 call writefile(lines, 'XTest_redraw_cpo') 3612 let buf = RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6}) 3613 call term_sendkeys(buf, "V:") 3614 call VerifyScreenDump(buf, 'Test_vim9_no_redraw', {}) 3615 3616 " clean up 3617 call term_sendkeys(buf, "\<Esc>u") 3618 call StopVimInTerminal(buf) 3619 call delete('XTest_redraw_cpo') 3620 call delete('Xdir', 'rf') 3621endfunc 3622 3623 3624def Test_unset_any_variable() 3625 var lines =<< trim END 3626 var name: any 3627 assert_equal(0, name) 3628 END 3629 CheckDefAndScriptSuccess(lines) 3630enddef 3631 3632func Test_define_func_at_command_line() 3633 CheckRunVimInTerminal 3634 3635 " call indirectly to avoid compilation error for missing functions 3636 call Run_Test_define_func_at_command_line() 3637endfunc 3638 3639def Run_Test_define_func_at_command_line() 3640 # run in a separate Vim instance to avoid the script context 3641 var lines =<< trim END 3642 func CheckAndQuit() 3643 call assert_fails('call Afunc()', 'E117: Unknown function: Bfunc') 3644 call writefile(['errors: ' .. string(v:errors)], 'Xdidcmd') 3645 endfunc 3646 END 3647 writefile([''], 'Xdidcmd') 3648 writefile(lines, 'XcallFunc') 3649 var buf = RunVimInTerminal('-S XcallFunc', {rows: 6}) 3650 # define Afunc() on the command line 3651 term_sendkeys(buf, ":def Afunc()\<CR>Bfunc()\<CR>enddef\<CR>") 3652 term_sendkeys(buf, ":call CheckAndQuit()\<CR>") 3653 WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd'))) 3654 3655 call StopVimInTerminal(buf) 3656 delete('XcallFunc') 3657 delete('Xdidcmd') 3658enddef 3659 3660def Test_script_var_scope() 3661 var lines =<< trim END 3662 vim9script 3663 if true 3664 if true 3665 var one = 'one' 3666 echo one 3667 endif 3668 echo one 3669 endif 3670 END 3671 CheckScriptFailure(lines, 'E121:', 7) 3672 3673 lines =<< trim END 3674 vim9script 3675 if true 3676 if false 3677 var one = 'one' 3678 echo one 3679 else 3680 var one = 'one' 3681 echo one 3682 endif 3683 echo one 3684 endif 3685 END 3686 CheckScriptFailure(lines, 'E121:', 10) 3687 3688 lines =<< trim END 3689 vim9script 3690 while true 3691 var one = 'one' 3692 echo one 3693 break 3694 endwhile 3695 echo one 3696 END 3697 CheckScriptFailure(lines, 'E121:', 7) 3698 3699 lines =<< trim END 3700 vim9script 3701 for i in range(1) 3702 var one = 'one' 3703 echo one 3704 endfor 3705 echo one 3706 END 3707 CheckScriptFailure(lines, 'E121:', 6) 3708 3709 lines =<< trim END 3710 vim9script 3711 { 3712 var one = 'one' 3713 assert_equal('one', one) 3714 } 3715 assert_false(exists('one')) 3716 assert_false(exists('s:one')) 3717 END 3718 CheckScriptSuccess(lines) 3719 3720 lines =<< trim END 3721 vim9script 3722 { 3723 var one = 'one' 3724 echo one 3725 } 3726 echo one 3727 END 3728 CheckScriptFailure(lines, 'E121:', 6) 3729enddef 3730 3731def Test_catch_exception_in_callback() 3732 var lines =<< trim END 3733 vim9script 3734 def Callback(...l: list<any>) 3735 try 3736 var x: string 3737 var y: string 3738 # this error should be caught with CHECKLEN 3739 [x, y] = [''] 3740 catch 3741 g:caught = 'yes' 3742 endtry 3743 enddef 3744 popup_menu('popup', {callback: Callback}) 3745 feedkeys("\r", 'xt') 3746 END 3747 CheckScriptSuccess(lines) 3748 3749 unlet g:caught 3750enddef 3751 3752def Test_no_unknown_error_after_error() 3753 if !has('unix') || !has('job') 3754 throw 'Skipped: not unix of missing +job feature' 3755 endif 3756 var lines =<< trim END 3757 vim9script 3758 var source: list<number> 3759 def Out_cb(...l: list<any>) 3760 eval [][0] 3761 enddef 3762 def Exit_cb(...l: list<any>) 3763 sleep 1m 3764 source += l 3765 enddef 3766 var myjob = job_start('echo burp', {out_cb: Out_cb, exit_cb: Exit_cb, mode: 'raw'}) 3767 while job_status(myjob) == 'run' 3768 sleep 10m 3769 endwhile 3770 # wait for Exit_cb() to be called 3771 sleep 200m 3772 END 3773 writefile(lines, 'Xdef') 3774 assert_fails('so Xdef', ['E684:', 'E1012:']) 3775 delete('Xdef') 3776enddef 3777 3778def InvokeNormal() 3779 exe "norm! :m+1\r" 3780enddef 3781 3782def Test_invoke_normal_in_visual_mode() 3783 xnoremap <F3> <Cmd>call <SID>InvokeNormal()<CR> 3784 new 3785 setline(1, ['aaa', 'bbb']) 3786 feedkeys("V\<F3>", 'xt') 3787 assert_equal(['bbb', 'aaa'], getline(1, 2)) 3788 xunmap <F3> 3789enddef 3790 3791def Test_white_space_after_command() 3792 var lines =<< trim END 3793 exit_cb: Func}) 3794 END 3795 CheckDefAndScriptFailure(lines, 'E1144:', 1) 3796 3797 lines =<< trim END 3798 e# 3799 END 3800 CheckDefAndScriptFailure(lines, 'E1144:', 1) 3801enddef 3802 3803def Test_script_var_gone_when_sourced_twice() 3804 var lines =<< trim END 3805 vim9script 3806 if exists('g:guard') 3807 finish 3808 endif 3809 g:guard = 1 3810 var name = 'thename' 3811 def g:GetName(): string 3812 return name 3813 enddef 3814 def g:SetName(arg: string) 3815 name = arg 3816 enddef 3817 END 3818 writefile(lines, 'XscriptTwice.vim') 3819 so XscriptTwice.vim 3820 assert_equal('thename', g:GetName()) 3821 g:SetName('newname') 3822 assert_equal('newname', g:GetName()) 3823 so XscriptTwice.vim 3824 assert_fails('call g:GetName()', 'E1149:') 3825 assert_fails('call g:SetName("x")', 'E1149:') 3826 3827 delfunc g:GetName 3828 delfunc g:SetName 3829 delete('XscriptTwice.vim') 3830 unlet g:guard 3831enddef 3832 3833def Test_import_gone_when_sourced_twice() 3834 var exportlines =<< trim END 3835 vim9script 3836 if exists('g:guard') 3837 finish 3838 endif 3839 g:guard = 1 3840 export var name = 'someName' 3841 END 3842 writefile(exportlines, 'XexportScript.vim') 3843 3844 var lines =<< trim END 3845 vim9script 3846 import name from './XexportScript.vim' 3847 def g:GetName(): string 3848 return name 3849 enddef 3850 END 3851 writefile(lines, 'XscriptImport.vim') 3852 so XscriptImport.vim 3853 assert_equal('someName', g:GetName()) 3854 3855 so XexportScript.vim 3856 assert_fails('call g:GetName()', 'E1149:') 3857 3858 delfunc g:GetName 3859 delete('XexportScript.vim') 3860 delete('XscriptImport.vim') 3861 unlet g:guard 3862enddef 3863 3864def Test_unsupported_commands() 3865 var lines =<< trim END 3866 ka 3867 END 3868 CheckDefFailure(lines, 'E476:') 3869 CheckScriptFailure(['vim9script'] + lines, 'E492:') 3870 3871 lines =<< trim END 3872 :1ka 3873 END 3874 CheckDefFailure(lines, 'E476:') 3875 CheckScriptFailure(['vim9script'] + lines, 'E492:') 3876 3877 lines =<< trim END 3878 t 3879 END 3880 CheckDefFailure(lines, 'E1100:') 3881 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 3882 3883 lines =<< trim END 3884 x 3885 END 3886 CheckDefFailure(lines, 'E1100:') 3887 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 3888 3889 lines =<< trim END 3890 xit 3891 END 3892 CheckDefFailure(lines, 'E1100:') 3893 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 3894enddef 3895 3896def Test_mapping_line_number() 3897 var lines =<< trim END 3898 vim9script 3899 def g:FuncA() 3900 # Some comment 3901 FuncB(0) 3902 enddef 3903 # Some comment 3904 def FuncB( 3905 # Some comment 3906 n: number 3907 ) 3908 exe 'nno ' 3909 # Some comment 3910 .. '<F3> a' 3911 .. 'b' 3912 .. 'c' 3913 enddef 3914 END 3915 CheckScriptSuccess(lines) 3916 var res = execute('verbose nmap <F3>') 3917 assert_match('No mapping found', res) 3918 3919 g:FuncA() 3920 res = execute('verbose nmap <F3>') 3921 assert_match(' <F3> .* abc.*Last set from .*XScriptSuccess\d\+ line 11', res) 3922 3923 nunmap <F3> 3924 delfunc g:FuncA 3925enddef 3926 3927" Keep this last, it messes up highlighting. 3928def Test_substitute_cmd() 3929 new 3930 setline(1, 'something') 3931 :substitute(some(other( 3932 assert_equal('otherthing', getline(1)) 3933 bwipe! 3934 3935 # also when the context is Vim9 script 3936 var lines =<< trim END 3937 vim9script 3938 new 3939 setline(1, 'something') 3940 :substitute(some(other( 3941 assert_equal('otherthing', getline(1)) 3942 bwipe! 3943 END 3944 writefile(lines, 'Xvim9lines') 3945 source Xvim9lines 3946 3947 delete('Xvim9lines') 3948enddef 3949 3950" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 3951