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_star_fails() 1481 writefile([], 'Xfoo.vim') 1482 var lines =<< trim END 1483 import * as foo from '/tmp/foo.vim' 1484 foo = 'bar' 1485 END 1486 CheckDefAndScriptFailure2(lines, 'E1094:', 'E1236: Cannot use foo itself') 1487 lines =<< trim END 1488 vim9script 1489 import * as foo from '/tmp/foo.vim' 1490 var that = foo 1491 END 1492 CheckScriptFailure(lines, 'E1029: Expected ''.''') 1493enddef 1494 1495def Test_import_as() 1496 var export_lines =<< trim END 1497 vim9script 1498 export var one = 1 1499 export var yes = 'yes' 1500 export var slist: list<string> 1501 END 1502 writefile(export_lines, 'XexportAs') 1503 1504 var import_lines =<< trim END 1505 vim9script 1506 var one = 'notused' 1507 var yes = 777 1508 import one as thatOne from './XexportAs' 1509 assert_equal(1, thatOne) 1510 import yes as yesYes from './XexportAs' 1511 assert_equal('yes', yesYes) 1512 END 1513 CheckScriptSuccess(import_lines) 1514 1515 import_lines =<< trim END 1516 vim9script 1517 import {one as thatOne, yes as yesYes} from './XexportAs' 1518 assert_equal(1, thatOne) 1519 assert_equal('yes', yesYes) 1520 assert_fails('echo one', 'E121:') 1521 assert_fails('echo yes', 'E121:') 1522 END 1523 CheckScriptSuccess(import_lines) 1524 1525 import_lines =<< trim END 1526 vim9script 1527 import {slist as impSlist} from './XexportAs' 1528 impSlist->add(123) 1529 END 1530 CheckScriptFailure(import_lines, 'E1012: Type mismatch; expected string but got number') 1531 1532 delete('XexportAs') 1533enddef 1534 1535func g:Trigger() 1536 source Ximport.vim 1537 return "echo 'yes'\<CR>" 1538endfunc 1539 1540def Test_import_export_expr_map() 1541 # check that :import and :export work when buffer is locked 1542 var export_lines =<< trim END 1543 vim9script 1544 export def That(): string 1545 return 'yes' 1546 enddef 1547 END 1548 writefile(export_lines, 'Xexport_that.vim') 1549 1550 var import_lines =<< trim END 1551 vim9script 1552 import That from './Xexport_that.vim' 1553 assert_equal('yes', That()) 1554 END 1555 writefile(import_lines, 'Ximport.vim') 1556 1557 nnoremap <expr> trigger g:Trigger() 1558 feedkeys('trigger', "xt") 1559 1560 delete('Xexport_that.vim') 1561 delete('Ximport.vim') 1562 nunmap trigger 1563enddef 1564 1565def Test_import_in_filetype() 1566 # check that :import works when the buffer is locked 1567 mkdir('ftplugin', 'p') 1568 var export_lines =<< trim END 1569 vim9script 1570 export var That = 'yes' 1571 END 1572 writefile(export_lines, 'ftplugin/Xexport_ft.vim') 1573 1574 var import_lines =<< trim END 1575 vim9script 1576 import That from './Xexport_ft.vim' 1577 assert_equal('yes', That) 1578 g:did_load_mytpe = 1 1579 END 1580 writefile(import_lines, 'ftplugin/qf.vim') 1581 1582 var save_rtp = &rtp 1583 &rtp = getcwd() .. ',' .. &rtp 1584 1585 filetype plugin on 1586 copen 1587 assert_equal(1, g:did_load_mytpe) 1588 1589 quit! 1590 delete('Xexport_ft.vim') 1591 delete('ftplugin', 'rf') 1592 &rtp = save_rtp 1593enddef 1594 1595def Test_use_import_in_mapping() 1596 var lines =<< trim END 1597 vim9script 1598 export def Funcx() 1599 g:result = 42 1600 enddef 1601 END 1602 writefile(lines, 'XsomeExport.vim') 1603 lines =<< trim END 1604 vim9script 1605 import Funcx from './XsomeExport.vim' 1606 nnoremap <F3> :call <sid>Funcx()<cr> 1607 END 1608 writefile(lines, 'Xmapscript.vim') 1609 1610 source Xmapscript.vim 1611 feedkeys("\<F3>", "xt") 1612 assert_equal(42, g:result) 1613 1614 unlet g:result 1615 delete('XsomeExport.vim') 1616 delete('Xmapscript.vim') 1617 nunmap <F3> 1618enddef 1619 1620def Test_vim9script_mix() 1621 var lines =<< trim END 1622 if has(g:feature) 1623 " legacy script 1624 let g:legacy = 1 1625 finish 1626 endif 1627 vim9script 1628 g:legacy = 0 1629 END 1630 g:feature = 'eval' 1631 g:legacy = -1 1632 CheckScriptSuccess(lines) 1633 assert_equal(1, g:legacy) 1634 1635 g:feature = 'noteval' 1636 g:legacy = -1 1637 CheckScriptSuccess(lines) 1638 assert_equal(0, g:legacy) 1639enddef 1640 1641def Test_vim9script_fails() 1642 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') 1643 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') 1644 CheckScriptFailure(['export var some = 123'], 'E1042:') 1645 CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:') 1646 CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:') 1647 CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') 1648 1649 CheckScriptFailure(['vim9script', 'var str: string', 'str = 1234'], 'E1012:') 1650 CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:') 1651 1652 assert_fails('vim9script', 'E1038:') 1653 assert_fails('export something', 'E1043:') 1654enddef 1655 1656func Test_import_fails_without_script() 1657 CheckRunVimInTerminal 1658 1659 " call indirectly to avoid compilation error for missing functions 1660 call Run_Test_import_fails_on_command_line() 1661endfunc 1662 1663def Run_Test_import_fails_on_command_line() 1664 var export =<< trim END 1665 vim9script 1666 export def Foo(): number 1667 return 0 1668 enddef 1669 END 1670 writefile(export, 'XexportCmd.vim') 1671 1672 var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', { 1673 rows: 6, wait_for_ruler: 0}) 1674 WaitForAssert(() => assert_match('^E1094:', term_getline(buf, 5))) 1675 1676 delete('XexportCmd.vim') 1677 StopVimInTerminal(buf) 1678enddef 1679 1680def Test_vim9script_reload_noclear() 1681 var lines =<< trim END 1682 vim9script 1683 export var exported = 'thexport' 1684 1685 export def TheFunc(x = 0) 1686 enddef 1687 END 1688 writefile(lines, 'XExportReload') 1689 lines =<< trim END 1690 vim9script noclear 1691 g:loadCount += 1 1692 var s:reloaded = 'init' 1693 import exported from './XExportReload' 1694 1695 def Again(): string 1696 return 'again' 1697 enddef 1698 1699 import TheFunc from './XExportReload' 1700 TheFunc() 1701 1702 if exists('s:loaded') | finish | endif 1703 var s:loaded = true 1704 1705 var s:notReloaded = 'yes' 1706 s:reloaded = 'first' 1707 def g:Values(): list<string> 1708 return [s:reloaded, s:notReloaded, Again(), Once(), exported] 1709 enddef 1710 1711 def Once(): string 1712 return 'once' 1713 enddef 1714 END 1715 writefile(lines, 'XReloaded') 1716 g:loadCount = 0 1717 source XReloaded 1718 assert_equal(1, g:loadCount) 1719 assert_equal(['first', 'yes', 'again', 'once', 'thexport'], g:Values()) 1720 source XReloaded 1721 assert_equal(2, g:loadCount) 1722 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1723 source XReloaded 1724 assert_equal(3, g:loadCount) 1725 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1726 1727 delete('XReloaded') 1728 delete('XExportReload') 1729 delfunc g:Values 1730 unlet g:loadCount 1731 1732 lines =<< trim END 1733 vim9script 1734 def Inner() 1735 enddef 1736 END 1737 lines->writefile('XreloadScript.vim') 1738 source XreloadScript.vim 1739 1740 lines =<< trim END 1741 vim9script 1742 def Outer() 1743 def Inner() 1744 enddef 1745 enddef 1746 defcompile 1747 END 1748 lines->writefile('XreloadScript.vim') 1749 source XreloadScript.vim 1750 1751 delete('XreloadScript.vim') 1752enddef 1753 1754def Test_vim9script_reload_import() 1755 var lines =<< trim END 1756 vim9script 1757 const var = '' 1758 var valone = 1234 1759 def MyFunc(arg: string) 1760 valone = 5678 1761 enddef 1762 END 1763 var morelines =<< trim END 1764 var valtwo = 222 1765 export def GetValtwo(): number 1766 return valtwo 1767 enddef 1768 END 1769 writefile(lines + morelines, 'Xreload.vim') 1770 source Xreload.vim 1771 source Xreload.vim 1772 source Xreload.vim 1773 1774 # cannot declare a var twice 1775 lines =<< trim END 1776 vim9script 1777 var valone = 1234 1778 var valone = 5678 1779 END 1780 writefile(lines, 'Xreload.vim') 1781 assert_fails('source Xreload.vim', 'E1041:', '', 3, 'Xreload.vim') 1782 1783 delete('Xreload.vim') 1784 delete('Ximport.vim') 1785enddef 1786 1787" if a script is reloaded with a script-local variable that changed its type, a 1788" compiled function using that variable must fail. 1789def Test_script_reload_change_type() 1790 var lines =<< trim END 1791 vim9script noclear 1792 var str = 'string' 1793 def g:GetStr(): string 1794 return str .. 'xxx' 1795 enddef 1796 END 1797 writefile(lines, 'Xreload.vim') 1798 source Xreload.vim 1799 echo g:GetStr() 1800 1801 lines =<< trim END 1802 vim9script noclear 1803 var str = 1234 1804 END 1805 writefile(lines, 'Xreload.vim') 1806 source Xreload.vim 1807 assert_fails('echo g:GetStr()', 'E1150:') 1808 1809 delfunc g:GetStr 1810 delete('Xreload.vim') 1811enddef 1812 1813" Define CallFunc so that the test can be compiled 1814command CallFunc echo 'nop' 1815 1816def Test_script_reload_from_function() 1817 var lines =<< trim END 1818 vim9script 1819 1820 if exists('g:loaded') 1821 finish 1822 endif 1823 g:loaded = 1 1824 delcommand CallFunc 1825 command CallFunc Func() 1826 def Func() 1827 so XreloadFunc.vim 1828 g:didTheFunc = 1 1829 enddef 1830 END 1831 writefile(lines, 'XreloadFunc.vim') 1832 source XreloadFunc.vim 1833 CallFunc 1834 assert_equal(1, g:didTheFunc) 1835 1836 delete('XreloadFunc.vim') 1837 delcommand CallFunc 1838 unlet g:loaded 1839 unlet g:didTheFunc 1840enddef 1841 1842def Test_script_var_shadows_function() 1843 var lines =<< trim END 1844 vim9script 1845 def Func(): number 1846 return 123 1847 enddef 1848 var Func = 1 1849 END 1850 CheckScriptFailure(lines, 'E1041:', 5) 1851enddef 1852 1853def Test_script_var_shadows_command() 1854 var lines =<< trim END 1855 var undo = 1 1856 undo = 2 1857 assert_equal(2, undo) 1858 END 1859 CheckDefAndScriptSuccess(lines) 1860 1861 lines =<< trim END 1862 var undo = 1 1863 undo 1864 END 1865 CheckDefAndScriptFailure(lines, 'E1207:', 2) 1866enddef 1867 1868def s:RetSome(): string 1869 return 'some' 1870enddef 1871 1872" Not exported function that is referenced needs to be accessed by the 1873" script-local name. 1874def Test_vim9script_funcref() 1875 var sortlines =<< trim END 1876 vim9script 1877 def Compare(i1: number, i2: number): number 1878 return i2 - i1 1879 enddef 1880 1881 export def FastSort(): list<number> 1882 return range(5)->sort(Compare) 1883 enddef 1884 1885 export def GetString(arg: string): string 1886 return arg 1887 enddef 1888 END 1889 writefile(sortlines, 'Xsort.vim') 1890 1891 var lines =<< trim END 1892 vim9script 1893 import FastSort from './Xsort.vim' 1894 def Test() 1895 g:result = FastSort() 1896 enddef 1897 Test() 1898 1899 # using a function imported with "as" 1900 import * as anAlias from './Xsort.vim' 1901 assert_equal('yes', anAlias.GetString('yes')) 1902 1903 # using the function from a compiled function 1904 def TestMore(): string 1905 var s = s:anAlias.GetString('foo') 1906 return s .. anAlias.GetString('bar') 1907 enddef 1908 assert_equal('foobar', TestMore()) 1909 1910 # error when using a function that isn't exported 1911 assert_fails('anAlias.Compare(1, 2)', 'E1049:') 1912 END 1913 writefile(lines, 'Xscript.vim') 1914 1915 source Xscript.vim 1916 assert_equal([4, 3, 2, 1, 0], g:result) 1917 1918 unlet g:result 1919 delete('Xsort.vim') 1920 delete('Xscript.vim') 1921 1922 var Funcref = function('s:RetSome') 1923 assert_equal('some', Funcref()) 1924enddef 1925 1926" Check that when searching for "FilterFunc" it finds the import in the 1927" script where FastFilter() is called from, both as a string and as a direct 1928" function reference. 1929def Test_vim9script_funcref_other_script() 1930 var filterLines =<< trim END 1931 vim9script 1932 export def FilterFunc(idx: number, val: number): bool 1933 return idx % 2 == 1 1934 enddef 1935 export def FastFilter(): list<number> 1936 return range(10)->filter('FilterFunc') 1937 enddef 1938 export def FastFilterDirect(): list<number> 1939 return range(10)->filter(FilterFunc) 1940 enddef 1941 END 1942 writefile(filterLines, 'Xfilter.vim') 1943 1944 var lines =<< trim END 1945 vim9script 1946 import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim' 1947 def Test() 1948 var x: list<number> = FastFilter() 1949 enddef 1950 Test() 1951 def TestDirect() 1952 var x: list<number> = FastFilterDirect() 1953 enddef 1954 TestDirect() 1955 END 1956 CheckScriptSuccess(lines) 1957 delete('Xfilter.vim') 1958enddef 1959 1960def Test_vim9script_reload_delfunc() 1961 var first_lines =<< trim END 1962 vim9script 1963 def FuncYes(): string 1964 return 'yes' 1965 enddef 1966 END 1967 var withno_lines =<< trim END 1968 def FuncNo(): string 1969 return 'no' 1970 enddef 1971 def g:DoCheck(no_exists: bool) 1972 assert_equal('yes', FuncYes()) 1973 assert_equal('no', FuncNo()) 1974 enddef 1975 END 1976 var nono_lines =<< trim END 1977 def g:DoCheck(no_exists: bool) 1978 assert_equal('yes', FuncYes()) 1979 assert_fails('FuncNo()', 'E117:', '', 2, 'DoCheck') 1980 enddef 1981 END 1982 1983 # FuncNo() is defined 1984 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1985 source Xreloaded.vim 1986 g:DoCheck(true) 1987 1988 # FuncNo() is not redefined 1989 writefile(first_lines + nono_lines, 'Xreloaded.vim') 1990 source Xreloaded.vim 1991 g:DoCheck(false) 1992 1993 # FuncNo() is back 1994 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1995 source Xreloaded.vim 1996 g:DoCheck(false) 1997 1998 delete('Xreloaded.vim') 1999enddef 2000 2001def Test_vim9script_reload_delvar() 2002 # write the script with a script-local variable 2003 var lines =<< trim END 2004 vim9script 2005 var name = 'string' 2006 END 2007 writefile(lines, 'XreloadVar.vim') 2008 source XreloadVar.vim 2009 2010 # now write the script using the same variable locally - works 2011 lines =<< trim END 2012 vim9script 2013 def Func() 2014 var name = 'string' 2015 enddef 2016 END 2017 writefile(lines, 'XreloadVar.vim') 2018 source XreloadVar.vim 2019 2020 delete('XreloadVar.vim') 2021enddef 2022 2023def Test_import_absolute() 2024 var import_lines = [ 2025 'vim9script', 2026 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 2027 'def UseExported()', 2028 ' g:imported_abs = exported', 2029 ' exported = 8888', 2030 ' g:imported_after = exported', 2031 'enddef', 2032 'UseExported()', 2033 'g:import_disassembled = execute("disass UseExported")', 2034 ] 2035 writefile(import_lines, 'Ximport_abs.vim') 2036 writefile(s:export_script_lines, 'Xexport_abs.vim') 2037 2038 source Ximport_abs.vim 2039 2040 assert_equal(9876, g:imported_abs) 2041 assert_equal(8888, g:imported_after) 2042 assert_match('<SNR>\d\+_UseExported\_s*' .. 2043 'g:imported_abs = exported\_s*' .. 2044 '0 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 2045 '1 STOREG g:imported_abs\_s*' .. 2046 'exported = 8888\_s*' .. 2047 '2 PUSHNR 8888\_s*' .. 2048 '3 STORESCRIPT exported-2 in .*Xexport_abs.vim\_s*' .. 2049 'g:imported_after = exported\_s*' .. 2050 '4 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 2051 '5 STOREG g:imported_after', 2052 g:import_disassembled) 2053 2054 Undo_export_script_lines() 2055 unlet g:imported_abs 2056 unlet g:import_disassembled 2057 2058 delete('Ximport_abs.vim') 2059 delete('Xexport_abs.vim') 2060enddef 2061 2062def Test_import_rtp() 2063 var import_lines = [ 2064 'vim9script', 2065 'import exported from "Xexport_rtp.vim"', 2066 'g:imported_rtp = exported', 2067 ] 2068 writefile(import_lines, 'Ximport_rtp.vim') 2069 mkdir('import', 'p') 2070 writefile(s:export_script_lines, 'import/Xexport_rtp.vim') 2071 2072 var save_rtp = &rtp 2073 &rtp = getcwd() 2074 source Ximport_rtp.vim 2075 &rtp = save_rtp 2076 2077 assert_equal(9876, g:imported_rtp) 2078 2079 Undo_export_script_lines() 2080 unlet g:imported_rtp 2081 delete('Ximport_rtp.vim') 2082 delete('import', 'rf') 2083enddef 2084 2085def Test_import_compile_error() 2086 var export_lines = [ 2087 'vim9script', 2088 'export def ExpFunc(): string', 2089 ' return notDefined', 2090 'enddef', 2091 ] 2092 writefile(export_lines, 'Xexported.vim') 2093 2094 var import_lines = [ 2095 'vim9script', 2096 'import ExpFunc from "./Xexported.vim"', 2097 'def ImpFunc()', 2098 ' echo ExpFunc()', 2099 'enddef', 2100 'defcompile', 2101 ] 2102 writefile(import_lines, 'Ximport.vim') 2103 2104 try 2105 source Ximport.vim 2106 catch /E1001/ 2107 # Error should be fore the Xexported.vim file. 2108 assert_match('E1001: Variable not found: notDefined', v:exception) 2109 assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint) 2110 endtry 2111 2112 delete('Xexported.vim') 2113 delete('Ximport.vim') 2114enddef 2115 2116def Test_func_redefine_error() 2117 var lines = [ 2118 'vim9script', 2119 'def Func()', 2120 ' eval [][0]', 2121 'enddef', 2122 'Func()', 2123 ] 2124 writefile(lines, 'Xtestscript.vim') 2125 2126 for count in range(3) 2127 try 2128 source Xtestscript.vim 2129 catch /E684/ 2130 # function name should contain <SNR> every time 2131 assert_match('E684: list index out of range', v:exception) 2132 assert_match('function <SNR>\d\+_Func, line 1', v:throwpoint) 2133 endtry 2134 endfor 2135 2136 delete('Xtestscript.vim') 2137enddef 2138 2139def Test_func_overrules_import_fails() 2140 var export_lines =<< trim END 2141 vim9script 2142 export def Func() 2143 echo 'imported' 2144 enddef 2145 END 2146 writefile(export_lines, 'XexportedFunc.vim') 2147 2148 var lines =<< trim END 2149 vim9script 2150 import Func from './XexportedFunc.vim' 2151 def Func() 2152 echo 'local to function' 2153 enddef 2154 END 2155 CheckScriptFailure(lines, 'E1073:') 2156 2157 lines =<< trim END 2158 vim9script 2159 import Func from './XexportedFunc.vim' 2160 def Outer() 2161 def Func() 2162 echo 'local to function' 2163 enddef 2164 enddef 2165 defcompile 2166 END 2167 CheckScriptFailure(lines, 'E1073:') 2168 2169 delete('XexportedFunc.vim') 2170enddef 2171 2172def Test_func_redefine_fails() 2173 var lines =<< trim END 2174 vim9script 2175 def Func() 2176 echo 'one' 2177 enddef 2178 def Func() 2179 echo 'two' 2180 enddef 2181 END 2182 CheckScriptFailure(lines, 'E1073:') 2183 2184 lines =<< trim END 2185 vim9script 2186 def Foo(): string 2187 return 'foo' 2188 enddef 2189 def Func() 2190 var Foo = {-> 'lambda'} 2191 enddef 2192 defcompile 2193 END 2194 CheckScriptFailure(lines, 'E1073:') 2195enddef 2196 2197def Test_fixed_size_list() 2198 # will be allocated as one piece of memory, check that changes work 2199 var l = [1, 2, 3, 4] 2200 l->remove(0) 2201 l->add(5) 2202 l->insert(99, 1) 2203 assert_equal([2, 99, 3, 4, 5], l) 2204enddef 2205 2206def Test_no_insert_xit() 2207 CheckDefExecFailure(['a = 1'], 'E1100:') 2208 CheckDefExecFailure(['c = 1'], 'E1100:') 2209 CheckDefExecFailure(['i = 1'], 'E1100:') 2210 CheckDefExecFailure(['t = 1'], 'E1100:') 2211 CheckDefExecFailure(['x = 1'], 'E1100:') 2212 2213 CheckScriptFailure(['vim9script', 'a = 1'], 'E488:') 2214 CheckScriptFailure(['vim9script', 'a'], 'E1100:') 2215 CheckScriptFailure(['vim9script', 'c = 1'], 'E488:') 2216 CheckScriptFailure(['vim9script', 'c'], 'E1100:') 2217 CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') 2218 CheckScriptFailure(['vim9script', 'i'], 'E1100:') 2219 CheckScriptFailure(['vim9script', 'o = 1'], 'E1100:') 2220 CheckScriptFailure(['vim9script', 'o'], 'E1100:') 2221 CheckScriptFailure(['vim9script', 't'], 'E1100:') 2222 CheckScriptFailure(['vim9script', 't = 1'], 'E1100:') 2223 CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') 2224enddef 2225 2226def IfElse(what: number): string 2227 var res = '' 2228 if what == 1 2229 res = "one" 2230 elseif what == 2 2231 res = "two" 2232 else 2233 res = "three" 2234 endif 2235 return res 2236enddef 2237 2238def Test_if_elseif_else() 2239 assert_equal('one', IfElse(1)) 2240 assert_equal('two', IfElse(2)) 2241 assert_equal('three', IfElse(3)) 2242enddef 2243 2244def Test_if_elseif_else_fails() 2245 CheckDefFailure(['elseif true'], 'E582:') 2246 CheckDefFailure(['else'], 'E581:') 2247 CheckDefFailure(['endif'], 'E580:') 2248 CheckDefFailure(['if g:abool', 'elseif xxx'], 'E1001:') 2249 CheckDefFailure(['if true', 'echo 1'], 'E171:') 2250 2251 var lines =<< trim END 2252 var s = '' 2253 if s = '' 2254 endif 2255 END 2256 CheckDefFailure(lines, 'E488:') 2257 2258 lines =<< trim END 2259 var s = '' 2260 if s == '' 2261 elseif s = '' 2262 endif 2263 END 2264 CheckDefFailure(lines, 'E488:') 2265enddef 2266 2267let g:bool_true = v:true 2268let g:bool_false = v:false 2269 2270def Test_if_const_expr() 2271 var res = false 2272 if true ? true : false 2273 res = true 2274 endif 2275 assert_equal(true, res) 2276 2277 g:glob = 2 2278 if false 2279 execute('g:glob = 3') 2280 endif 2281 assert_equal(2, g:glob) 2282 if true 2283 execute('g:glob = 3') 2284 endif 2285 assert_equal(3, g:glob) 2286 2287 res = false 2288 if g:bool_true ? true : false 2289 res = true 2290 endif 2291 assert_equal(true, res) 2292 2293 res = false 2294 if true ? g:bool_true : false 2295 res = true 2296 endif 2297 assert_equal(true, res) 2298 2299 res = false 2300 if true ? true : g:bool_false 2301 res = true 2302 endif 2303 assert_equal(true, res) 2304 2305 res = false 2306 if true ? false : true 2307 res = true 2308 endif 2309 assert_equal(false, res) 2310 2311 res = false 2312 if false ? false : true 2313 res = true 2314 endif 2315 assert_equal(true, res) 2316 2317 res = false 2318 if false ? true : false 2319 res = true 2320 endif 2321 assert_equal(false, res) 2322 2323 res = false 2324 if has('xyz') ? true : false 2325 res = true 2326 endif 2327 assert_equal(false, res) 2328 2329 res = false 2330 if true && true 2331 res = true 2332 endif 2333 assert_equal(true, res) 2334 2335 res = false 2336 if true && false 2337 res = true 2338 endif 2339 assert_equal(false, res) 2340 2341 res = false 2342 if g:bool_true && false 2343 res = true 2344 endif 2345 assert_equal(false, res) 2346 2347 res = false 2348 if true && g:bool_false 2349 res = true 2350 endif 2351 assert_equal(false, res) 2352 2353 res = false 2354 if false && false 2355 res = true 2356 endif 2357 assert_equal(false, res) 2358 2359 res = false 2360 if true || false 2361 res = true 2362 endif 2363 assert_equal(true, res) 2364 2365 res = false 2366 if g:bool_true || false 2367 res = true 2368 endif 2369 assert_equal(true, res) 2370 2371 res = false 2372 if true || g:bool_false 2373 res = true 2374 endif 2375 assert_equal(true, res) 2376 2377 res = false 2378 if false || false 2379 res = true 2380 endif 2381 assert_equal(false, res) 2382 2383 # with constant "false" expression may be invalid so long as the syntax is OK 2384 if false | eval 1 + 2 | endif 2385 if false | eval burp + 234 | endif 2386 if false | echo burp 234 'asd' | endif 2387 if false 2388 burp 2389 endif 2390 2391 # expression with line breaks skipped 2392 if false 2393 ('aaa' 2394 .. 'bbb' 2395 .. 'ccc' 2396 )->setline(1) 2397 endif 2398enddef 2399 2400def Test_if_const_expr_fails() 2401 CheckDefFailure(['if "aaa" == "bbb'], 'E114:') 2402 CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:') 2403 CheckDefFailure(["if has('aaa'"], 'E110:') 2404 CheckDefFailure(["if has('aaa') ? true false"], 'E109:') 2405enddef 2406 2407def RunNested(i: number): number 2408 var x: number = 0 2409 if i % 2 2410 if 1 2411 # comment 2412 else 2413 # comment 2414 endif 2415 x += 1 2416 else 2417 x += 1000 2418 endif 2419 return x 2420enddef 2421 2422def Test_nested_if() 2423 assert_equal(1, RunNested(1)) 2424 assert_equal(1000, RunNested(2)) 2425enddef 2426 2427def Test_execute_cmd() 2428 # missing argument is ignored 2429 execute 2430 execute # comment 2431 2432 new 2433 setline(1, 'default') 2434 execute 'setline(1, "execute-string")' 2435 assert_equal('execute-string', getline(1)) 2436 2437 execute "setline(1, 'execute-string')" 2438 assert_equal('execute-string', getline(1)) 2439 2440 var cmd1 = 'setline(1,' 2441 var cmd2 = '"execute-var")' 2442 execute cmd1 cmd2 # comment 2443 assert_equal('execute-var', getline(1)) 2444 2445 execute cmd1 cmd2 '|setline(1, "execute-var-string")' 2446 assert_equal('execute-var-string', getline(1)) 2447 2448 var cmd_first = 'call ' 2449 var cmd_last = 'setline(1, "execute-var-var")' 2450 execute cmd_first .. cmd_last 2451 assert_equal('execute-var-var', getline(1)) 2452 bwipe! 2453 2454 var n = true 2455 execute 'echomsg' (n ? '"true"' : '"no"') 2456 assert_match('^true$', Screenline(&lines)) 2457 2458 echomsg [1, 2, 3] {a: 1, b: 2} 2459 assert_match('^\[1, 2, 3\] {''a'': 1, ''b'': 2}$', Screenline(&lines)) 2460 2461 CheckDefFailure(['execute xxx'], 'E1001:', 1) 2462 CheckDefExecFailure(['execute "tabnext " .. 8'], 'E475:', 1) 2463 CheckDefFailure(['execute "cmd"# comment'], 'E488:', 1) 2464enddef 2465 2466def Test_execute_cmd_vimscript() 2467 # only checks line continuation 2468 var lines =<< trim END 2469 vim9script 2470 execute 'g:someVar' 2471 .. ' = ' .. 2472 '28' 2473 assert_equal(28, g:someVar) 2474 unlet g:someVar 2475 END 2476 CheckScriptSuccess(lines) 2477enddef 2478 2479def Test_echo_cmd() 2480 echo 'some' # comment 2481 echon 'thing' 2482 assert_match('^something$', Screenline(&lines)) 2483 2484 echo "some" # comment 2485 echon "thing" 2486 assert_match('^something$', Screenline(&lines)) 2487 2488 var str1 = 'some' 2489 var str2 = 'more' 2490 echo str1 str2 2491 assert_match('^some more$', Screenline(&lines)) 2492 2493 CheckDefFailure(['echo "xxx"# comment'], 'E488:') 2494enddef 2495 2496def Test_echomsg_cmd() 2497 echomsg 'some' 'more' # comment 2498 assert_match('^some more$', Screenline(&lines)) 2499 echo 'clear' 2500 :1messages 2501 assert_match('^some more$', Screenline(&lines)) 2502 2503 CheckDefFailure(['echomsg "xxx"# comment'], 'E488:') 2504enddef 2505 2506def Test_echomsg_cmd_vimscript() 2507 # only checks line continuation 2508 var lines =<< trim END 2509 vim9script 2510 echomsg 'here' 2511 .. ' is ' .. 2512 'a message' 2513 assert_match('^here is a message$', Screenline(&lines)) 2514 END 2515 CheckScriptSuccess(lines) 2516enddef 2517 2518def Test_echoerr_cmd() 2519 var local = 'local' 2520 try 2521 echoerr 'something' local 'wrong' # comment 2522 catch 2523 assert_match('something local wrong', v:exception) 2524 endtry 2525enddef 2526 2527def Test_echoerr_cmd_vimscript() 2528 # only checks line continuation 2529 var lines =<< trim END 2530 vim9script 2531 try 2532 echoerr 'this' 2533 .. ' is ' .. 2534 'wrong' 2535 catch 2536 assert_match('this is wrong', v:exception) 2537 endtry 2538 END 2539 CheckScriptSuccess(lines) 2540enddef 2541 2542def Test_echoconsole_cmd() 2543 var local = 'local' 2544 echoconsole 'something' local # comment 2545 # output goes anywhere 2546enddef 2547 2548def Test_for_outside_of_function() 2549 var lines =<< trim END 2550 vim9script 2551 new 2552 for var in range(0, 3) 2553 append(line('$'), var) 2554 endfor 2555 assert_equal(['', '0', '1', '2', '3'], getline(1, '$')) 2556 bwipe! 2557 2558 var result = '' 2559 for i in [1, 2, 3] 2560 var loop = ' loop ' .. i 2561 result ..= loop 2562 endfor 2563 assert_equal(' loop 1 loop 2 loop 3', result) 2564 END 2565 writefile(lines, 'Xvim9for.vim') 2566 source Xvim9for.vim 2567 delete('Xvim9for.vim') 2568enddef 2569 2570def Test_for_skipped_block() 2571 # test skipped blocks at outside of function 2572 var lines =<< trim END 2573 var result = [] 2574 if true 2575 for n in [1, 2] 2576 result += [n] 2577 endfor 2578 else 2579 for n in [3, 4] 2580 result += [n] 2581 endfor 2582 endif 2583 assert_equal([1, 2], result) 2584 2585 result = [] 2586 if false 2587 for n in [1, 2] 2588 result += [n] 2589 endfor 2590 else 2591 for n in [3, 4] 2592 result += [n] 2593 endfor 2594 endif 2595 assert_equal([3, 4], result) 2596 END 2597 CheckDefAndScriptSuccess(lines) 2598 2599 # test skipped blocks at inside of function 2600 lines =<< trim END 2601 def DefTrue() 2602 var result = [] 2603 if true 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([1, 2], result) 2613 enddef 2614 DefTrue() 2615 2616 def DefFalse() 2617 var result = [] 2618 if false 2619 for n in [1, 2] 2620 result += [n] 2621 endfor 2622 else 2623 for n in [3, 4] 2624 result += [n] 2625 endfor 2626 endif 2627 assert_equal([3, 4], result) 2628 enddef 2629 DefFalse() 2630 END 2631 CheckDefAndScriptSuccess(lines) 2632enddef 2633 2634def Test_for_loop() 2635 var lines =<< trim END 2636 var result = '' 2637 for cnt in range(7) 2638 if cnt == 4 2639 break 2640 endif 2641 if cnt == 2 2642 continue 2643 endif 2644 result ..= cnt .. '_' 2645 endfor 2646 assert_equal('0_1_3_', result) 2647 2648 var concat = '' 2649 for str in eval('["one", "two"]') 2650 concat ..= str 2651 endfor 2652 assert_equal('onetwo', concat) 2653 2654 var total = 0 2655 for nr in 2656 [1, 2, 3] 2657 total += nr 2658 endfor 2659 assert_equal(6, total) 2660 2661 total = 0 2662 for nr 2663 in [1, 2, 3] 2664 total += nr 2665 endfor 2666 assert_equal(6, total) 2667 2668 total = 0 2669 for nr 2670 in 2671 [1, 2, 3] 2672 total += nr 2673 endfor 2674 assert_equal(6, total) 2675 2676 # with type 2677 total = 0 2678 for n: number in [1, 2, 3] 2679 total += n 2680 endfor 2681 assert_equal(6, total) 2682 2683 var chars = '' 2684 for s: string in 'foobar' 2685 chars ..= s 2686 endfor 2687 assert_equal('foobar', chars) 2688 2689 chars = '' 2690 for x: string in {a: 'a', b: 'b'}->values() 2691 chars ..= x 2692 endfor 2693 assert_equal('ab', chars) 2694 2695 # unpack with type 2696 var res = '' 2697 for [n: number, s: string] in [[1, 'a'], [2, 'b']] 2698 res ..= n .. s 2699 endfor 2700 assert_equal('1a2b', res) 2701 2702 # unpack with one var 2703 var reslist = [] 2704 for [x] in [['aaa'], ['bbb']] 2705 reslist->add(x) 2706 endfor 2707 assert_equal(['aaa', 'bbb'], reslist) 2708 2709 # loop over string 2710 res = '' 2711 for c in 'aéc̀d' 2712 res ..= c .. '-' 2713 endfor 2714 assert_equal('a-é-c̀-d-', res) 2715 2716 res = '' 2717 for c in '' 2718 res ..= c .. '-' 2719 endfor 2720 assert_equal('', res) 2721 2722 res = '' 2723 for c in test_null_string() 2724 res ..= c .. '-' 2725 endfor 2726 assert_equal('', res) 2727 2728 var foo: list<dict<any>> = [ 2729 {a: 'Cat'} 2730 ] 2731 for dd in foo 2732 dd.counter = 12 2733 endfor 2734 assert_equal([{a: 'Cat', counter: 12}], foo) 2735 2736 reslist = [] 2737 for _ in range(3) 2738 reslist->add('x') 2739 endfor 2740 assert_equal(['x', 'x', 'x'], reslist) 2741 END 2742 CheckDefAndScriptSuccess(lines) 2743enddef 2744 2745def Test_for_loop_with_closure() 2746 var lines =<< trim END 2747 var flist: list<func> 2748 for i in range(5) 2749 var inloop = i 2750 flist[i] = () => inloop 2751 endfor 2752 for i in range(5) 2753 assert_equal(4, flist[i]()) 2754 endfor 2755 END 2756 CheckDefAndScriptSuccess(lines) 2757 2758 lines =<< trim END 2759 var flist: list<func> 2760 for i in range(5) 2761 var inloop = i 2762 flist[i] = () => { 2763 return inloop 2764 } 2765 endfor 2766 for i in range(5) 2767 assert_equal(4, flist[i]()) 2768 endfor 2769 END 2770 CheckDefAndScriptSuccess(lines) 2771enddef 2772 2773def Test_for_loop_fails() 2774 CheckDefAndScriptFailure2(['for '], 'E1097:', 'E690:') 2775 CheckDefAndScriptFailure2(['for x'], 'E1097:', 'E690:') 2776 CheckDefAndScriptFailure2(['for x in'], 'E1097:', 'E15:') 2777 CheckDefAndScriptFailure(['for # in range(5)'], 'E690:') 2778 CheckDefAndScriptFailure(['for i In range(5)'], 'E690:') 2779 CheckDefAndScriptFailure2(['var x = 5', 'for x in range(5)', 'endfor'], 'E1017:', 'E1041:') 2780 CheckScriptFailure(['vim9script', 'var x = 5', 'for x in range(5)', '# comment', 'endfor'], 'E1041:', 3) 2781 CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:') 2782 delfunc! g:Func 2783 CheckDefFailure(['for i in xxx'], 'E1001:') 2784 CheckDefFailure(['endfor'], 'E588:') 2785 CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:') 2786 2787 # wrong type detected at compile time 2788 CheckDefFailure(['for i in {a: 1}', 'echo 3', 'endfor'], 'E1177: For loop on dict not supported') 2789 2790 # wrong type detected at runtime 2791 g:adict = {a: 1} 2792 CheckDefExecFailure(['for i in g:adict', 'echo 3', 'endfor'], 'E1177: For loop on dict not supported') 2793 unlet g:adict 2794 2795 var lines =<< trim END 2796 var d: list<dict<any>> = [{a: 0}] 2797 for e in d 2798 e = {a: 0, b: ''} 2799 endfor 2800 END 2801 CheckDefAndScriptFailure2(lines, 'E1018:', 'E46:', 3) 2802 2803 lines =<< trim END 2804 for nr: number in ['foo'] 2805 endfor 2806 END 2807 CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got string', 1) 2808 2809 lines =<< trim END 2810 for n : number in [1, 2] 2811 echo n 2812 endfor 2813 END 2814 CheckDefAndScriptFailure(lines, 'E1059:', 1) 2815 2816 lines =<< trim END 2817 var d: dict<number> = {a: 1, b: 2} 2818 for [k: job, v: job] in d->items() 2819 echo k v 2820 endfor 2821 END 2822 CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected job but got string', 2) 2823enddef 2824 2825def Test_for_loop_script_var() 2826 # cannot use s:var in a :def function 2827 CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E1101:') 2828 2829 # can use s:var in Vim9 script, with or without s: 2830 var lines =<< trim END 2831 vim9script 2832 var total = 0 2833 for s:var in [1, 2, 3] 2834 total += s:var 2835 endfor 2836 assert_equal(6, total) 2837 2838 total = 0 2839 for var in [1, 2, 3] 2840 total += var 2841 endfor 2842 assert_equal(6, total) 2843 END 2844enddef 2845 2846def Test_for_loop_unpack() 2847 var lines =<< trim END 2848 var result = [] 2849 for [v1, v2] in [[1, 2], [3, 4]] 2850 result->add(v1) 2851 result->add(v2) 2852 endfor 2853 assert_equal([1, 2, 3, 4], result) 2854 2855 result = [] 2856 for [v1, v2; v3] in [[1, 2], [3, 4, 5, 6]] 2857 result->add(v1) 2858 result->add(v2) 2859 result->add(v3) 2860 endfor 2861 assert_equal([1, 2, [], 3, 4, [5, 6]], result) 2862 2863 result = [] 2864 for [&ts, &sw] in [[1, 2], [3, 4]] 2865 result->add(&ts) 2866 result->add(&sw) 2867 endfor 2868 assert_equal([1, 2, 3, 4], result) 2869 2870 var slist: list<string> 2871 for [$LOOPVAR, @r, v:errmsg] in [['a', 'b', 'c'], ['d', 'e', 'f']] 2872 slist->add($LOOPVAR) 2873 slist->add(@r) 2874 slist->add(v:errmsg) 2875 endfor 2876 assert_equal(['a', 'b', 'c', 'd', 'e', 'f'], slist) 2877 2878 slist = [] 2879 for [g:globalvar, b:bufvar, w:winvar, t:tabvar] in [['global', 'buf', 'win', 'tab'], ['1', '2', '3', '4']] 2880 slist->add(g:globalvar) 2881 slist->add(b:bufvar) 2882 slist->add(w:winvar) 2883 slist->add(t:tabvar) 2884 endfor 2885 assert_equal(['global', 'buf', 'win', 'tab', '1', '2', '3', '4'], slist) 2886 unlet! g:globalvar b:bufvar w:winvar t:tabvar 2887 2888 var res = [] 2889 for [_, n, _] in [[1, 2, 3], [4, 5, 6]] 2890 res->add(n) 2891 endfor 2892 assert_equal([2, 5], res) 2893 END 2894 CheckDefAndScriptSuccess(lines) 2895 2896 lines =<< trim END 2897 for [v1, v2] in [[1, 2, 3], [3, 4]] 2898 echo v1 v2 2899 endfor 2900 END 2901 CheckDefExecFailure(lines, 'E710:', 1) 2902 2903 lines =<< trim END 2904 for [v1, v2] in [[1], [3, 4]] 2905 echo v1 v2 2906 endfor 2907 END 2908 CheckDefExecFailure(lines, 'E711:', 1) 2909 2910 lines =<< trim END 2911 for [v1, v1] in [[1, 2], [3, 4]] 2912 echo v1 2913 endfor 2914 END 2915 CheckDefExecFailure(lines, 'E1017:', 1) 2916enddef 2917 2918def Test_for_loop_with_try_continue() 2919 var lines =<< trim END 2920 var looped = 0 2921 var cleanup = 0 2922 for i in range(3) 2923 looped += 1 2924 try 2925 eval [][0] 2926 catch 2927 continue 2928 finally 2929 cleanup += 1 2930 endtry 2931 endfor 2932 assert_equal(3, looped) 2933 assert_equal(3, cleanup) 2934 END 2935 CheckDefAndScriptSuccess(lines) 2936enddef 2937 2938def Test_while_skipped_block() 2939 # test skipped blocks at outside of function 2940 var lines =<< trim END 2941 var result = [] 2942 var n = 0 2943 if true 2944 n = 1 2945 while n < 3 2946 result += [n] 2947 n += 1 2948 endwhile 2949 else 2950 n = 3 2951 while n < 5 2952 result += [n] 2953 n += 1 2954 endwhile 2955 endif 2956 assert_equal([1, 2], result) 2957 2958 result = [] 2959 if false 2960 n = 1 2961 while n < 3 2962 result += [n] 2963 n += 1 2964 endwhile 2965 else 2966 n = 3 2967 while n < 5 2968 result += [n] 2969 n += 1 2970 endwhile 2971 endif 2972 assert_equal([3, 4], result) 2973 END 2974 CheckDefAndScriptSuccess(lines) 2975 2976 # test skipped blocks at inside of function 2977 lines =<< trim END 2978 def DefTrue() 2979 var result = [] 2980 var n = 0 2981 if true 2982 n = 1 2983 while n < 3 2984 result += [n] 2985 n += 1 2986 endwhile 2987 else 2988 n = 3 2989 while n < 5 2990 result += [n] 2991 n += 1 2992 endwhile 2993 endif 2994 assert_equal([1, 2], result) 2995 enddef 2996 DefTrue() 2997 2998 def DefFalse() 2999 var result = [] 3000 var n = 0 3001 if false 3002 n = 1 3003 while n < 3 3004 result += [n] 3005 n += 1 3006 endwhile 3007 else 3008 n = 3 3009 while n < 5 3010 result += [n] 3011 n += 1 3012 endwhile 3013 endif 3014 assert_equal([3, 4], result) 3015 enddef 3016 DefFalse() 3017 END 3018 CheckDefAndScriptSuccess(lines) 3019enddef 3020 3021def Test_while_loop() 3022 var result = '' 3023 var cnt = 0 3024 while cnt < 555 3025 if cnt == 3 3026 break 3027 endif 3028 cnt += 1 3029 if cnt == 2 3030 continue 3031 endif 3032 result ..= cnt .. '_' 3033 endwhile 3034 assert_equal('1_3_', result) 3035 3036 var s = '' 3037 while s == 'x' # {comment} 3038 endwhile 3039enddef 3040 3041def Test_while_loop_fails() 3042 CheckDefFailure(['while xxx'], 'E1001:') 3043 CheckDefFailure(['endwhile'], 'E588:') 3044 CheckDefFailure(['continue'], 'E586:') 3045 CheckDefFailure(['if true', 'continue'], 'E586:') 3046 CheckDefFailure(['break'], 'E587:') 3047 CheckDefFailure(['if true', 'break'], 'E587:') 3048 CheckDefFailure(['while 1', 'echo 3'], 'E170:') 3049 3050 var lines =<< trim END 3051 var s = '' 3052 while s = '' 3053 endwhile 3054 END 3055 CheckDefFailure(lines, 'E488:') 3056enddef 3057 3058def Test_interrupt_loop() 3059 var caught = false 3060 var x = 0 3061 try 3062 while 1 3063 x += 1 3064 if x == 100 3065 feedkeys("\<C-C>", 'Lt') 3066 endif 3067 endwhile 3068 catch 3069 caught = true 3070 assert_equal(100, x) 3071 endtry 3072 assert_true(caught, 'should have caught an exception') 3073 # consume the CTRL-C 3074 getchar(0) 3075enddef 3076 3077def Test_automatic_line_continuation() 3078 var mylist = [ 3079 'one', 3080 'two', 3081 'three', 3082 ] # comment 3083 assert_equal(['one', 'two', 'three'], mylist) 3084 3085 var mydict = { 3086 ['one']: 1, 3087 ['two']: 2, 3088 ['three']: 3089 3, 3090 } # comment 3091 assert_equal({one: 1, two: 2, three: 3}, mydict) 3092 mydict = { 3093 one: 1, # comment 3094 two: # comment 3095 2, # comment 3096 three: 3 # comment 3097 } 3098 assert_equal({one: 1, two: 2, three: 3}, mydict) 3099 mydict = { 3100 one: 1, 3101 two: 3102 2, 3103 three: 3 3104 } 3105 assert_equal({one: 1, two: 2, three: 3}, mydict) 3106 3107 assert_equal( 3108 ['one', 'two', 'three'], 3109 split('one two three') 3110 ) 3111enddef 3112 3113def Test_vim9_comment() 3114 CheckScriptSuccess([ 3115 'vim9script', 3116 '# something', 3117 '#something', 3118 '#{something', 3119 ]) 3120 3121 split Xfile 3122 CheckScriptSuccess([ 3123 'vim9script', 3124 'edit #something', 3125 ]) 3126 CheckScriptSuccess([ 3127 'vim9script', 3128 'edit #{something', 3129 ]) 3130 close 3131 3132 CheckScriptFailure([ 3133 'vim9script', 3134 ':# something', 3135 ], 'E488:') 3136 CheckScriptFailure([ 3137 '# something', 3138 ], 'E488:') 3139 CheckScriptFailure([ 3140 ':# something', 3141 ], 'E488:') 3142 3143 { # block start 3144 } # block end 3145 CheckDefFailure([ 3146 '{# comment', 3147 ], 'E488:') 3148 CheckDefFailure([ 3149 '{', 3150 '}# comment', 3151 ], 'E488:') 3152 3153 echo "yes" # comment 3154 CheckDefFailure([ 3155 'echo "yes"# comment', 3156 ], 'E488:') 3157 CheckScriptSuccess([ 3158 'vim9script', 3159 'echo "yes" # something', 3160 ]) 3161 CheckScriptFailure([ 3162 'vim9script', 3163 'echo "yes"# something', 3164 ], 'E121:') 3165 CheckScriptFailure([ 3166 'vim9script', 3167 'echo# something', 3168 ], 'E1144:') 3169 CheckScriptFailure([ 3170 'echo "yes" # something', 3171 ], 'E121:') 3172 3173 exe "echo" # comment 3174 CheckDefFailure([ 3175 'exe "echo"# comment', 3176 ], 'E488:') 3177 CheckScriptSuccess([ 3178 'vim9script', 3179 'exe "echo" # something', 3180 ]) 3181 CheckScriptFailure([ 3182 'vim9script', 3183 'exe "echo"# something', 3184 ], 'E121:') 3185 CheckScriptFailure([ 3186 'vim9script', 3187 'exe# something', 3188 ], 'E1144:') 3189 CheckScriptFailure([ 3190 'exe "echo" # something', 3191 ], 'E121:') 3192 3193 CheckDefFailure([ 3194 'try# comment', 3195 ' echo "yes"', 3196 'catch', 3197 'endtry', 3198 ], 'E1144:') 3199 CheckScriptFailure([ 3200 'vim9script', 3201 'try# comment', 3202 'echo "yes"', 3203 ], 'E1144:') 3204 CheckDefFailure([ 3205 'try', 3206 ' throw#comment', 3207 'catch', 3208 'endtry', 3209 ], 'E1144:') 3210 CheckDefFailure([ 3211 'try', 3212 ' throw "yes"#comment', 3213 'catch', 3214 'endtry', 3215 ], 'E488:') 3216 CheckDefFailure([ 3217 'try', 3218 ' echo "yes"', 3219 'catch# comment', 3220 'endtry', 3221 ], 'E1144:') 3222 CheckScriptFailure([ 3223 'vim9script', 3224 'try', 3225 ' echo "yes"', 3226 'catch# comment', 3227 'endtry', 3228 ], 'E1144:') 3229 CheckDefFailure([ 3230 'try', 3231 ' echo "yes"', 3232 'catch /pat/# comment', 3233 'endtry', 3234 ], 'E488:') 3235 CheckDefFailure([ 3236 'try', 3237 'echo "yes"', 3238 'catch', 3239 'endtry# comment', 3240 ], 'E1144:') 3241 CheckScriptFailure([ 3242 'vim9script', 3243 'try', 3244 ' echo "yes"', 3245 'catch', 3246 'endtry# comment', 3247 ], 'E1144:') 3248 3249 CheckScriptSuccess([ 3250 'vim9script', 3251 'hi # comment', 3252 ]) 3253 CheckScriptFailure([ 3254 'vim9script', 3255 'hi# comment', 3256 ], 'E1144:') 3257 CheckScriptSuccess([ 3258 'vim9script', 3259 'hi Search # comment', 3260 ]) 3261 CheckScriptFailure([ 3262 'vim9script', 3263 'hi Search# comment', 3264 ], 'E416:') 3265 CheckScriptSuccess([ 3266 'vim9script', 3267 'hi link This Search # comment', 3268 ]) 3269 CheckScriptFailure([ 3270 'vim9script', 3271 'hi link This That# comment', 3272 ], 'E413:') 3273 CheckScriptSuccess([ 3274 'vim9script', 3275 'hi clear This # comment', 3276 'hi clear # comment', 3277 ]) 3278 # not tested, because it doesn't give an error but a warning: 3279 # hi clear This# comment', 3280 CheckScriptFailure([ 3281 'vim9script', 3282 'hi clear# comment', 3283 ], 'E416:') 3284 3285 CheckScriptSuccess([ 3286 'vim9script', 3287 'hi Group term=bold', 3288 'match Group /todo/ # comment', 3289 ]) 3290 CheckScriptFailure([ 3291 'vim9script', 3292 'hi Group term=bold', 3293 'match Group /todo/# comment', 3294 ], 'E488:') 3295 CheckScriptSuccess([ 3296 'vim9script', 3297 'match # comment', 3298 ]) 3299 CheckScriptFailure([ 3300 'vim9script', 3301 'match# comment', 3302 ], 'E1144:') 3303 CheckScriptSuccess([ 3304 'vim9script', 3305 'match none # comment', 3306 ]) 3307 CheckScriptFailure([ 3308 'vim9script', 3309 'match none# comment', 3310 ], 'E475:') 3311 3312 CheckScriptSuccess([ 3313 'vim9script', 3314 'menutrans clear # comment', 3315 ]) 3316 CheckScriptFailure([ 3317 'vim9script', 3318 'menutrans clear# comment text', 3319 ], 'E474:') 3320 3321 CheckScriptSuccess([ 3322 'vim9script', 3323 'syntax clear # comment', 3324 ]) 3325 CheckScriptFailure([ 3326 'vim9script', 3327 'syntax clear# comment text', 3328 ], 'E28:') 3329 CheckScriptSuccess([ 3330 'vim9script', 3331 'syntax keyword Word some', 3332 'syntax clear Word # comment', 3333 ]) 3334 CheckScriptFailure([ 3335 'vim9script', 3336 'syntax keyword Word some', 3337 'syntax clear Word# comment text', 3338 ], 'E28:') 3339 3340 CheckScriptSuccess([ 3341 'vim9script', 3342 'syntax list # comment', 3343 ]) 3344 CheckScriptFailure([ 3345 'vim9script', 3346 'syntax list# comment text', 3347 ], 'E28:') 3348 3349 CheckScriptSuccess([ 3350 'vim9script', 3351 'syntax match Word /pat/ oneline # comment', 3352 ]) 3353 CheckScriptFailure([ 3354 'vim9script', 3355 'syntax match Word /pat/ oneline# comment', 3356 ], 'E475:') 3357 3358 CheckScriptSuccess([ 3359 'vim9script', 3360 'syntax keyword Word word # comm[ent', 3361 ]) 3362 CheckScriptFailure([ 3363 'vim9script', 3364 'syntax keyword Word word# comm[ent', 3365 ], 'E789:') 3366 3367 CheckScriptSuccess([ 3368 'vim9script', 3369 'syntax match Word /pat/ # comment', 3370 ]) 3371 CheckScriptFailure([ 3372 'vim9script', 3373 'syntax match Word /pat/# comment', 3374 ], 'E402:') 3375 3376 CheckScriptSuccess([ 3377 'vim9script', 3378 'syntax match Word /pat/ contains=Something # comment', 3379 ]) 3380 CheckScriptFailure([ 3381 'vim9script', 3382 'syntax match Word /pat/ contains=Something# comment', 3383 ], 'E475:') 3384 CheckScriptFailure([ 3385 'vim9script', 3386 'syntax match Word /pat/ contains= # comment', 3387 ], 'E406:') 3388 CheckScriptFailure([ 3389 'vim9script', 3390 'syntax match Word /pat/ contains=# comment', 3391 ], 'E475:') 3392 3393 CheckScriptSuccess([ 3394 'vim9script', 3395 'syntax region Word start=/pat/ end=/pat/ # comment', 3396 ]) 3397 CheckScriptFailure([ 3398 'vim9script', 3399 'syntax region Word start=/pat/ end=/pat/# comment', 3400 ], 'E402:') 3401 3402 CheckScriptSuccess([ 3403 'vim9script', 3404 'syntax sync # comment', 3405 ]) 3406 CheckScriptFailure([ 3407 'vim9script', 3408 'syntax sync# comment', 3409 ], 'E404:') 3410 CheckScriptSuccess([ 3411 'vim9script', 3412 'syntax sync ccomment # comment', 3413 ]) 3414 CheckScriptFailure([ 3415 'vim9script', 3416 'syntax sync ccomment# comment', 3417 ], 'E404:') 3418 3419 CheckScriptSuccess([ 3420 'vim9script', 3421 'syntax cluster Some contains=Word # comment', 3422 ]) 3423 CheckScriptFailure([ 3424 'vim9script', 3425 'syntax cluster Some contains=Word# comment', 3426 ], 'E475:') 3427 3428 CheckScriptSuccess([ 3429 'vim9script', 3430 'command Echo echo # comment', 3431 'command Echo # comment', 3432 'delcommand Echo', 3433 ]) 3434 CheckScriptFailure([ 3435 'vim9script', 3436 'command Echo echo# comment', 3437 'Echo', 3438 ], 'E1144:') 3439 delcommand Echo 3440 3441 var curdir = getcwd() 3442 CheckScriptSuccess([ 3443 'command Echo cd " comment', 3444 'Echo', 3445 'delcommand Echo', 3446 ]) 3447 CheckScriptSuccess([ 3448 'vim9script', 3449 'command Echo cd # comment', 3450 'Echo', 3451 'delcommand Echo', 3452 ]) 3453 CheckScriptFailure([ 3454 'vim9script', 3455 'command Echo cd " comment', 3456 'Echo', 3457 ], 'E344:') 3458 delcommand Echo 3459 chdir(curdir) 3460 3461 CheckScriptFailure([ 3462 'vim9script', 3463 'command Echo# comment', 3464 ], 'E182:') 3465 CheckScriptFailure([ 3466 'vim9script', 3467 'command Echo echo', 3468 'command Echo# comment', 3469 ], 'E182:') 3470 delcommand Echo 3471 3472 CheckScriptSuccess([ 3473 'vim9script', 3474 'function # comment', 3475 ]) 3476 CheckScriptFailure([ 3477 'vim9script', 3478 'function " comment', 3479 ], 'E129:') 3480 CheckScriptFailure([ 3481 'vim9script', 3482 'function# comment', 3483 ], 'E1144:') 3484 CheckScriptSuccess([ 3485 'vim9script', 3486 'function CheckScriptSuccess # comment', 3487 ]) 3488 CheckScriptFailure([ 3489 'vim9script', 3490 'function CheckScriptSuccess# comment', 3491 ], 'E488:') 3492 3493 CheckScriptSuccess([ 3494 'vim9script', 3495 'func g:DeleteMeA()', 3496 'endfunc', 3497 'delfunction g:DeleteMeA # comment', 3498 ]) 3499 CheckScriptFailure([ 3500 'vim9script', 3501 'func g:DeleteMeB()', 3502 'endfunc', 3503 'delfunction g:DeleteMeB# comment', 3504 ], 'E488:') 3505 3506 CheckScriptSuccess([ 3507 'vim9script', 3508 'call execute("ls") # comment', 3509 ]) 3510 CheckScriptFailure([ 3511 'vim9script', 3512 'call execute("ls")# comment', 3513 ], 'E488:') 3514 3515 CheckScriptFailure([ 3516 'def Test() " comment', 3517 'enddef', 3518 ], 'E488:') 3519 CheckScriptFailure([ 3520 'vim9script', 3521 'def Test() " comment', 3522 'enddef', 3523 ], 'E488:') 3524 3525 CheckScriptSuccess([ 3526 'func Test() " comment', 3527 'endfunc', 3528 'delfunc Test', 3529 ]) 3530 CheckScriptSuccess([ 3531 'vim9script', 3532 'func Test() " comment', 3533 'endfunc', 3534 ]) 3535 3536 CheckScriptSuccess([ 3537 'def Test() # comment', 3538 'enddef', 3539 ]) 3540 CheckScriptFailure([ 3541 'func Test() # comment', 3542 'endfunc', 3543 ], 'E488:') 3544 3545 var lines =<< trim END 3546 vim9script 3547 syn region Text 3548 \ start='foo' 3549 #\ comment 3550 \ end='bar' 3551 syn region Text start='foo' 3552 #\ comment 3553 \ end='bar' 3554 END 3555 CheckScriptSuccess(lines) 3556 3557 lines =<< trim END 3558 vim9script 3559 syn region Text 3560 \ start='foo' 3561 "\ comment 3562 \ end='bar' 3563 END 3564 CheckScriptFailure(lines, 'E399:') 3565enddef 3566 3567def Test_vim9_comment_gui() 3568 CheckCanRunGui 3569 3570 CheckScriptFailure([ 3571 'vim9script', 3572 'gui#comment' 3573 ], 'E1144:') 3574 CheckScriptFailure([ 3575 'vim9script', 3576 'gui -f#comment' 3577 ], 'E194:') 3578enddef 3579 3580def Test_vim9_comment_not_compiled() 3581 au TabEnter *.vim g:entered = 1 3582 au TabEnter *.x g:entered = 2 3583 3584 edit test.vim 3585 doautocmd TabEnter #comment 3586 assert_equal(1, g:entered) 3587 3588 doautocmd TabEnter f.x 3589 assert_equal(2, g:entered) 3590 3591 g:entered = 0 3592 doautocmd TabEnter f.x #comment 3593 assert_equal(2, g:entered) 3594 3595 assert_fails('doautocmd Syntax#comment', 'E216:') 3596 3597 au! TabEnter 3598 unlet g:entered 3599 3600 CheckScriptSuccess([ 3601 'vim9script', 3602 'g:var = 123', 3603 'b:var = 456', 3604 'w:var = 777', 3605 't:var = 888', 3606 'unlet g:var w:var # something', 3607 ]) 3608 3609 CheckScriptFailure([ 3610 'vim9script', 3611 'let var = 123', 3612 ], 'E1126: Cannot use :let in Vim9 script') 3613 3614 CheckScriptFailure([ 3615 'vim9script', 3616 'var g:var = 123', 3617 ], 'E1016: Cannot declare a global variable:') 3618 3619 CheckScriptFailure([ 3620 'vim9script', 3621 'var b:var = 123', 3622 ], 'E1016: Cannot declare a buffer variable:') 3623 3624 CheckScriptFailure([ 3625 'vim9script', 3626 'var w:var = 123', 3627 ], 'E1016: Cannot declare a window variable:') 3628 3629 CheckScriptFailure([ 3630 'vim9script', 3631 'var t:var = 123', 3632 ], 'E1016: Cannot declare a tab variable:') 3633 3634 CheckScriptFailure([ 3635 'vim9script', 3636 'var v:version = 123', 3637 ], 'E1016: Cannot declare a v: variable:') 3638 3639 CheckScriptFailure([ 3640 'vim9script', 3641 'var $VARIABLE = "text"', 3642 ], 'E1016: Cannot declare an environment variable:') 3643 3644 CheckScriptFailure([ 3645 'vim9script', 3646 'g:var = 123', 3647 'unlet g:var# comment1', 3648 ], 'E108:') 3649 3650 CheckScriptFailure([ 3651 'let g:var = 123', 3652 'unlet g:var # something', 3653 ], 'E488:') 3654 3655 CheckScriptSuccess([ 3656 'vim9script', 3657 'if 1 # comment2', 3658 ' echo "yes"', 3659 'elseif 2 #comment', 3660 ' echo "no"', 3661 'endif', 3662 ]) 3663 3664 CheckScriptFailure([ 3665 'vim9script', 3666 'if 1# comment3', 3667 ' echo "yes"', 3668 'endif', 3669 ], 'E488:') 3670 3671 CheckScriptFailure([ 3672 'vim9script', 3673 'if 0 # comment4', 3674 ' echo "yes"', 3675 'elseif 2#comment', 3676 ' echo "no"', 3677 'endif', 3678 ], 'E488:') 3679 3680 CheckScriptSuccess([ 3681 'vim9script', 3682 'var v = 1 # comment5', 3683 ]) 3684 3685 CheckScriptFailure([ 3686 'vim9script', 3687 'var v = 1# comment6', 3688 ], 'E488:') 3689 3690 CheckScriptSuccess([ 3691 'vim9script', 3692 'new' 3693 'setline(1, ["# define pat", "last"])', 3694 ':$', 3695 'dsearch /pat/ #comment', 3696 'bwipe!', 3697 ]) 3698 3699 CheckScriptFailure([ 3700 'vim9script', 3701 'new' 3702 'setline(1, ["# define pat", "last"])', 3703 ':$', 3704 'dsearch /pat/#comment', 3705 'bwipe!', 3706 ], 'E488:') 3707 3708 CheckScriptFailure([ 3709 'vim9script', 3710 'func! SomeFunc()', 3711 ], 'E477:') 3712enddef 3713 3714def Test_finish() 3715 var lines =<< trim END 3716 vim9script 3717 g:res = 'one' 3718 if v:false | finish | endif 3719 g:res = 'two' 3720 finish 3721 g:res = 'three' 3722 END 3723 writefile(lines, 'Xfinished') 3724 source Xfinished 3725 assert_equal('two', g:res) 3726 3727 unlet g:res 3728 delete('Xfinished') 3729enddef 3730 3731def Test_forward_declaration() 3732 var lines =<< trim END 3733 vim9script 3734 def GetValue(): string 3735 return theVal 3736 enddef 3737 var theVal = 'something' 3738 g:initVal = GetValue() 3739 theVal = 'else' 3740 g:laterVal = GetValue() 3741 END 3742 writefile(lines, 'Xforward') 3743 source Xforward 3744 assert_equal('something', g:initVal) 3745 assert_equal('else', g:laterVal) 3746 3747 unlet g:initVal 3748 unlet g:laterVal 3749 delete('Xforward') 3750enddef 3751 3752def Test_source_vim9_from_legacy() 3753 var vim9_lines =<< trim END 3754 vim9script 3755 var local = 'local' 3756 g:global = 'global' 3757 export var exported = 'exported' 3758 export def GetText(): string 3759 return 'text' 3760 enddef 3761 END 3762 writefile(vim9_lines, 'Xvim9_script.vim') 3763 3764 var legacy_lines =<< trim END 3765 source Xvim9_script.vim 3766 3767 call assert_false(exists('local')) 3768 call assert_false(exists('exported')) 3769 call assert_false(exists('s:exported')) 3770 call assert_equal('global', global) 3771 call assert_equal('global', g:global) 3772 3773 " imported variable becomes script-local 3774 import exported from './Xvim9_script.vim' 3775 call assert_equal('exported', s:exported) 3776 call assert_false(exists('exported')) 3777 3778 " imported function becomes script-local 3779 import GetText from './Xvim9_script.vim' 3780 call assert_equal('text', s:GetText()) 3781 call assert_false(exists('*GetText')) 3782 END 3783 writefile(legacy_lines, 'Xlegacy_script.vim') 3784 3785 source Xlegacy_script.vim 3786 assert_equal('global', g:global) 3787 unlet g:global 3788 3789 delete('Xlegacy_script.vim') 3790 delete('Xvim9_script.vim') 3791enddef 3792 3793def Test_declare_script_in_func() 3794 var lines =<< trim END 3795 vim9script 3796 func Declare() 3797 let s:local = 123 3798 endfunc 3799 Declare() 3800 assert_equal(123, local) 3801 3802 var error: string 3803 try 3804 local = 'asdf' 3805 catch 3806 error = v:exception 3807 endtry 3808 assert_match('E1012: Type mismatch; expected number but got string', error) 3809 3810 lockvar local 3811 try 3812 local = 999 3813 catch 3814 error = v:exception 3815 endtry 3816 assert_match('E741: Value is locked: local', error) 3817 END 3818 CheckScriptSuccess(lines) 3819enddef 3820 3821 3822func Test_vim9script_not_global() 3823 " check that items defined in Vim9 script are script-local, not global 3824 let vim9lines =<< trim END 3825 vim9script 3826 var name = 'local' 3827 func TheFunc() 3828 echo 'local' 3829 endfunc 3830 def DefFunc() 3831 echo 'local' 3832 enddef 3833 END 3834 call writefile(vim9lines, 'Xvim9script.vim') 3835 source Xvim9script.vim 3836 try 3837 echo g:var 3838 assert_report('did not fail') 3839 catch /E121:/ 3840 " caught 3841 endtry 3842 try 3843 call TheFunc() 3844 assert_report('did not fail') 3845 catch /E117:/ 3846 " caught 3847 endtry 3848 try 3849 call DefFunc() 3850 assert_report('did not fail') 3851 catch /E117:/ 3852 " caught 3853 endtry 3854 3855 call delete('Xvim9script.vim') 3856endfunc 3857 3858def Test_vim9_copen() 3859 # this was giving an error for setting w:quickfix_title 3860 copen 3861 quit 3862enddef 3863 3864" test using an auto-loaded function and variable 3865def Test_vim9_autoload() 3866 var lines =<< trim END 3867 vim9script 3868 def some#gettest(): string 3869 return 'test' 3870 enddef 3871 g:some#name = 'name' 3872 g:some#dict = {key: 'value'} 3873 3874 def some#varargs(a1: string, ...l: list<string>): string 3875 return a1 .. l[0] .. l[1] 3876 enddef 3877 END 3878 3879 mkdir('Xdir/autoload', 'p') 3880 writefile(lines, 'Xdir/autoload/some.vim') 3881 var save_rtp = &rtp 3882 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3883 3884 assert_equal('test', g:some#gettest()) 3885 assert_equal('name', g:some#name) 3886 assert_equal('value', g:some#dict.key) 3887 g:some#other = 'other' 3888 assert_equal('other', g:some#other) 3889 3890 assert_equal('abc', some#varargs('a', 'b', 'c')) 3891 3892 # upper case script name works 3893 lines =<< trim END 3894 vim9script 3895 def Other#getOther(): string 3896 return 'other' 3897 enddef 3898 END 3899 writefile(lines, 'Xdir/autoload/Other.vim') 3900 assert_equal('other', g:Other#getOther()) 3901 3902 delete('Xdir', 'rf') 3903 &rtp = save_rtp 3904enddef 3905 3906" test using a vim9script that is auto-loaded from an autocmd 3907def Test_vim9_aucmd_autoload() 3908 var lines =<< trim END 3909 vim9script 3910 def foo#test() 3911 echomsg getreg('"') 3912 enddef 3913 END 3914 3915 mkdir('Xdir/autoload', 'p') 3916 writefile(lines, 'Xdir/autoload/foo.vim') 3917 var save_rtp = &rtp 3918 exe 'set rtp^=' .. getcwd() .. '/Xdir' 3919 augroup test 3920 autocmd TextYankPost * call foo#test() 3921 augroup END 3922 3923 normal Y 3924 3925 augroup test 3926 autocmd! 3927 augroup END 3928 delete('Xdir', 'rf') 3929 &rtp = save_rtp 3930enddef 3931 3932" This was causing a crash because suppress_errthrow wasn't reset. 3933def Test_vim9_autoload_error() 3934 var lines =<< trim END 3935 vim9script 3936 def crash#func() 3937 try 3938 for x in List() 3939 endfor 3940 catch 3941 endtry 3942 g:ok = true 3943 enddef 3944 fu List() 3945 invalid 3946 endfu 3947 try 3948 alsoinvalid 3949 catch /wontmatch/ 3950 endtry 3951 END 3952 call mkdir('Xruntime/autoload', 'p') 3953 call writefile(lines, 'Xruntime/autoload/crash.vim') 3954 3955 # run in a separate Vim to avoid the side effects of assert_fails() 3956 lines =<< trim END 3957 exe 'set rtp^=' .. getcwd() .. '/Xruntime' 3958 call crash#func() 3959 call writefile(['ok'], 'Xdidit') 3960 qall! 3961 END 3962 writefile(lines, 'Xscript') 3963 RunVim([], [], '-S Xscript') 3964 assert_equal(['ok'], readfile('Xdidit')) 3965 3966 delete('Xdidit') 3967 delete('Xscript') 3968 delete('Xruntime', 'rf') 3969 3970 lines =<< trim END 3971 vim9script 3972 var foo#bar = 'asdf' 3973 END 3974 CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2) 3975enddef 3976 3977def Test_script_var_in_autocmd() 3978 # using a script variable from an autocommand, defined in a :def function in a 3979 # legacy Vim script, cannot check the variable type. 3980 var lines =<< trim END 3981 let s:counter = 1 3982 def s:Func() 3983 au! CursorHold 3984 au CursorHold * s:counter += 1 3985 enddef 3986 call s:Func() 3987 doau CursorHold 3988 call assert_equal(2, s:counter) 3989 au! CursorHold 3990 END 3991 CheckScriptSuccess(lines) 3992enddef 3993 3994def Test_error_in_autoload_script() 3995 var save_rtp = &rtp 3996 var dir = getcwd() .. '/Xruntime' 3997 &rtp = dir 3998 mkdir(dir .. '/autoload', 'p') 3999 4000 var lines =<< trim END 4001 vim9script noclear 4002 def script#autoloaded() 4003 enddef 4004 def Broken() 4005 var x: any = '' 4006 eval x != 0 4007 enddef 4008 Broken() 4009 END 4010 writefile(lines, dir .. '/autoload/script.vim') 4011 4012 lines =<< trim END 4013 vim9script 4014 def CallAutoloaded() 4015 script#autoloaded() 4016 enddef 4017 4018 function Legacy() 4019 try 4020 call s:CallAutoloaded() 4021 catch 4022 call assert_match('E1030: Using a String as a Number', v:exception) 4023 endtry 4024 endfunction 4025 4026 Legacy() 4027 END 4028 CheckScriptSuccess(lines) 4029 4030 &rtp = save_rtp 4031 delete(dir, 'rf') 4032enddef 4033 4034def Test_cmdline_win() 4035 # if the Vim syntax highlighting uses Vim9 constructs they can be used from 4036 # the command line window. 4037 mkdir('rtp/syntax', 'p') 4038 var export_lines =<< trim END 4039 vim9script 4040 export var That = 'yes' 4041 END 4042 writefile(export_lines, 'rtp/syntax/Xexport.vim') 4043 var import_lines =<< trim END 4044 vim9script 4045 import That from './Xexport.vim' 4046 END 4047 writefile(import_lines, 'rtp/syntax/vim.vim') 4048 var save_rtp = &rtp 4049 &rtp = getcwd() .. '/rtp' .. ',' .. &rtp 4050 syntax on 4051 augroup CmdWin 4052 autocmd CmdwinEnter * g:got_there = 'yes' 4053 augroup END 4054 # this will open and also close the cmdline window 4055 feedkeys('q:', 'xt') 4056 assert_equal('yes', g:got_there) 4057 4058 augroup CmdWin 4059 au! 4060 augroup END 4061 &rtp = save_rtp 4062 delete('rtp', 'rf') 4063enddef 4064 4065def Test_invalid_sid() 4066 assert_fails('func <SNR>1234_func', 'E123:') 4067 4068 if RunVim([], ['wq! Xdidit'], '+"func <SNR>1_func"') 4069 assert_equal([], readfile('Xdidit')) 4070 endif 4071 delete('Xdidit') 4072enddef 4073 4074def Test_restoring_cpo() 4075 writefile(['vim9script', 'set nocp'], 'Xsourced') 4076 writefile(['call writefile(["done"], "Xdone")', 'quit!'], 'Xclose') 4077 if RunVim([], [], '-u NONE +"set cpo+=a" -S Xsourced -S Xclose') 4078 assert_equal(['done'], readfile('Xdone')) 4079 endif 4080 delete('Xsourced') 4081 delete('Xclose') 4082 delete('Xdone') 4083 4084 writefile(['vim9script'], 'XanotherScript') 4085 set cpo=aABceFsMny> 4086 edit XanotherScript 4087 so % 4088 assert_equal('aABceFsMny>', &cpo) 4089 :1del 4090 w 4091 so % 4092 assert_equal('aABceFsMny>', &cpo) 4093 4094 delete('XanotherScript') 4095 set cpo&vim 4096enddef 4097 4098" Use :function so we can use Check commands 4099func Test_no_redraw_when_restoring_cpo() 4100 CheckScreendump 4101 CheckFeature timers 4102 4103 let lines =<< trim END 4104 vim9script 4105 def script#func() 4106 enddef 4107 END 4108 call mkdir('Xdir/autoload', 'p') 4109 call writefile(lines, 'Xdir/autoload/script.vim') 4110 4111 let lines =<< trim END 4112 vim9script 4113 set cpo+=M 4114 exe 'set rtp^=' .. getcwd() .. '/Xdir' 4115 au CmdlineEnter : ++once timer_start(0, (_) => script#func()) 4116 setline(1, 'some text') 4117 END 4118 call writefile(lines, 'XTest_redraw_cpo') 4119 let buf = RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6}) 4120 call term_sendkeys(buf, "V:") 4121 call VerifyScreenDump(buf, 'Test_vim9_no_redraw', {}) 4122 4123 " clean up 4124 call term_sendkeys(buf, "\<Esc>u") 4125 call StopVimInTerminal(buf) 4126 call delete('XTest_redraw_cpo') 4127 call delete('Xdir', 'rf') 4128endfunc 4129 4130 4131def Test_unset_any_variable() 4132 var lines =<< trim END 4133 var name: any 4134 assert_equal(0, name) 4135 END 4136 CheckDefAndScriptSuccess(lines) 4137enddef 4138 4139func Test_define_func_at_command_line() 4140 CheckRunVimInTerminal 4141 4142 " call indirectly to avoid compilation error for missing functions 4143 call Run_Test_define_func_at_command_line() 4144endfunc 4145 4146def Run_Test_define_func_at_command_line() 4147 # run in a separate Vim instance to avoid the script context 4148 var lines =<< trim END 4149 func CheckAndQuit() 4150 call assert_fails('call Afunc()', 'E117: Unknown function: Bfunc') 4151 call writefile(['errors: ' .. string(v:errors)], 'Xdidcmd') 4152 endfunc 4153 END 4154 writefile([''], 'Xdidcmd') 4155 writefile(lines, 'XcallFunc') 4156 var buf = RunVimInTerminal('-S XcallFunc', {rows: 6}) 4157 # define Afunc() on the command line 4158 term_sendkeys(buf, ":def Afunc()\<CR>Bfunc()\<CR>enddef\<CR>") 4159 term_sendkeys(buf, ":call CheckAndQuit()\<CR>") 4160 WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd'))) 4161 4162 call StopVimInTerminal(buf) 4163 delete('XcallFunc') 4164 delete('Xdidcmd') 4165enddef 4166 4167def Test_script_var_scope() 4168 var lines =<< trim END 4169 vim9script 4170 if true 4171 if true 4172 var one = 'one' 4173 echo one 4174 endif 4175 echo one 4176 endif 4177 END 4178 CheckScriptFailure(lines, 'E121:', 7) 4179 4180 lines =<< trim END 4181 vim9script 4182 if true 4183 if false 4184 var one = 'one' 4185 echo one 4186 else 4187 var one = 'one' 4188 echo one 4189 endif 4190 echo one 4191 endif 4192 END 4193 CheckScriptFailure(lines, 'E121:', 10) 4194 4195 lines =<< trim END 4196 vim9script 4197 while true 4198 var one = 'one' 4199 echo one 4200 break 4201 endwhile 4202 echo one 4203 END 4204 CheckScriptFailure(lines, 'E121:', 7) 4205 4206 lines =<< trim END 4207 vim9script 4208 for i in range(1) 4209 var one = 'one' 4210 echo one 4211 endfor 4212 echo one 4213 END 4214 CheckScriptFailure(lines, 'E121:', 6) 4215 4216 lines =<< trim END 4217 vim9script 4218 { 4219 var one = 'one' 4220 assert_equal('one', one) 4221 } 4222 assert_false(exists('one')) 4223 assert_false(exists('s:one')) 4224 END 4225 CheckScriptSuccess(lines) 4226 4227 lines =<< trim END 4228 vim9script 4229 { 4230 var one = 'one' 4231 echo one 4232 } 4233 echo one 4234 END 4235 CheckScriptFailure(lines, 'E121:', 6) 4236enddef 4237 4238def Test_catch_exception_in_callback() 4239 var lines =<< trim END 4240 vim9script 4241 def Callback(...l: list<any>) 4242 try 4243 var x: string 4244 var y: string 4245 # this error should be caught with CHECKLEN 4246 [x, y] = [''] 4247 catch 4248 g:caught = 'yes' 4249 endtry 4250 enddef 4251 popup_menu('popup', {callback: Callback}) 4252 feedkeys("\r", 'xt') 4253 END 4254 CheckScriptSuccess(lines) 4255 4256 unlet g:caught 4257enddef 4258 4259def Test_no_unknown_error_after_error() 4260 if !has('unix') || !has('job') 4261 throw 'Skipped: not unix of missing +job feature' 4262 endif 4263 var lines =<< trim END 4264 vim9script 4265 var source: list<number> 4266 def Out_cb(...l: list<any>) 4267 eval [][0] 4268 enddef 4269 def Exit_cb(...l: list<any>) 4270 sleep 1m 4271 source += l 4272 enddef 4273 var myjob = job_start('echo burp', {out_cb: Out_cb, exit_cb: Exit_cb, mode: 'raw'}) 4274 while job_status(myjob) == 'run' 4275 sleep 10m 4276 endwhile 4277 # wait for Exit_cb() to be called 4278 sleep 200m 4279 END 4280 writefile(lines, 'Xdef') 4281 assert_fails('so Xdef', ['E684:', 'E1012:']) 4282 delete('Xdef') 4283enddef 4284 4285def InvokeNormal() 4286 exe "norm! :m+1\r" 4287enddef 4288 4289def Test_invoke_normal_in_visual_mode() 4290 xnoremap <F3> <Cmd>call <SID>InvokeNormal()<CR> 4291 new 4292 setline(1, ['aaa', 'bbb']) 4293 feedkeys("V\<F3>", 'xt') 4294 assert_equal(['bbb', 'aaa'], getline(1, 2)) 4295 xunmap <F3> 4296enddef 4297 4298def Test_white_space_after_command() 4299 var lines =<< trim END 4300 exit_cb: Func}) 4301 END 4302 CheckDefAndScriptFailure(lines, 'E1144:', 1) 4303 4304 lines =<< trim END 4305 e# 4306 END 4307 CheckDefAndScriptFailure(lines, 'E1144:', 1) 4308enddef 4309 4310def Test_script_var_gone_when_sourced_twice() 4311 var lines =<< trim END 4312 vim9script 4313 if exists('g:guard') 4314 finish 4315 endif 4316 g:guard = 1 4317 var name = 'thename' 4318 def g:GetName(): string 4319 return name 4320 enddef 4321 def g:SetName(arg: string) 4322 name = arg 4323 enddef 4324 END 4325 writefile(lines, 'XscriptTwice.vim') 4326 so XscriptTwice.vim 4327 assert_equal('thename', g:GetName()) 4328 g:SetName('newname') 4329 assert_equal('newname', g:GetName()) 4330 so XscriptTwice.vim 4331 assert_fails('call g:GetName()', 'E1149:') 4332 assert_fails('call g:SetName("x")', 'E1149:') 4333 4334 delfunc g:GetName 4335 delfunc g:SetName 4336 delete('XscriptTwice.vim') 4337 unlet g:guard 4338enddef 4339 4340def Test_import_gone_when_sourced_twice() 4341 var exportlines =<< trim END 4342 vim9script 4343 if exists('g:guard') 4344 finish 4345 endif 4346 g:guard = 1 4347 export var name = 'someName' 4348 END 4349 writefile(exportlines, 'XexportScript.vim') 4350 4351 var lines =<< trim END 4352 vim9script 4353 import name from './XexportScript.vim' 4354 def g:GetName(): string 4355 return name 4356 enddef 4357 END 4358 writefile(lines, 'XscriptImport.vim') 4359 so XscriptImport.vim 4360 assert_equal('someName', g:GetName()) 4361 4362 so XexportScript.vim 4363 assert_fails('call g:GetName()', 'E1149:') 4364 4365 delfunc g:GetName 4366 delete('XexportScript.vim') 4367 delete('XscriptImport.vim') 4368 unlet g:guard 4369enddef 4370 4371def Test_unsupported_commands() 4372 var lines =<< trim END 4373 ka 4374 END 4375 CheckDefFailure(lines, 'E476:') 4376 CheckScriptFailure(['vim9script'] + lines, 'E492:') 4377 4378 lines =<< trim END 4379 :1ka 4380 END 4381 CheckDefFailure(lines, 'E476:') 4382 CheckScriptFailure(['vim9script'] + lines, 'E492:') 4383 4384 lines =<< trim END 4385 t 4386 END 4387 CheckDefFailure(lines, 'E1100:') 4388 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 4389 4390 lines =<< trim END 4391 x 4392 END 4393 CheckDefFailure(lines, 'E1100:') 4394 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 4395 4396 lines =<< trim END 4397 xit 4398 END 4399 CheckDefFailure(lines, 'E1100:') 4400 CheckScriptFailure(['vim9script'] + lines, 'E1100:') 4401enddef 4402 4403def Test_mapping_line_number() 4404 var lines =<< trim END 4405 vim9script 4406 def g:FuncA() 4407 # Some comment 4408 FuncB(0) 4409 enddef 4410 # Some comment 4411 def FuncB( 4412 # Some comment 4413 n: number 4414 ) 4415 exe 'nno ' 4416 # Some comment 4417 .. '<F3> a' 4418 .. 'b' 4419 .. 'c' 4420 enddef 4421 END 4422 CheckScriptSuccess(lines) 4423 var res = execute('verbose nmap <F3>') 4424 assert_match('No mapping found', res) 4425 4426 g:FuncA() 4427 res = execute('verbose nmap <F3>') 4428 assert_match(' <F3> .* abc.*Last set from .*XScriptSuccess\d\+ line 11', res) 4429 4430 nunmap <F3> 4431 delfunc g:FuncA 4432enddef 4433 4434def Test_option_set() 4435 # legacy script allows for white space 4436 var lines =<< trim END 4437 set foldlevel =11 4438 call assert_equal(11, &foldlevel) 4439 END 4440 CheckScriptSuccess(lines) 4441 4442 set foldlevel 4443 set foldlevel=12 4444 assert_equal(12, &foldlevel) 4445 set foldlevel+=2 4446 assert_equal(14, &foldlevel) 4447 set foldlevel-=3 4448 assert_equal(11, &foldlevel) 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 lines =<< trim END 4456 set foldlevel +=1 4457 END 4458 CheckDefExecAndScriptFailure(lines, 'E1205: No white space allowed between option and: +=1') 4459 4460 lines =<< trim END 4461 set foldlevel ^=1 4462 END 4463 CheckDefExecAndScriptFailure(lines, 'E1205: No white space allowed between option and: ^=1') 4464 4465 lines =<< trim END 4466 set foldlevel -=1 4467 END 4468 CheckDefExecAndScriptFailure(lines, 'E1205: No white space allowed between option and: -=1') 4469 4470 set foldlevel& 4471enddef 4472 4473def Test_option_modifier() 4474 # legacy script allows for white space 4475 var lines =<< trim END 4476 set hlsearch & hlsearch ! 4477 call assert_equal(1, &hlsearch) 4478 END 4479 CheckScriptSuccess(lines) 4480 4481 set hlsearch 4482 set hlsearch! 4483 assert_equal(false, &hlsearch) 4484 4485 set hlsearch 4486 set hlsearch& 4487 assert_equal(false, &hlsearch) 4488 4489 lines =<< trim END 4490 set hlsearch & 4491 END 4492 CheckDefExecAndScriptFailure(lines, 'E1205: No white space allowed between option and: &') 4493 4494 lines =<< trim END 4495 set hlsearch ! 4496 END 4497 CheckDefExecAndScriptFailure(lines, 'E1205: No white space allowed between option and: !') 4498 4499 set hlsearch& 4500enddef 4501 4502" This must be called last, it may cause following :def functions to fail 4503def Test_xxx_echoerr_line_number() 4504 var lines =<< trim END 4505 echoerr 'some' 4506 .. ' error' 4507 .. ' continued' 4508 END 4509 CheckDefExecAndScriptFailure(lines, 'some error continued', 1) 4510enddef 4511 4512def ProfiledWithLambda() 4513 var n = 3 4514 echo [[1, 2], [3, 4]]->filter((_, l) => l[0] == n) 4515enddef 4516 4517def ProfiledNested() 4518 var x = 0 4519 def Nested(): any 4520 return x 4521 enddef 4522 Nested() 4523enddef 4524 4525def ProfiledNestedProfiled() 4526 var x = 0 4527 def Nested(): any 4528 return x 4529 enddef 4530 Nested() 4531enddef 4532 4533" Execute this near the end, profiling doesn't stop until Vim exists. 4534" This only tests that it works, not the profiling output. 4535def Test_xx_profile_with_lambda() 4536 CheckFeature profile 4537 4538 profile start Xprofile.log 4539 profile func ProfiledWithLambda 4540 ProfiledWithLambda() 4541 4542 profile func ProfiledNested 4543 ProfiledNested() 4544 4545 # Also profile the nested function. Use a different function, although the 4546 # contents is the same, to make sure it was not already compiled. 4547 profile func * 4548 ProfiledNestedProfiled() 4549 4550 profdel func * 4551 profile pause 4552enddef 4553 4554" Keep this last, it messes up highlighting. 4555def Test_substitute_cmd() 4556 new 4557 setline(1, 'something') 4558 :substitute(some(other( 4559 assert_equal('otherthing', getline(1)) 4560 bwipe! 4561 4562 # also when the context is Vim9 script 4563 var lines =<< trim END 4564 vim9script 4565 new 4566 setline(1, 'something') 4567 :substitute(some(other( 4568 assert_equal('otherthing', getline(1)) 4569 bwipe! 4570 END 4571 writefile(lines, 'Xvim9lines') 4572 source Xvim9lines 4573 4574 delete('Xvim9lines') 4575enddef 4576 4577" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 4578