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