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