1" Test various aspects of the Vim9 script language. 2 3source check.vim 4 5" Check that "lines" inside ":def" results in an "error" message. 6func CheckDefFailure(lines, error) 7 call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef') 8 call assert_fails('so Xdef', a:error, a:lines) 9 call delete('Xdef') 10endfunc 11 12func CheckScriptFailure(lines, error) 13 call writefile(a:lines, 'Xdef') 14 call assert_fails('so Xdef', a:error, a:lines) 15 call delete('Xdef') 16endfunc 17 18def Test_syntax() 19 let var = 234 20 let other: list<string> = ['asdf'] 21enddef 22 23func Test_def_basic() 24 def SomeFunc(): string 25 return 'yes' 26 enddef 27 call assert_equal('yes', SomeFunc()) 28endfunc 29 30let s:appendToMe = 'xxx' 31let s:addToMe = 111 32 33def Test_assignment() 34 let bool1: bool = true 35 assert_equal(v:true, bool1) 36 let bool2: bool = false 37 assert_equal(v:false, bool2) 38 39 let list1: list<string> = ['sdf', 'asdf'] 40 let list2: list<number> = [1, 2, 3] 41 42 " TODO: does not work yet 43 " let listS: list<string> = [] 44 " let listN: list<number> = [] 45 46 let dict1: dict<string> = #{key: 'value'} 47 let dict2: dict<number> = #{one: 1, two: 2} 48 49 v:char = 'abc' 50 assert_equal('abc', v:char) 51 52 $ENVVAR = 'foobar' 53 assert_equal('foobar', $ENVVAR) 54 $ENVVAR = '' 55 56 appendToMe ..= 'yyy' 57 assert_equal('xxxyyy', appendToMe) 58 addToMe += 222 59 assert_equal(333, addToMe) 60enddef 61 62func Test_assignment_failure() 63 call CheckDefFailure(['let var=234'], 'E1004:') 64 call CheckDefFailure(['let var =234'], 'E1004:') 65 call CheckDefFailure(['let var= 234'], 'E1004:') 66 67 call CheckDefFailure(['let true = 1'], 'E1034:') 68 call CheckDefFailure(['let false = 1'], 'E1034:') 69 70 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>') 71 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>') 72 73 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>') 74 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>') 75 76 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:') 77 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void') 78endfunc 79 80func Test_const() 81 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:') 82 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:') 83 call CheckDefFailure(['const two'], 'E1021:') 84endfunc 85 86def Test_block() 87 let outer = 1 88 { 89 let inner = 2 90 assert_equal(1, outer) 91 assert_equal(2, inner) 92 } 93 assert_equal(1, outer) 94enddef 95 96func Test_block_failure() 97 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:') 98endfunc 99 100def ReturnString(): string 101 return 'string' 102enddef 103 104def ReturnNumber(): number 105 return 123 106enddef 107 108def Test_return_string() 109 assert_equal('string', ReturnString()) 110 assert_equal(123, ReturnNumber()) 111enddef 112 113func Increment() 114 let g:counter += 1 115endfunc 116 117def Test_call_ufunc_count() 118 g:counter = 1 119 Increment() 120 Increment() 121 Increment() 122 " works with and without :call 123 assert_equal(4, g:counter) 124 call assert_equal(4, g:counter) 125 unlet g:counter 126enddef 127 128def MyVarargs(arg: string, ...rest: list<string>): string 129 let res = arg 130 for s in rest 131 res ..= ',' .. s 132 endfor 133 return res 134enddef 135 136def Test_call_varargs() 137 assert_equal('one', MyVarargs('one')) 138 assert_equal('one,two', MyVarargs('one', 'two')) 139 assert_equal('one,two,three', MyVarargs('one', 'two', 'three')) 140enddef 141 142def MyDefaultArgs(name = 'string'): string 143 return name 144enddef 145 146def Test_call_default_args() 147 assert_equal('string', MyDefaultArgs()) 148 assert_equal('one', MyDefaultArgs('one')) 149 assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 150enddef 151 152func Test_call_default_args_from_func() 153 call assert_equal('string', MyDefaultArgs()) 154 call assert_equal('one', MyDefaultArgs('one')) 155 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 156endfunc 157 158" Default arg and varargs 159def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string 160 let res = one .. ',' .. two 161 for s in rest 162 res ..= ',' .. s 163 endfor 164 return res 165enddef 166 167def Test_call_def_varargs() 168 call assert_fails('call MyDefVarargs()', 'E119:') 169 assert_equal('one,foo', MyDefVarargs('one')) 170 assert_equal('one,two', MyDefVarargs('one', 'two')) 171 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) 172enddef 173 174 175"def Test_call_func_defined_later() 176" call assert_equal('one', DefineLater('one')) 177" call assert_fails('call NotDefined("one")', 'E99:') 178"enddef 179 180func DefineLater(arg) 181 return a:arg 182endfunc 183 184def Test_return_type_wrong() 185 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string') 186 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number') 187 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string') 188 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string') 189enddef 190 191def Test_arg_type_wrong() 192 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 193enddef 194 195def Test_try_catch() 196 let l = [] 197 try 198 add(l, '1') 199 throw 'wrong' 200 add(l, '2') 201 catch 202 add(l, v:exception) 203 finally 204 add(l, '3') 205 endtry 206 assert_equal(['1', 'wrong', '3'], l) 207enddef 208 209let s:export_script_lines =<< trim END 210 vim9script 211 let name: string = 'bob' 212 def Concat(arg: string): string 213 return name .. arg 214 enddef 215 let g:result = Concat('bie') 216 let g:localname = name 217 218 export const CONST = 1234 219 export let exported = 9876 220 export let exp_name = 'John' 221 export def Exported(): string 222 return 'Exported' 223 enddef 224END 225 226def Test_vim9script() 227 let import_script_lines =<< trim END 228 vim9script 229 import {exported, Exported} from './Xexport.vim' 230 g:imported = exported 231 exported += 3 232 g:imported_added = exported 233 g:imported_func = Exported() 234 235 import {exp_name} from './Xexport.vim' 236 g:imported_name = exp_name 237 exp_name ..= ' Doe' 238 g:imported_name_appended = exp_name 239 END 240 241 writefile(import_script_lines, 'Ximport.vim') 242 writefile(s:export_script_lines, 'Xexport.vim') 243 244 source Ximport.vim 245 246 assert_equal('bobbie', g:result) 247 assert_equal('bob', g:localname) 248 assert_equal(9876, g:imported) 249 assert_equal(9879, g:imported_added) 250 assert_equal('Exported', g:imported_func) 251 assert_equal('John', g:imported_name) 252 assert_equal('John Doe', g:imported_name_appended) 253 assert_false(exists('g:name')) 254 255 unlet g:result 256 unlet g:localname 257 unlet g:imported 258 unlet g:imported_added 259 unlet g:imported_func 260 unlet g:imported_name g:imported_name_appended 261 delete('Ximport.vim') 262 delete('Xexport.vim') 263 264 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') 265 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') 266enddef 267 268def Test_vim9script_call() 269 let lines =<< trim END 270 vim9script 271 let var = '' 272 def MyFunc(arg: string) 273 var = arg 274 enddef 275 MyFunc('foobar') 276 assert_equal('foobar', var) 277 278 let str = 'barfoo' 279 str->MyFunc() 280 assert_equal('barfoo', var) 281 282 let g:value = 'value' 283 g:value->MyFunc() 284 assert_equal('value', var) 285 286 let listvar = [] 287 def ListFunc(arg: list<number>) 288 listvar = arg 289 enddef 290 [1, 2, 3]->ListFunc() 291 assert_equal([1, 2, 3], listvar) 292 293 let dictvar = {} 294 def DictFunc(arg: dict<number>) 295 dictvar = arg 296 enddef 297 {'a': 1, 'b': 2}->DictFunc() 298 assert_equal(#{a: 1, b: 2}, dictvar) 299 #{a: 3, b: 4}->DictFunc() 300 assert_equal(#{a: 3, b: 4}, dictvar) 301 END 302 writefile(lines, 'Xcall.vim') 303 source Xcall.vim 304 delete('Xcall.vim') 305enddef 306 307def Test_vim9script_call_fail_decl() 308 let lines =<< trim END 309 vim9script 310 let var = '' 311 def MyFunc(arg: string) 312 let var = 123 313 enddef 314 END 315 writefile(lines, 'Xcall_decl.vim') 316 assert_fails('source Xcall_decl.vim', 'E1054:') 317 delete('Xcall_decl.vim') 318enddef 319 320def Test_vim9script_call_fail_const() 321 let lines =<< trim END 322 vim9script 323 const var = '' 324 def MyFunc(arg: string) 325 var = 'asdf' 326 enddef 327 END 328 writefile(lines, 'Xcall_const.vim') 329 assert_fails('source Xcall_const.vim', 'E46:') 330 delete('Xcall_const.vim') 331enddef 332 333def Test_vim9script_reload() 334 let lines =<< trim END 335 vim9script 336 const var = '' 337 let valone = 1234 338 def MyFunc(arg: string) 339 valone = 5678 340 enddef 341 END 342 let morelines =<< trim END 343 let valtwo = 222 344 export def GetValtwo(): number 345 return valtwo 346 enddef 347 END 348 writefile(lines + morelines, 'Xreload.vim') 349 source Xreload.vim 350 source Xreload.vim 351 source Xreload.vim 352 353 let testlines =<< trim END 354 vim9script 355 def TheFunc() 356 import GetValtwo from './Xreload.vim' 357 assert_equal(222, GetValtwo()) 358 enddef 359 TheFunc() 360 END 361 writefile(testlines, 'Ximport.vim') 362 source Ximport.vim 363 364 " test that when not using "morelines" valtwo is still defined 365 " need to source Xreload.vim again, import doesn't reload a script 366 writefile(lines, 'Xreload.vim') 367 source Xreload.vim 368 source Ximport.vim 369 370 " cannot declare a var twice 371 lines =<< trim END 372 vim9script 373 let valone = 1234 374 let valone = 5678 375 END 376 writefile(lines, 'Xreload.vim') 377 assert_fails('source Xreload.vim', 'E1041:') 378 379 delete('Xreload.vim') 380 delete('Ximport.vim') 381enddef 382 383def Test_import_absolute() 384 let import_lines = [ 385 \ 'vim9script', 386 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 387 \ 'def UseExported()', 388 \ ' g:imported_abs = exported', 389 \ ' exported = 8888', 390 \ ' g:imported_after = exported', 391 \ 'enddef', 392 \ 'UseExported()', 393 \ 'g:import_disassembled = execute("disass UseExported")', 394 \ ] 395 writefile(import_lines, 'Ximport_abs.vim') 396 writefile(s:export_script_lines, 'Xexport_abs.vim') 397 398 source Ximport_abs.vim 399 400 assert_equal(9876, g:imported_abs) 401 assert_equal(8888, g:imported_after) 402 assert_match('<SNR>\d\+_UseExported.*' 403 \ .. 'g:imported_abs = exported.*' 404 \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*' 405 \ .. '1 STOREG g:imported_abs.*' 406 \ .. 'exported = 8888.*' 407 \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*' 408 \ .. 'g:imported_after = exported.*' 409 \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*' 410 \ .. '5 STOREG g:imported_after.*' 411 \, g:import_disassembled) 412 unlet g:imported_abs 413 unlet g:import_disassembled 414 415 delete('Ximport_abs.vim') 416 delete('Xexport_abs.vim') 417enddef 418 419def Test_import_rtp() 420 let import_lines = [ 421 \ 'vim9script', 422 \ 'import exported from "Xexport_rtp.vim"', 423 \ 'g:imported_rtp = exported', 424 \ ] 425 writefile(import_lines, 'Ximport_rtp.vim') 426 mkdir('import') 427 writefile(s:export_script_lines, 'import/Xexport_rtp.vim') 428 429 let save_rtp = &rtp 430 &rtp = getcwd() 431 source Ximport_rtp.vim 432 &rtp = save_rtp 433 434 assert_equal(9876, g:imported_rtp) 435 unlet g:imported_rtp 436 437 delete('Ximport_rtp.vim') 438 delete('import/Xexport_rtp.vim') 439 delete('import', 'd') 440enddef 441 442def Test_fixed_size_list() 443 " will be allocated as one piece of memory, check that changes work 444 let l = [1, 2, 3, 4] 445 l->remove(0) 446 l->add(5) 447 l->insert(99, 1) 448 assert_equal([2, 99, 3, 4, 5], l) 449enddef 450 451" Test that inside :function a Python function can be defined, :def is not 452" recognized. 453func Test_function_python() 454 CheckFeature python3 455 let py = 'python3' 456 execute py "<< EOF" 457def do_something(): 458 return 1 459EOF 460endfunc 461 462def IfElse(what: number): string 463 let res = '' 464 if what == 1 465 res = "one" 466 elseif what == 2 467 res = "two" 468 else 469 res = "three" 470 endif 471 return res 472enddef 473 474def Test_if_elseif_else() 475 assert_equal('one', IfElse(1)) 476 assert_equal('two', IfElse(2)) 477 assert_equal('three', IfElse(3)) 478enddef 479 480 481" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 482