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