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 8 9def Test_range_only() 10 new 11 setline(1, ['blah', 'Blah']) 12 :/Blah/ 13 assert_equal(2, getcurpos()[1]) 14 bwipe! 15 16 # without range commands use current line 17 new 18 setline(1, ['one', 'two', 'three']) 19 :2 20 print 21 assert_equal('two', Screenline(&lines)) 22 :3 23 list 24 assert_equal('three$', Screenline(&lines)) 25 bwipe! 26 27 # won't generate anything 28 if false 29 :123 30 endif 31enddef 32 33let g:alist = [7] 34let g:astring = 'text' 35let g:anumber = 123 36 37def Test_delfunction() 38 # Check function is defined in script namespace 39 CheckScriptSuccess([ 40 'vim9script', 41 'func CheckMe()', 42 ' return 123', 43 'endfunc', 44 'assert_equal(123, s:CheckMe())', 45 ]) 46 47 # Check function in script namespace cannot be deleted 48 CheckScriptFailure([ 49 'vim9script', 50 'func DeleteMe1()', 51 'endfunc', 52 'delfunction DeleteMe1', 53 ], 'E1084:') 54 CheckScriptFailure([ 55 'vim9script', 56 'func DeleteMe2()', 57 'endfunc', 58 'def DoThat()', 59 ' delfunction DeleteMe2', 60 'enddef', 61 'DoThat()', 62 ], 'E1084:') 63 CheckScriptFailure([ 64 'vim9script', 65 'def DeleteMe3()', 66 'enddef', 67 'delfunction DeleteMe3', 68 ], 'E1084:') 69 CheckScriptFailure([ 70 'vim9script', 71 'def DeleteMe4()', 72 'enddef', 73 'def DoThat()', 74 ' delfunction DeleteMe4', 75 'enddef', 76 'DoThat()', 77 ], 'E1084:') 78 79 # Check that global :def function can be replaced and deleted 80 var lines =<< trim END 81 vim9script 82 def g:Global(): string 83 return "yes" 84 enddef 85 assert_equal("yes", g:Global()) 86 def! g:Global(): string 87 return "no" 88 enddef 89 assert_equal("no", g:Global()) 90 delfunc g:Global 91 assert_false(exists('*g:Global')) 92 END 93 CheckScriptSuccess(lines) 94 95 # Check that global function can be replaced by a :def function and deleted 96 lines =<< trim END 97 vim9script 98 func g:Global() 99 return "yes" 100 endfunc 101 assert_equal("yes", g:Global()) 102 def! g:Global(): string 103 return "no" 104 enddef 105 assert_equal("no", g:Global()) 106 delfunc g:Global 107 assert_false(exists('*g:Global')) 108 END 109 CheckScriptSuccess(lines) 110 111 # Check that global :def function can be replaced by a function and deleted 112 lines =<< trim END 113 vim9script 114 def g:Global(): string 115 return "yes" 116 enddef 117 assert_equal("yes", g:Global()) 118 func! g:Global() 119 return "no" 120 endfunc 121 assert_equal("no", g:Global()) 122 delfunc g:Global 123 assert_false(exists('*g:Global')) 124 END 125 CheckScriptSuccess(lines) 126enddef 127 128def Test_wrong_type() 129 CheckDefFailure(['var name: list<nothing>'], 'E1010:') 130 CheckDefFailure(['var name: list<list<nothing>>'], 'E1010:') 131 CheckDefFailure(['var name: dict<nothing>'], 'E1010:') 132 CheckDefFailure(['var name: dict<dict<nothing>>'], 'E1010:') 133 134 CheckDefFailure(['var name: dict<number'], 'E1009:') 135 CheckDefFailure(['var name: dict<list<number>'], 'E1009:') 136 137 CheckDefFailure(['var name: ally'], 'E1010:') 138 CheckDefFailure(['var name: bram'], 'E1010:') 139 CheckDefFailure(['var name: cathy'], 'E1010:') 140 CheckDefFailure(['var name: dom'], 'E1010:') 141 CheckDefFailure(['var name: freddy'], 'E1010:') 142 CheckDefFailure(['var name: john'], 'E1010:') 143 CheckDefFailure(['var name: larry'], 'E1010:') 144 CheckDefFailure(['var name: ned'], 'E1010:') 145 CheckDefFailure(['var name: pam'], 'E1010:') 146 CheckDefFailure(['var name: sam'], 'E1010:') 147 CheckDefFailure(['var name: vim'], 'E1010:') 148 149 CheckDefFailure(['var Ref: number', 'Ref()'], 'E1085:') 150 CheckDefFailure(['var Ref: string', 'var res = Ref()'], 'E1085:') 151enddef 152 153def Test_script_wrong_type() 154 var lines =<< trim END 155 vim9script 156 var s:dict: dict<string> 157 s:dict['a'] = ['x'] 158 END 159 CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got list<string>', 3) 160enddef 161 162def Test_const() 163 CheckDefFailure(['final name = 234', 'name = 99'], 'E1018:') 164 CheckDefFailure(['final one = 234', 'var one = 99'], 'E1017:') 165 CheckDefFailure(['final list = [1, 2]', 'var list = [3, 4]'], 'E1017:') 166 CheckDefFailure(['final two'], 'E1125:') 167 CheckDefFailure(['final &option'], 'E996:') 168 169 var lines =<< trim END 170 final list = [1, 2, 3] 171 list[0] = 4 172 list->assert_equal([4, 2, 3]) 173 const other = [5, 6, 7] 174 other->assert_equal([5, 6, 7]) 175 176 var varlist = [7, 8] 177 const constlist = [1, varlist, 3] 178 varlist[0] = 77 179 # TODO: does not work yet 180 # constlist[1][1] = 88 181 var cl = constlist[1] 182 cl[1] = 88 183 constlist->assert_equal([1, [77, 88], 3]) 184 185 var vardict = {five: 5, six: 6} 186 const constdict = {one: 1, two: vardict, three: 3} 187 vardict['five'] = 55 188 # TODO: does not work yet 189 # constdict['two']['six'] = 66 190 var cd = constdict['two'] 191 cd['six'] = 66 192 constdict->assert_equal({one: 1, two: {five: 55, six: 66}, three: 3}) 193 END 194 CheckDefAndScriptSuccess(lines) 195enddef 196 197def Test_const_bang() 198 var lines =<< trim END 199 const var = 234 200 var = 99 201 END 202 CheckDefExecFailure(lines, 'E1018:', 2) 203 CheckScriptFailure(['vim9script'] + lines, 'E46:', 3) 204 205 lines =<< trim END 206 const ll = [2, 3, 4] 207 ll[0] = 99 208 END 209 CheckDefExecFailure(lines, 'E1119:', 2) 210 CheckScriptFailure(['vim9script'] + lines, 'E741:', 3) 211 212 lines =<< trim END 213 const ll = [2, 3, 4] 214 ll[3] = 99 215 END 216 CheckDefExecFailure(lines, 'E1118:', 2) 217 CheckScriptFailure(['vim9script'] + lines, 'E684:', 3) 218 219 lines =<< trim END 220 const dd = {one: 1, two: 2} 221 dd["one"] = 99 222 END 223 CheckDefExecFailure(lines, 'E1121:', 2) 224 CheckScriptFailure(['vim9script'] + lines, 'E741:', 3) 225 226 lines =<< trim END 227 const dd = {one: 1, two: 2} 228 dd["three"] = 99 229 END 230 CheckDefExecFailure(lines, 'E1120:') 231 CheckScriptFailure(['vim9script'] + lines, 'E741:', 3) 232enddef 233 234def Test_range_no_colon() 235 CheckDefFailure(['%s/a/b/'], 'E1050:') 236 CheckDefFailure(['+ s/a/b/'], 'E1050:') 237 CheckDefFailure(['- s/a/b/'], 'E1050:') 238 CheckDefFailure(['. s/a/b/'], 'E1050:') 239enddef 240 241 242def Test_block() 243 var outer = 1 244 { 245 var inner = 2 246 assert_equal(1, outer) 247 assert_equal(2, inner) 248 } 249 assert_equal(1, outer) 250enddef 251 252def Test_block_failure() 253 CheckDefFailure(['{', 'var inner = 1', '}', 'echo inner'], 'E1001:') 254 CheckDefFailure(['}'], 'E1025:') 255 CheckDefFailure(['{', 'echo 1'], 'E1026:') 256enddef 257 258def Test_block_local_vars() 259 var lines =<< trim END 260 vim9script 261 v:testing = 1 262 if true 263 var text = ['hello'] 264 def SayHello(): list<string> 265 return text 266 enddef 267 def SetText(v: string) 268 text = [v] 269 enddef 270 endif 271 272 if true 273 var text = ['again'] 274 def SayAgain(): list<string> 275 return text 276 enddef 277 endif 278 279 # test that the "text" variables are not cleaned up 280 test_garbagecollect_now() 281 282 defcompile 283 284 assert_equal(['hello'], SayHello()) 285 assert_equal(['again'], SayAgain()) 286 287 SetText('foobar') 288 assert_equal(['foobar'], SayHello()) 289 290 call writefile(['ok'], 'Xdidit') 291 qall! 292 END 293 294 # need to execute this with a separate Vim instance to avoid the current 295 # context gets garbage collected. 296 writefile(lines, 'Xscript') 297 RunVim([], [], '-S Xscript') 298 assert_equal(['ok'], readfile('Xdidit')) 299 300 delete('Xscript') 301 delete('Xdidit') 302enddef 303 304def Test_block_local_vars_with_func() 305 var lines =<< trim END 306 vim9script 307 if true 308 var foo = 'foo' 309 if true 310 var bar = 'bar' 311 def Func(): list<string> 312 return [foo, bar] 313 enddef 314 endif 315 endif 316 # function is compiled here, after blocks have finished, can still access 317 # "foo" and "bar" 318 assert_equal(['foo', 'bar'], Func()) 319 END 320 CheckScriptSuccess(lines) 321enddef 322 323func g:NoSuchFunc() 324 echo 'none' 325endfunc 326 327def Test_try_catch() 328 var l = [] 329 try # comment 330 add(l, '1') 331 throw 'wrong' 332 add(l, '2') 333 catch # comment 334 add(l, v:exception) 335 finally # comment 336 add(l, '3') 337 endtry # comment 338 assert_equal(['1', 'wrong', '3'], l) 339 340 l = [] 341 try 342 try 343 add(l, '1') 344 throw 'wrong' 345 add(l, '2') 346 catch /right/ 347 add(l, v:exception) 348 endtry 349 catch /wrong/ 350 add(l, 'caught') 351 fina 352 add(l, 'finally') 353 endtry 354 assert_equal(['1', 'caught', 'finally'], l) 355 356 var n: number 357 try 358 n = l[3] 359 catch /E684:/ 360 n = 99 361 endtry 362 assert_equal(99, n) 363 364 var done = 'no' 365 if 0 366 try | catch | endtry 367 else 368 done = 'yes' 369 endif 370 assert_equal('yes', done) 371 372 done = 'no' 373 if 1 374 done = 'yes' 375 else 376 try | catch | endtry 377 done = 'never' 378 endif 379 assert_equal('yes', done) 380 381 if 1 382 else 383 try | catch /pat/ | endtry 384 try | catch /pat/ 385 endtry 386 try 387 catch /pat/ | endtry 388 try 389 catch /pat/ 390 endtry 391 endif 392 393 try 394 # string slice returns a string, not a number 395 n = g:astring[3] 396 catch /E1012:/ 397 n = 77 398 endtry 399 assert_equal(77, n) 400 401 try 402 n = l[g:astring] 403 catch /E1012:/ 404 n = 88 405 endtry 406 assert_equal(88, n) 407 408 try 409 n = s:does_not_exist 410 catch /E121:/ 411 n = 111 412 endtry 413 assert_equal(111, n) 414 415 try 416 n = g:does_not_exist 417 catch /E121:/ 418 n = 121 419 endtry 420 assert_equal(121, n) 421 422 var d = {one: 1} 423 try 424 n = d[g:astring] 425 catch /E716:/ 426 n = 222 427 endtry 428 assert_equal(222, n) 429 430 try 431 n = -g:astring 432 catch /E39:/ 433 n = 233 434 endtry 435 assert_equal(233, n) 436 437 try 438 n = +g:astring 439 catch /E1030:/ 440 n = 244 441 endtry 442 assert_equal(244, n) 443 444 try 445 n = +g:alist 446 catch /E745:/ 447 n = 255 448 endtry 449 assert_equal(255, n) 450 451 var nd: dict<any> 452 try 453 nd = {[g:anumber]: 1} 454 catch /E1012:/ 455 n = 266 456 endtry 457 assert_equal(266, n) 458 459 try 460 [n] = [1, 2, 3] 461 catch /E1093:/ 462 n = 277 463 endtry 464 assert_equal(277, n) 465 466 try 467 &ts = g:astring 468 catch /E1012:/ 469 n = 288 470 endtry 471 assert_equal(288, n) 472 473 try 474 &backspace = 'asdf' 475 catch /E474:/ 476 n = 299 477 endtry 478 assert_equal(299, n) 479 480 l = [1] 481 try 482 l[3] = 3 483 catch /E684:/ 484 n = 300 485 endtry 486 assert_equal(300, n) 487 488 try 489 unlet g:does_not_exist 490 catch /E108:/ 491 n = 322 492 endtry 493 assert_equal(322, n) 494 495 try 496 d = {text: 1, [g:astring]: 2} 497 catch /E721:/ 498 n = 333 499 endtry 500 assert_equal(333, n) 501 502 try 503 l = DeletedFunc() 504 catch /E933:/ 505 n = 344 506 endtry 507 assert_equal(344, n) 508 509 try 510 echo len(v:true) 511 catch /E701:/ 512 n = 355 513 endtry 514 assert_equal(355, n) 515 516 var P = function('g:NoSuchFunc') 517 delfunc g:NoSuchFunc 518 try 519 echo P() 520 catch /E117:/ 521 n = 366 522 endtry 523 assert_equal(366, n) 524 525 try 526 echo g:NoSuchFunc() 527 catch /E117:/ 528 n = 377 529 endtry 530 assert_equal(377, n) 531 532 try 533 echo g:alist + 4 534 catch /E745:/ 535 n = 388 536 endtry 537 assert_equal(388, n) 538 539 try 540 echo 4 + g:alist 541 catch /E745:/ 542 n = 399 543 endtry 544 assert_equal(399, n) 545 546 try 547 echo g:alist.member 548 catch /E715:/ 549 n = 400 550 endtry 551 assert_equal(400, n) 552 553 try 554 echo d.member 555 catch /E716:/ 556 n = 411 557 endtry 558 assert_equal(411, n) 559enddef 560 561def DeletedFunc(): list<any> 562 return ['delete me'] 563enddef 564defcompile 565delfunc DeletedFunc 566 567def ThrowFromDef() 568 throw "getout" # comment 569enddef 570 571func CatchInFunc() 572 try 573 call ThrowFromDef() 574 catch 575 let g:thrown_func = v:exception 576 endtry 577endfunc 578 579def CatchInDef() 580 try 581 ThrowFromDef() 582 catch 583 g:thrown_def = v:exception 584 endtry 585enddef 586 587def ReturnFinally(): string 588 try 589 return 'intry' 590 finall 591 g:in_finally = 'finally' 592 endtry 593 return 'end' 594enddef 595 596def Test_try_catch_nested() 597 CatchInFunc() 598 assert_equal('getout', g:thrown_func) 599 600 CatchInDef() 601 assert_equal('getout', g:thrown_def) 602 603 assert_equal('intry', ReturnFinally()) 604 assert_equal('finally', g:in_finally) 605enddef 606 607def TryOne(): number 608 try 609 return 0 610 catch 611 endtry 612 return 0 613enddef 614 615def TryTwo(n: number): string 616 try 617 var x = {} 618 catch 619 endtry 620 return 'text' 621enddef 622 623def Test_try_catch_twice() 624 assert_equal('text', TryOne()->TryTwo()) 625enddef 626 627def Test_try_catch_match() 628 var seq = 'a' 629 try 630 throw 'something' 631 catch /nothing/ 632 seq ..= 'x' 633 catch /some/ 634 seq ..= 'b' 635 catch /asdf/ 636 seq ..= 'x' 637 catch ?a\?sdf? 638 seq ..= 'y' 639 finally 640 seq ..= 'c' 641 endtry 642 assert_equal('abc', seq) 643enddef 644 645def Test_try_catch_fails() 646 CheckDefFailure(['catch'], 'E603:') 647 CheckDefFailure(['try', 'echo 0', 'catch', 'catch'], 'E1033:') 648 CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:') 649 CheckDefFailure(['finally'], 'E606:') 650 CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:') 651 CheckDefFailure(['endtry'], 'E602:') 652 CheckDefFailure(['while 1', 'endtry'], 'E170:') 653 CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:') 654 CheckDefFailure(['if 1', 'endtry'], 'E171:') 655 CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:') 656 657 CheckDefFailure(['throw'], 'E1143:') 658 CheckDefFailure(['throw xxx'], 'E1001:') 659enddef 660 661def Test_throw_vimscript() 662 # only checks line continuation 663 var lines =<< trim END 664 vim9script 665 try 666 throw 'one' 667 .. 'two' 668 catch 669 assert_equal('onetwo', v:exception) 670 endtry 671 END 672 CheckScriptSuccess(lines) 673 674 lines =<< trim END 675 vim9script 676 @r = '' 677 def Func() 678 throw @r 679 enddef 680 var result = '' 681 try 682 Func() 683 catch /E1129:/ 684 result = 'caught' 685 endtry 686 assert_equal('caught', result) 687 END 688 CheckScriptSuccess(lines) 689enddef 690 691def Test_error_in_nested_function() 692 # an error in a nested :function aborts executin in the calling :def function 693 var lines =<< trim END 694 vim9script 695 def Func() 696 Error() 697 g:test_var = 1 698 enddef 699 func Error() abort 700 eval [][0] 701 endfunc 702 Func() 703 END 704 g:test_var = 0 705 CheckScriptFailure(lines, 'E684:') 706 assert_equal(0, g:test_var) 707enddef 708 709def Test_cexpr_vimscript() 710 # only checks line continuation 711 set errorformat=File\ %f\ line\ %l 712 var lines =<< trim END 713 vim9script 714 cexpr 'File' 715 .. ' someFile' .. 716 ' line 19' 717 assert_equal(19, getqflist()[0].lnum) 718 END 719 CheckScriptSuccess(lines) 720 set errorformat& 721enddef 722 723def Test_statusline_syntax() 724 # legacy syntax is used for 'statusline' 725 var lines =<< trim END 726 vim9script 727 func g:Status() 728 return '%{"x" is# "x"}' 729 endfunc 730 set laststatus=2 statusline=%!Status() 731 redrawstatus 732 set laststatus statusline= 733 END 734 CheckScriptSuccess(lines) 735enddef 736 737def Test_list_vimscript() 738 # checks line continuation and comments 739 var lines =<< trim END 740 vim9script 741 var mylist = [ 742 'one', 743 # comment 744 'two', # empty line follows 745 746 'three', 747 ] 748 assert_equal(['one', 'two', 'three'], mylist) 749 END 750 CheckScriptSuccess(lines) 751 752 # check all lines from heredoc are kept 753 lines =<< trim END 754 # comment 1 755 two 756 # comment 3 757 758 five 759 # comment 6 760 END 761 assert_equal(['# comment 1', 'two', '# comment 3', '', 'five', '# comment 6'], lines) 762enddef 763 764if has('channel') 765 let someJob = test_null_job() 766 767 def FuncWithError() 768 echomsg g:someJob 769 enddef 770 771 func Test_convert_emsg_to_exception() 772 try 773 call FuncWithError() 774 catch 775 call assert_match('Vim:E908:', v:exception) 776 endtry 777 endfunc 778endif 779 780let s:export_script_lines =<< trim END 781 vim9script 782 var name: string = 'bob' 783 def Concat(arg: string): string 784 return name .. arg 785 enddef 786 g:result = Concat('bie') 787 g:localname = name 788 789 export const CONST = 1234 790 export var exported = 9876 791 export var exp_name = 'John' 792 export def Exported(): string 793 return 'Exported' 794 enddef 795END 796 797def Undo_export_script_lines() 798 unlet g:result 799 unlet g:localname 800enddef 801 802def Test_vim9_import_export() 803 var import_script_lines =<< trim END 804 vim9script 805 import {exported, Exported} from './Xexport.vim' 806 g:imported = exported 807 exported += 3 808 g:imported_added = exported 809 g:imported_func = Exported() 810 811 def GetExported(): string 812 var local_dict = {ref: Exported} 813 return local_dict.ref() 814 enddef 815 g:funcref_result = GetExported() 816 817 import {exp_name} from './Xexport.vim' 818 g:imported_name = exp_name 819 exp_name ..= ' Doe' 820 g:imported_name_appended = exp_name 821 g:imported_later = exported 822 END 823 824 writefile(import_script_lines, 'Ximport.vim') 825 writefile(s:export_script_lines, 'Xexport.vim') 826 827 source Ximport.vim 828 829 assert_equal('bobbie', g:result) 830 assert_equal('bob', g:localname) 831 assert_equal(9876, g:imported) 832 assert_equal(9879, g:imported_added) 833 assert_equal(9879, g:imported_later) 834 assert_equal('Exported', g:imported_func) 835 assert_equal('Exported', g:funcref_result) 836 assert_equal('John', g:imported_name) 837 assert_equal('John Doe', g:imported_name_appended) 838 assert_false(exists('g:name')) 839 840 Undo_export_script_lines() 841 unlet g:imported 842 unlet g:imported_added 843 unlet g:imported_later 844 unlet g:imported_func 845 unlet g:imported_name g:imported_name_appended 846 delete('Ximport.vim') 847 848 # similar, with line breaks 849 var import_line_break_script_lines =<< trim END 850 vim9script 851 import { 852 exported, 853 Exported, 854 } 855 from 856 './Xexport.vim' 857 g:imported = exported 858 exported += 5 859 g:imported_added = exported 860 g:imported_func = Exported() 861 END 862 writefile(import_line_break_script_lines, 'Ximport_lbr.vim') 863 source Ximport_lbr.vim 864 865 assert_equal(9876, g:imported) 866 assert_equal(9881, g:imported_added) 867 assert_equal('Exported', g:imported_func) 868 869 # exported script not sourced again 870 assert_false(exists('g:result')) 871 unlet g:imported 872 unlet g:imported_added 873 unlet g:imported_func 874 delete('Ximport_lbr.vim') 875 876 # import inside :def function 877 var import_in_def_lines =<< trim END 878 vim9script 879 def ImportInDef() 880 import exported from './Xexport.vim' 881 g:imported = exported 882 exported += 7 883 g:imported_added = exported 884 enddef 885 ImportInDef() 886 END 887 writefile(import_in_def_lines, 'Ximport2.vim') 888 source Ximport2.vim 889 # TODO: this should be 9879 890 assert_equal(9876, g:imported) 891 assert_equal(9883, g:imported_added) 892 unlet g:imported 893 unlet g:imported_added 894 delete('Ximport2.vim') 895 896 var import_star_as_lines =<< trim END 897 vim9script 898 import * as Export from './Xexport.vim' 899 def UseExport() 900 g:imported = Export.exported 901 enddef 902 UseExport() 903 END 904 writefile(import_star_as_lines, 'Ximport.vim') 905 source Ximport.vim 906 assert_equal(9883, g:imported) 907 908 var import_star_as_lines_no_dot =<< trim END 909 vim9script 910 import * as Export from './Xexport.vim' 911 def Func() 912 var dummy = 1 913 var imported = Export + dummy 914 enddef 915 defcompile 916 END 917 writefile(import_star_as_lines_no_dot, 'Ximport.vim') 918 assert_fails('source Ximport.vim', 'E1060:', '', 2, 'Func') 919 920 var import_star_as_lines_dot_space =<< trim END 921 vim9script 922 import * as Export from './Xexport.vim' 923 def Func() 924 var imported = Export . exported 925 enddef 926 defcompile 927 END 928 writefile(import_star_as_lines_dot_space, 'Ximport.vim') 929 assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func') 930 931 var import_star_as_duplicated =<< trim END 932 vim9script 933 import * as Export from './Xexport.vim' 934 var some = 'other' 935 import * as Export from './Xexport.vim' 936 defcompile 937 END 938 writefile(import_star_as_duplicated, 'Ximport.vim') 939 assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim') 940 941 var import_star_as_lines_missing_name =<< trim END 942 vim9script 943 import * as Export from './Xexport.vim' 944 def Func() 945 var imported = Export. 946 enddef 947 defcompile 948 END 949 writefile(import_star_as_lines_missing_name, 'Ximport.vim') 950 assert_fails('source Ximport.vim', 'E1048:', '', 1, 'Func') 951 952 var import_star_as_lbr_lines =<< trim END 953 vim9script 954 import * 955 as Export 956 from 957 './Xexport.vim' 958 def UseExport() 959 g:imported = Export.exported 960 enddef 961 UseExport() 962 END 963 writefile(import_star_as_lbr_lines, 'Ximport.vim') 964 source Ximport.vim 965 assert_equal(9883, g:imported) 966 967 var import_star_lines =<< trim END 968 vim9script 969 import * from './Xexport.vim' 970 END 971 writefile(import_star_lines, 'Ximport.vim') 972 assert_fails('source Ximport.vim', 'E1045:', '', 2, 'Ximport.vim') 973 974 # try to import something that exists but is not exported 975 var import_not_exported_lines =<< trim END 976 vim9script 977 import name from './Xexport.vim' 978 END 979 writefile(import_not_exported_lines, 'Ximport.vim') 980 assert_fails('source Ximport.vim', 'E1049:', '', 2, 'Ximport.vim') 981 982 # try to import something that is already defined 983 var import_already_defined =<< trim END 984 vim9script 985 var exported = 'something' 986 import exported from './Xexport.vim' 987 END 988 writefile(import_already_defined, 'Ximport.vim') 989 assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim') 990 991 # try to import something that is already defined 992 import_already_defined =<< trim END 993 vim9script 994 var exported = 'something' 995 import * as exported from './Xexport.vim' 996 END 997 writefile(import_already_defined, 'Ximport.vim') 998 assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim') 999 1000 # try to import something that is already defined 1001 import_already_defined =<< trim END 1002 vim9script 1003 var exported = 'something' 1004 import {exported} from './Xexport.vim' 1005 END 1006 writefile(import_already_defined, 'Ximport.vim') 1007 assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim') 1008 1009 # try changing an imported const 1010 var import_assign_to_const =<< trim END 1011 vim9script 1012 import CONST from './Xexport.vim' 1013 def Assign() 1014 CONST = 987 1015 enddef 1016 defcompile 1017 END 1018 writefile(import_assign_to_const, 'Ximport.vim') 1019 assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign') 1020 1021 # import a very long name, requires making a copy 1022 var import_long_name_lines =<< trim END 1023 vim9script 1024 import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim' 1025 END 1026 writefile(import_long_name_lines, 'Ximport.vim') 1027 assert_fails('source Ximport.vim', 'E1048:', '', 2, 'Ximport.vim') 1028 1029 var import_no_from_lines =<< trim END 1030 vim9script 1031 import name './Xexport.vim' 1032 END 1033 writefile(import_no_from_lines, 'Ximport.vim') 1034 assert_fails('source Ximport.vim', 'E1070:', '', 2, 'Ximport.vim') 1035 1036 var import_invalid_string_lines =<< trim END 1037 vim9script 1038 import name from Xexport.vim 1039 END 1040 writefile(import_invalid_string_lines, 'Ximport.vim') 1041 assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim') 1042 1043 var import_wrong_name_lines =<< trim END 1044 vim9script 1045 import name from './XnoExport.vim' 1046 END 1047 writefile(import_wrong_name_lines, 'Ximport.vim') 1048 assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim') 1049 1050 var import_missing_comma_lines =<< trim END 1051 vim9script 1052 import {exported name} from './Xexport.vim' 1053 END 1054 writefile(import_missing_comma_lines, 'Ximport3.vim') 1055 assert_fails('source Ximport3.vim', 'E1046:', '', 2, 'Ximport3.vim') 1056 1057 delete('Ximport.vim') 1058 delete('Ximport3.vim') 1059 delete('Xexport.vim') 1060 1061 # Check that in a Vim9 script 'cpo' is set to the Vim default. 1062 set cpo&vi 1063 var cpo_before = &cpo 1064 var lines =<< trim END 1065 vim9script 1066 g:cpo_in_vim9script = &cpo 1067 END 1068 writefile(lines, 'Xvim9_script') 1069 source Xvim9_script 1070 assert_equal(cpo_before, &cpo) 1071 set cpo&vim 1072 assert_equal(&cpo, g:cpo_in_vim9script) 1073 delete('Xvim9_script') 1074enddef 1075 1076func g:Trigger() 1077 source Ximport.vim 1078 return "echo 'yes'\<CR>" 1079endfunc 1080 1081def Test_import_export_expr_map() 1082 # check that :import and :export work when buffer is locked 1083 var export_lines =<< trim END 1084 vim9script 1085 export def That(): string 1086 return 'yes' 1087 enddef 1088 END 1089 writefile(export_lines, 'Xexport_that.vim') 1090 1091 var import_lines =<< trim END 1092 vim9script 1093 import That from './Xexport_that.vim' 1094 assert_equal('yes', That()) 1095 END 1096 writefile(import_lines, 'Ximport.vim') 1097 1098 nnoremap <expr> trigger g:Trigger() 1099 feedkeys('trigger', "xt") 1100 1101 delete('Xexport_that.vim') 1102 delete('Ximport.vim') 1103 nunmap trigger 1104enddef 1105 1106def Test_import_in_filetype() 1107 # check that :import works when the buffer is locked 1108 mkdir('ftplugin', 'p') 1109 var export_lines =<< trim END 1110 vim9script 1111 export var That = 'yes' 1112 END 1113 writefile(export_lines, 'ftplugin/Xexport_ft.vim') 1114 1115 var import_lines =<< trim END 1116 vim9script 1117 import That from './Xexport_ft.vim' 1118 assert_equal('yes', That) 1119 g:did_load_mytpe = 1 1120 END 1121 writefile(import_lines, 'ftplugin/qf.vim') 1122 1123 var save_rtp = &rtp 1124 &rtp = getcwd() .. ',' .. &rtp 1125 1126 filetype plugin on 1127 copen 1128 assert_equal(1, g:did_load_mytpe) 1129 1130 quit! 1131 delete('Xexport_ft.vim') 1132 delete('ftplugin', 'rf') 1133 &rtp = save_rtp 1134enddef 1135 1136def Test_use_import_in_mapping() 1137 var lines =<< trim END 1138 vim9script 1139 export def Funcx() 1140 g:result = 42 1141 enddef 1142 END 1143 writefile(lines, 'XsomeExport.vim') 1144 lines =<< trim END 1145 vim9script 1146 import Funcx from './XsomeExport.vim' 1147 nnoremap <F3> :call <sid>Funcx()<cr> 1148 END 1149 writefile(lines, 'Xmapscript.vim') 1150 1151 source Xmapscript.vim 1152 feedkeys("\<F3>", "xt") 1153 assert_equal(42, g:result) 1154 1155 unlet g:result 1156 delete('XsomeExport.vim') 1157 delete('Xmapscript.vim') 1158 nunmap <F3> 1159enddef 1160 1161def Test_vim9script_fails() 1162 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') 1163 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') 1164 CheckScriptFailure(['export var some = 123'], 'E1042:') 1165 CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:') 1166 CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:') 1167 CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') 1168 1169 CheckScriptFailure(['vim9script', 'var str: string', 'str = 1234'], 'E1012:') 1170 CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:') 1171 1172 assert_fails('vim9script', 'E1038:') 1173 assert_fails('export something', 'E1043:') 1174enddef 1175 1176func Test_import_fails_without_script() 1177 CheckRunVimInTerminal 1178 1179 " call indirectly to avoid compilation error for missing functions 1180 call Run_Test_import_fails_on_command_line() 1181endfunc 1182 1183def Run_Test_import_fails_on_command_line() 1184 var export =<< trim END 1185 vim9script 1186 export def Foo(): number 1187 return 0 1188 enddef 1189 END 1190 writefile(export, 'XexportCmd.vim') 1191 1192 var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', { 1193 rows: 6, wait_for_ruler: 0}) 1194 WaitForAssert(() => assert_match('^E1094:', term_getline(buf, 5))) 1195 1196 delete('XexportCmd.vim') 1197 StopVimInTerminal(buf) 1198enddef 1199 1200def Test_vim9script_reload_noclear() 1201 var lines =<< trim END 1202 vim9script 1203 export var exported = 'thexport' 1204 END 1205 writefile(lines, 'XExportReload') 1206 lines =<< trim END 1207 vim9script noclear 1208 g:loadCount += 1 1209 var s:reloaded = 'init' 1210 import exported from './XExportReload' 1211 1212 def Again(): string 1213 return 'again' 1214 enddef 1215 1216 if exists('s:loaded') | finish | endif 1217 var s:loaded = true 1218 1219 var s:notReloaded = 'yes' 1220 s:reloaded = 'first' 1221 def g:Values(): list<string> 1222 return [s:reloaded, s:notReloaded, Again(), Once(), exported] 1223 enddef 1224 1225 def Once(): string 1226 return 'once' 1227 enddef 1228 END 1229 writefile(lines, 'XReloaded') 1230 g:loadCount = 0 1231 source XReloaded 1232 assert_equal(1, g:loadCount) 1233 assert_equal(['first', 'yes', 'again', 'once', 'thexport'], g:Values()) 1234 source XReloaded 1235 assert_equal(2, g:loadCount) 1236 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1237 source XReloaded 1238 assert_equal(3, g:loadCount) 1239 assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) 1240 1241 delete('Xreloaded') 1242 delete('XExportReload') 1243 delfunc g:Values 1244 unlet g:loadCount 1245enddef 1246 1247def Test_vim9script_reload_import() 1248 var lines =<< trim END 1249 vim9script 1250 const var = '' 1251 var valone = 1234 1252 def MyFunc(arg: string) 1253 valone = 5678 1254 enddef 1255 END 1256 var morelines =<< trim END 1257 var valtwo = 222 1258 export def GetValtwo(): number 1259 return valtwo 1260 enddef 1261 END 1262 writefile(lines + morelines, 'Xreload.vim') 1263 source Xreload.vim 1264 source Xreload.vim 1265 source Xreload.vim 1266 1267 var testlines =<< trim END 1268 vim9script 1269 def TheFunc() 1270 import GetValtwo from './Xreload.vim' 1271 assert_equal(222, GetValtwo()) 1272 enddef 1273 TheFunc() 1274 END 1275 writefile(testlines, 'Ximport.vim') 1276 source Ximport.vim 1277 1278 # Test that when not using "morelines" GetValtwo() and valtwo are still 1279 # defined, because import doesn't reload a script. 1280 writefile(lines, 'Xreload.vim') 1281 source Ximport.vim 1282 1283 # cannot declare a var twice 1284 lines =<< trim END 1285 vim9script 1286 var valone = 1234 1287 var valone = 5678 1288 END 1289 writefile(lines, 'Xreload.vim') 1290 assert_fails('source Xreload.vim', 'E1041:', '', 3, 'Xreload.vim') 1291 1292 delete('Xreload.vim') 1293 delete('Ximport.vim') 1294enddef 1295 1296" if a script is reloaded with a script-local variable that changed its type, a 1297" compiled function using that variable must fail. 1298def Test_script_reload_change_type() 1299 var lines =<< trim END 1300 vim9script noclear 1301 var str = 'string' 1302 def g:GetStr(): string 1303 return str .. 'xxx' 1304 enddef 1305 END 1306 writefile(lines, 'Xreload.vim') 1307 source Xreload.vim 1308 echo g:GetStr() 1309 1310 lines =<< trim END 1311 vim9script noclear 1312 var str = 1234 1313 END 1314 writefile(lines, 'Xreload.vim') 1315 source Xreload.vim 1316 assert_fails('echo g:GetStr()', 'E1150:') 1317 1318 delfunc g:GetStr 1319 delete('Xreload.vim') 1320enddef 1321 1322def s:RetSome(): string 1323 return 'some' 1324enddef 1325 1326" Not exported function that is referenced needs to be accessed by the 1327" script-local name. 1328def Test_vim9script_funcref() 1329 var sortlines =<< trim END 1330 vim9script 1331 def Compare(i1: number, i2: number): number 1332 return i2 - i1 1333 enddef 1334 1335 export def FastSort(): list<number> 1336 return range(5)->sort(Compare) 1337 enddef 1338 END 1339 writefile(sortlines, 'Xsort.vim') 1340 1341 var lines =<< trim END 1342 vim9script 1343 import FastSort from './Xsort.vim' 1344 def Test() 1345 g:result = FastSort() 1346 enddef 1347 Test() 1348 END 1349 writefile(lines, 'Xscript.vim') 1350 1351 source Xscript.vim 1352 assert_equal([4, 3, 2, 1, 0], g:result) 1353 1354 unlet g:result 1355 delete('Xsort.vim') 1356 delete('Xscript.vim') 1357 1358 var Funcref = function('s:RetSome') 1359 assert_equal('some', Funcref()) 1360enddef 1361 1362" Check that when searching for "FilterFunc" it finds the import in the 1363" script where FastFilter() is called from, both as a string and as a direct 1364" function reference. 1365def Test_vim9script_funcref_other_script() 1366 var filterLines =<< trim END 1367 vim9script 1368 export def FilterFunc(idx: number, val: number): bool 1369 return idx % 2 == 1 1370 enddef 1371 export def FastFilter(): list<number> 1372 return range(10)->filter('FilterFunc') 1373 enddef 1374 export def FastFilterDirect(): list<number> 1375 return range(10)->filter(FilterFunc) 1376 enddef 1377 END 1378 writefile(filterLines, 'Xfilter.vim') 1379 1380 var lines =<< trim END 1381 vim9script 1382 import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim' 1383 def Test() 1384 var x: list<number> = FastFilter() 1385 enddef 1386 Test() 1387 def TestDirect() 1388 var x: list<number> = FastFilterDirect() 1389 enddef 1390 TestDirect() 1391 END 1392 CheckScriptSuccess(lines) 1393 delete('Xfilter.vim') 1394enddef 1395 1396def Test_vim9script_reload_delfunc() 1397 var first_lines =<< trim END 1398 vim9script 1399 def FuncYes(): string 1400 return 'yes' 1401 enddef 1402 END 1403 var withno_lines =<< trim END 1404 def FuncNo(): string 1405 return 'no' 1406 enddef 1407 def g:DoCheck(no_exists: bool) 1408 assert_equal('yes', FuncYes()) 1409 assert_equal('no', FuncNo()) 1410 enddef 1411 END 1412 var nono_lines =<< trim END 1413 def g:DoCheck(no_exists: bool) 1414 assert_equal('yes', FuncYes()) 1415 assert_fails('FuncNo()', 'E117:', '', 2, 'DoCheck') 1416 enddef 1417 END 1418 1419 # FuncNo() is defined 1420 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1421 source Xreloaded.vim 1422 g:DoCheck(true) 1423 1424 # FuncNo() is not redefined 1425 writefile(first_lines + nono_lines, 'Xreloaded.vim') 1426 source Xreloaded.vim 1427 g:DoCheck(false) 1428 1429 # FuncNo() is back 1430 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1431 source Xreloaded.vim 1432 g:DoCheck(false) 1433 1434 delete('Xreloaded.vim') 1435enddef 1436 1437def Test_vim9script_reload_delvar() 1438 # write the script with a script-local variable 1439 var lines =<< trim END 1440 vim9script 1441 var name = 'string' 1442 END 1443 writefile(lines, 'XreloadVar.vim') 1444 source XreloadVar.vim 1445 1446 # now write the script using the same variable locally - works 1447 lines =<< trim END 1448 vim9script 1449 def Func() 1450 var name = 'string' 1451 enddef 1452 END 1453 writefile(lines, 'XreloadVar.vim') 1454 source XreloadVar.vim 1455 1456 delete('XreloadVar.vim') 1457enddef 1458 1459def Test_import_absolute() 1460 var import_lines = [ 1461 'vim9script', 1462 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 1463 'def UseExported()', 1464 ' g:imported_abs = exported', 1465 ' exported = 8888', 1466 ' g:imported_after = exported', 1467 'enddef', 1468 'UseExported()', 1469 'g:import_disassembled = execute("disass UseExported")', 1470 ] 1471 writefile(import_lines, 'Ximport_abs.vim') 1472 writefile(s:export_script_lines, 'Xexport_abs.vim') 1473 1474 source Ximport_abs.vim 1475 1476 assert_equal(9876, g:imported_abs) 1477 assert_equal(8888, g:imported_after) 1478 assert_match('<SNR>\d\+_UseExported\_s*' .. 1479 'g:imported_abs = exported\_s*' .. 1480 '0 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 1481 '1 STOREG g:imported_abs\_s*' .. 1482 'exported = 8888\_s*' .. 1483 '2 PUSHNR 8888\_s*' .. 1484 '3 STORESCRIPT exported-2 in .*Xexport_abs.vim\_s*' .. 1485 'g:imported_after = exported\_s*' .. 1486 '4 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. 1487 '5 STOREG g:imported_after', 1488 g:import_disassembled) 1489 1490 Undo_export_script_lines() 1491 unlet g:imported_abs 1492 unlet g:import_disassembled 1493 1494 delete('Ximport_abs.vim') 1495 delete('Xexport_abs.vim') 1496enddef 1497 1498def Test_import_rtp() 1499 var import_lines = [ 1500 'vim9script', 1501 'import exported from "Xexport_rtp.vim"', 1502 'g:imported_rtp = exported', 1503 ] 1504 writefile(import_lines, 'Ximport_rtp.vim') 1505 mkdir('import') 1506 writefile(s:export_script_lines, 'import/Xexport_rtp.vim') 1507 1508 var save_rtp = &rtp 1509 &rtp = getcwd() 1510 source Ximport_rtp.vim 1511 &rtp = save_rtp 1512 1513 assert_equal(9876, g:imported_rtp) 1514 1515 Undo_export_script_lines() 1516 unlet g:imported_rtp 1517 delete('Ximport_rtp.vim') 1518 delete('import', 'rf') 1519enddef 1520 1521def Test_import_compile_error() 1522 var export_lines = [ 1523 'vim9script', 1524 'export def ExpFunc(): string', 1525 ' return notDefined', 1526 'enddef', 1527 ] 1528 writefile(export_lines, 'Xexported.vim') 1529 1530 var import_lines = [ 1531 'vim9script', 1532 'import ExpFunc from "./Xexported.vim"', 1533 'def ImpFunc()', 1534 ' echo ExpFunc()', 1535 'enddef', 1536 'defcompile', 1537 ] 1538 writefile(import_lines, 'Ximport.vim') 1539 1540 try 1541 source Ximport.vim 1542 catch /E1001/ 1543 # Error should be fore the Xexported.vim file. 1544 assert_match('E1001: Variable not found: notDefined', v:exception) 1545 assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint) 1546 endtry 1547 1548 delete('Xexported.vim') 1549 delete('Ximport.vim') 1550enddef 1551 1552def Test_func_redefine_error() 1553 var lines = [ 1554 'vim9script', 1555 'def Func()', 1556 ' eval [][0]', 1557 'enddef', 1558 'Func()', 1559 ] 1560 writefile(lines, 'Xtestscript.vim') 1561 1562 for count in range(3) 1563 try 1564 source Xtestscript.vim 1565 catch /E684/ 1566 # function name should contain <SNR> every time 1567 assert_match('E684: list index out of range', v:exception) 1568 assert_match('function <SNR>\d\+_Func, line 1', v:throwpoint) 1569 endtry 1570 endfor 1571 1572 delete('Xtestscript.vim') 1573enddef 1574 1575def Test_func_overrules_import_fails() 1576 var export_lines =<< trim END 1577 vim9script 1578 export def Func() 1579 echo 'imported' 1580 enddef 1581 END 1582 writefile(export_lines, 'XexportedFunc.vim') 1583 1584 var lines =<< trim END 1585 vim9script 1586 import Func from './XexportedFunc.vim' 1587 def Func() 1588 echo 'local to function' 1589 enddef 1590 END 1591 CheckScriptFailure(lines, 'E1073:') 1592 1593 lines =<< trim END 1594 vim9script 1595 import Func from './XexportedFunc.vim' 1596 def Outer() 1597 def Func() 1598 echo 'local to function' 1599 enddef 1600 enddef 1601 defcompile 1602 END 1603 CheckScriptFailure(lines, 'E1073:') 1604 1605 delete('XexportedFunc.vim') 1606enddef 1607 1608def Test_func_redefine_fails() 1609 var lines =<< trim END 1610 vim9script 1611 def Func() 1612 echo 'one' 1613 enddef 1614 def Func() 1615 echo 'two' 1616 enddef 1617 END 1618 CheckScriptFailure(lines, 'E1073:') 1619 1620 lines =<< trim END 1621 vim9script 1622 def Foo(): string 1623 return 'foo' 1624 enddef 1625 def Func() 1626 var Foo = {-> 'lambda'} 1627 enddef 1628 defcompile 1629 END 1630 CheckScriptFailure(lines, 'E1073:') 1631enddef 1632 1633def Test_fixed_size_list() 1634 # will be allocated as one piece of memory, check that changes work 1635 var l = [1, 2, 3, 4] 1636 l->remove(0) 1637 l->add(5) 1638 l->insert(99, 1) 1639 assert_equal([2, 99, 3, 4, 5], l) 1640enddef 1641 1642def Test_no_insert_xit() 1643 CheckDefExecFailure(['a = 1'], 'E1100:') 1644 CheckDefExecFailure(['c = 1'], 'E1100:') 1645 CheckDefExecFailure(['i = 1'], 'E1100:') 1646 CheckDefExecFailure(['t = 1'], 'E1100:') 1647 CheckDefExecFailure(['x = 1'], 'E1100:') 1648 1649 CheckScriptFailure(['vim9script', 'a = 1'], 'E488:') 1650 CheckScriptFailure(['vim9script', 'a'], 'E1100:') 1651 CheckScriptFailure(['vim9script', 'c = 1'], 'E488:') 1652 CheckScriptFailure(['vim9script', 'c'], 'E1100:') 1653 CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') 1654 CheckScriptFailure(['vim9script', 'i'], 'E1100:') 1655 CheckScriptFailure(['vim9script', 't'], 'E1100:') 1656 CheckScriptFailure(['vim9script', 't = 1'], 'E1100:') 1657 CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') 1658enddef 1659 1660def IfElse(what: number): string 1661 var res = '' 1662 if what == 1 1663 res = "one" 1664 elseif what == 2 1665 res = "two" 1666 else 1667 res = "three" 1668 endif 1669 return res 1670enddef 1671 1672def Test_if_elseif_else() 1673 assert_equal('one', IfElse(1)) 1674 assert_equal('two', IfElse(2)) 1675 assert_equal('three', IfElse(3)) 1676enddef 1677 1678def Test_if_elseif_else_fails() 1679 CheckDefFailure(['elseif true'], 'E582:') 1680 CheckDefFailure(['else'], 'E581:') 1681 CheckDefFailure(['endif'], 'E580:') 1682 CheckDefFailure(['if true', 'elseif xxx'], 'E1001:') 1683 CheckDefFailure(['if true', 'echo 1'], 'E171:') 1684enddef 1685 1686let g:bool_true = v:true 1687let g:bool_false = v:false 1688 1689def Test_if_const_expr() 1690 var res = false 1691 if true ? true : false 1692 res = true 1693 endif 1694 assert_equal(true, res) 1695 1696 g:glob = 2 1697 if false 1698 execute('g:glob = 3') 1699 endif 1700 assert_equal(2, g:glob) 1701 if true 1702 execute('g:glob = 3') 1703 endif 1704 assert_equal(3, g:glob) 1705 1706 res = false 1707 if g:bool_true ? true : false 1708 res = true 1709 endif 1710 assert_equal(true, res) 1711 1712 res = false 1713 if true ? g:bool_true : false 1714 res = true 1715 endif 1716 assert_equal(true, res) 1717 1718 res = false 1719 if true ? true : g:bool_false 1720 res = true 1721 endif 1722 assert_equal(true, res) 1723 1724 res = false 1725 if true ? false : true 1726 res = true 1727 endif 1728 assert_equal(false, res) 1729 1730 res = false 1731 if false ? false : true 1732 res = true 1733 endif 1734 assert_equal(true, res) 1735 1736 res = false 1737 if false ? true : false 1738 res = true 1739 endif 1740 assert_equal(false, res) 1741 1742 res = false 1743 if has('xyz') ? true : false 1744 res = true 1745 endif 1746 assert_equal(false, res) 1747 1748 res = false 1749 if true && true 1750 res = true 1751 endif 1752 assert_equal(true, res) 1753 1754 res = false 1755 if true && false 1756 res = true 1757 endif 1758 assert_equal(false, res) 1759 1760 res = false 1761 if g:bool_true && false 1762 res = true 1763 endif 1764 assert_equal(false, res) 1765 1766 res = false 1767 if true && g:bool_false 1768 res = true 1769 endif 1770 assert_equal(false, res) 1771 1772 res = false 1773 if false && false 1774 res = true 1775 endif 1776 assert_equal(false, res) 1777 1778 res = false 1779 if true || false 1780 res = true 1781 endif 1782 assert_equal(true, res) 1783 1784 res = false 1785 if g:bool_true || false 1786 res = true 1787 endif 1788 assert_equal(true, res) 1789 1790 res = false 1791 if true || g:bool_false 1792 res = true 1793 endif 1794 assert_equal(true, res) 1795 1796 res = false 1797 if false || false 1798 res = true 1799 endif 1800 assert_equal(false, res) 1801 1802 # with constant "false" expression may be invalid so long as the syntax is OK 1803 if false | eval 0 | endif 1804 if false | eval burp + 234 | endif 1805 if false | echo burp 234 'asd' | endif 1806 if false 1807 burp 1808 endif 1809enddef 1810 1811def Test_if_const_expr_fails() 1812 CheckDefFailure(['if "aaa" == "bbb'], 'E114:') 1813 CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:') 1814 CheckDefFailure(["if has('aaa'"], 'E110:') 1815 CheckDefFailure(["if has('aaa') ? true false"], 'E109:') 1816enddef 1817 1818def RunNested(i: number): number 1819 var x: number = 0 1820 if i % 2 1821 if 1 1822 # comment 1823 else 1824 # comment 1825 endif 1826 x += 1 1827 else 1828 x += 1000 1829 endif 1830 return x 1831enddef 1832 1833def Test_nested_if() 1834 assert_equal(1, RunNested(1)) 1835 assert_equal(1000, RunNested(2)) 1836enddef 1837 1838def Test_execute_cmd() 1839 # missing argument is ignored 1840 execute 1841 execute # comment 1842 1843 new 1844 setline(1, 'default') 1845 execute 'setline(1, "execute-string")' 1846 assert_equal('execute-string', getline(1)) 1847 1848 execute "setline(1, 'execute-string')" 1849 assert_equal('execute-string', getline(1)) 1850 1851 var cmd1 = 'setline(1,' 1852 var cmd2 = '"execute-var")' 1853 execute cmd1 cmd2 # comment 1854 assert_equal('execute-var', getline(1)) 1855 1856 execute cmd1 cmd2 '|setline(1, "execute-var-string")' 1857 assert_equal('execute-var-string', getline(1)) 1858 1859 var cmd_first = 'call ' 1860 var cmd_last = 'setline(1, "execute-var-var")' 1861 execute cmd_first .. cmd_last 1862 assert_equal('execute-var-var', getline(1)) 1863 bwipe! 1864 1865 var n = true 1866 execute 'echomsg' (n ? '"true"' : '"no"') 1867 assert_match('^true$', Screenline(&lines)) 1868 1869 echomsg [1, 2, 3] {a: 1, b: 2} 1870 assert_match('^\[1, 2, 3\] {''a'': 1, ''b'': 2}$', Screenline(&lines)) 1871 1872 CheckDefFailure(['execute xxx'], 'E1001:', 1) 1873 CheckDefExecFailure(['execute "tabnext " .. 8'], 'E475:', 1) 1874 CheckDefFailure(['execute "cmd"# comment'], 'E488:', 1) 1875enddef 1876 1877def Test_execute_cmd_vimscript() 1878 # only checks line continuation 1879 var lines =<< trim END 1880 vim9script 1881 execute 'g:someVar' 1882 .. ' = ' .. 1883 '28' 1884 assert_equal(28, g:someVar) 1885 unlet g:someVar 1886 END 1887 CheckScriptSuccess(lines) 1888enddef 1889 1890def Test_echo_cmd() 1891 echo 'some' # comment 1892 echon 'thing' 1893 assert_match('^something$', Screenline(&lines)) 1894 1895 echo "some" # comment 1896 echon "thing" 1897 assert_match('^something$', Screenline(&lines)) 1898 1899 var str1 = 'some' 1900 var str2 = 'more' 1901 echo str1 str2 1902 assert_match('^some more$', Screenline(&lines)) 1903 1904 CheckDefFailure(['echo "xxx"# comment'], 'E488:') 1905enddef 1906 1907def Test_echomsg_cmd() 1908 echomsg 'some' 'more' # comment 1909 assert_match('^some more$', Screenline(&lines)) 1910 echo 'clear' 1911 :1messages 1912 assert_match('^some more$', Screenline(&lines)) 1913 1914 CheckDefFailure(['echomsg "xxx"# comment'], 'E488:') 1915enddef 1916 1917def Test_echomsg_cmd_vimscript() 1918 # only checks line continuation 1919 var lines =<< trim END 1920 vim9script 1921 echomsg 'here' 1922 .. ' is ' .. 1923 'a message' 1924 assert_match('^here is a message$', Screenline(&lines)) 1925 END 1926 CheckScriptSuccess(lines) 1927enddef 1928 1929def Test_echoerr_cmd() 1930 try 1931 echoerr 'something' 'wrong' # comment 1932 catch 1933 assert_match('something wrong', v:exception) 1934 endtry 1935enddef 1936 1937def Test_echoerr_cmd_vimscript() 1938 # only checks line continuation 1939 var lines =<< trim END 1940 vim9script 1941 try 1942 echoerr 'this' 1943 .. ' is ' .. 1944 'wrong' 1945 catch 1946 assert_match('this is wrong', v:exception) 1947 endtry 1948 END 1949 CheckScriptSuccess(lines) 1950enddef 1951 1952def Test_for_outside_of_function() 1953 var lines =<< trim END 1954 vim9script 1955 new 1956 for var in range(0, 3) 1957 append(line('$'), var) 1958 endfor 1959 assert_equal(['', '0', '1', '2', '3'], getline(1, '$')) 1960 bwipe! 1961 END 1962 writefile(lines, 'Xvim9for.vim') 1963 source Xvim9for.vim 1964 delete('Xvim9for.vim') 1965enddef 1966 1967def Test_for_loop() 1968 var result = '' 1969 for cnt in range(7) 1970 if cnt == 4 1971 break 1972 endif 1973 if cnt == 2 1974 continue 1975 endif 1976 result ..= cnt .. '_' 1977 endfor 1978 assert_equal('0_1_3_', result) 1979 1980 var concat = '' 1981 for str in eval('["one", "two"]') 1982 concat ..= str 1983 endfor 1984 assert_equal('onetwo', concat) 1985 1986 var total = 0 1987 for nr in 1988 [1, 2, 3] 1989 total += nr 1990 endfor 1991 assert_equal(6, total) 1992 1993 total = 0 1994 for nr 1995 in [1, 2, 3] 1996 total += nr 1997 endfor 1998 assert_equal(6, total) 1999 2000 total = 0 2001 for nr 2002 in 2003 [1, 2, 3] 2004 total += nr 2005 endfor 2006 assert_equal(6, total) 2007enddef 2008 2009def Test_for_loop_fails() 2010 CheckDefFailure(['for '], 'E1097:') 2011 CheckDefFailure(['for x'], 'E1097:') 2012 CheckDefFailure(['for x in'], 'E1097:') 2013 CheckDefFailure(['for # in range(5)'], 'E690:') 2014 CheckDefFailure(['for i In range(5)'], 'E690:') 2015 CheckDefFailure(['var x = 5', 'for x in range(5)'], 'E1017:') 2016 CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:') 2017 delfunc! g:Func 2018 CheckDefFailure(['for i in "text"'], 'E1012:') 2019 CheckDefFailure(['for i in xxx'], 'E1001:') 2020 CheckDefFailure(['endfor'], 'E588:') 2021 CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:') 2022enddef 2023 2024def Test_for_loop_script_var() 2025 # cannot use s:var in a :def function 2026 CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E1101:') 2027 2028 # can use s:var in Vim9 script, with or without s: 2029 var lines =<< trim END 2030 vim9script 2031 var total = 0 2032 for s:var in [1, 2, 3] 2033 total += s:var 2034 endfor 2035 assert_equal(6, total) 2036 2037 total = 0 2038 for var in [1, 2, 3] 2039 total += var 2040 endfor 2041 assert_equal(6, total) 2042 END 2043enddef 2044 2045def Test_for_loop_unpack() 2046 var lines =<< trim END 2047 var result = [] 2048 for [v1, v2] in [[1, 2], [3, 4]] 2049 result->add(v1) 2050 result->add(v2) 2051 endfor 2052 assert_equal([1, 2, 3, 4], result) 2053 2054 result = [] 2055 for [v1, v2; v3] in [[1, 2], [3, 4, 5, 6]] 2056 result->add(v1) 2057 result->add(v2) 2058 result->add(v3) 2059 endfor 2060 assert_equal([1, 2, [], 3, 4, [5, 6]], result) 2061 2062 result = [] 2063 for [&ts, &sw] in [[1, 2], [3, 4]] 2064 result->add(&ts) 2065 result->add(&sw) 2066 endfor 2067 assert_equal([1, 2, 3, 4], result) 2068 2069 var slist: list<string> 2070 for [$LOOPVAR, @r, v:errmsg] in [['a', 'b', 'c'], ['d', 'e', 'f']] 2071 slist->add($LOOPVAR) 2072 slist->add(@r) 2073 slist->add(v:errmsg) 2074 endfor 2075 assert_equal(['a', 'b', 'c', 'd', 'e', 'f'], slist) 2076 2077 slist = [] 2078 for [g:globalvar, b:bufvar, w:winvar, t:tabvar] in [['global', 'buf', 'win', 'tab'], ['1', '2', '3', '4']] 2079 slist->add(g:globalvar) 2080 slist->add(b:bufvar) 2081 slist->add(w:winvar) 2082 slist->add(t:tabvar) 2083 endfor 2084 assert_equal(['global', 'buf', 'win', 'tab', '1', '2', '3', '4'], slist) 2085 unlet! g:globalvar b:bufvar w:winvar t:tabvar 2086 END 2087 CheckDefAndScriptSuccess(lines) 2088 2089 lines =<< trim END 2090 for [v1, v2] in [[1, 2, 3], [3, 4]] 2091 echo v1 v2 2092 endfor 2093 END 2094 CheckDefExecFailure(lines, 'E710:', 1) 2095 2096 lines =<< trim END 2097 for [v1, v2] in [[1], [3, 4]] 2098 echo v1 v2 2099 endfor 2100 END 2101 CheckDefExecFailure(lines, 'E711:', 1) 2102 2103 lines =<< trim END 2104 for [v1, v1] in [[1, 2], [3, 4]] 2105 echo v1 2106 endfor 2107 END 2108 CheckDefExecFailure(lines, 'E1017:', 1) 2109enddef 2110 2111def Test_while_loop() 2112 var result = '' 2113 var cnt = 0 2114 while cnt < 555 2115 if cnt == 3 2116 break 2117 endif 2118 cnt += 1 2119 if cnt == 2 2120 continue 2121 endif 2122 result ..= cnt .. '_' 2123 endwhile 2124 assert_equal('1_3_', result) 2125enddef 2126 2127def Test_while_loop_fails() 2128 CheckDefFailure(['while xxx'], 'E1001:') 2129 CheckDefFailure(['endwhile'], 'E588:') 2130 CheckDefFailure(['continue'], 'E586:') 2131 CheckDefFailure(['if true', 'continue'], 'E586:') 2132 CheckDefFailure(['break'], 'E587:') 2133 CheckDefFailure(['if true', 'break'], 'E587:') 2134 CheckDefFailure(['while 1', 'echo 3'], 'E170:') 2135enddef 2136 2137def Test_interrupt_loop() 2138 var caught = false 2139 var x = 0 2140 try 2141 while 1 2142 x += 1 2143 if x == 100 2144 feedkeys("\<C-C>", 'Lt') 2145 endif 2146 endwhile 2147 catch 2148 caught = true 2149 assert_equal(100, x) 2150 endtry 2151 assert_true(caught, 'should have caught an exception') 2152 # consume the CTRL-C 2153 getchar(0) 2154enddef 2155 2156def Test_automatic_line_continuation() 2157 var mylist = [ 2158 'one', 2159 'two', 2160 'three', 2161 ] # comment 2162 assert_equal(['one', 'two', 'three'], mylist) 2163 2164 var mydict = { 2165 ['one']: 1, 2166 ['two']: 2, 2167 ['three']: 2168 3, 2169 } # comment 2170 assert_equal({one: 1, two: 2, three: 3}, mydict) 2171 mydict = { 2172 one: 1, # comment 2173 two: # comment 2174 2, # comment 2175 three: 3 # comment 2176 } 2177 assert_equal({one: 1, two: 2, three: 3}, mydict) 2178 mydict = { 2179 one: 1, 2180 two: 2181 2, 2182 three: 3 2183 } 2184 assert_equal({one: 1, two: 2, three: 3}, mydict) 2185 2186 assert_equal( 2187 ['one', 'two', 'three'], 2188 split('one two three') 2189 ) 2190enddef 2191 2192def Test_vim9_comment() 2193 CheckScriptSuccess([ 2194 'vim9script', 2195 '# something', 2196 '#something', 2197 '#{something', 2198 ]) 2199 2200 split Xfile 2201 CheckScriptSuccess([ 2202 'vim9script', 2203 'edit #something', 2204 ]) 2205 CheckScriptSuccess([ 2206 'vim9script', 2207 'edit #{something', 2208 ]) 2209 close 2210 2211 CheckScriptFailure([ 2212 'vim9script', 2213 ':# something', 2214 ], 'E488:') 2215 CheckScriptFailure([ 2216 '# something', 2217 ], 'E488:') 2218 CheckScriptFailure([ 2219 ':# something', 2220 ], 'E488:') 2221 2222 { # block start 2223 } # block end 2224 CheckDefFailure([ 2225 '{# comment', 2226 ], 'E488:') 2227 CheckDefFailure([ 2228 '{', 2229 '}# comment', 2230 ], 'E488:') 2231 2232 echo "yes" # comment 2233 CheckDefFailure([ 2234 'echo "yes"# comment', 2235 ], 'E488:') 2236 CheckScriptSuccess([ 2237 'vim9script', 2238 'echo "yes" # something', 2239 ]) 2240 CheckScriptFailure([ 2241 'vim9script', 2242 'echo "yes"# something', 2243 ], 'E121:') 2244 CheckScriptFailure([ 2245 'vim9script', 2246 'echo# something', 2247 ], 'E1144:') 2248 CheckScriptFailure([ 2249 'echo "yes" # something', 2250 ], 'E121:') 2251 2252 exe "echo" # comment 2253 CheckDefFailure([ 2254 'exe "echo"# comment', 2255 ], 'E488:') 2256 CheckScriptSuccess([ 2257 'vim9script', 2258 'exe "echo" # something', 2259 ]) 2260 CheckScriptFailure([ 2261 'vim9script', 2262 'exe "echo"# something', 2263 ], 'E121:') 2264 CheckScriptFailure([ 2265 'vim9script', 2266 'exe# something', 2267 ], 'E1144:') 2268 CheckScriptFailure([ 2269 'exe "echo" # something', 2270 ], 'E121:') 2271 2272 CheckDefFailure([ 2273 'try# comment', 2274 ' echo "yes"', 2275 'catch', 2276 'endtry', 2277 ], 'E1144:') 2278 CheckScriptFailure([ 2279 'vim9script', 2280 'try# comment', 2281 'echo "yes"', 2282 ], 'E1144:') 2283 CheckDefFailure([ 2284 'try', 2285 ' throw#comment', 2286 'catch', 2287 'endtry', 2288 ], 'E1144:') 2289 CheckDefFailure([ 2290 'try', 2291 ' throw "yes"#comment', 2292 'catch', 2293 'endtry', 2294 ], 'E488:') 2295 CheckDefFailure([ 2296 'try', 2297 ' echo "yes"', 2298 'catch# comment', 2299 'endtry', 2300 ], 'E1144:') 2301 CheckScriptFailure([ 2302 'vim9script', 2303 'try', 2304 ' echo "yes"', 2305 'catch# comment', 2306 'endtry', 2307 ], 'E1144:') 2308 CheckDefFailure([ 2309 'try', 2310 ' echo "yes"', 2311 'catch /pat/# comment', 2312 'endtry', 2313 ], 'E488:') 2314 CheckDefFailure([ 2315 'try', 2316 'echo "yes"', 2317 'catch', 2318 'endtry# comment', 2319 ], 'E1144:') 2320 CheckScriptFailure([ 2321 'vim9script', 2322 'try', 2323 ' echo "yes"', 2324 'catch', 2325 'endtry# comment', 2326 ], 'E1144:') 2327 2328 CheckScriptSuccess([ 2329 'vim9script', 2330 'hi # comment', 2331 ]) 2332 CheckScriptFailure([ 2333 'vim9script', 2334 'hi# comment', 2335 ], 'E1144:') 2336 CheckScriptSuccess([ 2337 'vim9script', 2338 'hi Search # comment', 2339 ]) 2340 CheckScriptFailure([ 2341 'vim9script', 2342 'hi Search# comment', 2343 ], 'E416:') 2344 CheckScriptSuccess([ 2345 'vim9script', 2346 'hi link This Search # comment', 2347 ]) 2348 CheckScriptFailure([ 2349 'vim9script', 2350 'hi link This That# comment', 2351 ], 'E413:') 2352 CheckScriptSuccess([ 2353 'vim9script', 2354 'hi clear This # comment', 2355 'hi clear # comment', 2356 ]) 2357 # not tested, because it doesn't give an error but a warning: 2358 # hi clear This# comment', 2359 CheckScriptFailure([ 2360 'vim9script', 2361 'hi clear# comment', 2362 ], 'E416:') 2363 2364 CheckScriptSuccess([ 2365 'vim9script', 2366 'hi Group term=bold', 2367 'match Group /todo/ # comment', 2368 ]) 2369 CheckScriptFailure([ 2370 'vim9script', 2371 'hi Group term=bold', 2372 'match Group /todo/# comment', 2373 ], 'E488:') 2374 CheckScriptSuccess([ 2375 'vim9script', 2376 'match # comment', 2377 ]) 2378 CheckScriptFailure([ 2379 'vim9script', 2380 'match# comment', 2381 ], 'E1144:') 2382 CheckScriptSuccess([ 2383 'vim9script', 2384 'match none # comment', 2385 ]) 2386 CheckScriptFailure([ 2387 'vim9script', 2388 'match none# comment', 2389 ], 'E475:') 2390 2391 CheckScriptSuccess([ 2392 'vim9script', 2393 'menutrans clear # comment', 2394 ]) 2395 CheckScriptFailure([ 2396 'vim9script', 2397 'menutrans clear# comment text', 2398 ], 'E474:') 2399 2400 CheckScriptSuccess([ 2401 'vim9script', 2402 'syntax clear # comment', 2403 ]) 2404 CheckScriptFailure([ 2405 'vim9script', 2406 'syntax clear# comment text', 2407 ], 'E28:') 2408 CheckScriptSuccess([ 2409 'vim9script', 2410 'syntax keyword Word some', 2411 'syntax clear Word # comment', 2412 ]) 2413 CheckScriptFailure([ 2414 'vim9script', 2415 'syntax keyword Word some', 2416 'syntax clear Word# comment text', 2417 ], 'E28:') 2418 2419 CheckScriptSuccess([ 2420 'vim9script', 2421 'syntax list # comment', 2422 ]) 2423 CheckScriptFailure([ 2424 'vim9script', 2425 'syntax list# comment text', 2426 ], 'E28:') 2427 2428 CheckScriptSuccess([ 2429 'vim9script', 2430 'syntax match Word /pat/ oneline # comment', 2431 ]) 2432 CheckScriptFailure([ 2433 'vim9script', 2434 'syntax match Word /pat/ oneline# comment', 2435 ], 'E475:') 2436 2437 CheckScriptSuccess([ 2438 'vim9script', 2439 'syntax keyword Word word # comm[ent', 2440 ]) 2441 CheckScriptFailure([ 2442 'vim9script', 2443 'syntax keyword Word word# comm[ent', 2444 ], 'E789:') 2445 2446 CheckScriptSuccess([ 2447 'vim9script', 2448 'syntax match Word /pat/ # comment', 2449 ]) 2450 CheckScriptFailure([ 2451 'vim9script', 2452 'syntax match Word /pat/# comment', 2453 ], 'E402:') 2454 2455 CheckScriptSuccess([ 2456 'vim9script', 2457 'syntax match Word /pat/ contains=Something # comment', 2458 ]) 2459 CheckScriptFailure([ 2460 'vim9script', 2461 'syntax match Word /pat/ contains=Something# comment', 2462 ], 'E475:') 2463 CheckScriptFailure([ 2464 'vim9script', 2465 'syntax match Word /pat/ contains= # comment', 2466 ], 'E406:') 2467 CheckScriptFailure([ 2468 'vim9script', 2469 'syntax match Word /pat/ contains=# comment', 2470 ], 'E475:') 2471 2472 CheckScriptSuccess([ 2473 'vim9script', 2474 'syntax region Word start=/pat/ end=/pat/ # comment', 2475 ]) 2476 CheckScriptFailure([ 2477 'vim9script', 2478 'syntax region Word start=/pat/ end=/pat/# comment', 2479 ], 'E402:') 2480 2481 CheckScriptSuccess([ 2482 'vim9script', 2483 'syntax sync # comment', 2484 ]) 2485 CheckScriptFailure([ 2486 'vim9script', 2487 'syntax sync# comment', 2488 ], 'E404:') 2489 CheckScriptSuccess([ 2490 'vim9script', 2491 'syntax sync ccomment # comment', 2492 ]) 2493 CheckScriptFailure([ 2494 'vim9script', 2495 'syntax sync ccomment# comment', 2496 ], 'E404:') 2497 2498 CheckScriptSuccess([ 2499 'vim9script', 2500 'syntax cluster Some contains=Word # comment', 2501 ]) 2502 CheckScriptFailure([ 2503 'vim9script', 2504 'syntax cluster Some contains=Word# comment', 2505 ], 'E475:') 2506 2507 CheckScriptSuccess([ 2508 'vim9script', 2509 'command Echo echo # comment', 2510 'command Echo # comment', 2511 'delcommand Echo', 2512 ]) 2513 CheckScriptFailure([ 2514 'vim9script', 2515 'command Echo echo# comment', 2516 'Echo', 2517 ], 'E1144:') 2518 delcommand Echo 2519 2520 var curdir = getcwd() 2521 CheckScriptSuccess([ 2522 'command Echo cd " comment', 2523 'Echo', 2524 'delcommand Echo', 2525 ]) 2526 CheckScriptSuccess([ 2527 'vim9script', 2528 'command Echo cd # comment', 2529 'Echo', 2530 'delcommand Echo', 2531 ]) 2532 CheckScriptFailure([ 2533 'vim9script', 2534 'command Echo cd " comment', 2535 'Echo', 2536 ], 'E344:') 2537 delcommand Echo 2538 chdir(curdir) 2539 2540 CheckScriptFailure([ 2541 'vim9script', 2542 'command Echo# comment', 2543 ], 'E182:') 2544 CheckScriptFailure([ 2545 'vim9script', 2546 'command Echo echo', 2547 'command Echo# comment', 2548 ], 'E182:') 2549 delcommand Echo 2550 2551 CheckScriptSuccess([ 2552 'vim9script', 2553 'function # comment', 2554 ]) 2555 CheckScriptFailure([ 2556 'vim9script', 2557 'function " comment', 2558 ], 'E129:') 2559 CheckScriptFailure([ 2560 'vim9script', 2561 'function# comment', 2562 ], 'E1144:') 2563 CheckScriptSuccess([ 2564 'vim9script', 2565 'function CheckScriptSuccess # comment', 2566 ]) 2567 CheckScriptFailure([ 2568 'vim9script', 2569 'function CheckScriptSuccess# comment', 2570 ], 'E488:') 2571 2572 CheckScriptSuccess([ 2573 'vim9script', 2574 'func g:DeleteMeA()', 2575 'endfunc', 2576 'delfunction g:DeleteMeA # comment', 2577 ]) 2578 CheckScriptFailure([ 2579 'vim9script', 2580 'func g:DeleteMeB()', 2581 'endfunc', 2582 'delfunction g:DeleteMeB# comment', 2583 ], 'E488:') 2584 2585 CheckScriptSuccess([ 2586 'vim9script', 2587 'call execute("ls") # comment', 2588 ]) 2589 CheckScriptFailure([ 2590 'vim9script', 2591 'call execute("ls")# comment', 2592 ], 'E488:') 2593 2594 CheckScriptFailure([ 2595 'def Test() " comment', 2596 'enddef', 2597 ], 'E488:') 2598 CheckScriptFailure([ 2599 'vim9script', 2600 'def Test() " comment', 2601 'enddef', 2602 ], 'E488:') 2603 2604 CheckScriptSuccess([ 2605 'func Test() " comment', 2606 'endfunc', 2607 'delfunc Test', 2608 ]) 2609 CheckScriptSuccess([ 2610 'vim9script', 2611 'func Test() " comment', 2612 'endfunc', 2613 ]) 2614 2615 CheckScriptSuccess([ 2616 'def Test() # comment', 2617 'enddef', 2618 ]) 2619 CheckScriptFailure([ 2620 'func Test() # comment', 2621 'endfunc', 2622 ], 'E488:') 2623enddef 2624 2625def Test_vim9_comment_gui() 2626 CheckCanRunGui 2627 2628 CheckScriptFailure([ 2629 'vim9script', 2630 'gui#comment' 2631 ], 'E1144:') 2632 CheckScriptFailure([ 2633 'vim9script', 2634 'gui -f#comment' 2635 ], 'E499:') 2636enddef 2637 2638def Test_vim9_comment_not_compiled() 2639 au TabEnter *.vim g:entered = 1 2640 au TabEnter *.x g:entered = 2 2641 2642 edit test.vim 2643 doautocmd TabEnter #comment 2644 assert_equal(1, g:entered) 2645 2646 doautocmd TabEnter f.x 2647 assert_equal(2, g:entered) 2648 2649 g:entered = 0 2650 doautocmd TabEnter f.x #comment 2651 assert_equal(2, g:entered) 2652 2653 assert_fails('doautocmd Syntax#comment', 'E216:') 2654 2655 au! TabEnter 2656 unlet g:entered 2657 2658 CheckScriptSuccess([ 2659 'vim9script', 2660 'g:var = 123', 2661 'b:var = 456', 2662 'w:var = 777', 2663 't:var = 888', 2664 'unlet g:var w:var # something', 2665 ]) 2666 2667 CheckScriptFailure([ 2668 'vim9script', 2669 'let var = 123', 2670 ], 'E1126: Cannot use :let in Vim9 script') 2671 2672 CheckScriptFailure([ 2673 'vim9script', 2674 'var g:var = 123', 2675 ], 'E1016: Cannot declare a global variable:') 2676 2677 CheckScriptFailure([ 2678 'vim9script', 2679 'var b:var = 123', 2680 ], 'E1016: Cannot declare a buffer variable:') 2681 2682 CheckScriptFailure([ 2683 'vim9script', 2684 'var w:var = 123', 2685 ], 'E1016: Cannot declare a window variable:') 2686 2687 CheckScriptFailure([ 2688 'vim9script', 2689 'var t:var = 123', 2690 ], 'E1016: Cannot declare a tab variable:') 2691 2692 CheckScriptFailure([ 2693 'vim9script', 2694 'var v:version = 123', 2695 ], 'E1016: Cannot declare a v: variable:') 2696 2697 CheckScriptFailure([ 2698 'vim9script', 2699 'var $VARIABLE = "text"', 2700 ], 'E1016: Cannot declare an environment variable:') 2701 2702 CheckScriptFailure([ 2703 'vim9script', 2704 'g:var = 123', 2705 'unlet g:var# comment1', 2706 ], 'E108:') 2707 2708 CheckScriptFailure([ 2709 'let g:var = 123', 2710 'unlet g:var # something', 2711 ], 'E488:') 2712 2713 CheckScriptSuccess([ 2714 'vim9script', 2715 'if 1 # comment2', 2716 ' echo "yes"', 2717 'elseif 2 #comment', 2718 ' echo "no"', 2719 'endif', 2720 ]) 2721 2722 CheckScriptFailure([ 2723 'vim9script', 2724 'if 1# comment3', 2725 ' echo "yes"', 2726 'endif', 2727 ], 'E15:') 2728 2729 CheckScriptFailure([ 2730 'vim9script', 2731 'if 0 # comment4', 2732 ' echo "yes"', 2733 'elseif 2#comment', 2734 ' echo "no"', 2735 'endif', 2736 ], 'E15:') 2737 2738 CheckScriptSuccess([ 2739 'vim9script', 2740 'var v = 1 # comment5', 2741 ]) 2742 2743 CheckScriptFailure([ 2744 'vim9script', 2745 'var v = 1# comment6', 2746 ], 'E15:') 2747 2748 CheckScriptSuccess([ 2749 'vim9script', 2750 'new' 2751 'setline(1, ["# define pat", "last"])', 2752 ':$', 2753 'dsearch /pat/ #comment', 2754 'bwipe!', 2755 ]) 2756 2757 CheckScriptFailure([ 2758 'vim9script', 2759 'new' 2760 'setline(1, ["# define pat", "last"])', 2761 ':$', 2762 'dsearch /pat/#comment', 2763 'bwipe!', 2764 ], 'E488:') 2765 2766 CheckScriptFailure([ 2767 'vim9script', 2768 'func! SomeFunc()', 2769 ], 'E477:') 2770enddef 2771 2772def Test_finish() 2773 var lines =<< trim END 2774 vim9script 2775 g:res = 'one' 2776 if v:false | finish | endif 2777 g:res = 'two' 2778 finish 2779 g:res = 'three' 2780 END 2781 writefile(lines, 'Xfinished') 2782 source Xfinished 2783 assert_equal('two', g:res) 2784 2785 unlet g:res 2786 delete('Xfinished') 2787enddef 2788 2789def Test_forward_declaration() 2790 var lines =<< trim END 2791 vim9script 2792 def GetValue(): string 2793 return theVal 2794 enddef 2795 var theVal = 'something' 2796 g:initVal = GetValue() 2797 theVal = 'else' 2798 g:laterVal = GetValue() 2799 END 2800 writefile(lines, 'Xforward') 2801 source Xforward 2802 assert_equal('something', g:initVal) 2803 assert_equal('else', g:laterVal) 2804 2805 unlet g:initVal 2806 unlet g:laterVal 2807 delete('Xforward') 2808enddef 2809 2810def Test_source_vim9_from_legacy() 2811 var vim9_lines =<< trim END 2812 vim9script 2813 var local = 'local' 2814 g:global = 'global' 2815 export var exported = 'exported' 2816 export def GetText(): string 2817 return 'text' 2818 enddef 2819 END 2820 writefile(vim9_lines, 'Xvim9_script.vim') 2821 2822 var legacy_lines =<< trim END 2823 source Xvim9_script.vim 2824 2825 call assert_false(exists('local')) 2826 call assert_false(exists('exported')) 2827 call assert_false(exists('s:exported')) 2828 call assert_equal('global', global) 2829 call assert_equal('global', g:global) 2830 2831 " imported variable becomes script-local 2832 import exported from './Xvim9_script.vim' 2833 call assert_equal('exported', s:exported) 2834 call assert_false(exists('exported')) 2835 2836 " imported function becomes script-local 2837 import GetText from './Xvim9_script.vim' 2838 call assert_equal('text', s:GetText()) 2839 call assert_false(exists('*GetText')) 2840 END 2841 writefile(legacy_lines, 'Xlegacy_script.vim') 2842 2843 source Xlegacy_script.vim 2844 assert_equal('global', g:global) 2845 unlet g:global 2846 2847 delete('Xlegacy_script.vim') 2848 delete('Xvim9_script.vim') 2849enddef 2850 2851func Test_vim9script_not_global() 2852 " check that items defined in Vim9 script are script-local, not global 2853 let vim9lines =<< trim END 2854 vim9script 2855 var name = 'local' 2856 func TheFunc() 2857 echo 'local' 2858 endfunc 2859 def DefFunc() 2860 echo 'local' 2861 enddef 2862 END 2863 call writefile(vim9lines, 'Xvim9script.vim') 2864 source Xvim9script.vim 2865 try 2866 echo g:var 2867 assert_report('did not fail') 2868 catch /E121:/ 2869 " caught 2870 endtry 2871 try 2872 call TheFunc() 2873 assert_report('did not fail') 2874 catch /E117:/ 2875 " caught 2876 endtry 2877 try 2878 call DefFunc() 2879 assert_report('did not fail') 2880 catch /E117:/ 2881 " caught 2882 endtry 2883 2884 call delete('Xvim9script.vim') 2885endfunc 2886 2887def Test_vim9_copen() 2888 # this was giving an error for setting w:quickfix_title 2889 copen 2890 quit 2891enddef 2892 2893" test using an auto-loaded function and variable 2894def Test_vim9_autoload() 2895 var lines =<< trim END 2896 vim9script 2897 def some#gettest(): string 2898 return 'test' 2899 enddef 2900 g:some#name = 'name' 2901 END 2902 2903 mkdir('Xdir/autoload', 'p') 2904 writefile(lines, 'Xdir/autoload/some.vim') 2905 var save_rtp = &rtp 2906 exe 'set rtp^=' .. getcwd() .. '/Xdir' 2907 2908 assert_equal('test', g:some#gettest()) 2909 assert_equal('name', g:some#name) 2910 g:some#other = 'other' 2911 assert_equal('other', g:some#other) 2912 2913 # upper case script name works 2914 lines =<< trim END 2915 vim9script 2916 def Other#getOther(): string 2917 return 'other' 2918 enddef 2919 END 2920 writefile(lines, 'Xdir/autoload/Other.vim') 2921 assert_equal('other', g:Other#getOther()) 2922 2923 delete('Xdir', 'rf') 2924 &rtp = save_rtp 2925enddef 2926 2927" test using a vim9script that is auto-loaded from an autocmd 2928def Test_vim9_aucmd_autoload() 2929 var lines =<< trim END 2930 vim9script 2931 def foo#test() 2932 echomsg getreg('"') 2933 enddef 2934 END 2935 2936 mkdir('Xdir/autoload', 'p') 2937 writefile(lines, 'Xdir/autoload/foo.vim') 2938 var save_rtp = &rtp 2939 exe 'set rtp^=' .. getcwd() .. '/Xdir' 2940 augroup test 2941 autocmd TextYankPost * call foo#test() 2942 augroup END 2943 2944 normal Y 2945 2946 augroup test 2947 autocmd! 2948 augroup END 2949 delete('Xdir', 'rf') 2950 &rtp = save_rtp 2951enddef 2952 2953" This was causing a crash because suppress_errthrow wasn't reset. 2954def Test_vim9_autoload_error() 2955 var lines =<< trim END 2956 vim9script 2957 def crash#func() 2958 try 2959 for x in List() 2960 endfor 2961 catch 2962 endtry 2963 g:ok = true 2964 enddef 2965 fu List() 2966 invalid 2967 endfu 2968 try 2969 invalid 2970 catch /wontmatch/ 2971 endtry 2972 END 2973 call mkdir('Xruntime/autoload', 'p') 2974 call writefile(lines, 'Xruntime/autoload/crash.vim') 2975 2976 # run in a separate Vim to avoid the side effects of assert_fails() 2977 lines =<< trim END 2978 exe 'set rtp^=' .. getcwd() .. '/Xruntime' 2979 call crash#func() 2980 call writefile(['ok'], 'Xdidit') 2981 qall! 2982 END 2983 writefile(lines, 'Xscript') 2984 RunVim([], [], '-S Xscript') 2985 assert_equal(['ok'], readfile('Xdidit')) 2986 2987 delete('Xdidit') 2988 delete('Xscript') 2989 delete('Xruntime', 'rf') 2990 2991 lines =<< trim END 2992 vim9script 2993 var foo#bar = 'asdf' 2994 END 2995 CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2) 2996enddef 2997 2998def Test_script_var_in_autocmd() 2999 # using a script variable from an autocommand, defined in a :def function in a 3000 # legacy Vim script, cannot check the variable type. 3001 var lines =<< trim END 3002 let s:counter = 1 3003 def s:Func() 3004 au! CursorHold 3005 au CursorHold * s:counter += 1 3006 enddef 3007 call s:Func() 3008 doau CursorHold 3009 call assert_equal(2, s:counter) 3010 au! CursorHold 3011 END 3012 CheckScriptSuccess(lines) 3013enddef 3014 3015def Test_cmdline_win() 3016 # if the Vim syntax highlighting uses Vim9 constructs they can be used from 3017 # the command line window. 3018 mkdir('rtp/syntax', 'p') 3019 var export_lines =<< trim END 3020 vim9script 3021 export var That = 'yes' 3022 END 3023 writefile(export_lines, 'rtp/syntax/Xexport.vim') 3024 var import_lines =<< trim END 3025 vim9script 3026 import That from './Xexport.vim' 3027 END 3028 writefile(import_lines, 'rtp/syntax/vim.vim') 3029 var save_rtp = &rtp 3030 &rtp = getcwd() .. '/rtp' .. ',' .. &rtp 3031 syntax on 3032 augroup CmdWin 3033 autocmd CmdwinEnter * g:got_there = 'yes' 3034 augroup END 3035 # this will open and also close the cmdline window 3036 feedkeys('q:', 'xt') 3037 assert_equal('yes', g:got_there) 3038 3039 augroup CmdWin 3040 au! 3041 augroup END 3042 &rtp = save_rtp 3043 delete('rtp', 'rf') 3044enddef 3045 3046def Test_invalid_sid() 3047 assert_fails('func <SNR>1234_func', 'E123:') 3048 3049 if RunVim([], ['wq! Xdidit'], '+"func <SNR>1_func"') 3050 assert_equal([], readfile('Xdidit')) 3051 endif 3052 delete('Xdidit') 3053enddef 3054 3055def Test_restoring_cpo() 3056 writefile(['vim9script', 'set nocp'], 'Xsourced') 3057 writefile(['call writefile(["done"], "Xdone")', 'quit!'], 'Xclose') 3058 if RunVim([], [], '-u NONE +"set cpo+=a" -S Xsourced -S Xclose') 3059 assert_equal(['done'], readfile('Xdone')) 3060 endif 3061 delete('Xsourced') 3062 delete('Xclose') 3063 delete('Xdone') 3064enddef 3065 3066 3067def Test_unset_any_variable() 3068 var lines =<< trim END 3069 var name: any 3070 assert_equal(0, name) 3071 END 3072 CheckDefAndScriptSuccess(lines) 3073enddef 3074 3075func Test_define_func_at_command_line() 3076 CheckRunVimInTerminal 3077 3078 " call indirectly to avoid compilation error for missing functions 3079 call Run_Test_define_func_at_command_line() 3080endfunc 3081 3082def Run_Test_define_func_at_command_line() 3083 # run in a separate Vim instance to avoid the script context 3084 var lines =<< trim END 3085 func CheckAndQuit() 3086 call assert_fails('call Afunc()', 'E117: Unknown function: Bfunc') 3087 call writefile(['errors: ' .. string(v:errors)], 'Xdidcmd') 3088 endfunc 3089 END 3090 writefile([''], 'Xdidcmd') 3091 writefile(lines, 'XcallFunc') 3092 var buf = RunVimInTerminal('-S XcallFunc', {rows: 6}) 3093 # define Afunc() on the command line 3094 term_sendkeys(buf, ":def Afunc()\<CR>Bfunc()\<CR>enddef\<CR>") 3095 term_sendkeys(buf, ":call CheckAndQuit()\<CR>") 3096 WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd'))) 3097 3098 call StopVimInTerminal(buf) 3099 delete('XcallFunc') 3100 delete('Xdidcmd') 3101enddef 3102 3103def Test_script_var_scope() 3104 var lines =<< trim END 3105 vim9script 3106 if true 3107 if true 3108 var one = 'one' 3109 echo one 3110 endif 3111 echo one 3112 endif 3113 END 3114 CheckScriptFailure(lines, 'E121:', 7) 3115 3116 lines =<< trim END 3117 vim9script 3118 if true 3119 if false 3120 var one = 'one' 3121 echo one 3122 else 3123 var one = 'one' 3124 echo one 3125 endif 3126 echo one 3127 endif 3128 END 3129 CheckScriptFailure(lines, 'E121:', 10) 3130 3131 lines =<< trim END 3132 vim9script 3133 while true 3134 var one = 'one' 3135 echo one 3136 break 3137 endwhile 3138 echo one 3139 END 3140 CheckScriptFailure(lines, 'E121:', 7) 3141 3142 lines =<< trim END 3143 vim9script 3144 for i in range(1) 3145 var one = 'one' 3146 echo one 3147 endfor 3148 echo one 3149 END 3150 CheckScriptFailure(lines, 'E121:', 6) 3151 3152 lines =<< trim END 3153 vim9script 3154 { 3155 var one = 'one' 3156 assert_equal('one', one) 3157 } 3158 assert_false(exists('one')) 3159 assert_false(exists('s:one')) 3160 END 3161 CheckScriptSuccess(lines) 3162 3163 lines =<< trim END 3164 vim9script 3165 { 3166 var one = 'one' 3167 echo one 3168 } 3169 echo one 3170 END 3171 CheckScriptFailure(lines, 'E121:', 6) 3172enddef 3173 3174def Test_catch_exception_in_callback() 3175 var lines =<< trim END 3176 vim9script 3177 def Callback(...l: any) 3178 try 3179 var x: string 3180 var y: string 3181 # this error should be caught with CHECKLEN 3182 [x, y] = [''] 3183 catch 3184 g:caught = 'yes' 3185 endtry 3186 enddef 3187 popup_menu('popup', {callback: Callback}) 3188 feedkeys("\r", 'xt') 3189 END 3190 CheckScriptSuccess(lines) 3191 3192 unlet g:caught 3193enddef 3194 3195def Test_no_unknown_error_after_error() 3196 if !has('unix') || !has('job') 3197 throw 'Skipped: not unix of missing +job feature' 3198 endif 3199 var lines =<< trim END 3200 vim9script 3201 var source: list<number> 3202 def Out_cb(...l: any) 3203 eval [][0] 3204 enddef 3205 def Exit_cb(...l: any) 3206 sleep 1m 3207 source += l 3208 enddef 3209 var myjob = job_start('echo burp', {out_cb: Out_cb, exit_cb: Exit_cb, mode: 'raw'}) 3210 while job_status(myjob) == 'run' 3211 sleep 10m 3212 endwhile 3213 sleep 10m 3214 END 3215 writefile(lines, 'Xdef') 3216 assert_fails('so Xdef', ['E684:', 'E1012:']) 3217 delete('Xdef') 3218enddef 3219 3220def InvokeNormal() 3221 exe "norm! :m+1\r" 3222enddef 3223 3224def Test_invoke_normal_in_visual_mode() 3225 xnoremap <F3> <Cmd>call <SID>InvokeNormal()<CR> 3226 new 3227 setline(1, ['aaa', 'bbb']) 3228 feedkeys("V\<F3>", 'xt') 3229 assert_equal(['bbb', 'aaa'], getline(1, 2)) 3230 xunmap <F3> 3231enddef 3232 3233def Test_white_space_after_command() 3234 var lines =<< trim END 3235 exit_cb: Func}) 3236 END 3237 CheckDefAndScriptFailure(lines, 'E1144:', 1) 3238 3239 lines =<< trim END 3240 e# 3241 END 3242 CheckDefAndScriptFailure(lines, 'E1144:', 1) 3243enddef 3244 3245def Test_script_var_gone_when_sourced_twice() 3246 var lines =<< trim END 3247 vim9script 3248 if exists('g:guard') 3249 finish 3250 endif 3251 g:guard = 1 3252 var name = 'thename' 3253 def g:GetName(): string 3254 return name 3255 enddef 3256 def g:SetName(arg: string) 3257 name = arg 3258 enddef 3259 END 3260 writefile(lines, 'XscriptTwice.vim') 3261 so XscriptTwice.vim 3262 assert_equal('thename', g:GetName()) 3263 g:SetName('newname') 3264 assert_equal('newname', g:GetName()) 3265 so XscriptTwice.vim 3266 assert_fails('call g:GetName()', 'E1149:') 3267 assert_fails('call g:SetName("x")', 'E1149:') 3268 3269 delfunc g:GetName 3270 delfunc g:SetName 3271 delete('XscriptTwice.vim') 3272 unlet g:guard 3273enddef 3274 3275def Test_import_gone_when_sourced_twice() 3276 var exportlines =<< trim END 3277 vim9script 3278 if exists('g:guard') 3279 finish 3280 endif 3281 g:guard = 1 3282 export var name = 'someName' 3283 END 3284 writefile(exportlines, 'XexportScript.vim') 3285 3286 var lines =<< trim END 3287 vim9script 3288 import name from './XexportScript.vim' 3289 def g:GetName(): string 3290 return name 3291 enddef 3292 END 3293 writefile(lines, 'XscriptImport.vim') 3294 so XscriptImport.vim 3295 assert_equal('someName', g:GetName()) 3296 3297 so XexportScript.vim 3298 assert_fails('call g:GetName()', 'E1149:') 3299 3300 delfunc g:GetName 3301 delete('XexportScript.vim') 3302 delete('XscriptImport.vim') 3303 unlet g:guard 3304enddef 3305 3306" Keep this last, it messes up highlighting. 3307def Test_substitute_cmd() 3308 new 3309 setline(1, 'something') 3310 :substitute(some(other( 3311 assert_equal('otherthing', getline(1)) 3312 bwipe! 3313 3314 # also when the context is Vim9 script 3315 var lines =<< trim END 3316 vim9script 3317 new 3318 setline(1, 'something') 3319 :substitute(some(other( 3320 assert_equal('otherthing', getline(1)) 3321 bwipe! 3322 END 3323 writefile(lines, 'Xvim9lines') 3324 source Xvim9lines 3325 3326 delete('Xvim9lines') 3327enddef 3328 3329" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 3330