blob: e566a9e64cde17d406e8eef39f659f1672100661 [file] [log] [blame]
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001" Test Vim9 classes
2
3source check.vim
4import './vim9.vim' as v9
5
6def Test_class_basic()
7 var lines =<< trim END
8 class NotWorking
9 endclass
10 END
11 v9.CheckScriptFailure(lines, 'E1316:')
12
13 lines =<< trim END
14 vim9script
15 class notWorking
16 endclass
17 END
18 v9.CheckScriptFailure(lines, 'E1314:')
19
20 lines =<< trim END
21 vim9script
22 class Not@working
23 endclass
24 END
25 v9.CheckScriptFailure(lines, 'E1315:')
26
27 lines =<< trim END
28 vim9script
29 abstract noclass Something
30 endclass
31 END
32 v9.CheckScriptFailure(lines, 'E475:')
33
34 lines =<< trim END
35 vim9script
36 abstract classy Something
37 endclass
38 END
39 v9.CheckScriptFailure(lines, 'E475:')
40
41 lines =<< trim END
42 vim9script
43 class Something
44 endcl
45 END
46 v9.CheckScriptFailure(lines, 'E1065:')
47
48 lines =<< trim END
49 vim9script
50 class Something
Bram Moolenaar94722c52023-01-28 19:19:03 +000051 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000052 END
53 v9.CheckScriptFailure(lines, 'E488:')
54
55 lines =<< trim END
56 vim9script
57 class Something
58 endclass | echo 'done'
59 END
60 v9.CheckScriptFailure(lines, 'E488:')
61
62 lines =<< trim END
63 vim9script
64 class Something
65 this
66 endclass
67 END
68 v9.CheckScriptFailure(lines, 'E1317:')
69
70 lines =<< trim END
71 vim9script
72 class Something
73 this.
74 endclass
75 END
76 v9.CheckScriptFailure(lines, 'E1317:')
77
78 lines =<< trim END
79 vim9script
80 class Something
81 this .count
82 endclass
83 END
84 v9.CheckScriptFailure(lines, 'E1317:')
85
86 lines =<< trim END
87 vim9script
88 class Something
89 this. count
90 endclass
91 END
92 v9.CheckScriptFailure(lines, 'E1317:')
93
94 lines =<< trim END
95 vim9script
96 class Something
97 this.count: number
98 that.count
99 endclass
100 END
101 v9.CheckScriptFailure(lines, 'E1318: Not a valid command in a class: that.count')
102
103 lines =<< trim END
104 vim9script
105 class Something
106 this.count
107 endclass
108 END
109 v9.CheckScriptFailure(lines, 'E1022:')
110
111 lines =<< trim END
112 vim9script
113 class Something
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000114 def new()
115 this.state = 0
116 enddef
117 endclass
118 var obj = Something.new()
119 END
120 v9.CheckScriptFailure(lines, 'E1089:')
121
122 lines =<< trim END
123 vim9script
124 class Something
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000125 this.count : number
126 endclass
127 END
128 v9.CheckScriptFailure(lines, 'E1059:')
129
130 lines =<< trim END
131 vim9script
132 class Something
133 this.count:number
134 endclass
135 END
136 v9.CheckScriptFailure(lines, 'E1069:')
137
138 lines =<< trim END
139 vim9script
140
141 class TextPosition
142 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000143 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000144
Bram Moolenaar418b5472022-12-20 13:38:22 +0000145 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000146 def ToString(): string
147 return $'({this.lnum}, {this.col})'
148 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000149 endclass
150
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000151 # use the automatically generated new() method
152 var pos = TextPosition.new(2, 12)
153 assert_equal(2, pos.lnum)
154 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000155
156 # call an object method
157 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000158
159 assert_equal(v:t_class, type(TextPosition))
160 assert_equal(v:t_object, type(pos))
161 assert_equal('class<TextPosition>', typename(TextPosition))
162 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000163 END
164 v9.CheckScriptSuccess(lines)
165enddef
166
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000167def Test_class_defined_twice()
168 # class defined twice should fail
169 var lines =<< trim END
170 vim9script
171 class There
172 endclass
173 class There
174 endclass
175 END
176 v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "There"')
177
178 # one class, reload same script twice is OK
179 lines =<< trim END
180 vim9script
181 class There
182 endclass
183 END
184 writefile(lines, 'XclassTwice.vim', 'D')
185 source XclassTwice.vim
186 source XclassTwice.vim
187enddef
188
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000189def Test_returning_null_object()
190 # this was causing an internal error
191 var lines =<< trim END
192 vim9script
193
194 class BufferList
195 def Current(): any
196 return null_object
197 enddef
198 endclass
199
200 var buffers = BufferList.new()
201 echo buffers.Current()
202 END
203 v9.CheckScriptSuccess(lines)
204enddef
205
Bram Moolenaard13dd302023-03-11 20:56:35 +0000206def Test_using_null_class()
207 var lines =<< trim END
208 @_ = null_class.member
209 END
210 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
211enddef
212
Bram Moolenaar657aea72023-01-27 13:16:19 +0000213def Test_class_interface_wrong_end()
214 var lines =<< trim END
215 vim9script
216 abstract class SomeName
217 this.member = 'text'
218 endinterface
219 END
220 v9.CheckScriptFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
221
222 lines =<< trim END
223 vim9script
224 export interface AnotherName
225 this.member: string
226 endclass
227 END
228 v9.CheckScriptFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
229enddef
230
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000231def Test_object_not_set()
232 var lines =<< trim END
233 vim9script
234
235 class State
236 this.value = 'xyz'
237 endclass
238
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000239 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000240 var db = {'xyz': 789}
241 echo db[state.value]
242 END
243 v9.CheckScriptFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000244
245 lines =<< trim END
246 vim9script
247
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000248 class Class
249 this.id: string
250 def Method1()
251 echo 'Method1' .. this.id
252 enddef
253 endclass
254
255 var obj: Class
256 def Func()
257 obj.Method1()
258 enddef
259 Func()
260 END
261 v9.CheckScriptFailure(lines, 'E1360:')
262
263 lines =<< trim END
264 vim9script
265
Bram Moolenaar0917e862023-02-18 14:42:44 +0000266 class Background
267 this.background = 'dark'
268 endclass
269
270 class Colorscheme
271 this._bg: Background
272
273 def GetBackground(): string
274 return this._bg.background
275 enddef
276 endclass
277
278 var bg: Background # UNINITIALIZED
279 echo Colorscheme.new(bg).GetBackground()
280 END
281 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Background> but got object<Unknown>')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000282
283 # TODO: this should not give an error but be handled at runtime
284 lines =<< trim END
285 vim9script
286
287 class Class
288 this.id: string
289 def Method1()
290 echo 'Method1' .. this.id
291 enddef
292 endclass
293
294 var obj = null_object
295 def Func()
296 obj.Method1()
297 enddef
298 Func()
299 END
300 v9.CheckScriptFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000301enddef
302
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000303def Test_class_member_initializer()
304 var lines =<< trim END
305 vim9script
306
307 class TextPosition
308 this.lnum: number = 1
309 this.col: number = 1
310
Bram Moolenaar418b5472022-12-20 13:38:22 +0000311 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000312 def new(lnum: number)
313 this.lnum = lnum
314 enddef
315 endclass
316
317 var pos = TextPosition.new(3)
318 assert_equal(3, pos.lnum)
319 assert_equal(1, pos.col)
320
321 var instr = execute('disassemble TextPosition.new')
322 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000323 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000324 '\d PUSHNR 1\_s*' ..
325 '\d STORE_THIS 0\_s*' ..
326 '\d PUSHNR 1\_s*' ..
327 '\d STORE_THIS 1\_s*' ..
328 'this.lnum = lnum\_s*' ..
329 '\d LOAD arg\[-1]\_s*' ..
330 '\d PUSHNR 0\_s*' ..
331 '\d LOAD $0\_s*' ..
332 '\d\+ STOREINDEX object\_s*' ..
333 '\d\+ RETURN object.*',
334 instr)
335 END
336 v9.CheckScriptSuccess(lines)
337enddef
338
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000339def Test_member_any_used_as_object()
340 var lines =<< trim END
341 vim9script
342
343 class Inner
344 this.value: number = 0
345 endclass
346
347 class Outer
348 this.inner: any
349 endclass
350
351 def F(outer: Outer)
352 outer.inner.value = 1
353 enddef
354
355 var inner_obj = Inner.new(0)
356 var outer_obj = Outer.new(inner_obj)
357 F(outer_obj)
358 assert_equal(1, inner_obj.value)
359 END
360 v9.CheckScriptSuccess(lines)
361
362 lines =<< trim END
363 vim9script
364
365 class Inner
366 this.value: number = 0
367 endclass
368
369 class Outer
370 this.inner: Inner
371 endclass
372
373 def F(outer: Outer)
374 outer.inner.value = 1
375 enddef
376
377 def Test_assign_to_nested_typed_member()
378 var inner = Inner.new(0)
379 var outer = Outer.new(inner)
380 F(outer)
381 assert_equal(1, inner.value)
382 enddef
383
384 Test_assign_to_nested_typed_member()
385 END
386 v9.CheckScriptSuccess(lines)
387enddef
388
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000389def Test_assignment_with_operator()
390 var lines =<< trim END
391 vim9script
392
393 class Foo
394 this.x: number
395
396 def Add(n: number)
397 this.x += n
398 enddef
399 endclass
400
401 var f = Foo.new(3)
402 f.Add(17)
403 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100404
405 def AddToFoo(obj: Foo)
406 obj.x += 3
407 enddef
408
409 AddToFoo(f)
410 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000411 END
412 v9.CheckScriptSuccess(lines)
413enddef
414
Bram Moolenaarf4508042023-01-15 16:54:57 +0000415def Test_list_of_objects()
416 var lines =<< trim END
417 vim9script
418
419 class Foo
420 def Add()
421 enddef
422 endclass
423
424 def ProcessList(fooList: list<Foo>)
425 for foo in fooList
426 foo.Add()
427 endfor
428 enddef
429
430 var l: list<Foo> = [Foo.new()]
431 ProcessList(l)
432 END
433 v9.CheckScriptSuccess(lines)
434enddef
435
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000436def Test_expr_after_using_object()
437 var lines =<< trim END
438 vim9script
439
440 class Something
441 this.label: string = ''
442 endclass
443
444 def Foo(): Something
445 var v = Something.new()
446 echo 'in Foo(): ' .. typename(v)
447 return v
448 enddef
449
450 Foo()
451 END
452 v9.CheckScriptSuccess(lines)
453enddef
454
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000455def Test_class_default_new()
456 var lines =<< trim END
457 vim9script
458
459 class TextPosition
460 this.lnum: number = 1
461 this.col: number = 1
462 endclass
463
464 var pos = TextPosition.new()
465 assert_equal(1, pos.lnum)
466 assert_equal(1, pos.col)
467
468 pos = TextPosition.new(v:none, v:none)
469 assert_equal(1, pos.lnum)
470 assert_equal(1, pos.col)
471
472 pos = TextPosition.new(3, 22)
473 assert_equal(3, pos.lnum)
474 assert_equal(22, pos.col)
475
476 pos = TextPosition.new(v:none, 33)
477 assert_equal(1, pos.lnum)
478 assert_equal(33, pos.col)
479 END
480 v9.CheckScriptSuccess(lines)
481
482 lines =<< trim END
483 vim9script
484 class Person
485 this.name: string
486 this.age: number = 42
487 this.education: string = "unknown"
488
489 def new(this.name, this.age = v:none, this.education = v:none)
490 enddef
491 endclass
492
493 var piet = Person.new("Piet")
494 assert_equal("Piet", piet.name)
495 assert_equal(42, piet.age)
496 assert_equal("unknown", piet.education)
497
498 var chris = Person.new("Chris", 4, "none")
499 assert_equal("Chris", chris.name)
500 assert_equal(4, chris.age)
501 assert_equal("none", chris.education)
502 END
503 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000504
505 lines =<< trim END
506 vim9script
507 class Person
508 this.name: string
509 this.age: number = 42
510 this.education: string = "unknown"
511
512 def new(this.name, this.age = v:none, this.education = v:none)
513 enddef
514 endclass
515
516 var missing = Person.new()
517 END
518 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000519enddef
520
Bram Moolenaar74e12742022-12-13 21:14:28 +0000521def Test_class_object_member_inits()
522 var lines =<< trim END
523 vim9script
524 class TextPosition
525 this.lnum: number
526 this.col = 1
527 this.addcol: number = 2
528 endclass
529
530 var pos = TextPosition.new()
531 assert_equal(0, pos.lnum)
532 assert_equal(1, pos.col)
533 assert_equal(2, pos.addcol)
534 END
535 v9.CheckScriptSuccess(lines)
536
537 lines =<< trim END
538 vim9script
539 class TextPosition
540 this.lnum
541 this.col = 1
542 endclass
543 END
544 v9.CheckScriptFailure(lines, 'E1022:')
545
546 lines =<< trim END
547 vim9script
548 class TextPosition
549 this.lnum = v:none
550 this.col = 1
551 endclass
552 END
553 v9.CheckScriptFailure(lines, 'E1330:')
554enddef
555
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000556def Test_class_object_member_access()
557 var lines =<< trim END
558 vim9script
559 class Triple
560 this._one = 1
561 this.two = 2
562 public this.three = 3
563
564 def GetOne(): number
565 return this._one
566 enddef
567 endclass
568
569 var trip = Triple.new()
570 assert_equal(1, trip.GetOne())
571 assert_equal(2, trip.two)
572 assert_equal(3, trip.three)
573 assert_fails('echo trip._one', 'E1333')
574
575 assert_fails('trip._one = 11', 'E1333')
576 assert_fails('trip.two = 22', 'E1335')
577 trip.three = 33
578 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000579
580 assert_fails('trip.four = 4', 'E1334')
581 END
582 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000583
584 lines =<< trim END
585 vim9script
586
587 class MyCar
588 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000589 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000590
591 def new(make_arg: string)
592 this.make = make_arg
593 enddef
594
595 def GetMake(): string
596 return $"make = {this.make}"
597 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000598 def GetAge(): number
599 return this.age
600 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000601 endclass
602
603 var c = MyCar.new("abc")
604 assert_equal('make = abc', c.GetMake())
605
606 c = MyCar.new("def")
607 assert_equal('make = def', c.GetMake())
608
609 var c2 = MyCar.new("123")
610 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000611
612 def CheckCar()
613 assert_equal("make = def", c.GetMake())
614 assert_equal(5, c.GetAge())
615 enddef
616 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000617 END
618 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000619
620 lines =<< trim END
621 vim9script
622
623 class MyCar
624 this.make: string
625
626 def new(make_arg: string)
627 this.make = make_arg
628 enddef
629 endclass
630
631 var c = MyCar.new("abc")
632 var c = MyCar.new("def")
633 END
634 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000635
636 lines =<< trim END
637 vim9script
638
639 class Foo
640 this.x: list<number> = []
641
642 def Add(n: number): any
643 this.x->add(n)
644 return this
645 enddef
646 endclass
647
648 echo Foo.new().Add(1).Add(2).x
649 echo Foo.new().Add(1).Add(2)
650 .x
651 echo Foo.new().Add(1)
652 .Add(2).x
653 echo Foo.new()
654 .Add(1).Add(2).x
655 echo Foo.new()
656 .Add(1)
657 .Add(2)
658 .x
659 END
660 v9.CheckScriptSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +0000661enddef
662
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000663def Test_class_object_compare()
664 var class_lines =<< trim END
665 vim9script
666 class Item
667 this.nr = 0
668 this.name = 'xx'
669 endclass
670 END
671
672 # used at the script level and in a compiled function
673 var test_lines =<< trim END
674 var i1 = Item.new()
675 assert_equal(i1, i1)
676 assert_true(i1 is i1)
677 var i2 = Item.new()
678 assert_equal(i1, i2)
679 assert_false(i1 is i2)
680 var i3 = Item.new(0, 'xx')
681 assert_equal(i1, i3)
682
683 var io1 = Item.new(1, 'xx')
684 assert_notequal(i1, io1)
685 var io2 = Item.new(0, 'yy')
686 assert_notequal(i1, io2)
687 END
688
689 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000690 v9.CheckScriptSuccess(
691 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000692
693 for op in ['>', '>=', '<', '<=', '=~', '!~']
694 var op_lines = [
695 'var i1 = Item.new()',
696 'var i2 = Item.new()',
697 'echo i1 ' .. op .. ' i2',
698 ]
699 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000700 v9.CheckScriptFailure(class_lines
701 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000702 endfor
703enddef
704
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000705def Test_object_type()
706 var lines =<< trim END
707 vim9script
708
709 class One
710 this.one = 1
711 endclass
712 class Two
713 this.two = 2
714 endclass
715 class TwoMore extends Two
716 this.more = 9
717 endclass
718
719 var o: One = One.new()
720 var t: Two = Two.new()
721 var m: TwoMore = TwoMore.new()
722 var tm: Two = TwoMore.new()
723
724 t = m
725 END
726 v9.CheckScriptSuccess(lines)
727
728 lines =<< trim END
729 vim9script
730
731 class One
732 this.one = 1
733 endclass
734 class Two
735 this.two = 2
736 endclass
737
738 var o: One = Two.new()
739 END
740 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000741
742 lines =<< trim END
743 vim9script
744
745 interface One
746 def GetMember(): number
747 endinterface
748 class Two implements One
749 this.one = 1
750 def GetMember(): number
751 return this.one
752 enddef
753 endclass
754
755 var o: One = Two.new(5)
756 assert_equal(5, o.GetMember())
757 END
758 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +0000759
760 lines =<< trim END
761 vim9script
762
763 class Num
764 this.n: number = 0
765 endclass
766
767 def Ref(name: string): func(Num): Num
768 return (arg: Num): Num => {
769 return eval(name)(arg)
770 }
771 enddef
772
773 const Fn = Ref('Double')
774 var Double = (m: Num): Num => Num.new(m.n * 2)
775
776 echo Fn(Num.new(4))
777 END
778 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000779enddef
780
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000781def Test_class_member()
782 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +0000783 var lines =<< trim END
784 vim9script
785 class TextPos
786 this.lnum = 1
787 this.col = 1
788 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000789 static _secret = 7
790 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +0000791
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000792 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +0000793 counter += nr
794 enddef
795 endclass
796
797 assert_equal(0, TextPos.counter)
798 TextPos.AddToCounter(3)
799 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000800 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000801
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000802 def GetCounter(): number
803 return TextPos.counter
804 enddef
805 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +0000806
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000807 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000808 assert_fails('TextPos.counter = 5', 'E1335:')
809 assert_fails('TextPos.counter += 5', 'E1335:')
810
811 assert_fails('echo TextPos._secret', 'E1333:')
812 assert_fails('TextPos._secret = 8', 'E1333:')
813
814 assert_equal(42, TextPos.anybody)
815 TextPos.anybody = 12
816 assert_equal(12, TextPos.anybody)
817 TextPos.anybody += 5
818 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000819 END
820 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000821
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000822 # example in the help
823 lines =<< trim END
824 vim9script
825 class OtherThing
826 this.size: number
827 static totalSize: number
828
829 def new(this.size)
830 totalSize += this.size
831 enddef
832 endclass
833 assert_equal(0, OtherThing.totalSize)
834 var to3 = OtherThing.new(3)
835 assert_equal(3, OtherThing.totalSize)
836 var to7 = OtherThing.new(7)
837 assert_equal(10, OtherThing.totalSize)
838 END
839 v9.CheckScriptSuccess(lines)
840
Bram Moolenaar4e2406c2023-06-24 19:22:21 +0100841 # using static class member twice
842 lines =<< trim END
843 vim9script
844
845 class HTML
846 static author: string = 'John Doe'
847
848 static def MacroSubstitute(s: string): string
849 return substitute(s, '{{author}}', author, 'gi')
850 enddef
851 endclass
852
853 assert_equal('some text', HTML.MacroSubstitute('some text'))
854 assert_equal('some text', HTML.MacroSubstitute('some text'))
855 END
856 v9.CheckScriptSuccess(lines)
857
Bram Moolenaar62a69232023-01-24 15:07:04 +0000858 # access private member in lambda
859 lines =<< trim END
860 vim9script
861
862 class Foo
863 this._x: number = 0
864
865 def Add(n: number): number
866 const F = (): number => this._x + n
867 return F()
868 enddef
869 endclass
870
871 var foo = Foo.new()
872 assert_equal(5, foo.Add(5))
873 END
874 v9.CheckScriptSuccess(lines)
875
h-east2bd6a092023-05-19 19:01:17 +0100876 # access private member in lambda body
877 lines =<< trim END
878 vim9script
879
880 class Foo
881 this._x: number = 6
882
883 def Add(n: number): number
884 var Lam = () => {
885 this._x = this._x + n
886 }
887 Lam()
888 return this._x
889 enddef
890 endclass
891
892 var foo = Foo.new()
893 assert_equal(13, foo.Add(7))
894 END
895 v9.CheckScriptSuccess(lines)
896
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000897 # check shadowing
898 lines =<< trim END
899 vim9script
900
901 class Some
902 static count = 0
903 def Method(count: number)
904 echo count
905 enddef
906 endclass
907
908 var s = Some.new()
909 s.Method(7)
910 END
911 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
912
913 lines =<< trim END
914 vim9script
915
916 class Some
917 static count = 0
918 def Method(arg: number)
919 var count = 3
920 echo arg count
921 enddef
922 endclass
923
924 var s = Some.new()
925 s.Method(7)
926 END
927 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000928enddef
929
Bram Moolenaarcf760d52023-01-05 13:16:04 +0000930func Test_class_garbagecollect()
931 let lines =<< trim END
932 vim9script
933
934 class Point
935 this.p = [2, 3]
936 static pl = ['a', 'b']
937 static pd = {a: 'a', b: 'b'}
938 endclass
939
940 echo Point.pl Point.pd
941 call test_garbagecollect_now()
942 echo Point.pl Point.pd
943 END
944 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +0100945
946 let lines =<< trim END
947 vim9script
948
949 interface View
950 endinterface
951
952 class Widget
953 this.view: View
954 endclass
955
956 class MyView implements View
957 this.widget: Widget
958
959 def new()
960 # this will result in a circular reference to this object
961 this.widget = Widget.new(this)
962 enddef
963 endclass
964
965 var view = MyView.new()
966
967 # overwrite "view", will be garbage-collected next
968 view = MyView.new()
969 test_garbagecollect_now()
970 END
971 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +0000972endfunc
973
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000974def Test_class_function()
975 var lines =<< trim END
976 vim9script
977 class Value
978 this.value = 0
979 static objects = 0
980
981 def new(v: number)
982 this.value = v
983 ++objects
984 enddef
985
986 static def GetCount(): number
987 return objects
988 enddef
989 endclass
990
991 assert_equal(0, Value.GetCount())
992 var v1 = Value.new(2)
993 assert_equal(1, Value.GetCount())
994 var v2 = Value.new(7)
995 assert_equal(2, Value.GetCount())
996 END
997 v9.CheckScriptSuccess(lines)
998enddef
999
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001000def Test_class_defcompile()
1001 var lines =<< trim END
1002 vim9script
1003
1004 class C
1005 def Fo(i: number): string
1006 return i
1007 enddef
1008 endclass
1009
1010 defcompile C.Fo
1011 END
1012 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1013
1014 lines =<< trim END
1015 vim9script
1016
1017 class C
1018 static def Fc(): number
1019 return 'x'
1020 enddef
1021 endclass
1022
1023 defcompile C.Fc
1024 END
1025 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
1026enddef
1027
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001028def Test_class_object_to_string()
1029 var lines =<< trim END
1030 vim9script
1031 class TextPosition
1032 this.lnum = 1
1033 this.col = 22
1034 endclass
1035
1036 assert_equal("class TextPosition", string(TextPosition))
1037
1038 var pos = TextPosition.new()
1039 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1040 END
1041 v9.CheckScriptSuccess(lines)
1042enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001043
Bram Moolenaar554d0312023-01-05 19:59:18 +00001044def Test_interface_basics()
1045 var lines =<< trim END
1046 vim9script
1047 interface Something
1048 this.value: string
1049 static count: number
1050 def GetCount(): number
1051 endinterface
1052 END
1053 v9.CheckScriptSuccess(lines)
1054
1055 lines =<< trim END
1056 interface SomethingWrong
1057 static count = 7
1058 endinterface
1059 END
1060 v9.CheckScriptFailure(lines, 'E1342:')
1061
1062 lines =<< trim END
1063 vim9script
1064
1065 interface Some
1066 static count: number
1067 def Method(count: number)
1068 endinterface
1069 END
h-east61378a12023-04-18 19:07:29 +01001070 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001071
1072 lines =<< trim END
1073 vim9script
1074
1075 interface Some
1076 this.value: number
1077 def Method(value: number)
1078 endinterface
1079 END
h-east61378a12023-04-18 19:07:29 +01001080 # The argument name and the object member name are the same, but this is not a
1081 # problem because object members are always accessed with the "this." prefix.
1082 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001083
1084 lines =<< trim END
1085 vim9script
1086 interface somethingWrong
1087 static count = 7
1088 endinterface
1089 END
1090 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1091
1092 lines =<< trim END
1093 vim9script
1094 interface SomethingWrong
1095 this.value: string
1096 static count = 7
1097 def GetCount(): number
1098 endinterface
1099 END
1100 v9.CheckScriptFailure(lines, 'E1344:')
1101
1102 lines =<< trim END
1103 vim9script
1104 interface SomethingWrong
1105 this.value: string
1106 static count: number
1107 def GetCount(): number
1108 return 5
1109 enddef
1110 endinterface
1111 END
1112 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001113
1114 lines =<< trim END
1115 vim9script
1116 export interface EnterExit
1117 def Enter(): void
1118 def Exit(): void
1119 endinterface
1120 END
1121 writefile(lines, 'XdefIntf.vim', 'D')
1122
1123 lines =<< trim END
1124 vim9script
1125 import './XdefIntf.vim' as defIntf
1126 export def With(ee: defIntf.EnterExit, F: func)
1127 ee.Enter()
1128 try
1129 F()
1130 finally
1131 ee.Exit()
1132 endtry
1133 enddef
1134 END
1135 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001136
1137 var imported =<< trim END
1138 vim9script
1139 export abstract class EnterExit
1140 def Enter(): void
1141 enddef
1142 def Exit(): void
1143 enddef
1144 endclass
1145 END
1146 writefile(imported, 'XdefIntf2.vim', 'D')
1147
1148 lines[1] = " import './XdefIntf2.vim' as defIntf"
1149 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001150enddef
1151
Bram Moolenaar94674f22023-01-06 18:42:20 +00001152def Test_class_implements_interface()
1153 var lines =<< trim END
1154 vim9script
1155
1156 interface Some
1157 static count: number
1158 def Method(nr: number)
1159 endinterface
1160
1161 class SomeImpl implements Some
1162 static count: number
1163 def Method(nr: number)
1164 echo nr
1165 enddef
1166 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001167
1168 interface Another
1169 this.member: string
1170 endinterface
1171
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001172 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001173 this.member = 'abc'
1174 static count: number
1175 def Method(nr: number)
1176 echo nr
1177 enddef
1178 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001179 END
1180 v9.CheckScriptSuccess(lines)
1181
1182 lines =<< trim END
1183 vim9script
1184
1185 interface Some
1186 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001187 endinterface
1188
1189 class SomeImpl implements Some implements Some
1190 static count: number
1191 endclass
1192 END
1193 v9.CheckScriptFailure(lines, 'E1350:')
1194
1195 lines =<< trim END
1196 vim9script
1197
1198 interface Some
1199 static counter: number
1200 endinterface
1201
1202 class SomeImpl implements Some, Some
1203 static count: number
1204 endclass
1205 END
1206 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1207
1208 lines =<< trim END
1209 vim9script
1210
1211 interface Some
1212 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001213 def Method(nr: number)
1214 endinterface
1215
1216 class SomeImpl implements Some
1217 static count: number
1218 def Method(nr: number)
1219 echo nr
1220 enddef
1221 endclass
1222 END
1223 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1224
1225 lines =<< trim END
1226 vim9script
1227
1228 interface Some
1229 static count: number
1230 def Methods(nr: number)
1231 endinterface
1232
1233 class SomeImpl implements Some
1234 static count: number
1235 def Method(nr: number)
1236 echo nr
1237 enddef
1238 endclass
1239 END
1240 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001241
1242 # Check different order of members in class and interface works.
1243 lines =<< trim END
1244 vim9script
1245
1246 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001247 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001248 this.errpos: number
1249 endinterface
1250
1251 # order of members is opposite of interface
1252 class Failure implements Result
1253 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001254 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001255 endclass
1256
1257 def Test()
1258 var result: Result = Failure.new()
1259
1260 assert_equal('label', result.label)
1261 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001262
1263 result.label = 'different'
1264 assert_equal('different', result.label)
1265 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001266 enddef
1267
1268 Test()
1269 END
1270 v9.CheckScriptSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00001271enddef
1272
Bram Moolenaard0200c82023-01-28 15:19:40 +00001273def Test_call_interface_method()
1274 var lines =<< trim END
1275 vim9script
1276 interface Base
1277 def Enter(): void
1278 endinterface
1279
1280 class Child implements Base
1281 def Enter(): void
1282 g:result ..= 'child'
1283 enddef
1284 endclass
1285
1286 def F(obj: Base)
1287 obj.Enter()
1288 enddef
1289
1290 g:result = ''
1291 F(Child.new())
1292 assert_equal('child', g:result)
1293 unlet g:result
1294 END
1295 v9.CheckScriptSuccess(lines)
1296
1297 lines =<< trim END
1298 vim9script
1299 class Base
1300 def Enter(): void
1301 g:result ..= 'base'
1302 enddef
1303 endclass
1304
1305 class Child extends Base
1306 def Enter(): void
1307 g:result ..= 'child'
1308 enddef
1309 endclass
1310
1311 def F(obj: Base)
1312 obj.Enter()
1313 enddef
1314
1315 g:result = ''
1316 F(Child.new())
1317 assert_equal('child', g:result)
1318 unlet g:result
1319 END
1320 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001321
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001322 # method of interface returns a value
1323 lines =<< trim END
1324 vim9script
1325 interface Base
1326 def Enter(): string
1327 endinterface
1328
1329 class Child implements Base
1330 def Enter(): string
1331 g:result ..= 'child'
1332 return "/resource"
1333 enddef
1334 endclass
1335
1336 def F(obj: Base)
1337 var r = obj.Enter()
1338 g:result ..= r
1339 enddef
1340
1341 g:result = ''
1342 F(Child.new())
1343 assert_equal('child/resource', g:result)
1344 unlet g:result
1345 END
1346 v9.CheckScriptSuccess(lines)
1347
1348 lines =<< trim END
1349 vim9script
1350 class Base
1351 def Enter(): string
1352 return null_string
1353 enddef
1354 endclass
1355
1356 class Child extends Base
1357 def Enter(): string
1358 g:result ..= 'child'
1359 return "/resource"
1360 enddef
1361 endclass
1362
1363 def F(obj: Base)
1364 var r = obj.Enter()
1365 g:result ..= r
1366 enddef
1367
1368 g:result = ''
1369 F(Child.new())
1370 assert_equal('child/resource', g:result)
1371 unlet g:result
1372 END
1373 v9.CheckScriptSuccess(lines)
1374
1375
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001376 # No class that implements the interface.
1377 lines =<< trim END
1378 vim9script
1379
1380 interface IWithEE
1381 def Enter(): any
1382 def Exit(): void
1383 endinterface
1384
1385 def With1(ee: IWithEE, F: func)
1386 var r = ee.Enter()
1387 enddef
1388
1389 defcompile
1390 END
1391 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001392enddef
1393
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001394def Test_class_used_as_type()
1395 var lines =<< trim END
1396 vim9script
1397
1398 class Point
1399 this.x = 0
1400 this.y = 0
1401 endclass
1402
1403 var p: Point
1404 p = Point.new(2, 33)
1405 assert_equal(2, p.x)
1406 assert_equal(33, p.y)
1407 END
1408 v9.CheckScriptSuccess(lines)
1409
1410 lines =<< trim END
1411 vim9script
1412
1413 interface HasX
1414 this.x: number
1415 endinterface
1416
1417 class Point implements HasX
1418 this.x = 0
1419 this.y = 0
1420 endclass
1421
1422 var p: Point
1423 p = Point.new(2, 33)
1424 var hx = p
1425 assert_equal(2, hx.x)
1426 END
1427 v9.CheckScriptSuccess(lines)
1428
1429 lines =<< trim END
1430 vim9script
1431
1432 class Point
1433 this.x = 0
1434 this.y = 0
1435 endclass
1436
1437 var p: Point
1438 p = 'text'
1439 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001440 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001441enddef
1442
Bram Moolenaar83677162023-01-08 19:54:10 +00001443def Test_class_extends()
1444 var lines =<< trim END
1445 vim9script
1446 class Base
1447 this.one = 1
1448 def GetOne(): number
1449 return this.one
1450 enddef
1451 endclass
1452 class Child extends Base
1453 this.two = 2
1454 def GetTotal(): number
1455 return this.one + this.two
1456 enddef
1457 endclass
1458 var o = Child.new()
1459 assert_equal(1, o.one)
1460 assert_equal(2, o.two)
1461 assert_equal(1, o.GetOne())
1462 assert_equal(3, o.GetTotal())
1463 END
1464 v9.CheckScriptSuccess(lines)
1465
1466 lines =<< trim END
1467 vim9script
1468 class Base
1469 this.one = 1
1470 endclass
1471 class Child extends Base
1472 this.two = 2
1473 endclass
1474 var o = Child.new(3, 44)
1475 assert_equal(3, o.one)
1476 assert_equal(44, o.two)
1477 END
1478 v9.CheckScriptSuccess(lines)
1479
1480 lines =<< trim END
1481 vim9script
1482 class Base
1483 this.one = 1
1484 endclass
1485 class Child extends Base extends Base
1486 this.two = 2
1487 endclass
1488 END
1489 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1490
1491 lines =<< trim END
1492 vim9script
1493 class Child extends BaseClass
1494 this.two = 2
1495 endclass
1496 END
1497 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1498
1499 lines =<< trim END
1500 vim9script
1501 var SomeVar = 99
1502 class Child extends SomeVar
1503 this.two = 2
1504 endclass
1505 END
1506 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001507
1508 lines =<< trim END
1509 vim9script
1510 class Base
1511 this.name: string
1512 def ToString(): string
1513 return this.name
1514 enddef
1515 endclass
1516
1517 class Child extends Base
1518 this.age: number
1519 def ToString(): string
1520 return super.ToString() .. ': ' .. this.age
1521 enddef
1522 endclass
1523
1524 var o = Child.new('John', 42)
1525 assert_equal('John: 42', o.ToString())
1526 END
1527 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001528
1529 lines =<< trim END
1530 vim9script
1531 class Child
1532 this.age: number
1533 def ToString(): number
1534 return this.age
1535 enddef
1536 def ToString(): string
1537 return this.age
1538 enddef
1539 endclass
1540 END
1541 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1542
1543 lines =<< trim END
1544 vim9script
1545 class Child
1546 this.age: number
1547 def ToString(): string
1548 return super .ToString() .. ': ' .. this.age
1549 enddef
1550 endclass
1551 var o = Child.new(42)
1552 echo o.ToString()
1553 END
1554 v9.CheckScriptFailure(lines, 'E1356:')
1555
1556 lines =<< trim END
1557 vim9script
1558 class Base
1559 this.name: string
1560 def ToString(): string
1561 return this.name
1562 enddef
1563 endclass
1564
1565 var age = 42
1566 def ToString(): string
1567 return super.ToString() .. ': ' .. age
1568 enddef
1569 echo ToString()
1570 END
1571 v9.CheckScriptFailure(lines, 'E1357:')
1572
1573 lines =<< trim END
1574 vim9script
1575 class Child
1576 this.age: number
1577 def ToString(): string
1578 return super.ToString() .. ': ' .. this.age
1579 enddef
1580 endclass
1581 var o = Child.new(42)
1582 echo o.ToString()
1583 END
1584 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001585
1586 lines =<< trim END
1587 vim9script
1588 class Base
1589 this.name: string
1590 static def ToString(): string
1591 return 'Base class'
1592 enddef
1593 endclass
1594
1595 class Child extends Base
1596 this.age: number
1597 def ToString(): string
1598 return Base.ToString() .. ': ' .. this.age
1599 enddef
1600 endclass
1601
1602 var o = Child.new('John', 42)
1603 assert_equal('Base class: 42', o.ToString())
1604 END
1605 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001606
1607 lines =<< trim END
1608 vim9script
1609 class Base
1610 this.value = 1
1611 def new(init: number)
1612 this.value = number + 1
1613 enddef
1614 endclass
1615 class Child extends Base
1616 def new()
1617 this.new(3)
1618 enddef
1619 endclass
1620 var c = Child.new()
1621 END
1622 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00001623
1624 # base class with more than one object member
1625 lines =<< trim END
1626 vim9script
1627
1628 class Result
1629 this.success: bool
1630 this.value: any = null
1631 endclass
1632
1633 class Success extends Result
1634 def new(this.value = v:none)
1635 this.success = true
1636 enddef
1637 endclass
1638
1639 var v = Success.new('asdf')
1640 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
1641 END
1642 v9.CheckScriptSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00001643enddef
1644
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00001645def Test_using_base_class()
1646 var lines =<< trim END
1647 vim9script
1648
1649 class BaseEE
1650 def Enter(): any
1651 return null
1652 enddef
1653 def Exit(resource: any): void
1654 enddef
1655 endclass
1656
1657 class ChildEE extends BaseEE
1658 def Enter(): any
1659 return 42
1660 enddef
1661
1662 def Exit(resource: number): void
1663 g:result ..= '/exit'
1664 enddef
1665 endclass
1666
1667 def With(ee: BaseEE)
1668 var r = ee.Enter()
1669 try
1670 g:result ..= r
1671 finally
1672 g:result ..= '/finally'
1673 ee.Exit(r)
1674 endtry
1675 enddef
1676
1677 g:result = ''
1678 With(ChildEE.new())
1679 assert_equal('42/finally/exit', g:result)
1680 END
1681 v9.CheckScriptSuccess(lines)
1682 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01001683
1684 # Using super, Child invokes Base method which has optional arg. #12471
1685 lines =<< trim END
1686 vim9script
1687
1688 class Base
1689 this.success: bool = false
1690 def Method(arg = 0)
1691 this.success = true
1692 enddef
1693 endclass
1694
1695 class Child extends Base
1696 def new()
1697 super.Method()
1698 enddef
1699 endclass
1700
1701 var obj = Child.new()
1702 assert_equal(true, obj.success)
1703 END
1704 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00001705enddef
1706
1707
Bram Moolenaara86655a2023-01-12 17:06:27 +00001708def Test_class_import()
1709 var lines =<< trim END
1710 vim9script
1711 export class Animal
1712 this.kind: string
1713 this.name: string
1714 endclass
1715 END
1716 writefile(lines, 'Xanimal.vim', 'D')
1717
1718 lines =<< trim END
1719 vim9script
1720 import './Xanimal.vim' as animal
1721
1722 var a: animal.Animal
1723 a = animal.Animal.new('fish', 'Eric')
1724 assert_equal('fish', a.kind)
1725 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00001726
1727 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
1728 assert_equal('cat', b.kind)
1729 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00001730 END
1731 v9.CheckScriptSuccess(lines)
1732enddef
1733
Bram Moolenaar24a8d062023-01-14 13:12:06 +00001734def Test_abstract_class()
1735 var lines =<< trim END
1736 vim9script
1737 abstract class Base
1738 this.name: string
1739 endclass
1740 class Person extends Base
1741 this.age: number
1742 endclass
1743 var p: Base = Person.new('Peter', 42)
1744 assert_equal('Peter', p.name)
1745 assert_equal(42, p.age)
1746 END
1747 v9.CheckScriptSuccess(lines)
1748
1749 lines =<< trim END
1750 vim9script
1751 abstract class Base
1752 this.name: string
1753 endclass
1754 class Person extends Base
1755 this.age: number
1756 endclass
1757 var p = Base.new('Peter')
1758 END
1759 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
1760
1761 lines =<< trim END
1762 abstract class Base
1763 this.name: string
1764 endclass
1765 END
1766 v9.CheckScriptFailure(lines, 'E1316:')
1767enddef
1768
Bram Moolenaar486fc252023-01-18 14:51:07 +00001769def Test_closure_in_class()
1770 var lines =<< trim END
1771 vim9script
1772
1773 class Foo
1774 this.y: list<string> = ['B']
1775
1776 def new()
1777 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
1778 enddef
1779 endclass
1780
1781 Foo.new()
1782 assert_equal(['A'], g:result)
1783 END
1784 v9.CheckScriptSuccess(lines)
1785enddef
1786
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01001787def Test_call_constructor_from_legacy()
1788 var lines =<< trim END
1789 vim9script
1790
1791 var newCalled = 'false'
1792
1793 class A
1794 def new()
1795 newCalled = 'true'
1796 enddef
1797 endclass
1798
1799 export def F(options = {}): any
1800 return A
1801 enddef
1802
1803 g:p = F()
1804 legacy call p.new()
1805 assert_equal('true', newCalled)
1806 END
1807 v9.CheckScriptSuccess(lines)
1808enddef
1809
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001810def Test_defer_with_object()
1811 var lines =<< trim END
1812 vim9script
1813
1814 class CWithEE
1815 def Enter()
1816 g:result ..= "entered/"
1817 enddef
1818 def Exit()
1819 g:result ..= "exited"
1820 enddef
1821 endclass
1822
1823 def With(ee: CWithEE, F: func)
1824 ee.Enter()
1825 defer ee.Exit()
1826 F()
1827 enddef
1828
1829 g:result = ''
1830 var obj = CWithEE.new()
1831 obj->With(() => {
1832 g:result ..= "called/"
1833 })
1834 assert_equal('entered/called/exited', g:result)
1835 END
1836 v9.CheckScriptSuccess(lines)
1837 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00001838
1839 lines =<< trim END
1840 vim9script
1841
1842 class BaseWithEE
1843 def Enter()
1844 g:result ..= "entered-base/"
1845 enddef
1846 def Exit()
1847 g:result ..= "exited-base"
1848 enddef
1849 endclass
1850
1851 class CWithEE extends BaseWithEE
1852 def Enter()
1853 g:result ..= "entered-child/"
1854 enddef
1855 def Exit()
1856 g:result ..= "exited-child"
1857 enddef
1858 endclass
1859
1860 def With(ee: BaseWithEE, F: func)
1861 ee.Enter()
1862 defer ee.Exit()
1863 F()
1864 enddef
1865
1866 g:result = ''
1867 var obj = CWithEE.new()
1868 obj->With(() => {
1869 g:result ..= "called/"
1870 })
1871 assert_equal('entered-child/called/exited-child', g:result)
1872 END
1873 v9.CheckScriptSuccess(lines)
1874 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001875enddef
1876
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02001877" The following test used to crash Vim (Github issue #12676)
1878def Test_extends_method_crashes_vim()
1879 var lines =<< trim END
1880 vim9script
1881
1882 class Observer
1883 endclass
1884
1885 class Property
1886 this.value: any
1887
1888 def Set(v: any)
1889 if v != this.value
1890 this.value = v
1891 endif
1892 enddef
1893
1894 def Register(observer: Observer)
1895 enddef
1896 endclass
1897
1898 class Bool extends Property
1899 this.value: bool
1900 endclass
1901
1902 def Observe(obj: Property, who: Observer)
1903 obj.Register(who)
1904 enddef
1905
1906 var p = Bool.new(false)
1907 var myObserver = Observer.new()
1908
1909 Observe(p, myObserver)
1910
1911 p.Set(true)
1912 END
1913 v9.CheckScriptSuccess(lines)
1914enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001915
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02001916" Test for calling a method in a class that is extended
1917def Test_call_method_in_extended_class()
1918 var lines =<< trim END
1919 vim9script
1920
1921 var prop_init_called = false
1922 var prop_register_called = false
1923
1924 class Property
1925 def Init()
1926 prop_init_called = true
1927 enddef
1928
1929 def Register()
1930 prop_register_called = true
1931 enddef
1932 endclass
1933
1934 class Bool extends Property
1935 endclass
1936
1937 def Observe(obj: Property)
1938 obj.Register()
1939 enddef
1940
1941 var p = Property.new()
1942 Observe(p)
1943
1944 p.Init()
1945 assert_true(prop_init_called)
1946 assert_true(prop_register_called)
1947 END
1948 v9.CheckScriptSuccess(lines)
1949enddef
1950
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001951" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker