blob: 2ac97d0f46741c22f1256f187e42a967a20be3ba [file] [log] [blame]
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001" Test various aspects of the Vim9 script language.
2
3source check.vim
Bram Moolenaarad304702020-09-06 18:22:53 +02004source term_util.vim
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005source view_util.vim
Bram Moolenaar04b12692020-05-04 23:24:44 +02006source vim9.vim
Bram Moolenaar47e7d702020-07-05 18:18:42 +02007source screendump.vim
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02008
9func Test_def_basic()
10 def SomeFunc(): string
11 return 'yes'
12 enddef
Bram Moolenaarc0c71e92020-09-11 19:09:48 +020013 call SomeFunc()->assert_equal('yes')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +020014endfunc
15
Bram Moolenaar2b9b17e2020-10-13 18:38:11 +020016func Test_compiling_error()
17 " use a terminal to see the whole error message
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +020018 CheckRunVimInTerminal
19
Bram Moolenaar2b9b17e2020-10-13 18:38:11 +020020 call TestCompilingError()
Bram Moolenaare8c46602021-04-05 22:27:37 +020021 call TestCompilingErrorInTry()
Bram Moolenaar2b9b17e2020-10-13 18:38:11 +020022endfunc
23
24def TestCompilingError()
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +020025 var lines =<< trim END
26 vim9script
27 def Fails()
28 echo nothing
29 enddef
30 defcompile
31 END
Bram Moolenaare8c46602021-04-05 22:27:37 +020032 writefile(lines, 'XTest_compile_error')
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +020033 var buf = RunVimInTerminal('-S XTest_compile_error',
Bram Moolenaare0de1712020-12-02 17:36:54 +010034 {rows: 10, wait_for_ruler: 0})
Bram Moolenaare8c46602021-04-05 22:27:37 +020035 WaitForAssert(() => assert_match('Error detected while compiling command line.*Fails.*Variable not found: nothing',
Bram Moolenaar03dfde22021-02-14 13:17:22 +010036 Term_getlines(buf, range(1, 9))))
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +020037
38 # clean up
Bram Moolenaare8c46602021-04-05 22:27:37 +020039 StopVimInTerminal(buf)
40 delete('XTest_compile_error')
41enddef
42
43def TestCompilingErrorInTry()
44 var dir = 'Xdir/autoload'
45 mkdir(dir, 'p')
46
47 var lines =<< trim END
48 vim9script
49 def script#OnlyCompiled()
50 g:runtime = 'yes'
51 invalid
52 enddef
53 END
54 writefile(lines, dir .. '/script.vim')
55
56 lines =<< trim END
57 vim9script
58 todo
59 try
60 script#OnlyCompiled()
61 catch /nothing/
62 endtry
63 END
64 lines[1] = 'set rtp=' .. getcwd() .. '/Xdir'
65 writefile(lines, 'XTest_compile_error')
66
67 var buf = RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0})
68 WaitForAssert(() => assert_match('Error detected while compiling command line.*function script#OnlyCompiled.*Invalid command: invalid',
69 Term_getlines(buf, range(1, 9))))
70
71 # clean up
72 StopVimInTerminal(buf)
73 delete('XTest_compile_error')
74 delete('Xdir', 'rf')
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +020075enddef
76
Bram Moolenaarf48b2fa2021-04-12 22:02:36 +020077def Test_autoload_name_mismatch()
78 var dir = 'Xdir/autoload'
79 mkdir(dir, 'p')
80
81 var lines =<< trim END
82 vim9script
83 def scriptX#Function()
84 # comment
85 g:runtime = 'yes'
86 enddef
87 END
88 writefile(lines, dir .. '/script.vim')
89
90 var save_rtp = &rtp
91 exe 'set rtp=' .. getcwd() .. '/Xdir'
92 lines =<< trim END
93 call script#Function()
94 END
95 CheckScriptFailure(lines, 'E746:', 2)
96
97 &rtp = save_rtp
98 delete(dir, 'rf')
99enddef
100
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100101def CallRecursive(n: number): number
102 return CallRecursive(n + 1)
103enddef
104
105def CallMapRecursive(l: list<number>): number
Bram Moolenaar2949cfd2020-12-31 21:28:47 +0100106 return map(l, (_, v) => CallMapRecursive([v]))[0]
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100107enddef
108
109def Test_funcdepth_error()
110 set maxfuncdepth=10
111
112 var caught = false
113 try
114 CallRecursive(1)
115 catch /E132:/
116 caught = true
117 endtry
118 assert_true(caught)
119
120 caught = false
121 try
122 CallMapRecursive([1])
123 catch /E132:/
124 caught = true
125 endtry
126 assert_true(caught)
127
128 set maxfuncdepth&
129enddef
130
Bram Moolenaar5178b1b2021-01-01 18:43:51 +0100131def Test_endfunc_enddef()
132 var lines =<< trim END
133 def Test()
134 echo 'test'
135 endfunc
136 enddef
137 END
138 CheckScriptFailure(lines, 'E1151:', 3)
139
140 lines =<< trim END
141 def Test()
142 func Nested()
143 echo 'test'
144 enddef
145 enddef
146 END
147 CheckScriptFailure(lines, 'E1152:', 4)
Bram Moolenaar49f1e9e2021-03-22 20:49:02 +0100148
149 lines =<< trim END
150 def Ok()
151 echo 'hello'
152 enddef | echo 'there'
153 def Bad()
154 echo 'hello'
155 enddef there
156 END
157 CheckScriptFailure(lines, 'E1173: Text found after enddef: there', 6)
Bram Moolenaar5178b1b2021-01-01 18:43:51 +0100158enddef
159
Bram Moolenaarb8ba9b92021-01-01 18:54:34 +0100160def Test_missing_endfunc_enddef()
161 var lines =<< trim END
162 vim9script
163 def Test()
164 echo 'test'
165 endef
166 END
167 CheckScriptFailure(lines, 'E1057:', 2)
168
169 lines =<< trim END
170 vim9script
171 func Some()
172 echo 'test'
173 enfffunc
174 END
175 CheckScriptFailure(lines, 'E126:', 2)
176enddef
177
Bram Moolenaar4efd9942021-01-24 21:14:20 +0100178def Test_white_space_before_paren()
179 var lines =<< trim END
180 vim9script
181 def Test ()
182 echo 'test'
183 enddef
184 END
185 CheckScriptFailure(lines, 'E1068:', 2)
186
187 lines =<< trim END
188 vim9script
189 func Test ()
190 echo 'test'
191 endfunc
192 END
193 CheckScriptFailure(lines, 'E1068:', 2)
194
195 lines =<< trim END
196 def Test ()
197 echo 'test'
198 enddef
199 END
200 CheckScriptFailure(lines, 'E1068:', 1)
201
202 lines =<< trim END
203 func Test ()
204 echo 'test'
205 endfunc
206 END
207 CheckScriptSuccess(lines)
208enddef
209
Bram Moolenaar832ea892021-01-08 21:55:26 +0100210def Test_enddef_dict_key()
211 var d = {
212 enddef: 'x',
213 endfunc: 'y',
214 }
215 assert_equal({enddef: 'x', endfunc: 'y'}, d)
216enddef
217
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200218def ReturnString(): string
219 return 'string'
220enddef
221
222def ReturnNumber(): number
223 return 123
224enddef
225
226let g:notNumber = 'string'
227
228def ReturnGlobal(): number
229 return g:notNumber
230enddef
231
232def Test_return_something()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200233 ReturnString()->assert_equal('string')
234 ReturnNumber()->assert_equal(123)
Bram Moolenaar5e654232020-09-16 15:22:00 +0200235 assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200236enddef
237
Bram Moolenaare32e5162021-01-21 20:21:29 +0100238def Test_check_argument_type()
239 var lines =<< trim END
240 vim9script
241 def Val(a: number, b: number): number
242 return 0
243 enddef
244 def Func()
245 var x: any = true
246 Val(0, x)
247 enddef
248 disass Func
249 Func()
250 END
251 CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got bool', 2)
252enddef
253
Bram Moolenaarefd88552020-06-18 20:50:10 +0200254def Test_missing_return()
255 CheckDefFailure(['def Missing(): number',
256 ' if g:cond',
257 ' echo "no return"',
258 ' else',
259 ' return 0',
260 ' endif'
261 'enddef'], 'E1027:')
262 CheckDefFailure(['def Missing(): number',
263 ' if g:cond',
264 ' return 1',
265 ' else',
266 ' echo "no return"',
267 ' endif'
268 'enddef'], 'E1027:')
269 CheckDefFailure(['def Missing(): number',
270 ' if g:cond',
271 ' return 1',
272 ' else',
273 ' return 2',
274 ' endif'
275 ' return 3'
276 'enddef'], 'E1095:')
277enddef
278
Bram Moolenaar403dc312020-10-17 19:29:51 +0200279def Test_return_bool()
280 var lines =<< trim END
281 vim9script
282 def MenuFilter(id: number, key: string): bool
283 return popup_filter_menu(id, key)
284 enddef
285 def YesnoFilter(id: number, key: string): bool
286 return popup_filter_yesno(id, key)
287 enddef
288 defcompile
289 END
290 CheckScriptSuccess(lines)
291enddef
292
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200293let s:nothing = 0
294def ReturnNothing()
295 s:nothing = 1
296 if true
297 return
298 endif
299 s:nothing = 2
300enddef
301
302def Test_return_nothing()
303 ReturnNothing()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200304 s:nothing->assert_equal(1)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200305enddef
306
Bram Moolenaar648ea762021-01-15 19:04:32 +0100307def Test_return_invalid()
308 var lines =<< trim END
309 vim9script
310 def Func(): invalid
311 return xxx
312 enddef
313 defcompile
314 END
315 CheckScriptFailure(lines, 'E1010:', 2)
Bram Moolenaar31842cd2021-02-12 22:10:21 +0100316
317 lines =<< trim END
318 vim9script
319 def Test(Fun: func(number): number): list<number>
320 return map([1, 2, 3], (_, i) => Fun(i))
321 enddef
322 defcompile
323 def Inc(nr: number): nr
324 return nr + 2
325 enddef
326 echo Test(Inc)
327 END
328 # doing this twice was leaking memory
329 CheckScriptFailure(lines, 'E1010:')
330 CheckScriptFailure(lines, 'E1010:')
Bram Moolenaar648ea762021-01-15 19:04:32 +0100331enddef
332
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200333func Increment()
334 let g:counter += 1
335endfunc
336
337def Test_call_ufunc_count()
338 g:counter = 1
339 Increment()
340 Increment()
341 Increment()
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +0200342 # works with and without :call
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200343 g:counter->assert_equal(4)
344 eval g:counter->assert_equal(4)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200345 unlet g:counter
346enddef
347
348def MyVarargs(arg: string, ...rest: list<string>): string
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200349 var res = arg
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200350 for s in rest
351 res ..= ',' .. s
352 endfor
353 return res
354enddef
355
356def Test_call_varargs()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200357 MyVarargs('one')->assert_equal('one')
358 MyVarargs('one', 'two')->assert_equal('one,two')
359 MyVarargs('one', 'two', 'three')->assert_equal('one,two,three')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200360enddef
361
362def MyDefaultArgs(name = 'string'): string
363 return name
364enddef
365
Bram Moolenaare30f64b2020-07-15 19:48:20 +0200366def MyDefaultSecond(name: string, second: bool = true): string
367 return second ? name : 'none'
368enddef
369
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200370
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200371def Test_call_default_args()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200372 MyDefaultArgs()->assert_equal('string')
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200373 MyDefaultArgs(v:none)->assert_equal('string')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200374 MyDefaultArgs('one')->assert_equal('one')
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200375 assert_fails('MyDefaultArgs("one", "two")', 'E118:', '', 4, 'Test_call_default_args')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200376
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200377 MyDefaultSecond('test')->assert_equal('test')
378 MyDefaultSecond('test', true)->assert_equal('test')
379 MyDefaultSecond('test', false)->assert_equal('none')
Bram Moolenaare30f64b2020-07-15 19:48:20 +0200380
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200381 var lines =<< trim END
382 def MyDefaultThird(name: string, aa = 'aa', bb = 'bb'): string
383 return name .. aa .. bb
384 enddef
385
386 MyDefaultThird('->')->assert_equal('->aabb')
387 MyDefaultThird('->', v:none)->assert_equal('->aabb')
388 MyDefaultThird('->', 'xx')->assert_equal('->xxbb')
389 MyDefaultThird('->', v:none, v:none)->assert_equal('->aabb')
390 MyDefaultThird('->', 'xx', v:none)->assert_equal('->xxbb')
391 MyDefaultThird('->', v:none, 'yy')->assert_equal('->aayy')
392 MyDefaultThird('->', 'xx', 'yy')->assert_equal('->xxyy')
393 END
394 CheckDefAndScriptSuccess(lines)
395
Bram Moolenaar822ba242020-05-24 23:00:18 +0200396 CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:')
Bram Moolenaar2d870f82020-12-05 13:41:01 +0100397 delfunc g:Func
Bram Moolenaar77072282020-09-16 17:55:40 +0200398 CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string')
Bram Moolenaar2d870f82020-12-05 13:41:01 +0100399 delfunc g:Func
Bram Moolenaar12bce952021-03-11 20:04:04 +0100400
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200401 lines =<< trim END
Bram Moolenaar12bce952021-03-11 20:04:04 +0100402 vim9script
403 def Func(a = b == 0 ? 1 : 2, b = 0)
404 enddef
405 defcompile
406 END
407 CheckScriptFailure(lines, 'E1001: Variable not found: b')
Bram Moolenaar04b12692020-05-04 23:24:44 +0200408enddef
409
Bram Moolenaarcef12702021-01-04 14:09:43 +0100410def FuncWithComment( # comment
411 a: number, #comment
412 b: bool, # comment
413 c: string) #comment
414 assert_equal(4, a)
415 assert_equal(true, b)
416 assert_equal('yes', c)
417enddef
418
419def Test_func_with_comments()
420 FuncWithComment(4, true, 'yes')
421
422 var lines =<< trim END
423 def Func(# comment
424 arg: string)
425 enddef
426 END
427 CheckScriptFailure(lines, 'E125:', 1)
428
429 lines =<< trim END
430 def Func(
431 arg: string# comment
432 )
433 enddef
434 END
435 CheckScriptFailure(lines, 'E475:', 2)
436
437 lines =<< trim END
438 def Func(
439 arg: string
440 )# comment
441 enddef
442 END
443 CheckScriptFailure(lines, 'E488:', 3)
444enddef
445
Bram Moolenaar04b12692020-05-04 23:24:44 +0200446def Test_nested_function()
447 def Nested(arg: string): string
448 return 'nested ' .. arg
449 enddef
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200450 Nested('function')->assert_equal('nested function')
Bram Moolenaar04b12692020-05-04 23:24:44 +0200451
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +0200452 CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
453 CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
454
Bram Moolenaar04b12692020-05-04 23:24:44 +0200455 CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
Bram Moolenaarbcbf4132020-08-01 22:35:13 +0200456 CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:')
457 CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:')
Bram Moolenaar8b848ca2020-09-10 22:28:01 +0200458
Bram Moolenaar54021752020-12-06 18:50:36 +0100459 var lines =<< trim END
460 def Outer()
461 def Inner()
462 # comment
463 enddef
464 def Inner()
465 enddef
466 enddef
467 END
468 CheckDefFailure(lines, 'E1073:')
469
470 lines =<< trim END
471 def Outer()
472 def Inner()
473 # comment
474 enddef
475 def! Inner()
476 enddef
477 enddef
478 END
479 CheckDefFailure(lines, 'E1117:')
480
481 # nested function inside conditional
Bram Moolenaar54021752020-12-06 18:50:36 +0100482 lines =<< trim END
483 vim9script
484 var thecount = 0
485 if true
486 def Test(): number
487 def TheFunc(): number
488 thecount += 1
489 return thecount
490 enddef
491 return TheFunc()
492 enddef
493 endif
494 defcompile
495 assert_equal(1, Test())
496 assert_equal(2, Test())
497 END
498 CheckScriptSuccess(lines)
Bram Moolenaar8863bda2021-03-17 18:42:08 +0100499
500 # also works when "thecount" is inside the "if" block
501 lines =<< trim END
502 vim9script
503 if true
504 var thecount = 0
505 def Test(): number
506 def TheFunc(): number
507 thecount += 1
508 return thecount
509 enddef
510 return TheFunc()
511 enddef
512 endif
513 defcompile
514 assert_equal(1, Test())
515 assert_equal(2, Test())
516 END
517 CheckScriptSuccess(lines)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200518enddef
519
Bram Moolenaaradc8e442020-12-31 18:28:18 +0100520def Test_not_nested_function()
521 echo printf('%d',
522 function('len')('xxx'))
523enddef
524
Bram Moolenaaraf8edbb2020-08-01 00:03:09 +0200525func Test_call_default_args_from_func()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200526 call MyDefaultArgs()->assert_equal('string')
527 call MyDefaultArgs('one')->assert_equal('one')
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200528 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args_from_func')
Bram Moolenaaraf8edbb2020-08-01 00:03:09 +0200529endfunc
530
Bram Moolenaar38ddf332020-07-31 22:05:04 +0200531def Test_nested_global_function()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200532 var lines =<< trim END
Bram Moolenaar38ddf332020-07-31 22:05:04 +0200533 vim9script
534 def Outer()
535 def g:Inner(): string
536 return 'inner'
537 enddef
538 enddef
Bram Moolenaaraf8edbb2020-08-01 00:03:09 +0200539 defcompile
540 Outer()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200541 g:Inner()->assert_equal('inner')
Bram Moolenaaraf8edbb2020-08-01 00:03:09 +0200542 delfunc g:Inner
543 Outer()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200544 g:Inner()->assert_equal('inner')
Bram Moolenaaraf8edbb2020-08-01 00:03:09 +0200545 delfunc g:Inner
546 Outer()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200547 g:Inner()->assert_equal('inner')
Bram Moolenaaraf8edbb2020-08-01 00:03:09 +0200548 delfunc g:Inner
Bram Moolenaar38ddf332020-07-31 22:05:04 +0200549 END
550 CheckScriptSuccess(lines)
Bram Moolenaar2c79e9d2020-08-01 18:57:52 +0200551
552 lines =<< trim END
553 vim9script
554 def Outer()
555 def g:Inner(): string
556 return 'inner'
557 enddef
558 enddef
559 defcompile
560 Outer()
561 Outer()
562 END
563 CheckScriptFailure(lines, "E122:")
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100564 delfunc g:Inner
Bram Moolenaarad486a02020-08-01 23:22:18 +0200565
566 lines =<< trim END
567 vim9script
Bram Moolenaar58a52f22020-12-22 18:56:55 +0100568 def Outer()
569 def g:Inner()
Bram Moolenaar2949cfd2020-12-31 21:28:47 +0100570 echo map([1, 2, 3], (_, v) => v + 1)
Bram Moolenaar58a52f22020-12-22 18:56:55 +0100571 enddef
572 g:Inner()
573 enddef
574 Outer()
575 END
576 CheckScriptSuccess(lines)
577 delfunc g:Inner
578
579 lines =<< trim END
580 vim9script
Bram Moolenaarad486a02020-08-01 23:22:18 +0200581 def Func()
582 echo 'script'
583 enddef
584 def Outer()
585 def Func()
586 echo 'inner'
587 enddef
588 enddef
589 defcompile
590 END
591 CheckScriptFailure(lines, "E1073:")
Bram Moolenaar38ddf332020-07-31 22:05:04 +0200592enddef
593
Bram Moolenaar6abdcf82020-11-22 18:15:44 +0100594def DefListAll()
595 def
596enddef
597
598def DefListOne()
599 def DefListOne
600enddef
601
602def DefListMatches()
603 def /DefList
604enddef
605
606def Test_nested_def_list()
607 var funcs = split(execute('call DefListAll()'), "\n")
608 assert_true(len(funcs) > 10)
609 assert_true(funcs->index('def DefListAll()') >= 0)
610
611 funcs = split(execute('call DefListOne()'), "\n")
612 assert_equal([' def DefListOne()', '1 def DefListOne', ' enddef'], funcs)
613
614 funcs = split(execute('call DefListMatches()'), "\n")
615 assert_true(len(funcs) >= 3)
616 assert_true(funcs->index('def DefListAll()') >= 0)
617 assert_true(funcs->index('def DefListOne()') >= 0)
618 assert_true(funcs->index('def DefListMatches()') >= 0)
Bram Moolenaar54021752020-12-06 18:50:36 +0100619
620 var lines =<< trim END
621 vim9script
622 def Func()
623 def +Func+
624 enddef
625 defcompile
626 END
627 CheckScriptFailure(lines, 'E476:', 1)
Bram Moolenaar6abdcf82020-11-22 18:15:44 +0100628enddef
629
Bram Moolenaar333894b2020-08-01 18:53:07 +0200630def Test_global_local_function()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200631 var lines =<< trim END
Bram Moolenaar333894b2020-08-01 18:53:07 +0200632 vim9script
633 def g:Func(): string
634 return 'global'
635 enddef
636 def Func(): string
637 return 'local'
638 enddef
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200639 g:Func()->assert_equal('global')
640 Func()->assert_equal('local')
Bram Moolenaar2d870f82020-12-05 13:41:01 +0100641 delfunc g:Func
Bram Moolenaar333894b2020-08-01 18:53:07 +0200642 END
643 CheckScriptSuccess(lines)
Bram Moolenaar035d6e92020-08-11 22:30:42 +0200644
645 lines =<< trim END
646 vim9script
647 def g:Funcy()
648 echo 'funcy'
649 enddef
650 s:Funcy()
651 END
652 CheckScriptFailure(lines, 'E117:')
Bram Moolenaar333894b2020-08-01 18:53:07 +0200653enddef
654
Bram Moolenaar0f769812020-09-12 18:32:34 +0200655def Test_local_function_shadows_global()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200656 var lines =<< trim END
Bram Moolenaar0f769812020-09-12 18:32:34 +0200657 vim9script
658 def g:Gfunc(): string
659 return 'global'
660 enddef
661 def AnotherFunc(): number
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200662 var Gfunc = function('len')
Bram Moolenaar0f769812020-09-12 18:32:34 +0200663 return Gfunc('testing')
664 enddef
665 g:Gfunc()->assert_equal('global')
666 AnotherFunc()->assert_equal(7)
667 delfunc g:Gfunc
668 END
669 CheckScriptSuccess(lines)
670
671 lines =<< trim END
672 vim9script
673 def g:Func(): string
674 return 'global'
675 enddef
676 def AnotherFunc()
677 g:Func = function('len')
678 enddef
679 AnotherFunc()
680 END
681 CheckScriptFailure(lines, 'E705:')
682 delfunc g:Func
Bram Moolenaar0865b152021-04-05 15:38:51 +0200683
684 # global function is found without g: prefix
685 lines =<< trim END
686 vim9script
687 def g:Func(): string
688 return 'global'
689 enddef
690 def AnotherFunc(): string
691 return Func()
692 enddef
693 assert_equal('global', AnotherFunc())
694 delfunc g:Func
695 END
696 CheckScriptSuccess(lines)
697
698 lines =<< trim END
699 vim9script
700 def g:Func(): string
701 return 'global'
702 enddef
703 assert_equal('global', Func())
704 delfunc g:Func
705 END
706 CheckScriptSuccess(lines)
Bram Moolenaar0f769812020-09-12 18:32:34 +0200707enddef
708
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200709func TakesOneArg(arg)
710 echo a:arg
711endfunc
712
713def Test_call_wrong_args()
Bram Moolenaard2c61702020-09-06 15:58:36 +0200714 CheckDefFailure(['TakesOneArg()'], 'E119:')
715 CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
716 CheckDefFailure(['bufnr(xxx)'], 'E1001:')
717 CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:')
Bram Moolenaaree8580e2020-08-28 17:19:07 +0200718
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200719 var lines =<< trim END
Bram Moolenaaree8580e2020-08-28 17:19:07 +0200720 vim9script
721 def Func(s: string)
722 echo s
723 enddef
724 Func([])
725 END
Bram Moolenaar77072282020-09-16 17:55:40 +0200726 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5)
Bram Moolenaarb185a402020-09-18 22:42:00 +0200727
728 lines =<< trim END
729 vim9script
Bram Moolenaarb4893b82021-02-21 22:20:24 +0100730 var name = 'piet'
731 def FuncOne(name: string)
732 echo nr
733 enddef
734 END
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100735 CheckScriptFailure(lines, 'E1168:')
Bram Moolenaarb4893b82021-02-21 22:20:24 +0100736
737 lines =<< trim END
738 vim9script
Bram Moolenaarb185a402020-09-18 22:42:00 +0200739 def FuncOne(nr: number)
740 echo nr
741 enddef
742 def FuncTwo()
743 FuncOne()
744 enddef
745 defcompile
746 END
747 writefile(lines, 'Xscript')
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200748 var didCatch = false
Bram Moolenaarb185a402020-09-18 22:42:00 +0200749 try
750 source Xscript
751 catch
752 assert_match('E119: Not enough arguments for function: <SNR>\d\+_FuncOne', v:exception)
753 assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
754 didCatch = true
755 endtry
756 assert_true(didCatch)
757
758 lines =<< trim END
759 vim9script
760 def FuncOne(nr: number)
761 echo nr
762 enddef
763 def FuncTwo()
764 FuncOne(1, 2)
765 enddef
766 defcompile
767 END
768 writefile(lines, 'Xscript')
769 didCatch = false
770 try
771 source Xscript
772 catch
773 assert_match('E118: Too many arguments for function: <SNR>\d\+_FuncOne', v:exception)
774 assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
775 didCatch = true
776 endtry
777 assert_true(didCatch)
778
779 delete('Xscript')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200780enddef
781
Bram Moolenaar50824712020-12-20 21:10:17 +0100782def Test_call_funcref_wrong_args()
783 var head =<< trim END
784 vim9script
785 def Func3(a1: string, a2: number, a3: list<number>)
786 echo a1 .. a2 .. a3[0]
787 enddef
788 def Testme()
789 var funcMap: dict<func> = {func: Func3}
790 END
791 var tail =<< trim END
792 enddef
793 Testme()
794 END
795 CheckScriptSuccess(head + ["funcMap['func']('str', 123, [1, 2, 3])"] + tail)
796
797 CheckScriptFailure(head + ["funcMap['func']('str', 123)"] + tail, 'E119:')
798 CheckScriptFailure(head + ["funcMap['func']('str', 123, [1], 4)"] + tail, 'E118:')
Bram Moolenaar32b3f822021-01-06 21:59:39 +0100799
800 var lines =<< trim END
801 vim9script
802 var Ref: func(number): any
803 Ref = (j) => !j
804 echo Ref(false)
805 END
806 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4)
807
808 lines =<< trim END
809 vim9script
810 var Ref: func(number): any
811 Ref = (j) => !j
812 call Ref(false)
813 END
814 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4)
Bram Moolenaar50824712020-12-20 21:10:17 +0100815enddef
816
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +0100817def Test_call_lambda_args()
Bram Moolenaar2a389082021-04-09 20:24:31 +0200818 var lines =<< trim END
819 var Callback = (..._) => 'anything'
820 assert_equal('anything', Callback())
821 assert_equal('anything', Callback(1))
822 assert_equal('anything', Callback('a', 2))
Bram Moolenaar1088b692021-04-09 22:12:44 +0200823
824 assert_equal('xyz', ((a: string): string => a)('xyz'))
Bram Moolenaar2a389082021-04-09 20:24:31 +0200825 END
826 CheckDefAndScriptSuccess(lines)
827
Bram Moolenaar2949cfd2020-12-31 21:28:47 +0100828 CheckDefFailure(['echo ((i) => 0)()'],
829 'E119: Not enough arguments for function: ((i) => 0)()')
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +0100830
Bram Moolenaar2a389082021-04-09 20:24:31 +0200831 lines =<< trim END
Bram Moolenaar2949cfd2020-12-31 21:28:47 +0100832 var Ref = (x: number, y: number) => x + y
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +0100833 echo Ref(1, 'x')
834 END
835 CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string')
Bram Moolenaare68b02a2021-01-03 13:09:51 +0100836
837 lines =<< trim END
838 var Ref: func(job, string, number)
839 Ref = (x, y) => 0
840 END
841 CheckDefAndScriptFailure(lines, 'E1012:')
842
843 lines =<< trim END
844 var Ref: func(job, string)
845 Ref = (x, y, z) => 0
846 END
847 CheckDefAndScriptFailure(lines, 'E1012:')
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100848
849 lines =<< trim END
850 var one = 1
851 var l = [1, 2, 3]
852 echo map(l, (one) => one)
853 END
854 CheckDefFailure(lines, 'E1167:')
855 CheckScriptFailure(['vim9script'] + lines, 'E1168:')
856
857 lines =<< trim END
858 def ShadowLocal()
859 var one = 1
860 var l = [1, 2, 3]
861 echo map(l, (one) => one)
862 enddef
863 END
864 CheckDefFailure(lines, 'E1167:')
865
866 lines =<< trim END
867 def Shadowarg(one: number)
868 var l = [1, 2, 3]
869 echo map(l, (one) => one)
870 enddef
871 END
872 CheckDefFailure(lines, 'E1167:')
Bram Moolenaar767034c2021-04-09 17:24:52 +0200873
874 lines =<< trim END
875 echo ((a) => a)('aa', 'bb')
876 END
877 CheckDefAndScriptFailure(lines, 'E118:', 1)
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +0100878enddef
879
Bram Moolenaar5f91e742021-03-17 21:29:29 +0100880def FilterWithCond(x: string, Cond: func(string): bool): bool
881 return Cond(x)
882enddef
883
Bram Moolenaar0346b792021-01-31 22:18:29 +0100884def Test_lambda_return_type()
885 var lines =<< trim END
886 var Ref = (): => 123
887 END
888 CheckDefAndScriptFailure(lines, 'E1157:', 1)
Bram Moolenaar5f91e742021-03-17 21:29:29 +0100889
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200890 # no space before the return type
891 lines =<< trim END
892 var Ref = (x):number => x + 1
893 END
894 CheckDefAndScriptFailure(lines, 'E1069:', 1)
895
Bram Moolenaar5f91e742021-03-17 21:29:29 +0100896 # this works
897 for x in ['foo', 'boo']
898 echo FilterWithCond(x, (v) => v =~ '^b')
899 endfor
900
901 # this fails
902 lines =<< trim END
903 echo FilterWithCond('foo', (v) => v .. '^b')
904 END
905 CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1)
Bram Moolenaar0346b792021-01-31 22:18:29 +0100906enddef
907
Bram Moolenaar709664c2020-12-12 14:33:41 +0100908def Test_lambda_uses_assigned_var()
909 CheckDefSuccess([
910 'var x: any = "aaa"'
Bram Moolenaar2949cfd2020-12-31 21:28:47 +0100911 'x = filter(["bbb"], (_, v) => v =~ x)'])
Bram Moolenaar709664c2020-12-12 14:33:41 +0100912enddef
913
Bram Moolenaar18062fc2021-03-05 21:35:47 +0100914def Test_pass_legacy_lambda_to_def_func()
915 var lines =<< trim END
916 vim9script
917 func Foo()
918 eval s:Bar({x -> 0})
919 endfunc
920 def Bar(y: any)
921 enddef
922 Foo()
923 END
924 CheckScriptSuccess(lines)
925enddef
926
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200927" Default arg and varargs
928def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200929 var res = one .. ',' .. two
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200930 for s in rest
931 res ..= ',' .. s
932 endfor
933 return res
934enddef
935
936def Test_call_def_varargs()
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200937 assert_fails('MyDefVarargs()', 'E119:', '', 1, 'Test_call_def_varargs')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +0200938 MyDefVarargs('one')->assert_equal('one,foo')
939 MyDefVarargs('one', 'two')->assert_equal('one,two')
940 MyDefVarargs('one', 'two', 'three')->assert_equal('one,two,three')
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200941 CheckDefFailure(['MyDefVarargs("one", 22)'],
Bram Moolenaar77072282020-09-16 17:55:40 +0200942 'E1013: Argument 2: type mismatch, expected string but got number')
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200943 CheckDefFailure(['MyDefVarargs("one", "two", 123)'],
Bram Moolenaar77072282020-09-16 17:55:40 +0200944 'E1013: Argument 3: type mismatch, expected string but got number')
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200945
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +0200946 var lines =<< trim END
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200947 vim9script
948 def Func(...l: list<string>)
949 echo l
950 enddef
951 Func('a', 'b', 'c')
952 END
953 CheckScriptSuccess(lines)
954
955 lines =<< trim END
956 vim9script
957 def Func(...l: list<string>)
958 echo l
959 enddef
960 Func()
961 END
962 CheckScriptSuccess(lines)
963
964 lines =<< trim END
965 vim9script
Bram Moolenaar2a389082021-04-09 20:24:31 +0200966 def Func(...l: list<any>)
Bram Moolenaar2f8cbc42020-09-16 17:22:59 +0200967 echo l
968 enddef
969 Func(0)
970 END
971 CheckScriptSuccess(lines)
972
973 lines =<< trim END
974 vim9script
Bram Moolenaar2a389082021-04-09 20:24:31 +0200975 def Func(...l: any)
976 echo l
977 enddef
978 Func(0)
979 END
980 CheckScriptFailure(lines, 'E1180:', 2)
981
982 lines =<< trim END
983 vim9script
Bram Moolenaar28022722020-09-21 22:02:49 +0200984 def Func(..._l: list<string>)
985 echo _l
986 enddef
987 Func('a', 'b', 'c')
988 END
989 CheckScriptSuccess(lines)
990
991 lines =<< trim END
992 vim9script
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200993 def Func(...l: list<string>)
994 echo l
995 enddef
996 Func(1, 2, 3)
997 END
Bram Moolenaar77072282020-09-16 17:55:40 +0200998 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200999
1000 lines =<< trim END
1001 vim9script
1002 def Func(...l: list<string>)
1003 echo l
1004 enddef
1005 Func('a', 9)
1006 END
Bram Moolenaar77072282020-09-16 17:55:40 +02001007 CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch')
Bram Moolenaar24aa48b2020-07-25 16:33:02 +02001008
1009 lines =<< trim END
1010 vim9script
1011 def Func(...l: list<string>)
1012 echo l
1013 enddef
1014 Func(1, 'a')
1015 END
Bram Moolenaar77072282020-09-16 17:55:40 +02001016 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
Bram Moolenaar4f53b792021-02-07 15:59:49 +01001017
1018 lines =<< trim END
1019 vim9script
1020 def Func( # some comment
1021 ...l = []
1022 )
1023 echo l
1024 enddef
1025 END
1026 CheckScriptFailure(lines, 'E1160:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001027enddef
1028
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001029let s:value = ''
1030
1031def FuncOneDefArg(opt = 'text')
1032 s:value = opt
1033enddef
1034
1035def FuncTwoDefArg(nr = 123, opt = 'text'): string
1036 return nr .. opt
1037enddef
1038
1039def FuncVarargs(...arg: list<string>): string
1040 return join(arg, ',')
1041enddef
1042
1043def Test_func_type_varargs()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001044 var RefDefArg: func(?string)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001045 RefDefArg = FuncOneDefArg
1046 RefDefArg()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001047 s:value->assert_equal('text')
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001048 RefDefArg('some')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001049 s:value->assert_equal('some')
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001050
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001051 var RefDef2Arg: func(?number, ?string): string
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001052 RefDef2Arg = FuncTwoDefArg
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001053 RefDef2Arg()->assert_equal('123text')
1054 RefDef2Arg(99)->assert_equal('99text')
1055 RefDef2Arg(77, 'some')->assert_equal('77some')
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001056
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001057 CheckDefFailure(['var RefWrong: func(string?)'], 'E1010:')
1058 CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:')
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001059
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001060 var RefVarargs: func(...list<string>): string
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001061 RefVarargs = FuncVarargs
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001062 RefVarargs()->assert_equal('')
1063 RefVarargs('one')->assert_equal('one')
1064 RefVarargs('one', 'two')->assert_equal('one,two')
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001065
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001066 CheckDefFailure(['var RefWrong: func(...list<string>, string)'], 'E110:')
1067 CheckDefFailure(['var RefWrong: func(...list<string>, ?string)'], 'E110:')
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001068enddef
1069
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001070" Only varargs
1071def MyVarargsOnly(...args: list<string>): string
1072 return join(args, ',')
1073enddef
1074
1075def Test_call_varargs_only()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001076 MyVarargsOnly()->assert_equal('')
1077 MyVarargsOnly('one')->assert_equal('one')
1078 MyVarargsOnly('one', 'two')->assert_equal('one,two')
Bram Moolenaar77072282020-09-16 17:55:40 +02001079 CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number')
1080 CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number')
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001081enddef
1082
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001083def Test_using_var_as_arg()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001084 writefile(['def Func(x: number)', 'var x = 234', 'enddef', 'defcompile'], 'Xdef')
Bram Moolenaar9bd5d872020-09-06 21:47:48 +02001085 assert_fails('so Xdef', 'E1006:', '', 1, 'Func')
Bram Moolenaard2c61702020-09-06 15:58:36 +02001086 delete('Xdef')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001087enddef
1088
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001089def DictArg(arg: dict<string>)
1090 arg['key'] = 'value'
1091enddef
1092
1093def ListArg(arg: list<string>)
1094 arg[0] = 'value'
1095enddef
1096
1097def Test_assign_to_argument()
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001098 # works for dict and list
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001099 var d: dict<string> = {}
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001100 DictArg(d)
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001101 d['key']->assert_equal('value')
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001102 var l: list<string> = []
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001103 ListArg(l)
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001104 l[0]->assert_equal('value')
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001105
Bram Moolenaard2c61702020-09-06 15:58:36 +02001106 CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001107 delfunc! g:Func
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001108enddef
1109
Bram Moolenaarb816dae2020-09-20 22:04:00 +02001110" These argument names are reserved in legacy functions.
1111def WithReservedNames(firstline: string, lastline: string): string
1112 return firstline .. lastline
1113enddef
1114
1115def Test_argument_names()
1116 assert_equal('OK', WithReservedNames('O', 'K'))
1117enddef
1118
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001119def Test_call_func_defined_later()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001120 g:DefinedLater('one')->assert_equal('one')
Bram Moolenaar9bd5d872020-09-06 21:47:48 +02001121 assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001122enddef
1123
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001124func DefinedLater(arg)
1125 return a:arg
1126endfunc
1127
1128def Test_call_funcref()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001129 g:SomeFunc('abc')->assert_equal(3)
Bram Moolenaar9bd5d872020-09-06 21:47:48 +02001130 assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call
1131 assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref')
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001132
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001133 var lines =<< trim END
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001134 vim9script
1135 def RetNumber(): number
1136 return 123
1137 enddef
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001138 var Funcref: func: number = function('RetNumber')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001139 Funcref()->assert_equal(123)
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001140 END
1141 CheckScriptSuccess(lines)
Bram Moolenaar0f60e802020-07-22 20:16:11 +02001142
1143 lines =<< trim END
1144 vim9script
1145 def RetNumber(): number
1146 return 123
1147 enddef
1148 def Bar(F: func: number): number
1149 return F()
1150 enddef
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001151 var Funcref = function('RetNumber')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001152 Bar(Funcref)->assert_equal(123)
Bram Moolenaar0f60e802020-07-22 20:16:11 +02001153 END
1154 CheckScriptSuccess(lines)
Bram Moolenaarbfba8652020-07-23 20:09:10 +02001155
1156 lines =<< trim END
1157 vim9script
1158 def UseNumber(nr: number)
1159 echo nr
1160 enddef
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001161 var Funcref: func(number) = function('UseNumber')
Bram Moolenaarbfba8652020-07-23 20:09:10 +02001162 Funcref(123)
1163 END
1164 CheckScriptSuccess(lines)
Bram Moolenaarb8070e32020-07-23 20:56:04 +02001165
1166 lines =<< trim END
1167 vim9script
1168 def UseNumber(nr: number)
1169 echo nr
1170 enddef
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001171 var Funcref: func(string) = function('UseNumber')
Bram Moolenaarb8070e32020-07-23 20:56:04 +02001172 END
Bram Moolenaar5e654232020-09-16 15:22:00 +02001173 CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)')
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001174
1175 lines =<< trim END
1176 vim9script
1177 def EchoNr(nr = 34)
1178 g:echo = nr
1179 enddef
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001180 var Funcref: func(?number) = function('EchoNr')
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001181 Funcref()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001182 g:echo->assert_equal(34)
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001183 Funcref(123)
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001184 g:echo->assert_equal(123)
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001185 END
1186 CheckScriptSuccess(lines)
Bram Moolenaarace61322020-07-26 18:16:58 +02001187
1188 lines =<< trim END
1189 vim9script
1190 def EchoList(...l: list<number>)
1191 g:echo = l
1192 enddef
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001193 var Funcref: func(...list<number>) = function('EchoList')
Bram Moolenaarace61322020-07-26 18:16:58 +02001194 Funcref()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001195 g:echo->assert_equal([])
Bram Moolenaarace61322020-07-26 18:16:58 +02001196 Funcref(1, 2, 3)
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001197 g:echo->assert_equal([1, 2, 3])
Bram Moolenaarace61322020-07-26 18:16:58 +02001198 END
1199 CheckScriptSuccess(lines)
Bram Moolenaar01865ad2020-07-26 18:33:09 +02001200
1201 lines =<< trim END
1202 vim9script
1203 def OptAndVar(nr: number, opt = 12, ...l: list<number>): number
1204 g:optarg = opt
1205 g:listarg = l
1206 return nr
1207 enddef
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001208 var Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001209 Funcref(10)->assert_equal(10)
1210 g:optarg->assert_equal(12)
1211 g:listarg->assert_equal([])
Bram Moolenaar01865ad2020-07-26 18:33:09 +02001212
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001213 Funcref(11, 22)->assert_equal(11)
1214 g:optarg->assert_equal(22)
1215 g:listarg->assert_equal([])
Bram Moolenaar01865ad2020-07-26 18:33:09 +02001216
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001217 Funcref(17, 18, 1, 2, 3)->assert_equal(17)
1218 g:optarg->assert_equal(18)
1219 g:listarg->assert_equal([1, 2, 3])
Bram Moolenaar01865ad2020-07-26 18:33:09 +02001220 END
1221 CheckScriptSuccess(lines)
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001222enddef
1223
1224let SomeFunc = function('len')
1225let NotAFunc = 'text'
1226
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001227def CombineFuncrefTypes()
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001228 # same arguments, different return type
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001229 var Ref1: func(bool): string
1230 var Ref2: func(bool): number
1231 var Ref3: func(bool): any
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001232 Ref3 = g:cond ? Ref1 : Ref2
1233
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001234 # different number of arguments
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001235 var Refa1: func(bool): number
1236 var Refa2: func(bool, number): number
1237 var Refa3: func: number
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001238 Refa3 = g:cond ? Refa1 : Refa2
1239
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001240 # different argument types
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001241 var Refb1: func(bool, string): number
1242 var Refb2: func(string, number): number
1243 var Refb3: func(any, any): number
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001244 Refb3 = g:cond ? Refb1 : Refb2
1245enddef
1246
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001247def FuncWithForwardCall()
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001248 return g:DefinedEvenLater("yes")
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001249enddef
1250
1251def DefinedEvenLater(arg: string): string
1252 return arg
1253enddef
1254
1255def Test_error_in_nested_function()
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001256 # Error in called function requires unwinding the call stack.
Bram Moolenaar44d66522020-09-06 22:26:57 +02001257 assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001258enddef
1259
1260def Test_return_type_wrong()
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001261 CheckScriptFailure([
1262 'def Func(): number',
1263 'return "a"',
1264 'enddef',
1265 'defcompile'], 'expected number but got string')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001266 delfunc! g:Func
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001267 CheckScriptFailure([
1268 'def Func(): string',
1269 'return 1',
1270 'enddef',
1271 'defcompile'], 'expected string but got number')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001272 delfunc! g:Func
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001273 CheckScriptFailure([
1274 'def Func(): void',
1275 'return "a"',
1276 'enddef',
1277 'defcompile'],
1278 'E1096: Returning a value in a function without a return type')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001279 delfunc! g:Func
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001280 CheckScriptFailure([
1281 'def Func()',
1282 'return "a"',
1283 'enddef',
1284 'defcompile'],
1285 'E1096: Returning a value in a function without a return type')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001286 delfunc! g:Func
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001287
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001288 CheckScriptFailure([
1289 'def Func(): number',
1290 'return',
1291 'enddef',
1292 'defcompile'], 'E1003:')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001293 delfunc! g:Func
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001294
1295 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001296 delfunc! g:Func
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001297 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001298 delfunc! g:Func
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02001299 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001300 delfunc! g:Func
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001301
1302 CheckScriptFailure([
1303 'vim9script',
1304 'def FuncB()',
1305 ' return 123',
1306 'enddef',
1307 'def FuncA()',
1308 ' FuncB()',
1309 'enddef',
1310 'defcompile'], 'E1096:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001311enddef
1312
1313def Test_arg_type_wrong()
1314 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02001315 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001316 CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
Bram Moolenaar6e949782020-04-13 17:21:00 +02001317 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001318enddef
1319
Bram Moolenaar86cdb8a2021-04-06 19:01:03 +02001320def Test_white_space_before_comma()
1321 var lines =<< trim END
1322 vim9script
1323 def Func(a: number , b: number)
1324 enddef
1325 END
1326 CheckScriptFailure(lines, 'E1068:')
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +02001327 call assert_fails('vim9cmd echo stridx("a" .. "b" , "a")', 'E1068:')
Bram Moolenaar86cdb8a2021-04-06 19:01:03 +02001328enddef
1329
Bram Moolenaar608d78f2021-03-06 22:33:12 +01001330def Test_white_space_after_comma()
1331 var lines =<< trim END
1332 vim9script
1333 def Func(a: number,b: number)
1334 enddef
1335 END
1336 CheckScriptFailure(lines, 'E1069:')
1337
1338 # OK in legacy function
1339 lines =<< trim END
1340 vim9script
1341 func Func(a,b)
1342 endfunc
1343 END
1344 CheckScriptSuccess(lines)
1345enddef
1346
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001347def Test_vim9script_call()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001348 var lines =<< trim END
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001349 vim9script
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001350 var name = ''
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001351 def MyFunc(arg: string)
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001352 name = arg
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001353 enddef
1354 MyFunc('foobar')
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001355 name->assert_equal('foobar')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001356
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001357 var str = 'barfoo'
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001358 str->MyFunc()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001359 name->assert_equal('barfoo')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001360
Bram Moolenaar67979662020-06-20 22:50:47 +02001361 g:value = 'value'
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001362 g:value->MyFunc()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001363 name->assert_equal('value')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001364
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001365 var listvar = []
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001366 def ListFunc(arg: list<number>)
1367 listvar = arg
1368 enddef
1369 [1, 2, 3]->ListFunc()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001370 listvar->assert_equal([1, 2, 3])
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001371
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001372 var dictvar = {}
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001373 def DictFunc(arg: dict<number>)
1374 dictvar = arg
1375 enddef
Bram Moolenaare0de1712020-12-02 17:36:54 +01001376 {a: 1, b: 2}->DictFunc()
1377 dictvar->assert_equal({a: 1, b: 2})
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001378 def CompiledDict()
Bram Moolenaare0de1712020-12-02 17:36:54 +01001379 {a: 3, b: 4}->DictFunc()
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001380 enddef
1381 CompiledDict()
Bram Moolenaare0de1712020-12-02 17:36:54 +01001382 dictvar->assert_equal({a: 3, b: 4})
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001383
Bram Moolenaare0de1712020-12-02 17:36:54 +01001384 {a: 3, b: 4}->DictFunc()
1385 dictvar->assert_equal({a: 3, b: 4})
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001386
1387 ('text')->MyFunc()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001388 name->assert_equal('text')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001389 ("some")->MyFunc()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001390 name->assert_equal('some')
Bram Moolenaare6b53242020-07-01 17:28:33 +02001391
Bram Moolenaar13e12b82020-07-24 18:47:22 +02001392 # line starting with single quote is not a mark
Bram Moolenaar10409562020-07-29 20:00:38 +02001393 # line starting with double quote can be a method call
Bram Moolenaar3d48e252020-07-15 14:15:52 +02001394 'asdfasdf'->MyFunc()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001395 name->assert_equal('asdfasdf')
Bram Moolenaar10409562020-07-29 20:00:38 +02001396 "xyz"->MyFunc()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001397 name->assert_equal('xyz')
Bram Moolenaar3d48e252020-07-15 14:15:52 +02001398
1399 def UseString()
1400 'xyork'->MyFunc()
1401 enddef
1402 UseString()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001403 name->assert_equal('xyork')
Bram Moolenaar3d48e252020-07-15 14:15:52 +02001404
Bram Moolenaar10409562020-07-29 20:00:38 +02001405 def UseString2()
1406 "knife"->MyFunc()
1407 enddef
1408 UseString2()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001409 name->assert_equal('knife')
Bram Moolenaar10409562020-07-29 20:00:38 +02001410
Bram Moolenaar13e12b82020-07-24 18:47:22 +02001411 # prepending a colon makes it a mark
1412 new
1413 setline(1, ['aaa', 'bbb', 'ccc'])
1414 normal! 3Gmt1G
1415 :'t
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001416 getcurpos()[1]->assert_equal(3)
Bram Moolenaar13e12b82020-07-24 18:47:22 +02001417 bwipe!
1418
Bram Moolenaare6b53242020-07-01 17:28:33 +02001419 MyFunc(
1420 'continued'
1421 )
1422 assert_equal('continued',
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001423 name
Bram Moolenaare6b53242020-07-01 17:28:33 +02001424 )
1425
1426 call MyFunc(
1427 'more'
1428 ..
1429 'lines'
1430 )
1431 assert_equal(
1432 'morelines',
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001433 name)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001434 END
1435 writefile(lines, 'Xcall.vim')
1436 source Xcall.vim
1437 delete('Xcall.vim')
1438enddef
1439
1440def Test_vim9script_call_fail_decl()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001441 var lines =<< trim END
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001442 vim9script
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001443 var name = ''
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001444 def MyFunc(arg: string)
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001445 var name = 123
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001446 enddef
Bram Moolenaar822ba242020-05-24 23:00:18 +02001447 defcompile
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001448 END
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02001449 CheckScriptFailure(lines, 'E1054:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001450enddef
1451
Bram Moolenaar65b95452020-07-19 14:03:09 +02001452def Test_vim9script_call_fail_type()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001453 var lines =<< trim END
Bram Moolenaar65b95452020-07-19 14:03:09 +02001454 vim9script
1455 def MyFunc(arg: string)
1456 echo arg
1457 enddef
1458 MyFunc(1234)
1459 END
Bram Moolenaar77072282020-09-16 17:55:40 +02001460 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
Bram Moolenaar65b95452020-07-19 14:03:09 +02001461enddef
1462
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001463def Test_vim9script_call_fail_const()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001464 var lines =<< trim END
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001465 vim9script
1466 const var = ''
1467 def MyFunc(arg: string)
1468 var = 'asdf'
1469 enddef
Bram Moolenaar822ba242020-05-24 23:00:18 +02001470 defcompile
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001471 END
1472 writefile(lines, 'Xcall_const.vim')
Bram Moolenaar9bd5d872020-09-06 21:47:48 +02001473 assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001474 delete('Xcall_const.vim')
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01001475
1476 lines =<< trim END
1477 const g:Aconst = 77
1478 def Change()
1479 # comment
1480 g:Aconst = 99
1481 enddef
1482 call Change()
1483 unlet g:Aconst
1484 END
Bram Moolenaar1dcf55d2020-12-22 22:07:30 +01001485 CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001486enddef
1487
1488" Test that inside :function a Python function can be defined, :def is not
1489" recognized.
1490func Test_function_python()
1491 CheckFeature python3
Bram Moolenaar727345e2020-09-27 23:33:59 +02001492 let py = 'python3'
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001493 execute py "<< EOF"
1494def do_something():
1495 return 1
1496EOF
1497endfunc
1498
1499def Test_delfunc()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001500 var lines =<< trim END
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001501 vim9script
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02001502 def g:GoneSoon()
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001503 echo 'hello'
1504 enddef
1505
1506 def CallGoneSoon()
1507 GoneSoon()
1508 enddef
Bram Moolenaar822ba242020-05-24 23:00:18 +02001509 defcompile
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001510
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02001511 delfunc g:GoneSoon
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001512 CallGoneSoon()
1513 END
1514 writefile(lines, 'XToDelFunc')
Bram Moolenaar9bd5d872020-09-06 21:47:48 +02001515 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
1516 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001517
1518 delete('XToDelFunc')
1519enddef
1520
1521def Test_redef_failure()
Bram Moolenaard2c61702020-09-06 15:58:36 +02001522 writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001523 so Xdef
Bram Moolenaard2c61702020-09-06 15:58:36 +02001524 writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001525 so Xdef
Bram Moolenaard2c61702020-09-06 15:58:36 +02001526 writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
Bram Moolenaar9bd5d872020-09-06 21:47:48 +02001527 assert_fails('so Xdef', 'E1027:', '', 1, 'Func0')
Bram Moolenaard2c61702020-09-06 15:58:36 +02001528 writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001529 so Xdef
Bram Moolenaard2c61702020-09-06 15:58:36 +02001530 delete('Xdef')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001531
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02001532 assert_fails('g:Func0()', 'E1091:')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001533 g:Func1()->assert_equal('Func1')
1534 g:Func2()->assert_equal('Func2')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001535
1536 delfunc! Func0
1537 delfunc! Func1
1538 delfunc! Func2
1539enddef
1540
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001541def Test_vim9script_func()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001542 var lines =<< trim END
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001543 vim9script
1544 func Func(arg)
1545 echo a:arg
1546 endfunc
1547 Func('text')
1548 END
1549 writefile(lines, 'XVim9Func')
1550 so XVim9Func
1551
1552 delete('XVim9Func')
1553enddef
1554
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001555let s:funcResult = 0
1556
1557def FuncNoArgNoRet()
Bram Moolenaar53900992020-08-22 19:02:02 +02001558 s:funcResult = 11
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001559enddef
1560
1561def FuncNoArgRetNumber(): number
Bram Moolenaar53900992020-08-22 19:02:02 +02001562 s:funcResult = 22
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001563 return 1234
1564enddef
1565
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001566def FuncNoArgRetString(): string
Bram Moolenaar53900992020-08-22 19:02:02 +02001567 s:funcResult = 45
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001568 return 'text'
1569enddef
1570
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001571def FuncOneArgNoRet(arg: number)
Bram Moolenaar53900992020-08-22 19:02:02 +02001572 s:funcResult = arg
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001573enddef
1574
1575def FuncOneArgRetNumber(arg: number): number
Bram Moolenaar53900992020-08-22 19:02:02 +02001576 s:funcResult = arg
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001577 return arg
1578enddef
1579
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001580def FuncTwoArgNoRet(one: bool, two: number)
Bram Moolenaar53900992020-08-22 19:02:02 +02001581 s:funcResult = two
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001582enddef
1583
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001584def FuncOneArgRetString(arg: string): string
1585 return arg
1586enddef
1587
Bram Moolenaar89228602020-04-05 22:14:54 +02001588def FuncOneArgRetAny(arg: any): any
1589 return arg
1590enddef
1591
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001592def Test_func_type()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001593 var Ref1: func()
Bram Moolenaar53900992020-08-22 19:02:02 +02001594 s:funcResult = 0
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001595 Ref1 = FuncNoArgNoRet
1596 Ref1()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001597 s:funcResult->assert_equal(11)
Bram Moolenaar4c683752020-04-05 21:38:23 +02001598
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001599 var Ref2: func
Bram Moolenaar53900992020-08-22 19:02:02 +02001600 s:funcResult = 0
Bram Moolenaar4c683752020-04-05 21:38:23 +02001601 Ref2 = FuncNoArgNoRet
1602 Ref2()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001603 s:funcResult->assert_equal(11)
Bram Moolenaar4c683752020-04-05 21:38:23 +02001604
Bram Moolenaar53900992020-08-22 19:02:02 +02001605 s:funcResult = 0
Bram Moolenaar4c683752020-04-05 21:38:23 +02001606 Ref2 = FuncOneArgNoRet
1607 Ref2(12)
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001608 s:funcResult->assert_equal(12)
Bram Moolenaar4c683752020-04-05 21:38:23 +02001609
Bram Moolenaar53900992020-08-22 19:02:02 +02001610 s:funcResult = 0
Bram Moolenaar4c683752020-04-05 21:38:23 +02001611 Ref2 = FuncNoArgRetNumber
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001612 Ref2()->assert_equal(1234)
1613 s:funcResult->assert_equal(22)
Bram Moolenaar4c683752020-04-05 21:38:23 +02001614
Bram Moolenaar53900992020-08-22 19:02:02 +02001615 s:funcResult = 0
Bram Moolenaar4c683752020-04-05 21:38:23 +02001616 Ref2 = FuncOneArgRetNumber
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001617 Ref2(13)->assert_equal(13)
1618 s:funcResult->assert_equal(13)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001619enddef
1620
Bram Moolenaar9978d472020-07-05 16:01:56 +02001621def Test_repeat_return_type()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001622 var res = 0
Bram Moolenaar9978d472020-07-05 16:01:56 +02001623 for n in repeat([1], 3)
1624 res += n
1625 endfor
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001626 res->assert_equal(3)
Bram Moolenaarfce82b32020-07-05 16:07:21 +02001627
1628 res = 0
1629 for n in add([1, 2], 3)
1630 res += n
1631 endfor
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001632 res->assert_equal(6)
Bram Moolenaar9978d472020-07-05 16:01:56 +02001633enddef
1634
Bram Moolenaar846178a2020-07-05 17:04:13 +02001635def Test_argv_return_type()
1636 next fileone filetwo
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001637 var res = ''
Bram Moolenaar846178a2020-07-05 17:04:13 +02001638 for name in argv()
1639 res ..= name
1640 endfor
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001641 res->assert_equal('fileonefiletwo')
Bram Moolenaar846178a2020-07-05 17:04:13 +02001642enddef
1643
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001644def Test_func_type_part()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001645 var RefVoid: func: void
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001646 RefVoid = FuncNoArgNoRet
1647 RefVoid = FuncOneArgNoRet
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001648 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
1649 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001650
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001651 var RefAny: func(): any
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001652 RefAny = FuncNoArgRetNumber
1653 RefAny = FuncNoArgRetString
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001654 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
1655 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001656
Bram Moolenaar6abd3dc2020-10-04 14:17:32 +02001657 var RefAnyNoArgs: func: any = RefAny
1658
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001659 var RefNr: func: number
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001660 RefNr = FuncNoArgRetNumber
1661 RefNr = FuncOneArgRetNumber
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001662 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
1663 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001664
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001665 var RefStr: func: string
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001666 RefStr = FuncNoArgRetString
1667 RefStr = FuncOneArgRetString
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001668 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
1669 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001670enddef
1671
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001672def Test_func_type_fails()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001673 CheckDefFailure(['var ref1: func()'], 'E704:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001674
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001675 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
1676 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
1677 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
1678 CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
1679 CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
1680 CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001681
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001682 CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:')
1683 CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:')
1684 CheckDefFailure(['var RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E1005:')
1685 CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001686enddef
1687
Bram Moolenaar89228602020-04-05 22:14:54 +02001688def Test_func_return_type()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001689 var nr: number
Bram Moolenaar89228602020-04-05 22:14:54 +02001690 nr = FuncNoArgRetNumber()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001691 nr->assert_equal(1234)
Bram Moolenaar89228602020-04-05 22:14:54 +02001692
1693 nr = FuncOneArgRetAny(122)
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001694 nr->assert_equal(122)
Bram Moolenaar89228602020-04-05 22:14:54 +02001695
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001696 var str: string
Bram Moolenaar89228602020-04-05 22:14:54 +02001697 str = FuncOneArgRetAny('yes')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001698 str->assert_equal('yes')
Bram Moolenaar89228602020-04-05 22:14:54 +02001699
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001700 CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar89228602020-04-05 22:14:54 +02001701enddef
1702
Bram Moolenaar6abd3dc2020-10-04 14:17:32 +02001703def Test_func_common_type()
1704 def FuncOne(n: number): number
1705 return n
1706 enddef
1707 def FuncTwo(s: string): number
1708 return len(s)
1709 enddef
1710 def FuncThree(n: number, s: string): number
1711 return n + len(s)
1712 enddef
1713 var list = [FuncOne, FuncTwo, FuncThree]
1714 assert_equal(8, list[0](8))
1715 assert_equal(4, list[1]('word'))
1716 assert_equal(7, list[2](3, 'word'))
1717enddef
1718
Bram Moolenaar5e774c72020-04-12 21:53:00 +02001719def MultiLine(
1720 arg1: string,
1721 arg2 = 1234,
1722 ...rest: list<string>
1723 ): string
1724 return arg1 .. arg2 .. join(rest, '-')
1725enddef
1726
Bram Moolenaar2c330432020-04-13 14:41:35 +02001727def MultiLineComment(
1728 arg1: string, # comment
1729 arg2 = 1234, # comment
1730 ...rest: list<string> # comment
1731 ): string # comment
1732 return arg1 .. arg2 .. join(rest, '-')
1733enddef
1734
Bram Moolenaar5e774c72020-04-12 21:53:00 +02001735def Test_multiline()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001736 MultiLine('text')->assert_equal('text1234')
1737 MultiLine('text', 777)->assert_equal('text777')
1738 MultiLine('text', 777, 'one')->assert_equal('text777one')
1739 MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
Bram Moolenaar5e774c72020-04-12 21:53:00 +02001740enddef
1741
Bram Moolenaar23e03252020-04-12 22:22:31 +02001742func Test_multiline_not_vim9()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001743 call MultiLine('text')->assert_equal('text1234')
1744 call MultiLine('text', 777)->assert_equal('text777')
1745 call MultiLine('text', 777, 'one')->assert_equal('text777one')
1746 call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
Bram Moolenaar23e03252020-04-12 22:22:31 +02001747endfunc
1748
Bram Moolenaar5e774c72020-04-12 21:53:00 +02001749
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02001750" When using CheckScriptFailure() for the below test, E1010 is generated instead
1751" of E1056.
1752func Test_E1056_1059()
1753 let caught_1056 = 0
1754 try
1755 def F():
1756 return 1
1757 enddef
1758 catch /E1056:/
1759 let caught_1056 = 1
1760 endtry
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001761 eval caught_1056->assert_equal(1)
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02001762
1763 let caught_1059 = 0
1764 try
1765 def F5(items : list)
1766 echo 'a'
1767 enddef
1768 catch /E1059:/
1769 let caught_1059 = 1
1770 endtry
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001771 eval caught_1059->assert_equal(1)
Bram Moolenaaree4e0c12020-04-06 21:35:05 +02001772endfunc
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001773
Bram Moolenaar015f4262020-05-05 21:25:22 +02001774func DelMe()
1775 echo 'DelMe'
1776endfunc
1777
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001778def Test_error_reporting()
1779 # comment lines at the start of the function
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001780 var lines =<< trim END
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001781 " comment
1782 def Func()
1783 # comment
1784 # comment
1785 invalid
1786 enddef
1787 defcompile
1788 END
Bram Moolenaar08052222020-09-14 17:04:31 +02001789 writefile(lines, 'Xdef')
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001790 try
1791 source Xdef
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001792 assert_report('should have failed')
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001793 catch /E476:/
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001794 v:exception->assert_match('Invalid command: invalid')
1795 v:throwpoint->assert_match(', line 3$')
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001796 endtry
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001797 delfunc! g:Func
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001798
1799 # comment lines after the start of the function
1800 lines =<< trim END
1801 " comment
1802 def Func()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001803 var x = 1234
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001804 # comment
1805 # comment
1806 invalid
1807 enddef
1808 defcompile
1809 END
Bram Moolenaar08052222020-09-14 17:04:31 +02001810 writefile(lines, 'Xdef')
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001811 try
1812 source Xdef
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001813 assert_report('should have failed')
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001814 catch /E476:/
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001815 v:exception->assert_match('Invalid command: invalid')
1816 v:throwpoint->assert_match(', line 4$')
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001817 endtry
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001818 delfunc! g:Func
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001819
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001820 lines =<< trim END
1821 vim9script
1822 def Func()
Bram Moolenaare0de1712020-12-02 17:36:54 +01001823 var db = {foo: 1, bar: 2}
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001824 # comment
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001825 var x = db.asdf
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001826 enddef
1827 defcompile
1828 Func()
1829 END
Bram Moolenaar08052222020-09-14 17:04:31 +02001830 writefile(lines, 'Xdef')
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001831 try
1832 source Xdef
1833 assert_report('should have failed')
1834 catch /E716:/
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001835 v:throwpoint->assert_match('_Func, line 3$')
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001836 endtry
Bram Moolenaar2d870f82020-12-05 13:41:01 +01001837 delfunc! g:Func
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001838
Bram Moolenaar08052222020-09-14 17:04:31 +02001839 delete('Xdef')
Bram Moolenaarbf8feb52020-08-08 14:26:31 +02001840enddef
1841
Bram Moolenaar015f4262020-05-05 21:25:22 +02001842def Test_deleted_function()
1843 CheckDefExecFailure([
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001844 'var RefMe: func = function("g:DelMe")',
Bram Moolenaar015f4262020-05-05 21:25:22 +02001845 'delfunc g:DelMe',
1846 'echo RefMe()'], 'E117:')
1847enddef
1848
1849def Test_unknown_function()
1850 CheckDefExecFailure([
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001851 'var Ref: func = function("NotExist")',
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001852 'delfunc g:NotExist'], 'E700:')
Bram Moolenaar015f4262020-05-05 21:25:22 +02001853enddef
1854
Bram Moolenaar328eac22021-01-07 19:23:08 +01001855def RefFunc(Ref: func(any): any): string
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001856 return Ref('more')
1857enddef
1858
1859def Test_closure_simple()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001860 var local = 'some '
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01001861 RefFunc((s) => local .. s)->assert_equal('some more')
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001862enddef
1863
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001864def MakeRef()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001865 var local = 'some '
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01001866 g:Ref = (s) => local .. s
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001867enddef
1868
1869def Test_closure_ref_after_return()
1870 MakeRef()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001871 g:Ref('thing')->assert_equal('some thing')
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001872 unlet g:Ref
1873enddef
1874
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001875def MakeTwoRefs()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001876 var local = ['some']
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01001877 g:Extend = (s) => local->add(s)
1878 g:Read = () => local
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001879enddef
1880
1881def Test_closure_two_refs()
1882 MakeTwoRefs()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001883 join(g:Read(), ' ')->assert_equal('some')
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001884 g:Extend('more')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001885 join(g:Read(), ' ')->assert_equal('some more')
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001886 g:Extend('even')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001887 join(g:Read(), ' ')->assert_equal('some more even')
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001888
1889 unlet g:Extend
1890 unlet g:Read
1891enddef
1892
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001893def ReadRef(Ref: func(): list<string>): string
1894 return join(Ref(), ' ')
1895enddef
1896
Bram Moolenaar5e654232020-09-16 15:22:00 +02001897def ExtendRef(Ref: func(string): list<string>, add: string)
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001898 Ref(add)
1899enddef
1900
1901def Test_closure_two_indirect_refs()
Bram Moolenaarf7779c62020-05-03 15:38:16 +02001902 MakeTwoRefs()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001903 ReadRef(g:Read)->assert_equal('some')
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001904 ExtendRef(g:Extend, 'more')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001905 ReadRef(g:Read)->assert_equal('some more')
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001906 ExtendRef(g:Extend, 'even')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001907 ReadRef(g:Read)->assert_equal('some more even')
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001908
1909 unlet g:Extend
1910 unlet g:Read
1911enddef
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001912
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001913def MakeArgRefs(theArg: string)
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001914 var local = 'loc_val'
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01001915 g:UseArg = (s) => theArg .. '/' .. local .. '/' .. s
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001916enddef
1917
1918def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001919 var local = 'the_loc'
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01001920 g:UseVararg = (s) => theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001921enddef
1922
1923def Test_closure_using_argument()
1924 MakeArgRefs('arg_val')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001925 g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val')
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001926
1927 MakeArgRefsVarargs('arg_val', 'one', 'two')
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001928 g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two')
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001929
1930 unlet g:UseArg
1931 unlet g:UseVararg
Bram Moolenaar44ec21c2021-02-12 21:50:57 +01001932
1933 var lines =<< trim END
1934 vim9script
1935 def Test(Fun: func(number): number): list<number>
1936 return map([1, 2, 3], (_, i) => Fun(i))
1937 enddef
1938 def Inc(nr: number): number
1939 return nr + 2
1940 enddef
1941 assert_equal([3, 4, 5], Test(Inc))
1942 END
1943 CheckScriptSuccess(lines)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001944enddef
1945
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +02001946def MakeGetAndAppendRefs()
1947 var local = 'a'
1948
1949 def Append(arg: string)
1950 local ..= arg
1951 enddef
1952 g:Append = Append
1953
1954 def Get(): string
1955 return local
1956 enddef
1957 g:Get = Get
1958enddef
1959
1960def Test_closure_append_get()
1961 MakeGetAndAppendRefs()
1962 g:Get()->assert_equal('a')
1963 g:Append('-b')
1964 g:Get()->assert_equal('a-b')
1965 g:Append('-c')
1966 g:Get()->assert_equal('a-b-c')
1967
1968 unlet g:Append
1969 unlet g:Get
1970enddef
Bram Moolenaarb68b3462020-05-06 21:06:30 +02001971
Bram Moolenaar04b12692020-05-04 23:24:44 +02001972def Test_nested_closure()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001973 var local = 'text'
Bram Moolenaar04b12692020-05-04 23:24:44 +02001974 def Closure(arg: string): string
1975 return local .. arg
1976 enddef
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001977 Closure('!!!')->assert_equal('text!!!')
Bram Moolenaar04b12692020-05-04 23:24:44 +02001978enddef
1979
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02001980func GetResult(Ref)
1981 return a:Ref('some')
1982endfunc
1983
1984def Test_call_closure_not_compiled()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001985 var text = 'text'
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01001986 g:Ref = (s) => s .. text
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02001987 GetResult(g:Ref)->assert_equal('sometext')
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02001988enddef
1989
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02001990def Test_double_closure_fails()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001991 var lines =<< trim END
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02001992 vim9script
1993 def Func()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001994 var name = 0
1995 for i in range(2)
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01001996 timer_start(0, () => name)
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02001997 endfor
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02001998 enddef
1999 Func()
2000 END
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02002001 CheckScriptSuccess(lines)
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02002002enddef
2003
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +02002004def Test_nested_closure_used()
2005 var lines =<< trim END
2006 vim9script
2007 def Func()
2008 var x = 'hello'
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01002009 var Closure = () => x
2010 g:Myclosure = () => Closure()
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +02002011 enddef
2012 Func()
2013 assert_equal('hello', g:Myclosure())
2014 END
2015 CheckScriptSuccess(lines)
2016enddef
Bram Moolenaar0876c782020-10-07 19:08:04 +02002017
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02002018def Test_nested_closure_fails()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02002019 var lines =<< trim END
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02002020 vim9script
2021 def FuncA()
2022 FuncB(0)
2023 enddef
2024 def FuncB(n: number): list<string>
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01002025 return map([0], (_, v) => n)
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02002026 enddef
2027 FuncA()
2028 END
2029 CheckScriptFailure(lines, 'E1012:')
2030enddef
2031
Bram Moolenaarf112f302020-12-20 17:47:52 +01002032def Test_global_closure()
2033 var lines =<< trim END
2034 vim9script
2035 def ReverseEveryNLines(n: number, line1: number, line2: number)
2036 var mods = 'sil keepj keepp lockm '
2037 var range = ':' .. line1 .. ',' .. line2
2038 def g:Offset(): number
2039 var offset = (line('.') - line1 + 1) % n
2040 return offset != 0 ? offset : n
2041 enddef
2042 exe mods .. range .. 'g/^/exe "m .-" .. g:Offset()'
2043 enddef
2044
2045 new
2046 repeat(['aaa', 'bbb', 'ccc'], 3)->setline(1)
2047 ReverseEveryNLines(3, 1, 9)
2048 END
2049 CheckScriptSuccess(lines)
2050 var expected = repeat(['ccc', 'bbb', 'aaa'], 3)
2051 assert_equal(expected, getline(1, 9))
2052 bwipe!
2053enddef
2054
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01002055def Test_global_closure_called_directly()
2056 var lines =<< trim END
2057 vim9script
2058 def Outer()
2059 var x = 1
2060 def g:Inner()
2061 var y = x
2062 x += 1
2063 assert_equal(1, y)
2064 enddef
2065 g:Inner()
2066 assert_equal(2, x)
2067 enddef
2068 Outer()
2069 END
2070 CheckScriptSuccess(lines)
2071 delfunc g:Inner
2072enddef
2073
Bram Moolenaar34c54eb2020-11-25 19:15:19 +01002074def Test_failure_in_called_function()
2075 # this was using the frame index as the return value
2076 var lines =<< trim END
2077 vim9script
2078 au TerminalWinOpen * eval [][0]
2079 def PopupTerm(a: any)
2080 # make sure typvals on stack are string
2081 ['a', 'b', 'c', 'd', 'e', 'f', 'g']->join()
2082 FireEvent()
2083 enddef
2084 def FireEvent()
2085 do TerminalWinOpen
2086 enddef
2087 # use try/catch to make eval fail
2088 try
2089 call PopupTerm(0)
2090 catch
2091 endtry
2092 au! TerminalWinOpen
2093 END
2094 CheckScriptSuccess(lines)
2095enddef
2096
Bram Moolenaar5366e1a2020-10-01 13:01:34 +02002097def Test_nested_lambda()
2098 var lines =<< trim END
2099 vim9script
2100 def Func()
2101 var x = 4
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01002102 var Lambda1 = () => 7
2103 var Lambda2 = () => [Lambda1(), x]
Bram Moolenaar5366e1a2020-10-01 13:01:34 +02002104 var res = Lambda2()
2105 assert_equal([7, 4], res)
2106 enddef
2107 Func()
2108 END
2109 CheckScriptSuccess(lines)
2110enddef
2111
Bram Moolenaar074f84c2021-05-18 11:47:44 +02002112def Test_nested_inline_lambda()
2113 # TODO: use the "text" argument
2114 var lines =<< trim END
2115 vim9script
2116 def F(text: string): func(string): func(string): string
2117 return (arg: string): func(string): string => ((sep: string): string => {
2118 return sep .. arg
2119 })
2120 enddef
2121 assert_equal('--there', F('unused')('there')('--'))
2122 END
2123 CheckScriptSuccess(lines)
2124enddef
2125
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01002126def Shadowed(): list<number>
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01002127 var FuncList: list<func: number> = [() => 42]
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01002128 return FuncList->mapnew((_, Shadowed) => Shadowed())
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01002129enddef
2130
2131def Test_lambda_arg_shadows_func()
2132 assert_equal([42], Shadowed())
2133enddef
2134
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002135def Line_continuation_in_def(dir: string = ''): string
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02002136 var path: string = empty(dir)
2137 \ ? 'empty'
2138 \ : 'full'
2139 return path
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002140enddef
2141
2142def Test_line_continuation_in_def()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02002143 Line_continuation_in_def('.')->assert_equal('full')
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002144enddef
2145
Bram Moolenaar2ea95b62020-11-19 21:47:56 +01002146def Test_script_var_in_lambda()
2147 var lines =<< trim END
2148 vim9script
2149 var script = 'test'
Bram Moolenaarbb8a7ce2021-04-10 20:10:26 +02002150 assert_equal(['test'], map(['one'], (_, _) => script))
Bram Moolenaar2ea95b62020-11-19 21:47:56 +01002151 END
2152 CheckScriptSuccess(lines)
2153enddef
2154
Bram Moolenaar5e654232020-09-16 15:22:00 +02002155def Line_continuation_in_lambda(): list<string>
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02002156 var x = range(97, 100)
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01002157 ->mapnew((_, v) => nr2char(v)
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01002158 ->toupper())
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002159 ->reverse()
2160 return x
2161enddef
2162
2163def Test_line_continuation_in_lambda()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02002164 Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
Bram Moolenaarf898f7c2021-01-16 18:09:52 +01002165
2166 var lines =<< trim END
2167 vim9script
2168 var res = [{n: 1, m: 2, s: 'xxx'}]
2169 ->mapnew((_, v: dict<any>): string => printf('%d:%d:%s',
2170 v.n,
2171 v.m,
2172 substitute(v.s, '.*', 'yyy', '')
2173 ))
2174 assert_equal(['1:2:yyy'], res)
2175 END
2176 CheckScriptSuccess(lines)
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002177enddef
2178
Bram Moolenaarb6571982021-01-08 22:24:19 +01002179def Test_list_lambda()
2180 timer_start(1000, (_) => 0)
2181 var body = execute(timer_info()[0].callback
2182 ->string()
2183 ->substitute("('", ' ', '')
2184 ->substitute("')", '', '')
2185 ->substitute('function\zs', ' ', ''))
Bram Moolenaar767034c2021-04-09 17:24:52 +02002186 assert_match('def <lambda>\d\+(_: any): number\n1 return 0\n enddef', body)
Bram Moolenaarb6571982021-01-08 22:24:19 +01002187enddef
2188
Bram Moolenaar96cf4ba2021-04-24 14:15:41 +02002189def Test_legacy_lambda()
2190 legacy echo {x -> 'hello ' .. x}('foo')
Bram Moolenaardc4c2302021-04-25 13:54:42 +02002191
Bram Moolenaar96cf4ba2021-04-24 14:15:41 +02002192 var lines =<< trim END
2193 echo {x -> 'hello ' .. x}('foo')
2194 END
2195 CheckDefAndScriptFailure(lines, 'E720:')
Bram Moolenaardc4c2302021-04-25 13:54:42 +02002196
2197 lines =<< trim END
2198 vim9script
2199 def Func()
2200 echo (() => 'no error')()
2201 enddef
2202 legacy call s:Func()
2203 END
2204 CheckScriptSuccess(lines)
Bram Moolenaar96cf4ba2021-04-24 14:15:41 +02002205enddef
2206
Bram Moolenaarab360522021-01-10 14:02:28 +01002207def DoFilterThis(a: string): list<string>
2208 # closure nested inside another closure using argument
2209 var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0)
2210 return ['x', 'y', 'a', 'x2', 'c']->Filter()
2211enddef
2212
2213def Test_nested_closure_using_argument()
2214 assert_equal(['x', 'x2'], DoFilterThis('x'))
2215enddef
2216
Bram Moolenaar0186e582021-01-10 18:33:11 +01002217def Test_triple_nested_closure()
2218 var what = 'x'
2219 var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0
2220 var Filter = (l) => filter(l, (_, v) => Match(v, what))
2221 assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter())
2222enddef
2223
Bram Moolenaar8f510af2020-07-05 18:48:23 +02002224func Test_silent_echo()
Bram Moolenaar47e7d702020-07-05 18:18:42 +02002225 CheckScreendump
2226
2227 let lines =<< trim END
2228 vim9script
2229 def EchoNothing()
2230 silent echo ''
2231 enddef
2232 defcompile
2233 END
Bram Moolenaar8f510af2020-07-05 18:48:23 +02002234 call writefile(lines, 'XTest_silent_echo')
Bram Moolenaar47e7d702020-07-05 18:18:42 +02002235
2236 " Check that the balloon shows up after a mouse move
2237 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
Bram Moolenaar8f510af2020-07-05 18:48:23 +02002238 call term_sendkeys(buf, ":abc")
Bram Moolenaar47e7d702020-07-05 18:18:42 +02002239 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
2240
2241 " clean up
2242 call StopVimInTerminal(buf)
2243 call delete('XTest_silent_echo')
Bram Moolenaar8f510af2020-07-05 18:48:23 +02002244endfunc
Bram Moolenaar47e7d702020-07-05 18:18:42 +02002245
Bram Moolenaar171fb922020-10-28 16:54:47 +01002246def SilentlyError()
2247 execute('silent! invalid')
2248 g:did_it = 'yes'
2249enddef
2250
Bram Moolenaar28ee8922020-10-28 20:20:00 +01002251func UserError()
2252 silent! invalid
2253endfunc
2254
2255def SilentlyUserError()
2256 UserError()
2257 g:did_it = 'yes'
2258enddef
Bram Moolenaar171fb922020-10-28 16:54:47 +01002259
2260" This can't be a :def function, because the assert would not be reached.
Bram Moolenaar171fb922020-10-28 16:54:47 +01002261func Test_ignore_silent_error()
2262 let g:did_it = 'no'
2263 call SilentlyError()
2264 call assert_equal('yes', g:did_it)
2265
Bram Moolenaar28ee8922020-10-28 20:20:00 +01002266 let g:did_it = 'no'
2267 call SilentlyUserError()
2268 call assert_equal('yes', g:did_it)
Bram Moolenaar171fb922020-10-28 16:54:47 +01002269
2270 unlet g:did_it
2271endfunc
2272
Bram Moolenaarcd030c42020-10-30 21:49:40 +01002273def Test_ignore_silent_error_in_filter()
2274 var lines =<< trim END
2275 vim9script
2276 def Filter(winid: number, key: string): bool
2277 if key == 'o'
2278 silent! eval [][0]
2279 return true
2280 endif
2281 return popup_filter_menu(winid, key)
2282 enddef
2283
Bram Moolenaare0de1712020-12-02 17:36:54 +01002284 popup_create('popup', {filter: Filter})
Bram Moolenaarcd030c42020-10-30 21:49:40 +01002285 feedkeys("o\r", 'xnt')
2286 END
2287 CheckScriptSuccess(lines)
2288enddef
2289
Bram Moolenaar4b9bd692020-09-05 21:57:53 +02002290def Fibonacci(n: number): number
2291 if n < 2
2292 return n
2293 else
2294 return Fibonacci(n - 1) + Fibonacci(n - 2)
2295 endif
2296enddef
2297
Bram Moolenaar985116a2020-07-12 17:31:09 +02002298def Test_recursive_call()
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02002299 Fibonacci(20)->assert_equal(6765)
Bram Moolenaar985116a2020-07-12 17:31:09 +02002300enddef
2301
Bram Moolenaar08f7a412020-07-13 20:41:08 +02002302def TreeWalk(dir: string): list<any>
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01002303 return readdir(dir)->mapnew((_, val) =>
Bram Moolenaar08f7a412020-07-13 20:41:08 +02002304 fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
Bram Moolenaar2bede172020-11-19 18:53:18 +01002305 ? {[val]: TreeWalk(dir .. '/' .. val)}
Bram Moolenaar08f7a412020-07-13 20:41:08 +02002306 : val
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01002307 )
Bram Moolenaar08f7a412020-07-13 20:41:08 +02002308enddef
2309
2310def Test_closure_in_map()
2311 mkdir('XclosureDir/tdir', 'p')
2312 writefile(['111'], 'XclosureDir/file1')
2313 writefile(['222'], 'XclosureDir/file2')
2314 writefile(['333'], 'XclosureDir/tdir/file3')
2315
Bram Moolenaare0de1712020-12-02 17:36:54 +01002316 TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}])
Bram Moolenaar08f7a412020-07-13 20:41:08 +02002317
2318 delete('XclosureDir', 'rf')
2319enddef
2320
Bram Moolenaar7b5d5442020-10-04 13:42:34 +02002321def Test_invalid_function_name()
2322 var lines =<< trim END
2323 vim9script
2324 def s: list<string>
2325 END
2326 CheckScriptFailure(lines, 'E129:')
2327
2328 lines =<< trim END
2329 vim9script
2330 def g: list<string>
2331 END
2332 CheckScriptFailure(lines, 'E129:')
2333
2334 lines =<< trim END
2335 vim9script
2336 def <SID>: list<string>
2337 END
2338 CheckScriptFailure(lines, 'E884:')
2339
2340 lines =<< trim END
2341 vim9script
2342 def F list<string>
2343 END
2344 CheckScriptFailure(lines, 'E488:')
2345enddef
2346
Bram Moolenaara90afb92020-07-15 22:38:56 +02002347def Test_partial_call()
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02002348 var Xsetlist = function('setloclist', [0])
Bram Moolenaare0de1712020-12-02 17:36:54 +01002349 Xsetlist([], ' ', {title: 'test'})
2350 getloclist(0, {title: 1})->assert_equal({title: 'test'})
Bram Moolenaara90afb92020-07-15 22:38:56 +02002351
2352 Xsetlist = function('setloclist', [0, [], ' '])
Bram Moolenaare0de1712020-12-02 17:36:54 +01002353 Xsetlist({title: 'test'})
2354 getloclist(0, {title: 1})->assert_equal({title: 'test'})
Bram Moolenaara90afb92020-07-15 22:38:56 +02002355
2356 Xsetlist = function('setqflist')
Bram Moolenaare0de1712020-12-02 17:36:54 +01002357 Xsetlist([], ' ', {title: 'test'})
2358 getqflist({title: 1})->assert_equal({title: 'test'})
Bram Moolenaara90afb92020-07-15 22:38:56 +02002359
2360 Xsetlist = function('setqflist', [[], ' '])
Bram Moolenaare0de1712020-12-02 17:36:54 +01002361 Xsetlist({title: 'test'})
2362 getqflist({title: 1})->assert_equal({title: 'test'})
Bram Moolenaar6abd3dc2020-10-04 14:17:32 +02002363
2364 var Len: func: number = function('len', ['word'])
2365 assert_equal(4, Len())
Bram Moolenaara90afb92020-07-15 22:38:56 +02002366enddef
2367
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002368def Test_cmd_modifier()
2369 tab echo '0'
Bram Moolenaard2c61702020-09-06 15:58:36 +02002370 CheckDefFailure(['5tab echo 3'], 'E16:')
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002371enddef
2372
2373def Test_restore_modifiers()
2374 # check that when compiling a :def function command modifiers are not messed
2375 # up.
Bram Moolenaar7a9cbca2020-09-27 22:47:05 +02002376 var lines =<< trim END
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002377 vim9script
2378 set eventignore=
2379 autocmd QuickFixCmdPost * copen
2380 def AutocmdsDisabled()
Bram Moolenaar6cf7e3b2020-10-28 14:31:16 +01002381 eval 0
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002382 enddef
2383 func Func()
2384 noautocmd call s:AutocmdsDisabled()
2385 let g:ei_after = &eventignore
2386 endfunc
2387 Func()
2388 END
2389 CheckScriptSuccess(lines)
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02002390 g:ei_after->assert_equal('')
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002391enddef
2392
Bram Moolenaardfa3d552020-09-10 22:05:08 +02002393def StackTop()
2394 eval 1
2395 eval 2
2396 # call not on fourth line
2397 StackBot()
2398enddef
2399
2400def StackBot()
2401 # throw an error
2402 eval [][0]
2403enddef
2404
2405def Test_callstack_def()
2406 try
2407 StackTop()
2408 catch
Bram Moolenaarc0c71e92020-09-11 19:09:48 +02002409 v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2')
Bram Moolenaardfa3d552020-09-10 22:05:08 +02002410 endtry
2411enddef
2412
Bram Moolenaare8211a32020-10-09 22:04:29 +02002413" Re-using spot for variable used in block
2414def Test_block_scoped_var()
2415 var lines =<< trim END
2416 vim9script
2417 def Func()
2418 var x = ['a', 'b', 'c']
2419 if 1
2420 var y = 'x'
Bram Moolenaarbb8a7ce2021-04-10 20:10:26 +02002421 map(x, (_, _) => y)
Bram Moolenaare8211a32020-10-09 22:04:29 +02002422 endif
2423 var z = x
2424 assert_equal(['x', 'x', 'x'], z)
2425 enddef
2426 Func()
2427 END
2428 CheckScriptSuccess(lines)
2429enddef
2430
Bram Moolenaareeece9e2020-11-20 19:26:48 +01002431def Test_reset_did_emsg()
2432 var lines =<< trim END
2433 @s = 'blah'
2434 au BufWinLeave * #
2435 def Func()
2436 var winid = popup_create('popup', {})
2437 exe '*s'
2438 popup_close(winid)
2439 enddef
2440 Func()
2441 END
2442 CheckScriptFailure(lines, 'E492:', 8)
Bram Moolenaar2d870f82020-12-05 13:41:01 +01002443 delfunc! g:Func
Bram Moolenaareeece9e2020-11-20 19:26:48 +01002444enddef
2445
Bram Moolenaar57f799e2020-12-12 20:42:19 +01002446def Test_did_emsg_reset()
2447 # executing an autocommand resets did_emsg, this should not result in a
2448 # builtin function considered failing
2449 var lines =<< trim END
2450 vim9script
2451 au BufWinLeave * #
2452 def Func()
Bram Moolenaar767034c2021-04-09 17:24:52 +02002453 popup_menu('', {callback: (a, b) => popup_create('', {})->popup_close()})
Bram Moolenaar57f799e2020-12-12 20:42:19 +01002454 eval [][0]
2455 enddef
2456 nno <F3> <cmd>call <sid>Func()<cr>
2457 feedkeys("\<F3>\e", 'xt')
2458 END
2459 writefile(lines, 'XemsgReset')
2460 assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2)
2461 delete('XemsgReset')
2462 nunmap <F3>
2463 au! BufWinLeave
2464enddef
2465
Bram Moolenaar56602ba2020-12-05 21:22:08 +01002466def Test_abort_with_silent_call()
2467 var lines =<< trim END
2468 vim9script
2469 g:result = 'none'
2470 def Func()
2471 g:result += 3
2472 g:result = 'yes'
2473 enddef
2474 # error is silenced, but function aborts on error
2475 silent! Func()
2476 assert_equal('none', g:result)
2477 unlet g:result
2478 END
2479 CheckScriptSuccess(lines)
2480enddef
2481
Bram Moolenaarf665e972020-12-05 19:17:16 +01002482def Test_continues_with_silent_error()
2483 var lines =<< trim END
2484 vim9script
2485 g:result = 'none'
2486 def Func()
2487 silent! g:result += 3
2488 g:result = 'yes'
2489 enddef
2490 # error is silenced, function does not abort
2491 Func()
2492 assert_equal('yes', g:result)
2493 unlet g:result
2494 END
2495 CheckScriptSuccess(lines)
2496enddef
2497
Bram Moolenaaraf0df472020-12-02 20:51:22 +01002498def Test_abort_even_with_silent()
2499 var lines =<< trim END
2500 vim9script
2501 g:result = 'none'
2502 def Func()
2503 eval {-> ''}() .. '' .. {}['X']
2504 g:result = 'yes'
2505 enddef
Bram Moolenaarf665e972020-12-05 19:17:16 +01002506 silent! Func()
Bram Moolenaaraf0df472020-12-02 20:51:22 +01002507 assert_equal('none', g:result)
Bram Moolenaar4029cab2020-12-05 18:13:27 +01002508 unlet g:result
2509 END
2510 CheckScriptSuccess(lines)
2511enddef
2512
Bram Moolenaarf665e972020-12-05 19:17:16 +01002513def Test_cmdmod_silent_restored()
2514 var lines =<< trim END
2515 vim9script
2516 def Func()
2517 g:result = 'none'
2518 silent! g:result += 3
2519 g:result = 'none'
2520 g:result += 3
2521 enddef
2522 Func()
2523 END
2524 # can't use CheckScriptFailure, it ignores the :silent!
2525 var fname = 'Xdefsilent'
2526 writefile(lines, fname)
2527 var caught = 'no'
2528 try
2529 exe 'source ' .. fname
2530 catch /E1030:/
2531 caught = 'yes'
2532 assert_match('Func, line 4', v:throwpoint)
2533 endtry
2534 assert_equal('yes', caught)
2535 delete(fname)
2536enddef
2537
Bram Moolenaar2fecb532021-03-24 22:00:56 +01002538def Test_cmdmod_silent_nested()
2539 var lines =<< trim END
2540 vim9script
2541 var result = ''
2542
2543 def Error()
2544 result ..= 'Eb'
2545 eval [][0]
2546 result ..= 'Ea'
2547 enddef
2548
2549 def Crash()
2550 result ..= 'Cb'
2551 sil! Error()
2552 result ..= 'Ca'
2553 enddef
2554
2555 Crash()
2556 assert_equal('CbEbEaCa', result)
2557 END
2558 CheckScriptSuccess(lines)
2559enddef
2560
Bram Moolenaar4029cab2020-12-05 18:13:27 +01002561def Test_dict_member_with_silent()
2562 var lines =<< trim END
2563 vim9script
2564 g:result = 'none'
2565 var d: dict<any>
2566 def Func()
2567 try
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01002568 g:result = map([], (_, v) => ({}[v]))->join() .. d['']
Bram Moolenaar4029cab2020-12-05 18:13:27 +01002569 catch
2570 endtry
2571 enddef
2572 silent! Func()
2573 assert_equal('0', g:result)
2574 unlet g:result
Bram Moolenaaraf0df472020-12-02 20:51:22 +01002575 END
2576 CheckScriptSuccess(lines)
2577enddef
2578
Bram Moolenaarf9041332021-01-21 19:41:16 +01002579def Test_skip_cmds_with_silent()
2580 var lines =<< trim END
2581 vim9script
2582
2583 def Func(b: bool)
2584 Crash()
2585 enddef
2586
2587 def Crash()
2588 sil! :/not found/d _
2589 sil! :/not found/put _
2590 enddef
2591
2592 Func(true)
2593 END
2594 CheckScriptSuccess(lines)
2595enddef
2596
Bram Moolenaar5b3d1bb2020-12-22 12:20:08 +01002597def Test_opfunc()
2598 nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@
2599 def g:Opfunc(_: any): string
2600 setline(1, 'ASDF')
2601 return ''
2602 enddef
2603 new
2604 setline(1, 'asdf')
2605 feedkeys("\<F3>$", 'x')
2606 assert_equal('ASDF', getline(1))
2607
2608 bwipe!
2609 nunmap <F3>
2610enddef
2611
Bram Moolenaar077a4232020-12-22 18:33:27 +01002612" this was crashing on exit
2613def Test_nested_lambda_in_closure()
2614 var lines =<< trim END
2615 vim9script
Bram Moolenaar227c58a2021-04-28 20:40:44 +02002616 command WriteDone writefile(['Done'], 'XnestedDone')
Bram Moolenaar077a4232020-12-22 18:33:27 +01002617 def Outer()
2618 def g:Inner()
2619 echo map([1, 2, 3], {_, v -> v + 1})
2620 enddef
2621 g:Inner()
2622 enddef
2623 defcompile
Bram Moolenaar227c58a2021-04-28 20:40:44 +02002624 # not reached
Bram Moolenaar077a4232020-12-22 18:33:27 +01002625 END
Bram Moolenaar227c58a2021-04-28 20:40:44 +02002626 if !RunVim([], lines, '--clean -c WriteDone -c quit')
Bram Moolenaar077a4232020-12-22 18:33:27 +01002627 return
2628 endif
2629 assert_equal(['Done'], readfile('XnestedDone'))
2630 delete('XnestedDone')
2631enddef
2632
Bram Moolenaar04947cc2021-03-06 19:26:46 +01002633def Test_check_func_arg_types()
2634 var lines =<< trim END
2635 vim9script
2636 def F1(x: string): string
2637 return x
2638 enddef
2639
2640 def F2(x: number): number
2641 return x + 1
2642 enddef
2643
2644 def G(g: func): dict<func>
2645 return {f: g}
2646 enddef
2647
2648 def H(d: dict<func>): string
2649 return d.f('a')
2650 enddef
2651 END
2652
2653 CheckScriptSuccess(lines + ['echo H(G(F1))'])
2654 CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:')
2655enddef
2656
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02002657def Test_compile_error()
2658 var lines =<< trim END
2659 def g:Broken()
2660 echo 'a' + {}
2661 enddef
2662 call g:Broken()
2663 END
2664 # First call: compilation error
2665 CheckScriptFailure(lines, 'E1051: Wrong argument type for +')
2666
2667 # Second call won't try compiling again
2668 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken')
Bram Moolenaar599410c2021-04-10 14:03:43 +02002669 delfunc g:Broken
2670
2671 # No error when compiling with :silent!
2672 lines =<< trim END
2673 def g:Broken()
2674 echo 'a' + []
2675 enddef
2676 silent! defcompile
2677 END
2678 CheckScriptSuccess(lines)
2679
2680 # Calling the function won't try compiling again
2681 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken')
2682 delfunc g:Broken
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02002683enddef
2684
Bram Moolenaar962c43b2021-04-10 17:18:09 +02002685def Test_ignored_argument()
2686 var lines =<< trim END
2687 vim9script
2688 def Ignore(_, _): string
2689 return 'yes'
2690 enddef
2691 assert_equal('yes', Ignore(1, 2))
2692
2693 func Ok(_)
2694 return a:_
2695 endfunc
2696 assert_equal('ok', Ok('ok'))
2697
2698 func Oktoo()
2699 let _ = 'too'
2700 return _
2701 endfunc
2702 assert_equal('too', Oktoo())
Bram Moolenaarda479c72021-04-10 21:01:38 +02002703
2704 assert_equal([[1], [2], [3]], range(3)->mapnew((_, v) => [v]->map((_, w) => w + 1)))
Bram Moolenaar962c43b2021-04-10 17:18:09 +02002705 END
2706 CheckScriptSuccess(lines)
2707
2708 lines =<< trim END
2709 def Ignore(_: string): string
2710 return _
2711 enddef
2712 defcompile
2713 END
2714 CheckScriptFailure(lines, 'E1181:', 1)
2715
2716 lines =<< trim END
2717 var _ = 1
2718 END
2719 CheckDefAndScriptFailure(lines, 'E1181:', 1)
2720enddef
2721
Bram Moolenaarbb8a7ce2021-04-10 20:10:26 +02002722def Test_too_many_arguments()
2723 var lines =<< trim END
2724 echo [0, 1, 2]->map(() => 123)
2725 END
2726 CheckDefExecAndScriptFailure(lines, 'E1106: 2 arguments too many', 1)
2727
2728 lines =<< trim END
2729 echo [0, 1, 2]->map((_) => 123)
2730 END
2731 CheckDefExecAndScriptFailure(lines, 'E1106: One argument too many', 1)
2732enddef
Bram Moolenaar077a4232020-12-22 18:33:27 +01002733
Bram Moolenaara6aa1642021-04-23 19:32:23 +02002734def Test_closing_brace_at_start_of_line()
2735 var lines =<< trim END
2736 def Func()
2737 enddef
2738 Func(
2739 )
2740 END
2741 call CheckDefAndScriptSuccess(lines)
2742enddef
2743
Bram Moolenaarf7779c62020-05-03 15:38:16 +02002744
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002745" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker