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