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