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