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