1" Test various aspects of the Vim9 script language. 2 3source check.vim 4source term_util.vim 5source view_util.vim 6source vim9.vim 7 8def Test_syntax() 9 let var = 234 10 let other: list<string> = ['asdf'] 11enddef 12 13let s:appendToMe = 'xxx' 14let s:addToMe = 111 15let g:existing = 'yes' 16let g:inc_counter = 1 17let $SOME_ENV_VAR = 'some' 18let g:alist = [7] 19let g:astring = 'text' 20 21def Test_assignment() 22 let bool1: bool = true 23 assert_equal(v:true, bool1) 24 let bool2: bool = false 25 assert_equal(v:false, bool2) 26 27 call CheckDefFailure(['let x:string'], 'E1069:') 28 call CheckDefFailure(['let x:string = "x"'], 'E1069:') 29 call CheckDefFailure(['let a:string = "x"'], 'E1069:') 30 31 let a: number = 6 32 assert_equal(6, a) 33 34 if has('channel') 35 let chan1: channel 36 let job1: job 37 let job2: job = job_start('willfail') 38 endif 39 if has('float') 40 let float1: float = 3.4 41 endif 42 let Funky1: func 43 let Funky2: func = function('len') 44 let Party2: func = funcref('g:Test_syntax') 45 46 g:newvar = 'new' 47 assert_equal('new', g:newvar) 48 49 assert_equal('yes', g:existing) 50 g:existing = 'no' 51 assert_equal('no', g:existing) 52 53 v:char = 'abc' 54 assert_equal('abc', v:char) 55 56 $ENVVAR = 'foobar' 57 assert_equal('foobar', $ENVVAR) 58 $ENVVAR = '' 59 60 s:appendToMe ..= 'yyy' 61 assert_equal('xxxyyy', s:appendToMe) 62 s:addToMe += 222 63 assert_equal(333, s:addToMe) 64 s:newVar = 'new' 65 assert_equal('new', s:newVar) 66 67 set ts=7 68 &ts += 1 69 assert_equal(8, &ts) 70 &ts -= 3 71 assert_equal(5, &ts) 72 &ts *= 2 73 assert_equal(10, &ts) 74 &ts /= 3 75 assert_equal(3, &ts) 76 set ts=10 77 &ts %= 4 78 assert_equal(2, &ts) 79 call CheckDefFailure(['¬ex += 3'], 'E113:') 80 call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:') 81 call CheckDefFailure(['&ts = [7]'], 'E1013:') 82 call CheckDefExecFailure(['&ts = g:alist'], 'E1029: Expected number but got list') 83 call CheckDefFailure(['&ts = "xx"'], 'E1013:') 84 call CheckDefExecFailure(['&ts = g:astring'], 'E1029: Expected number but got string') 85 call CheckDefFailure(['&path += 3'], 'E1013:') 86 call CheckDefExecFailure(['&bs = "asdf"'], 'E474:') 87 # test freeing ISN_STOREOPT 88 call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:') 89 &ts = 8 90 91 g:inc_counter += 1 92 assert_equal(2, g:inc_counter) 93 94 $SOME_ENV_VAR ..= 'more' 95 assert_equal('somemore', $SOME_ENV_VAR) 96 call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1013:') 97 call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:') 98 99 @a = 'areg' 100 @a ..= 'add' 101 assert_equal('aregadd', @a) 102 call CheckDefFailure(['@a += "more"'], 'E1013:') 103 call CheckDefFailure(['@a += 123'], 'E1013:') 104 105 v:errmsg = 'none' 106 v:errmsg ..= 'again' 107 assert_equal('noneagain', v:errmsg) 108 call CheckDefFailure(['v:errmsg += "more"'], 'E1013:') 109 call CheckDefFailure(['v:errmsg += 123'], 'E1013:') 110enddef 111 112def Test_vim9_single_char_vars() 113 let lines =<< trim END 114 vim9script 115 116 " single character variable declarations work 117 let a: string 118 let b: number 119 let l: list<any> 120 let s: string 121 let t: number 122 let v: number 123 let w: number 124 125 " script-local variables can be used without s: prefix 126 a = 'script-a' 127 b = 111 128 l = [1, 2, 3] 129 s = 'script-s' 130 t = 222 131 v = 333 132 w = 444 133 134 assert_equal('script-a', a) 135 assert_equal(111, b) 136 assert_equal([1, 2, 3], l) 137 assert_equal('script-s', s) 138 assert_equal(222, t) 139 assert_equal(333, v) 140 assert_equal(444, w) 141 END 142 writefile(lines, 'Xsinglechar') 143 source Xsinglechar 144 delete('Xsinglechar') 145enddef 146 147def Test_assignment_list() 148 let list1: list<bool> = [false, true, false] 149 let list2: list<number> = [1, 2, 3] 150 let list3: list<string> = ['sdf', 'asdf'] 151 let list4: list<any> = ['yes', true, 1234] 152 let list5: list<blob> = [0z01, 0z02] 153 154 let listS: list<string> = [] 155 let listN: list<number> = [] 156 157 assert_equal([1, 2, 3], list2) 158 list2[-1] = 99 159 assert_equal([1, 2, 99], list2) 160 list2[-2] = 88 161 assert_equal([1, 88, 99], list2) 162 list2[-3] = 77 163 assert_equal([77, 88, 99], list2) 164 call CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:') 165 call CheckDefExecFailure(['let [v1, v2] = [1, 2]'], 'E1092:') 166 167 # type becomes list<any> 168 let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c'] 169enddef 170 171def Test_assignment_dict() 172 let dict1: dict<bool> = #{one: false, two: true} 173 let dict2: dict<number> = #{one: 1, two: 2} 174 let dict3: dict<string> = #{key: 'value'} 175 let dict4: dict<any> = #{one: 1, two: '2'} 176 let dict5: dict<blob> = #{one: 0z01, two: 0z02} 177 178 " overwrite 179 dict3['key'] = 'another' 180 181 call CheckDefExecFailure(['let dd = {}', 'dd[""] = 6'], 'E713:') 182 183 # type becomes dict<any> 184 let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'} 185enddef 186 187def Test_assignment_local() 188 " Test in a separated file in order not to the current buffer/window/tab is 189 " changed. 190 let script_lines: list<string> =<< trim END 191 let b:existing = 'yes' 192 let w:existing = 'yes' 193 let t:existing = 'yes' 194 195 def Test_assignment_local_internal() 196 b:newvar = 'new' 197 assert_equal('new', b:newvar) 198 assert_equal('yes', b:existing) 199 b:existing = 'no' 200 assert_equal('no', b:existing) 201 b:existing ..= 'NO' 202 assert_equal('noNO', b:existing) 203 204 w:newvar = 'new' 205 assert_equal('new', w:newvar) 206 assert_equal('yes', w:existing) 207 w:existing = 'no' 208 assert_equal('no', w:existing) 209 w:existing ..= 'NO' 210 assert_equal('noNO', w:existing) 211 212 t:newvar = 'new' 213 assert_equal('new', t:newvar) 214 assert_equal('yes', t:existing) 215 t:existing = 'no' 216 assert_equal('no', t:existing) 217 t:existing ..= 'NO' 218 assert_equal('noNO', t:existing) 219 enddef 220 call Test_assignment_local_internal() 221 END 222 call CheckScriptSuccess(script_lines) 223enddef 224 225def Test_assignment_default() 226 227 # Test default values. 228 let thebool: bool 229 assert_equal(v:false, thebool) 230 231 let thenumber: number 232 assert_equal(0, thenumber) 233 234 if has('float') 235 let thefloat: float 236 assert_equal(0.0, thefloat) 237 endif 238 239 let thestring: string 240 assert_equal('', thestring) 241 242 let theblob: blob 243 assert_equal(0z, theblob) 244 245 let Thefunc: func 246 assert_equal(test_null_function(), Thefunc) 247 248 let thelist: list<any> 249 assert_equal([], thelist) 250 251 let thedict: dict<any> 252 assert_equal({}, thedict) 253 254 if has('channel') 255 let thejob: job 256 assert_equal(test_null_job(), thejob) 257 258 let thechannel: channel 259 assert_equal(test_null_channel(), thechannel) 260 261 if has('unix') && executable('cat') 262 " check with non-null job and channel, types must match 263 thejob = job_start("cat ", #{}) 264 thechannel = job_getchannel(thejob) 265 job_stop(thejob, 'kill') 266 endif 267 endif 268 269 let nr = 1234 | nr = 5678 270 assert_equal(5678, nr) 271enddef 272 273def Test_assignment_var_list() 274 let v1: string 275 let v2: string 276 let vrem: list<string> 277 [v1] = ['aaa'] 278 assert_equal('aaa', v1) 279 280 [v1, v2] = ['one', 'two'] 281 assert_equal('one', v1) 282 assert_equal('two', v2) 283 284 [v1, v2; vrem] = ['one', 'two'] 285 assert_equal('one', v1) 286 assert_equal('two', v2) 287 assert_equal([], vrem) 288 289 [v1, v2; vrem] = ['one', 'two', 'three'] 290 assert_equal('one', v1) 291 assert_equal('two', v2) 292 assert_equal(['three'], vrem) 293enddef 294 295def Mess(): string 296 v:foldstart = 123 297 return 'xxx' 298enddef 299 300def Test_assignment_failure() 301 call CheckDefFailure(['let var=234'], 'E1004:') 302 call CheckDefFailure(['let var =234'], 'E1004:') 303 call CheckDefFailure(['let var= 234'], 'E1004:') 304 305 call CheckDefFailure(['let true = 1'], 'E1034:') 306 call CheckDefFailure(['let false = 1'], 'E1034:') 307 308 call CheckDefFailure(['[a; b; c] = g:list'], 'E452:') 309 call CheckDefExecFailure(['let a: number', 310 '[a] = test_null_list()'], 'E1093:') 311 call CheckDefExecFailure(['let a: number', 312 '[a] = []'], 'E1093:') 313 call CheckDefExecFailure(['let x: number', 314 'let y: number', 315 '[x, y] = [1]'], 'E1093:') 316 call CheckDefExecFailure(['let x: number', 317 'let y: number', 318 'let z: list<number>', 319 '[x, y; z] = [1]'], 'E1093:') 320 321 call CheckDefFailure(['let somevar'], "E1022:") 322 call CheckDefFailure(['let &option'], 'E1052:') 323 call CheckDefFailure(['&g:option = 5'], 'E113:') 324 325 call CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:') 326 327 call CheckDefFailure(['let @~ = 5'], 'E354:') 328 call CheckDefFailure(['let @a = 5'], 'E1066:') 329 330 call CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global variable:') 331 call CheckDefFailure(['let w:var = 5'], 'E1016: Cannot declare a window variable:') 332 call CheckDefFailure(['let b:var = 5'], 'E1016: Cannot declare a buffer variable:') 333 call CheckDefFailure(['let t:var = 5'], 'E1016: Cannot declare a tab variable:') 334 335 call CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:') 336 call CheckDefFailure(['let xnr += 4'], 'E1020:') 337 338 call CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef', 'defcompile'], 'E1050:') 339 340 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>') 341 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>') 342 343 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>') 344 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>') 345 346 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:') 347 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void') 348 349 call CheckDefFailure(['let var: dict <number>'], 'E1068:') 350 call CheckDefFailure(['let var: dict<number'], 'E1009:') 351 352 call assert_fails('s/^/\=Mess()/n', 'E794:') 353 call CheckDefFailure(['let var: dict<number'], 'E1009:') 354enddef 355 356def Test_unlet() 357 g:somevar = 'yes' 358 assert_true(exists('g:somevar')) 359 unlet g:somevar 360 assert_false(exists('g:somevar')) 361 unlet! g:somevar 362 363 call CheckScriptFailure([ 364 'vim9script', 365 'let svar = 123', 366 'unlet svar', 367 ], 'E1081:') 368 call CheckScriptFailure([ 369 'vim9script', 370 'let svar = 123', 371 'unlet s:svar', 372 ], 'E1081:') 373 call CheckScriptFailure([ 374 'vim9script', 375 'let svar = 123', 376 'def Func()', 377 ' unlet svar', 378 'enddef', 379 'defcompile', 380 ], 'E1081:') 381 call CheckScriptFailure([ 382 'vim9script', 383 'let svar = 123', 384 'def Func()', 385 ' unlet s:svar', 386 'enddef', 387 'defcompile', 388 ], 'E1081:') 389 390 $ENVVAR = 'foobar' 391 assert_equal('foobar', $ENVVAR) 392 unlet $ENVVAR 393 assert_equal('', $ENVVAR) 394enddef 395 396def Test_delfunction() 397 " Check function is defined in script namespace 398 CheckScriptSuccess([ 399 'vim9script', 400 'func CheckMe()', 401 ' return 123', 402 'endfunc', 403 'assert_equal(123, s:CheckMe())', 404 ]) 405 406 " Check function in script namespace cannot be deleted 407 CheckScriptFailure([ 408 'vim9script', 409 'func DeleteMe1()', 410 'endfunc', 411 'delfunction DeleteMe1', 412 ], 'E1084:') 413 CheckScriptFailure([ 414 'vim9script', 415 'func DeleteMe2()', 416 'endfunc', 417 'def DoThat()', 418 ' delfunction DeleteMe2', 419 'enddef', 420 'DoThat()', 421 ], 'E1084:') 422 CheckScriptFailure([ 423 'vim9script', 424 'def DeleteMe3()', 425 'enddef', 426 'delfunction DeleteMe3', 427 ], 'E1084:') 428 CheckScriptFailure([ 429 'vim9script', 430 'def DeleteMe4()', 431 'enddef', 432 'def DoThat()', 433 ' delfunction DeleteMe4', 434 'enddef', 435 'DoThat()', 436 ], 'E1084:') 437enddef 438 439func Test_wrong_type() 440 call CheckDefFailure(['let var: list<nothing>'], 'E1010:') 441 call CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:') 442 call CheckDefFailure(['let var: dict<nothing>'], 'E1010:') 443 call CheckDefFailure(['let var: dict<dict<nothing>>'], 'E1010:') 444 445 call CheckDefFailure(['let var: dict<number'], 'E1009:') 446 call CheckDefFailure(['let var: dict<list<number>'], 'E1009:') 447 448 call CheckDefFailure(['let var: ally'], 'E1010:') 449 call CheckDefFailure(['let var: bram'], 'E1010:') 450 call CheckDefFailure(['let var: cathy'], 'E1010:') 451 call CheckDefFailure(['let var: dom'], 'E1010:') 452 call CheckDefFailure(['let var: freddy'], 'E1010:') 453 call CheckDefFailure(['let var: john'], 'E1010:') 454 call CheckDefFailure(['let var: larry'], 'E1010:') 455 call CheckDefFailure(['let var: ned'], 'E1010:') 456 call CheckDefFailure(['let var: pam'], 'E1010:') 457 call CheckDefFailure(['let var: sam'], 'E1010:') 458 call CheckDefFailure(['let var: vim'], 'E1010:') 459 460 call CheckDefFailure(['let Ref: number', 'Ref()'], 'E1085:') 461 call CheckDefFailure(['let Ref: string', 'let res = Ref()'], 'E1085:') 462endfunc 463 464func Test_const() 465 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:') 466 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:') 467 call CheckDefFailure(['const two'], 'E1021:') 468 call CheckDefFailure(['const &option'], 'E996:') 469endfunc 470 471def Test_range_no_colon() 472 call CheckDefFailure(['%s/a/b/'], 'E1050:') 473 call CheckDefFailure(['+ s/a/b/'], 'E1050:') 474 call CheckDefFailure(['- s/a/b/'], 'E1050:') 475 call CheckDefFailure(['. s/a/b/'], 'E1050:') 476enddef 477 478 479def Test_block() 480 let outer = 1 481 { 482 let inner = 2 483 assert_equal(1, outer) 484 assert_equal(2, inner) 485 } 486 assert_equal(1, outer) 487enddef 488 489func Test_block_failure() 490 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:') 491 call CheckDefFailure(['}'], 'E1025:') 492 call CheckDefFailure(['{', 'echo 1'], 'E1026:') 493endfunc 494 495def Test_cmd_modifier() 496 tab echo '0' 497 call CheckDefFailure(['5tab echo 3'], 'E16:') 498enddef 499 500def Test_try_catch() 501 let l = [] 502 try # comment 503 add(l, '1') 504 throw 'wrong' 505 add(l, '2') 506 catch # comment 507 add(l, v:exception) 508 finally # comment 509 add(l, '3') 510 endtry # comment 511 assert_equal(['1', 'wrong', '3'], l) 512enddef 513 514def ThrowFromDef() 515 throw "getout" # comment 516enddef 517 518func CatchInFunc() 519 try 520 call ThrowFromDef() 521 catch 522 let g:thrown_func = v:exception 523 endtry 524endfunc 525 526def CatchInDef() 527 try 528 ThrowFromDef() 529 catch 530 g:thrown_def = v:exception 531 endtry 532enddef 533 534def ReturnFinally(): string 535 try 536 return 'intry' 537 finally 538 g:in_finally = 'finally' 539 endtry 540 return 'end' 541enddef 542 543def Test_try_catch_nested() 544 CatchInFunc() 545 assert_equal('getout', g:thrown_func) 546 547 CatchInDef() 548 assert_equal('getout', g:thrown_def) 549 550 assert_equal('intry', ReturnFinally()) 551 assert_equal('finally', g:in_finally) 552enddef 553 554def Test_try_catch_match() 555 let seq = 'a' 556 try 557 throw 'something' 558 catch /nothing/ 559 seq ..= 'x' 560 catch /some/ 561 seq ..= 'b' 562 catch /asdf/ 563 seq ..= 'x' 564 catch ?a\?sdf? 565 seq ..= 'y' 566 finally 567 seq ..= 'c' 568 endtry 569 assert_equal('abc', seq) 570enddef 571 572def Test_try_catch_fails() 573 call CheckDefFailure(['catch'], 'E603:') 574 call CheckDefFailure(['try', 'echo 0', 'catch', 'catch'], 'E1033:') 575 call CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:') 576 call CheckDefFailure(['finally'], 'E606:') 577 call CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:') 578 call CheckDefFailure(['endtry'], 'E602:') 579 call CheckDefFailure(['while 1', 'endtry'], 'E170:') 580 call CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:') 581 call CheckDefFailure(['if 2', 'endtry'], 'E171:') 582 call CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:') 583 584 call CheckDefFailure(['throw'], 'E1015:') 585 call CheckDefFailure(['throw xxx'], 'E1001:') 586enddef 587 588def Test_throw_vimscript() 589 " only checks line continuation 590 let lines =<< trim END 591 vim9script 592 try 593 throw 'one' 594 .. 'two' 595 catch 596 assert_equal('onetwo', v:exception) 597 endtry 598 END 599 CheckScriptSuccess(lines) 600enddef 601 602def Test_cexpr_vimscript() 603 " only checks line continuation 604 set errorformat=File\ %f\ line\ %l 605 let lines =<< trim END 606 vim9script 607 cexpr 'File' 608 .. ' someFile' .. 609 ' line 19' 610 assert_equal(19, getqflist()[0].lnum) 611 END 612 CheckScriptSuccess(lines) 613 set errorformat& 614enddef 615 616if has('channel') 617 let someJob = test_null_job() 618 619 def FuncWithError() 620 echomsg g:someJob 621 enddef 622 623 func Test_convert_emsg_to_exception() 624 try 625 call FuncWithError() 626 catch 627 call assert_match('Vim:E908:', v:exception) 628 endtry 629 endfunc 630endif 631 632let s:export_script_lines =<< trim END 633 vim9script 634 let name: string = 'bob' 635 def Concat(arg: string): string 636 return name .. arg 637 enddef 638 g:result = Concat('bie') 639 g:localname = name 640 641 export const CONST = 1234 642 export let exported = 9876 643 export let exp_name = 'John' 644 export def Exported(): string 645 return 'Exported' 646 enddef 647END 648 649def Test_vim9_import_export() 650 let import_script_lines =<< trim END 651 vim9script 652 import {exported, Exported} from './Xexport.vim' 653 g:imported = exported 654 exported += 3 655 g:imported_added = exported 656 g:imported_func = Exported() 657 658 import {exp_name} from './Xexport.vim' 659 g:imported_name = exp_name 660 exp_name ..= ' Doe' 661 g:imported_name_appended = exp_name 662 g:imported_later = exported 663 END 664 665 writefile(import_script_lines, 'Ximport.vim') 666 writefile(s:export_script_lines, 'Xexport.vim') 667 668 source Ximport.vim 669 670 assert_equal('bobbie', g:result) 671 assert_equal('bob', g:localname) 672 assert_equal(9876, g:imported) 673 assert_equal(9879, g:imported_added) 674 assert_equal(9879, g:imported_later) 675 assert_equal('Exported', g:imported_func) 676 assert_equal('John', g:imported_name) 677 assert_equal('John Doe', g:imported_name_appended) 678 assert_false(exists('g:name')) 679 680 unlet g:result 681 unlet g:localname 682 unlet g:imported 683 unlet g:imported_added 684 unlet g:imported_later 685 unlet g:imported_func 686 unlet g:imported_name g:imported_name_appended 687 delete('Ximport.vim') 688 689 # similar, with line breaks 690 let import_line_break_script_lines =<< trim END 691 vim9script 692 import { 693 exported, 694 Exported, 695 } 696 from 697 './Xexport.vim' 698 g:imported = exported 699 exported += 5 700 g:imported_added = exported 701 g:imported_func = Exported() 702 END 703 writefile(import_line_break_script_lines, 'Ximport_lbr.vim') 704 source Ximport_lbr.vim 705 706 assert_equal(9876, g:imported) 707 assert_equal(9881, g:imported_added) 708 assert_equal('Exported', g:imported_func) 709 710 # exported script not sourced again 711 assert_false(exists('g:result')) 712 unlet g:imported 713 unlet g:imported_added 714 unlet g:imported_func 715 delete('Ximport_lbr.vim') 716 717 # import inside :def function 718 let import_in_def_lines =<< trim END 719 vim9script 720 def ImportInDef() 721 import exported from './Xexport.vim' 722 g:imported = exported 723 exported += 7 724 g:imported_added = exported 725 enddef 726 ImportInDef() 727 END 728 writefile(import_in_def_lines, 'Ximport2.vim') 729 source Ximport2.vim 730 " TODO: this should be 9879 731 assert_equal(9876, g:imported) 732 assert_equal(9883, g:imported_added) 733 unlet g:imported 734 unlet g:imported_added 735 delete('Ximport2.vim') 736 737 let import_star_as_lines =<< trim END 738 vim9script 739 import * as Export from './Xexport.vim' 740 def UseExport() 741 g:imported = Export.exported 742 enddef 743 UseExport() 744 END 745 writefile(import_star_as_lines, 'Ximport.vim') 746 source Ximport.vim 747 assert_equal(9883, g:imported) 748 749 let import_star_as_lines_no_dot =<< trim END 750 vim9script 751 import * as Export from './Xexport.vim' 752 def Func() 753 let dummy = 1 754 let imported = Export + dummy 755 enddef 756 defcompile 757 END 758 writefile(import_star_as_lines_no_dot, 'Ximport.vim') 759 assert_fails('source Ximport.vim', 'E1060:') 760 761 let import_star_as_lines_dot_space =<< trim END 762 vim9script 763 import * as Export from './Xexport.vim' 764 def Func() 765 let imported = Export . exported 766 enddef 767 defcompile 768 END 769 writefile(import_star_as_lines_dot_space, 'Ximport.vim') 770 assert_fails('source Ximport.vim', 'E1074:') 771 772 let import_star_as_lines_missing_name =<< trim END 773 vim9script 774 import * as Export from './Xexport.vim' 775 def Func() 776 let imported = Export. 777 enddef 778 defcompile 779 END 780 writefile(import_star_as_lines_missing_name, 'Ximport.vim') 781 assert_fails('source Ximport.vim', 'E1048:') 782 783 let import_star_as_lbr_lines =<< trim END 784 vim9script 785 import * 786 as Export 787 from 788 './Xexport.vim' 789 def UseExport() 790 g:imported = Export.exported 791 enddef 792 UseExport() 793 END 794 writefile(import_star_as_lbr_lines, 'Ximport.vim') 795 source Ximport.vim 796 assert_equal(9883, g:imported) 797 798 let import_star_lines =<< trim END 799 vim9script 800 import * from './Xexport.vim' 801 END 802 writefile(import_star_lines, 'Ximport.vim') 803 assert_fails('source Ximport.vim', 'E1045:') 804 805 " try to import something that exists but is not exported 806 let import_not_exported_lines =<< trim END 807 vim9script 808 import name from './Xexport.vim' 809 END 810 writefile(import_not_exported_lines, 'Ximport.vim') 811 assert_fails('source Ximport.vim', 'E1049:') 812 813 " try to import something that is already defined 814 let import_already_defined =<< trim END 815 vim9script 816 let exported = 'something' 817 import exported from './Xexport.vim' 818 END 819 writefile(import_already_defined, 'Ximport.vim') 820 assert_fails('source Ximport.vim', 'E1073:') 821 822 " try to import something that is already defined 823 import_already_defined =<< trim END 824 vim9script 825 let exported = 'something' 826 import * as exported from './Xexport.vim' 827 END 828 writefile(import_already_defined, 'Ximport.vim') 829 assert_fails('source Ximport.vim', 'E1073:') 830 831 " try to import something that is already defined 832 import_already_defined =<< trim END 833 vim9script 834 let exported = 'something' 835 import {exported} from './Xexport.vim' 836 END 837 writefile(import_already_defined, 'Ximport.vim') 838 assert_fails('source Ximport.vim', 'E1073:') 839 840 " import a very long name, requires making a copy 841 let import_long_name_lines =<< trim END 842 vim9script 843 import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim' 844 END 845 writefile(import_long_name_lines, 'Ximport.vim') 846 assert_fails('source Ximport.vim', 'E1048:') 847 848 let import_no_from_lines =<< trim END 849 vim9script 850 import name './Xexport.vim' 851 END 852 writefile(import_no_from_lines, 'Ximport.vim') 853 assert_fails('source Ximport.vim', 'E1070:') 854 855 let import_invalid_string_lines =<< trim END 856 vim9script 857 import name from Xexport.vim 858 END 859 writefile(import_invalid_string_lines, 'Ximport.vim') 860 assert_fails('source Ximport.vim', 'E1071:') 861 862 let import_wrong_name_lines =<< trim END 863 vim9script 864 import name from './XnoExport.vim' 865 END 866 writefile(import_wrong_name_lines, 'Ximport.vim') 867 assert_fails('source Ximport.vim', 'E1053:') 868 869 let import_missing_comma_lines =<< trim END 870 vim9script 871 import {exported name} from './Xexport.vim' 872 END 873 writefile(import_missing_comma_lines, 'Ximport3.vim') 874 assert_fails('source Ximport3.vim', 'E1046:') 875 876 delete('Ximport.vim') 877 delete('Ximport3.vim') 878 delete('Xexport.vim') 879 880 " Check that in a Vim9 script 'cpo' is set to the Vim default. 881 set cpo&vi 882 let cpo_before = &cpo 883 let lines =<< trim END 884 vim9script 885 g:cpo_in_vim9script = &cpo 886 END 887 writefile(lines, 'Xvim9_script') 888 source Xvim9_script 889 assert_equal(cpo_before, &cpo) 890 set cpo&vim 891 assert_equal(&cpo, g:cpo_in_vim9script) 892 delete('Xvim9_script') 893enddef 894 895def Test_vim9script_fails() 896 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') 897 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') 898 CheckScriptFailure(['export let some = 123'], 'E1042:') 899 CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:') 900 CheckScriptFailure(['vim9script', 'export let g:some'], 'E1022:') 901 CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') 902 903 CheckScriptFailure(['vim9script', 'let str: string', 'str = 1234'], 'E1013:') 904 CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:') 905 906 assert_fails('vim9script', 'E1038') 907 assert_fails('export something', 'E1043') 908enddef 909 910func Test_import_fails_without_script() 911 CheckRunVimInTerminal 912 913 " call indirectly to avoid compilation error for missing functions 914 call Run_Test_import_fails_on_command_line() 915endfunc 916 917def Run_Test_import_fails_on_command_line() 918 let export =<< trim END 919 vim9script 920 export def Foo(): number 921 return 0 922 enddef 923 END 924 writefile(export, 'Xexport.vim') 925 926 let buf = RunVimInTerminal('-c "import Foo from ''./Xexport.vim''"', #{ 927 rows: 6, wait_for_ruler: 0}) 928 WaitForAssert({-> assert_match('^E1094:', term_getline(buf, 5))}) 929 930 delete('Xexport.vim') 931 StopVimInTerminal(buf) 932enddef 933 934def Test_vim9script_reload_import() 935 let lines =<< trim END 936 vim9script 937 const var = '' 938 let valone = 1234 939 def MyFunc(arg: string) 940 valone = 5678 941 enddef 942 END 943 let morelines =<< trim END 944 let valtwo = 222 945 export def GetValtwo(): number 946 return valtwo 947 enddef 948 END 949 writefile(lines + morelines, 'Xreload.vim') 950 source Xreload.vim 951 source Xreload.vim 952 source Xreload.vim 953 954 let testlines =<< trim END 955 vim9script 956 def TheFunc() 957 import GetValtwo from './Xreload.vim' 958 assert_equal(222, GetValtwo()) 959 enddef 960 TheFunc() 961 END 962 writefile(testlines, 'Ximport.vim') 963 source Ximport.vim 964 965 " Test that when not using "morelines" GetValtwo() and valtwo are still 966 " defined, because import doesn't reload a script. 967 writefile(lines, 'Xreload.vim') 968 source Ximport.vim 969 970 " cannot declare a var twice 971 lines =<< trim END 972 vim9script 973 let valone = 1234 974 let valone = 5678 975 END 976 writefile(lines, 'Xreload.vim') 977 assert_fails('source Xreload.vim', 'E1041:') 978 979 delete('Xreload.vim') 980 delete('Ximport.vim') 981enddef 982 983" Not exported function that is referenced needs to be accessed by the 984" script-local name. 985def Test_vim9script_funcref() 986 let sortlines =<< trim END 987 vim9script 988 def Compare(i1: number, i2: number): number 989 return i2 - i1 990 enddef 991 992 export def FastSort(): list<number> 993 return range(5)->sort(Compare) 994 enddef 995 END 996 writefile(sortlines, 'Xsort.vim') 997 998 let lines =<< trim END 999 vim9script 1000 import FastSort from './Xsort.vim' 1001 def Test() 1002 g:result = FastSort() 1003 enddef 1004 Test() 1005 END 1006 writefile(lines, 'Xscript.vim') 1007 1008 source Xscript.vim 1009 assert_equal([4, 3, 2, 1, 0], g:result) 1010 1011 unlet g:result 1012 delete('Xsort.vim') 1013 delete('Xscript.vim') 1014enddef 1015 1016" Check that when searcing for "FilterFunc" it doesn't find the import in the 1017" script where FastFilter() is called from. 1018def Test_vim9script_funcref_other_script() 1019 let filterLines =<< trim END 1020 vim9script 1021 export def FilterFunc(idx: number, val: number): bool 1022 return idx % 2 == 1 1023 enddef 1024 export def FastFilter(): list<number> 1025 return range(10)->filter('FilterFunc') 1026 enddef 1027 END 1028 writefile(filterLines, 'Xfilter.vim') 1029 1030 let lines =<< trim END 1031 vim9script 1032 import {FilterFunc, FastFilter} from './Xfilter.vim' 1033 def Test() 1034 let x: list<number> = FastFilter() 1035 enddef 1036 Test() 1037 END 1038 writefile(lines, 'Ximport.vim') 1039 assert_fails('source Ximport.vim', 'E121:') 1040 1041 delete('Xfilter.vim') 1042 delete('Ximport.vim') 1043enddef 1044 1045def Test_vim9script_reload_delfunc() 1046 let first_lines =<< trim END 1047 vim9script 1048 def FuncYes(): string 1049 return 'yes' 1050 enddef 1051 END 1052 let withno_lines =<< trim END 1053 def FuncNo(): string 1054 return 'no' 1055 enddef 1056 def g:DoCheck(no_exists: bool) 1057 assert_equal('yes', FuncYes()) 1058 assert_equal('no', FuncNo()) 1059 enddef 1060 END 1061 let nono_lines =<< trim END 1062 def g:DoCheck(no_exists: bool) 1063 assert_equal('yes', FuncYes()) 1064 assert_fails('call FuncNo()', 'E117:') 1065 enddef 1066 END 1067 1068 # FuncNo() is defined 1069 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1070 source Xreloaded.vim 1071 g:DoCheck(true) 1072 1073 # FuncNo() is not redefined 1074 writefile(first_lines + nono_lines, 'Xreloaded.vim') 1075 source Xreloaded.vim 1076 g:DoCheck() 1077 1078 # FuncNo() is back 1079 writefile(first_lines + withno_lines, 'Xreloaded.vim') 1080 source Xreloaded.vim 1081 g:DoCheck() 1082 1083 delete('Xreloaded.vim') 1084enddef 1085 1086def Test_vim9script_reload_delvar() 1087 # write the script with a script-local variable 1088 let lines =<< trim END 1089 vim9script 1090 let var = 'string' 1091 END 1092 writefile(lines, 'XreloadVar.vim') 1093 source XreloadVar.vim 1094 1095 # now write the script using the same variable locally - works 1096 lines =<< trim END 1097 vim9script 1098 def Func() 1099 let var = 'string' 1100 enddef 1101 END 1102 writefile(lines, 'XreloadVar.vim') 1103 source XreloadVar.vim 1104 1105 delete('XreloadVar.vim') 1106enddef 1107 1108def Test_import_absolute() 1109 let import_lines = [ 1110 'vim9script', 1111 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 1112 'def UseExported()', 1113 ' g:imported_abs = exported', 1114 ' exported = 8888', 1115 ' g:imported_after = exported', 1116 'enddef', 1117 'UseExported()', 1118 'g:import_disassembled = execute("disass UseExported")', 1119 ] 1120 writefile(import_lines, 'Ximport_abs.vim') 1121 writefile(s:export_script_lines, 'Xexport_abs.vim') 1122 1123 source Ximport_abs.vim 1124 1125 assert_equal(9876, g:imported_abs) 1126 assert_equal(8888, g:imported_after) 1127 assert_match('<SNR>\d\+_UseExported.*' .. 1128 'g:imported_abs = exported.*' .. 1129 '0 LOADSCRIPT exported from .*Xexport_abs.vim.*' .. 1130 '1 STOREG g:imported_abs.*' .. 1131 'exported = 8888.*' .. 1132 '3 STORESCRIPT exported in .*Xexport_abs.vim.*' .. 1133 'g:imported_after = exported.*' .. 1134 '4 LOADSCRIPT exported from .*Xexport_abs.vim.*' .. 1135 '5 STOREG g:imported_after.*', 1136 g:import_disassembled) 1137 unlet g:imported_abs 1138 unlet g:import_disassembled 1139 1140 delete('Ximport_abs.vim') 1141 delete('Xexport_abs.vim') 1142enddef 1143 1144def Test_import_rtp() 1145 let import_lines = [ 1146 'vim9script', 1147 'import exported from "Xexport_rtp.vim"', 1148 'g:imported_rtp = exported', 1149 ] 1150 writefile(import_lines, 'Ximport_rtp.vim') 1151 mkdir('import') 1152 writefile(s:export_script_lines, 'import/Xexport_rtp.vim') 1153 1154 let save_rtp = &rtp 1155 &rtp = getcwd() 1156 source Ximport_rtp.vim 1157 &rtp = save_rtp 1158 1159 assert_equal(9876, g:imported_rtp) 1160 unlet g:imported_rtp 1161 1162 delete('Ximport_rtp.vim') 1163 delete('import', 'rf') 1164enddef 1165 1166def Test_import_compile_error() 1167 let export_lines = [ 1168 'vim9script', 1169 'export def ExpFunc(): string', 1170 ' return notDefined', 1171 'enddef', 1172 ] 1173 writefile(export_lines, 'Xexported.vim') 1174 1175 let import_lines = [ 1176 'vim9script', 1177 'import ExpFunc from "./Xexported.vim"', 1178 'def ImpFunc()', 1179 ' echo ExpFunc()', 1180 'enddef', 1181 'defcompile', 1182 ] 1183 writefile(import_lines, 'Ximport.vim') 1184 1185 try 1186 source Ximport.vim 1187 catch /E1001/ 1188 " Error should be fore the Xexported.vim file. 1189 assert_match('E1001: variable not found: notDefined', v:exception) 1190 assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint) 1191 endtry 1192 1193 delete('Xexported.vim') 1194 delete('Ximport.vim') 1195enddef 1196 1197def Test_fixed_size_list() 1198 " will be allocated as one piece of memory, check that changes work 1199 let l = [1, 2, 3, 4] 1200 l->remove(0) 1201 l->add(5) 1202 l->insert(99, 1) 1203 assert_equal([2, 99, 3, 4, 5], l) 1204enddef 1205 1206def IfElse(what: number): string 1207 let res = '' 1208 if what == 1 1209 res = "one" 1210 elseif what == 2 1211 res = "two" 1212 else 1213 res = "three" 1214 endif 1215 return res 1216enddef 1217 1218def Test_if_elseif_else() 1219 assert_equal('one', IfElse(1)) 1220 assert_equal('two', IfElse(2)) 1221 assert_equal('three', IfElse(3)) 1222enddef 1223 1224def Test_if_elseif_else_fails() 1225 call CheckDefFailure(['elseif true'], 'E582:') 1226 call CheckDefFailure(['else'], 'E581:') 1227 call CheckDefFailure(['endif'], 'E580:') 1228 call CheckDefFailure(['if true', 'elseif xxx'], 'E1001:') 1229 call CheckDefFailure(['if true', 'echo 1'], 'E171:') 1230enddef 1231 1232let g:bool_true = v:true 1233let g:bool_false = v:false 1234 1235def Test_if_const_expr() 1236 let res = false 1237 if true ? true : false 1238 res = true 1239 endif 1240 assert_equal(true, res) 1241 1242 g:glob = 2 1243 if false 1244 execute('g:glob = 3') 1245 endif 1246 assert_equal(2, g:glob) 1247 if true 1248 execute('g:glob = 3') 1249 endif 1250 assert_equal(3, g:glob) 1251 1252 res = false 1253 if g:bool_true ? true : false 1254 res = true 1255 endif 1256 assert_equal(true, res) 1257 1258 res = false 1259 if true ? g:bool_true : false 1260 res = true 1261 endif 1262 assert_equal(true, res) 1263 1264 res = false 1265 if true ? true : g:bool_false 1266 res = true 1267 endif 1268 assert_equal(true, res) 1269 1270 res = false 1271 if true ? false : true 1272 res = true 1273 endif 1274 assert_equal(false, res) 1275 1276 res = false 1277 if false ? false : true 1278 res = true 1279 endif 1280 assert_equal(true, res) 1281 1282 res = false 1283 if false ? true : false 1284 res = true 1285 endif 1286 assert_equal(false, res) 1287 1288 res = false 1289 if has('xyz') ? true : false 1290 res = true 1291 endif 1292 assert_equal(false, res) 1293 1294 res = false 1295 if true && true 1296 res = true 1297 endif 1298 assert_equal(true, res) 1299 1300 res = false 1301 if true && false 1302 res = true 1303 endif 1304 assert_equal(false, res) 1305 1306 res = false 1307 if g:bool_true && false 1308 res = true 1309 endif 1310 assert_equal(false, res) 1311 1312 res = false 1313 if true && g:bool_false 1314 res = true 1315 endif 1316 assert_equal(false, res) 1317 1318 res = false 1319 if false && false 1320 res = true 1321 endif 1322 assert_equal(false, res) 1323 1324 res = false 1325 if true || false 1326 res = true 1327 endif 1328 assert_equal(true, res) 1329 1330 res = false 1331 if g:bool_true || false 1332 res = true 1333 endif 1334 assert_equal(true, res) 1335 1336 res = false 1337 if true || g:bool_false 1338 res = true 1339 endif 1340 assert_equal(true, res) 1341 1342 res = false 1343 if false || false 1344 res = true 1345 endif 1346 assert_equal(false, res) 1347enddef 1348 1349def Test_if_const_expr_fails() 1350 call CheckDefFailure(['if "aaa" == "bbb'], 'E114:') 1351 call CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:') 1352 call CheckDefFailure(["if has('aaa'"], 'E110:') 1353 call CheckDefFailure(["if has('aaa') ? true false"], 'E109:') 1354enddef 1355 1356def RunNested(i: number): number 1357 let x: number = 0 1358 if i % 2 1359 if 1 1360 " comment 1361 else 1362 " comment 1363 endif 1364 x += 1 1365 else 1366 x += 1000 1367 endif 1368 return x 1369enddef 1370 1371def Test_nested_if() 1372 assert_equal(1, RunNested(1)) 1373 assert_equal(1000, RunNested(2)) 1374enddef 1375 1376def Test_execute_cmd() 1377 new 1378 setline(1, 'default') 1379 execute 'call setline(1, "execute-string")' 1380 assert_equal('execute-string', getline(1)) 1381 1382 execute "call setline(1, 'execute-string')" 1383 assert_equal('execute-string', getline(1)) 1384 1385 let cmd1 = 'call setline(1,' 1386 let cmd2 = '"execute-var")' 1387 execute cmd1 cmd2 # comment 1388 assert_equal('execute-var', getline(1)) 1389 1390 execute cmd1 cmd2 '|call setline(1, "execute-var-string")' 1391 assert_equal('execute-var-string', getline(1)) 1392 1393 let cmd_first = 'call ' 1394 let cmd_last = 'setline(1, "execute-var-var")' 1395 execute cmd_first .. cmd_last 1396 assert_equal('execute-var-var', getline(1)) 1397 bwipe! 1398 1399 call CheckDefFailure(['execute xxx'], 'E1001:') 1400 call CheckDefFailure(['execute "cmd"# comment'], 'E488:') 1401enddef 1402 1403def Test_execute_cmd_vimscript() 1404 " only checks line continuation 1405 let lines =<< trim END 1406 vim9script 1407 execute 'g:someVar' 1408 .. ' = ' .. 1409 '28' 1410 assert_equal(28, g:someVar) 1411 unlet g:someVar 1412 END 1413 CheckScriptSuccess(lines) 1414enddef 1415 1416def Test_echo_cmd() 1417 echo 'some' # comment 1418 echon 'thing' 1419 assert_match('^something$', Screenline(&lines)) 1420 1421 echo "some" # comment 1422 echon "thing" 1423 assert_match('^something$', Screenline(&lines)) 1424 1425 let str1 = 'some' 1426 let str2 = 'more' 1427 echo str1 str2 1428 assert_match('^some more$', Screenline(&lines)) 1429 1430 call CheckDefFailure(['echo "xxx"# comment'], 'E488:') 1431enddef 1432 1433def Test_echomsg_cmd() 1434 echomsg 'some' 'more' # comment 1435 assert_match('^some more$', Screenline(&lines)) 1436 echo 'clear' 1437 :1messages 1438 assert_match('^some more$', Screenline(&lines)) 1439 1440 call CheckDefFailure(['echomsg "xxx"# comment'], 'E488:') 1441enddef 1442 1443def Test_echomsg_cmd_vimscript() 1444 " only checks line continuation 1445 let lines =<< trim END 1446 vim9script 1447 echomsg 'here' 1448 .. ' is ' .. 1449 'a message' 1450 assert_match('^here is a message$', Screenline(&lines)) 1451 END 1452 CheckScriptSuccess(lines) 1453enddef 1454 1455def Test_echoerr_cmd() 1456 try 1457 echoerr 'something' 'wrong' # comment 1458 catch 1459 assert_match('something wrong', v:exception) 1460 endtry 1461enddef 1462 1463def Test_echoerr_cmd_vimscript() 1464 " only checks line continuation 1465 let lines =<< trim END 1466 vim9script 1467 try 1468 echoerr 'this' 1469 .. ' is ' .. 1470 'wrong' 1471 catch 1472 assert_match('this is wrong', v:exception) 1473 endtry 1474 END 1475 CheckScriptSuccess(lines) 1476enddef 1477 1478def Test_for_outside_of_function() 1479 let lines =<< trim END 1480 vim9script 1481 new 1482 for var in range(0, 3) 1483 append(line('$'), var) 1484 endfor 1485 assert_equal(['', '0', '1', '2', '3'], getline(1, '$')) 1486 bwipe! 1487 END 1488 writefile(lines, 'Xvim9for.vim') 1489 source Xvim9for.vim 1490 delete('Xvim9for.vim') 1491enddef 1492 1493def Test_for_loop() 1494 let result = '' 1495 for cnt in range(7) 1496 if cnt == 4 1497 break 1498 endif 1499 if cnt == 2 1500 continue 1501 endif 1502 result ..= cnt .. '_' 1503 endfor 1504 assert_equal('0_1_3_', result) 1505 1506 let concat = '' 1507 for str in eval('["one", "two"]') 1508 concat ..= str 1509 endfor 1510 assert_equal('onetwo', concat) 1511enddef 1512 1513def Test_for_loop_fails() 1514 CheckDefFailure(['for # in range(5)'], 'E690:') 1515 CheckDefFailure(['for i In range(5)'], 'E690:') 1516 CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:') 1517 CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:') 1518 CheckDefFailure(['for i in "text"'], 'E1013:') 1519 CheckDefFailure(['for i in xxx'], 'E1001:') 1520 CheckDefFailure(['endfor'], 'E588:') 1521 CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:') 1522enddef 1523 1524def Test_while_loop() 1525 let result = '' 1526 let cnt = 0 1527 while cnt < 555 1528 if cnt == 3 1529 break 1530 endif 1531 cnt += 1 1532 if cnt == 2 1533 continue 1534 endif 1535 result ..= cnt .. '_' 1536 endwhile 1537 assert_equal('1_3_', result) 1538enddef 1539 1540def Test_while_loop_fails() 1541 CheckDefFailure(['while xxx'], 'E1001:') 1542 CheckDefFailure(['endwhile'], 'E588:') 1543 CheckDefFailure(['continue'], 'E586:') 1544 CheckDefFailure(['if true', 'continue'], 'E586:') 1545 CheckDefFailure(['break'], 'E587:') 1546 CheckDefFailure(['if true', 'break'], 'E587:') 1547 CheckDefFailure(['while 1', 'echo 3'], 'E170:') 1548enddef 1549 1550def Test_interrupt_loop() 1551 let caught = false 1552 let x = 0 1553 try 1554 while 1 1555 x += 1 1556 if x == 100 1557 feedkeys("\<C-C>", 'Lt') 1558 endif 1559 endwhile 1560 catch 1561 caught = true 1562 assert_equal(100, x) 1563 endtry 1564 assert_true(caught, 'should have caught an exception') 1565enddef 1566 1567def Test_automatic_line_continuation() 1568 let mylist = [ 1569 'one', 1570 'two', 1571 'three', 1572 ] " comment 1573 assert_equal(['one', 'two', 'three'], mylist) 1574 1575 let mydict = { 1576 'one': 1, 1577 'two': 2, 1578 'three': 1579 3, 1580 } " comment 1581 assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict) 1582 mydict = #{ 1583 one: 1, # comment 1584 two: # comment 1585 2, # comment 1586 three: 3 # comment 1587 } 1588 assert_equal(#{one: 1, two: 2, three: 3}, mydict) 1589 mydict = #{ 1590 one: 1, 1591 two: 1592 2, 1593 three: 3 1594 } 1595 assert_equal(#{one: 1, two: 2, three: 3}, mydict) 1596 1597 assert_equal( 1598 ['one', 'two', 'three'], 1599 split('one two three') 1600 ) 1601enddef 1602 1603def Test_vim9_comment() 1604 CheckScriptSuccess([ 1605 'vim9script', 1606 '# something', 1607 ]) 1608 CheckScriptFailure([ 1609 'vim9script', 1610 ':# something', 1611 ], 'E488:') 1612 CheckScriptFailure([ 1613 '# something', 1614 ], 'E488:') 1615 CheckScriptFailure([ 1616 ':# something', 1617 ], 'E488:') 1618 1619 { # block start 1620 } # block end 1621 CheckDefFailure([ 1622 '{# comment', 1623 ], 'E488:') 1624 CheckDefFailure([ 1625 '{', 1626 '}# comment', 1627 ], 'E488:') 1628 1629 echo "yes" # comment 1630 CheckDefFailure([ 1631 'echo "yes"# comment', 1632 ], 'E488:') 1633 CheckScriptSuccess([ 1634 'vim9script', 1635 'echo "yes" # something', 1636 ]) 1637 CheckScriptFailure([ 1638 'vim9script', 1639 'echo "yes"# something', 1640 ], 'E121:') 1641 CheckScriptFailure([ 1642 'vim9script', 1643 'echo# something', 1644 ], 'E121:') 1645 CheckScriptFailure([ 1646 'echo "yes" # something', 1647 ], 'E121:') 1648 1649 exe "echo" # comment 1650 CheckDefFailure([ 1651 'exe "echo"# comment', 1652 ], 'E488:') 1653 CheckScriptSuccess([ 1654 'vim9script', 1655 'exe "echo" # something', 1656 ]) 1657 CheckScriptFailure([ 1658 'vim9script', 1659 'exe "echo"# something', 1660 ], 'E121:') 1661 CheckDefFailure([ 1662 'exe # comment', 1663 ], 'E1015:') 1664 CheckScriptFailure([ 1665 'vim9script', 1666 'exe# something', 1667 ], 'E121:') 1668 CheckScriptFailure([ 1669 'exe "echo" # something', 1670 ], 'E121:') 1671 1672 CheckDefFailure([ 1673 'try# comment', 1674 ' echo "yes"', 1675 'catch', 1676 'endtry', 1677 ], 'E488:') 1678 CheckScriptFailure([ 1679 'vim9script', 1680 'try# comment', 1681 'echo "yes"', 1682 ], 'E488:') 1683 CheckDefFailure([ 1684 'try', 1685 ' throw#comment', 1686 'catch', 1687 'endtry', 1688 ], 'E1015:') 1689 CheckDefFailure([ 1690 'try', 1691 ' throw "yes"#comment', 1692 'catch', 1693 'endtry', 1694 ], 'E488:') 1695 CheckDefFailure([ 1696 'try', 1697 ' echo "yes"', 1698 'catch# comment', 1699 'endtry', 1700 ], 'E488:') 1701 CheckScriptFailure([ 1702 'vim9script', 1703 'try', 1704 ' echo "yes"', 1705 'catch# comment', 1706 'endtry', 1707 ], 'E654:') 1708 CheckDefFailure([ 1709 'try', 1710 ' echo "yes"', 1711 'catch /pat/# comment', 1712 'endtry', 1713 ], 'E488:') 1714 CheckDefFailure([ 1715 'try', 1716 'echo "yes"', 1717 'catch', 1718 'endtry# comment', 1719 ], 'E488:') 1720 CheckScriptFailure([ 1721 'vim9script', 1722 'try', 1723 ' echo "yes"', 1724 'catch', 1725 'endtry# comment', 1726 ], 'E488:') 1727 1728 CheckScriptSuccess([ 1729 'vim9script', 1730 'hi # comment', 1731 ]) 1732 CheckScriptFailure([ 1733 'vim9script', 1734 'hi# comment', 1735 ], 'E416:') 1736 CheckScriptSuccess([ 1737 'vim9script', 1738 'hi Search # comment', 1739 ]) 1740 CheckScriptFailure([ 1741 'vim9script', 1742 'hi Search# comment', 1743 ], 'E416:') 1744 CheckScriptSuccess([ 1745 'vim9script', 1746 'hi link This Search # comment', 1747 ]) 1748 CheckScriptFailure([ 1749 'vim9script', 1750 'hi link This That# comment', 1751 ], 'E413:') 1752 CheckScriptSuccess([ 1753 'vim9script', 1754 'hi clear This # comment', 1755 'hi clear # comment', 1756 ]) 1757 " not tested, because it doesn't give an error but a warning: 1758 " hi clear This# comment', 1759 CheckScriptFailure([ 1760 'vim9script', 1761 'hi clear# comment', 1762 ], 'E416:') 1763 1764 CheckScriptSuccess([ 1765 'vim9script', 1766 'hi Group term=bold', 1767 'match Group /todo/ # comment', 1768 ]) 1769 CheckScriptFailure([ 1770 'vim9script', 1771 'hi Group term=bold', 1772 'match Group /todo/# comment', 1773 ], 'E488:') 1774 CheckScriptSuccess([ 1775 'vim9script', 1776 'match # comment', 1777 ]) 1778 CheckScriptFailure([ 1779 'vim9script', 1780 'match# comment', 1781 ], 'E475:') 1782 CheckScriptSuccess([ 1783 'vim9script', 1784 'match none # comment', 1785 ]) 1786 CheckScriptFailure([ 1787 'vim9script', 1788 'match none# comment', 1789 ], 'E475:') 1790 1791 CheckScriptSuccess([ 1792 'vim9script', 1793 'menutrans clear # comment', 1794 ]) 1795 CheckScriptFailure([ 1796 'vim9script', 1797 'menutrans clear# comment text', 1798 ], 'E474:') 1799 1800 CheckScriptSuccess([ 1801 'vim9script', 1802 'syntax clear # comment', 1803 ]) 1804 CheckScriptFailure([ 1805 'vim9script', 1806 'syntax clear# comment text', 1807 ], 'E28:') 1808 CheckScriptSuccess([ 1809 'vim9script', 1810 'syntax keyword Word some', 1811 'syntax clear Word # comment', 1812 ]) 1813 CheckScriptFailure([ 1814 'vim9script', 1815 'syntax keyword Word some', 1816 'syntax clear Word# comment text', 1817 ], 'E28:') 1818 1819 CheckScriptSuccess([ 1820 'vim9script', 1821 'syntax list # comment', 1822 ]) 1823 CheckScriptFailure([ 1824 'vim9script', 1825 'syntax list# comment text', 1826 ], 'E28:') 1827 1828 CheckScriptSuccess([ 1829 'vim9script', 1830 'syntax match Word /pat/ oneline # comment', 1831 ]) 1832 CheckScriptFailure([ 1833 'vim9script', 1834 'syntax match Word /pat/ oneline# comment', 1835 ], 'E475:') 1836 1837 CheckScriptSuccess([ 1838 'vim9script', 1839 'syntax keyword Word word # comm[ent', 1840 ]) 1841 CheckScriptFailure([ 1842 'vim9script', 1843 'syntax keyword Word word# comm[ent', 1844 ], 'E789:') 1845 1846 CheckScriptSuccess([ 1847 'vim9script', 1848 'syntax match Word /pat/ # comment', 1849 ]) 1850 CheckScriptFailure([ 1851 'vim9script', 1852 'syntax match Word /pat/# comment', 1853 ], 'E402:') 1854 1855 CheckScriptSuccess([ 1856 'vim9script', 1857 'syntax match Word /pat/ contains=Something # comment', 1858 ]) 1859 CheckScriptFailure([ 1860 'vim9script', 1861 'syntax match Word /pat/ contains=Something# comment', 1862 ], 'E475:') 1863 CheckScriptFailure([ 1864 'vim9script', 1865 'syntax match Word /pat/ contains= # comment', 1866 ], 'E406:') 1867 CheckScriptFailure([ 1868 'vim9script', 1869 'syntax match Word /pat/ contains=# comment', 1870 ], 'E475:') 1871 1872 CheckScriptSuccess([ 1873 'vim9script', 1874 'syntax region Word start=/pat/ end=/pat/ # comment', 1875 ]) 1876 CheckScriptFailure([ 1877 'vim9script', 1878 'syntax region Word start=/pat/ end=/pat/# comment', 1879 ], 'E475:') 1880 1881 CheckScriptSuccess([ 1882 'vim9script', 1883 'syntax sync # comment', 1884 ]) 1885 CheckScriptFailure([ 1886 'vim9script', 1887 'syntax sync# comment', 1888 ], 'E404:') 1889 CheckScriptSuccess([ 1890 'vim9script', 1891 'syntax sync ccomment # comment', 1892 ]) 1893 CheckScriptFailure([ 1894 'vim9script', 1895 'syntax sync ccomment# comment', 1896 ], 'E404:') 1897 1898 CheckScriptSuccess([ 1899 'vim9script', 1900 'syntax cluster Some contains=Word # comment', 1901 ]) 1902 CheckScriptFailure([ 1903 'vim9script', 1904 'syntax cluster Some contains=Word# comment', 1905 ], 'E475:') 1906 1907 CheckScriptSuccess([ 1908 'vim9script', 1909 'command Echo echo # comment', 1910 'command Echo # comment', 1911 ]) 1912 CheckScriptFailure([ 1913 'vim9script', 1914 'command Echo echo# comment', 1915 'Echo', 1916 ], 'E121:') 1917 CheckScriptFailure([ 1918 'vim9script', 1919 'command Echo# comment', 1920 ], 'E182:') 1921 CheckScriptFailure([ 1922 'vim9script', 1923 'command Echo echo', 1924 'command Echo# comment', 1925 ], 'E182:') 1926 1927 CheckScriptSuccess([ 1928 'vim9script', 1929 'function # comment', 1930 ]) 1931 CheckScriptFailure([ 1932 'vim9script', 1933 'function# comment', 1934 ], 'E129:') 1935 CheckScriptSuccess([ 1936 'vim9script', 1937 'function CheckScriptSuccess # comment', 1938 ]) 1939 CheckScriptFailure([ 1940 'vim9script', 1941 'function CheckScriptSuccess# comment', 1942 ], 'E488:') 1943 1944 CheckScriptSuccess([ 1945 'vim9script', 1946 'func g:DeleteMeA()', 1947 'endfunc', 1948 'delfunction g:DeleteMeA # comment', 1949 ]) 1950 CheckScriptFailure([ 1951 'vim9script', 1952 'func g:DeleteMeB()', 1953 'endfunc', 1954 'delfunction g:DeleteMeB# comment', 1955 ], 'E488:') 1956 1957 CheckScriptSuccess([ 1958 'vim9script', 1959 'call execute("ls") # comment', 1960 ]) 1961 CheckScriptFailure([ 1962 'vim9script', 1963 'call execute("ls")# comment', 1964 ], 'E488:') 1965enddef 1966 1967def Test_vim9_comment_gui() 1968 CheckCanRunGui 1969 1970 CheckScriptFailure([ 1971 'vim9script', 1972 'gui#comment' 1973 ], 'E499:') 1974 CheckScriptFailure([ 1975 'vim9script', 1976 'gui -f#comment' 1977 ], 'E499:') 1978enddef 1979 1980def Test_vim9_comment_not_compiled() 1981 au TabEnter *.vim g:entered = 1 1982 au TabEnter *.x g:entered = 2 1983 1984 edit test.vim 1985 doautocmd TabEnter #comment 1986 assert_equal(1, g:entered) 1987 1988 doautocmd TabEnter f.x 1989 assert_equal(2, g:entered) 1990 1991 g:entered = 0 1992 doautocmd TabEnter f.x #comment 1993 assert_equal(2, g:entered) 1994 1995 assert_fails('doautocmd Syntax#comment', 'E216:') 1996 1997 au! TabEnter 1998 unlet g:entered 1999 2000 CheckScriptSuccess([ 2001 'vim9script', 2002 'g:var = 123', 2003 'b:var = 456', 2004 'w:var = 777', 2005 't:var = 888', 2006 'unlet g:var w:var # something', 2007 ]) 2008 2009 CheckScriptFailure([ 2010 'vim9script', 2011 'let g:var = 123', 2012 ], 'E1016: Cannot declare a global variable:') 2013 2014 CheckScriptFailure([ 2015 'vim9script', 2016 'let b:var = 123', 2017 ], 'E1016: Cannot declare a buffer variable:') 2018 2019 CheckScriptFailure([ 2020 'vim9script', 2021 'let w:var = 123', 2022 ], 'E1016: Cannot declare a window variable:') 2023 2024 CheckScriptFailure([ 2025 'vim9script', 2026 'let t:var = 123', 2027 ], 'E1016: Cannot declare a tab variable:') 2028 2029 CheckScriptFailure([ 2030 'vim9script', 2031 'let v:version = 123', 2032 ], 'E1016: Cannot declare a v: variable:') 2033 2034 CheckScriptFailure([ 2035 'vim9script', 2036 'let $VARIABLE = "text"', 2037 ], 'E1016: Cannot declare an environment variable:') 2038 2039 CheckScriptFailure([ 2040 'vim9script', 2041 'g:var = 123', 2042 'unlet g:var# comment1', 2043 ], 'E108:') 2044 2045 CheckScriptFailure([ 2046 'let g:var = 123', 2047 'unlet g:var # something', 2048 ], 'E488:') 2049 2050 CheckScriptSuccess([ 2051 'vim9script', 2052 'if 1 # comment2', 2053 ' echo "yes"', 2054 'elseif 2 #comment', 2055 ' echo "no"', 2056 'endif', 2057 ]) 2058 2059 CheckScriptFailure([ 2060 'vim9script', 2061 'if 1# comment3', 2062 ' echo "yes"', 2063 'endif', 2064 ], 'E15:') 2065 2066 CheckScriptFailure([ 2067 'vim9script', 2068 'if 0 # comment4', 2069 ' echo "yes"', 2070 'elseif 2#comment', 2071 ' echo "no"', 2072 'endif', 2073 ], 'E15:') 2074 2075 CheckScriptSuccess([ 2076 'vim9script', 2077 'let v = 1 # comment5', 2078 ]) 2079 2080 CheckScriptFailure([ 2081 'vim9script', 2082 'let v = 1# comment6', 2083 ], 'E15:') 2084 2085 CheckScriptSuccess([ 2086 'vim9script', 2087 'new' 2088 'call setline(1, ["# define pat", "last"])', 2089 ':$', 2090 'dsearch /pat/ #comment', 2091 'bwipe!', 2092 ]) 2093 2094" CheckScriptFailure([ 2095" 'vim9script', 2096" 'new' 2097" 'call setline(1, ["# define pat", "last"])', 2098" ':$', 2099" 'dsearch /pat/#comment', 2100" 'bwipe!', 2101" ], 'E488:') 2102" 2103" CheckScriptFailure([ 2104" 'vim9script', 2105" 'func! SomeFunc()', 2106" ], 'E477:') 2107enddef 2108 2109def Test_finish() 2110 let lines =<< trim END 2111 vim9script 2112 g:res = 'one' 2113 if v:false | finish | endif 2114 g:res = 'two' 2115 finish 2116 g:res = 'three' 2117 END 2118 writefile(lines, 'Xfinished') 2119 source Xfinished 2120 assert_equal('two', g:res) 2121 2122 unlet g:res 2123 delete('Xfinished') 2124enddef 2125 2126def Test_let_func_call() 2127 let lines =<< trim END 2128 vim9script 2129 func GetValue() 2130 if exists('g:count') 2131 let g:count += 1 2132 else 2133 let g:count = 1 2134 endif 2135 return 'this' 2136 endfunc 2137 let val: string = GetValue() 2138 " env var is always a string 2139 let env = $TERM 2140 END 2141 writefile(lines, 'Xfinished') 2142 source Xfinished 2143 " GetValue() is not called during discovery phase 2144 assert_equal(1, g:count) 2145 2146 unlet g:count 2147 delete('Xfinished') 2148enddef 2149 2150def Test_let_missing_type() 2151 let lines =<< trim END 2152 vim9script 2153 let var = g:unknown 2154 END 2155 CheckScriptFailure(lines, 'E121:') 2156 2157 lines =<< trim END 2158 vim9script 2159 let nr: number = 123 2160 let var = nr 2161 END 2162 CheckScriptSuccess(lines) 2163enddef 2164 2165def Test_let_declaration() 2166 let lines =<< trim END 2167 vim9script 2168 let var: string 2169 g:var_uninit = var 2170 var = 'text' 2171 g:var_test = var 2172 " prefixing s: is optional 2173 s:var = 'prefixed' 2174 g:var_prefixed = s:var 2175 2176 let s:other: number 2177 other = 1234 2178 g:other_var = other 2179 END 2180 CheckScriptSuccess(lines) 2181 assert_equal('', g:var_uninit) 2182 assert_equal('text', g:var_test) 2183 assert_equal('prefixed', g:var_prefixed) 2184 assert_equal(1234, g:other_var) 2185 2186 unlet g:var_uninit 2187 unlet g:var_test 2188 unlet g:var_prefixed 2189 unlet g:other_var 2190enddef 2191 2192def Test_let_declaration_fails() 2193 let lines =<< trim END 2194 vim9script 2195 const var: string 2196 END 2197 CheckScriptFailure(lines, 'E1021:') 2198 2199 lines =<< trim END 2200 vim9script 2201 let 9var: string 2202 END 2203 CheckScriptFailure(lines, 'E475:') 2204enddef 2205 2206def Test_let_type_check() 2207 let lines =<< trim END 2208 vim9script 2209 let var: string 2210 var = 1234 2211 END 2212 CheckScriptFailure(lines, 'E1013:') 2213 2214 lines =<< trim END 2215 vim9script 2216 let var:string 2217 END 2218 CheckScriptFailure(lines, 'E1069:') 2219 2220 lines =<< trim END 2221 vim9script 2222 let var: asdf 2223 END 2224 CheckScriptFailure(lines, 'E1010:') 2225enddef 2226 2227def Test_forward_declaration() 2228 let lines =<< trim END 2229 vim9script 2230 def GetValue(): string 2231 return theVal 2232 enddef 2233 let theVal = 'something' 2234 g:initVal = GetValue() 2235 theVal = 'else' 2236 g:laterVal = GetValue() 2237 END 2238 writefile(lines, 'Xforward') 2239 source Xforward 2240 assert_equal('something', g:initVal) 2241 assert_equal('else', g:laterVal) 2242 2243 unlet g:initVal 2244 unlet g:laterVal 2245 delete('Xforward') 2246enddef 2247 2248def Test_source_vim9_from_legacy() 2249 let legacy_lines =<< trim END 2250 source Xvim9_script.vim 2251 2252 call assert_false(exists('local')) 2253 call assert_false(exists('exported')) 2254 call assert_false(exists('s:exported')) 2255 call assert_equal('global', global) 2256 call assert_equal('global', g:global) 2257 2258 " imported variable becomes script-local 2259 import exported from './Xvim9_script.vim' 2260 call assert_equal('exported', s:exported) 2261 call assert_false(exists('exported')) 2262 2263 " imported function becomes script-local 2264 import GetText from './Xvim9_script.vim' 2265 call assert_equal('text', s:GetText()) 2266 call assert_false(exists('*GetText')) 2267 END 2268 writefile(legacy_lines, 'Xlegacy_script.vim') 2269 2270 let vim9_lines =<< trim END 2271 vim9script 2272 let local = 'local' 2273 g:global = 'global' 2274 export let exported = 'exported' 2275 export def GetText(): string 2276 return 'text' 2277 enddef 2278 END 2279 writefile(vim9_lines, 'Xvim9_script.vim') 2280 2281 source Xlegacy_script.vim 2282 2283 assert_equal('global', g:global) 2284" unlet g:global 2285 2286 delete('Xlegacy_script.vim') 2287 delete('Xvim9_script.vim') 2288enddef 2289 2290def Test_vim9_copen() 2291 # this was giving an error for setting w:quickfix_title 2292 copen 2293 quit 2294enddef 2295 2296" Keep this last, it messes up highlighting. 2297def Test_substitute_cmd() 2298 new 2299 setline(1, 'something') 2300 :substitute(some(other( 2301 assert_equal('otherthing', getline(1)) 2302 bwipe! 2303 2304 " also when the context is Vim9 script 2305 let lines =<< trim END 2306 vim9script 2307 new 2308 setline(1, 'something') 2309 :substitute(some(other( 2310 assert_equal('otherthing', getline(1)) 2311 bwipe! 2312 END 2313 writefile(lines, 'Xvim9lines') 2314 source Xvim9lines 2315 2316 delete('Xvim9lines') 2317enddef 2318 2319" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 2320