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