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