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