blob: cd67b54153897f036d3772cb6baf6f1ab4fe25c1 [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
h-east2261c892023-08-16 21:49:54 +0900521
522def Test_class_new_with_object_member()
523 var lines =<< trim END
524 vim9script
525
526 class C
527 this.str: string
528 this.num: number
529 def new(this.str, this.num)
530 enddef
531 def newVals(this.str, this.num)
532 enddef
533 endclass
534
535 def Check()
536 try
537 var c = C.new('cats', 2)
538 assert_equal('cats', c.str)
539 assert_equal(2, c.num)
540
541 c = C.newVals('dogs', 4)
542 assert_equal('dogs', c.str)
543 assert_equal(4, c.num)
544 catch
545 assert_report($'Unexpected exception was caught: {v:exception}')
546 endtry
547 enddef
548
549 Check()
550 END
551 v9.CheckScriptSuccess(lines)
552
553 lines =<< trim END
554 vim9script
555
556 class C
557 this.str: string
558 this.num: number
559 def new(this.str, this.num)
560 enddef
561 endclass
562
563 def Check()
564 try
565 var c = C.new(1, 2)
566 catch
567 assert_report($'Unexpected exception was caught: {v:exception}')
568 endtry
569 enddef
570
571 Check()
572 END
573 v9.CheckScriptFailure(lines, 'E1013:')
574
575 lines =<< trim END
576 vim9script
577
578 class C
579 this.str: string
580 this.num: number
581 def newVals(this.str, this.num)
582 enddef
583 endclass
584
585 def Check()
586 try
587 var c = C.newVals('dogs', 'apes')
588 catch
589 assert_report($'Unexpected exception was caught: {v:exception}')
590 endtry
591 enddef
592
593 Check()
594 END
595 v9.CheckScriptFailure(lines, 'E1013:')
596enddef
597
Bram Moolenaar74e12742022-12-13 21:14:28 +0000598def Test_class_object_member_inits()
599 var lines =<< trim END
600 vim9script
601 class TextPosition
602 this.lnum: number
603 this.col = 1
604 this.addcol: number = 2
605 endclass
606
607 var pos = TextPosition.new()
608 assert_equal(0, pos.lnum)
609 assert_equal(1, pos.col)
610 assert_equal(2, pos.addcol)
611 END
612 v9.CheckScriptSuccess(lines)
613
614 lines =<< trim END
615 vim9script
616 class TextPosition
617 this.lnum
618 this.col = 1
619 endclass
620 END
621 v9.CheckScriptFailure(lines, 'E1022:')
622
623 lines =<< trim END
624 vim9script
625 class TextPosition
626 this.lnum = v:none
627 this.col = 1
628 endclass
629 END
630 v9.CheckScriptFailure(lines, 'E1330:')
631enddef
632
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000633def Test_class_object_member_access()
634 var lines =<< trim END
635 vim9script
636 class Triple
637 this._one = 1
638 this.two = 2
639 public this.three = 3
640
641 def GetOne(): number
642 return this._one
643 enddef
644 endclass
645
646 var trip = Triple.new()
647 assert_equal(1, trip.GetOne())
648 assert_equal(2, trip.two)
649 assert_equal(3, trip.three)
650 assert_fails('echo trip._one', 'E1333')
651
652 assert_fails('trip._one = 11', 'E1333')
653 assert_fails('trip.two = 22', 'E1335')
654 trip.three = 33
655 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000656
657 assert_fails('trip.four = 4', 'E1334')
658 END
659 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000660
661 lines =<< trim END
662 vim9script
663
664 class MyCar
665 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000666 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000667
668 def new(make_arg: string)
669 this.make = make_arg
670 enddef
671
672 def GetMake(): string
673 return $"make = {this.make}"
674 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000675 def GetAge(): number
676 return this.age
677 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000678 endclass
679
680 var c = MyCar.new("abc")
681 assert_equal('make = abc', c.GetMake())
682
683 c = MyCar.new("def")
684 assert_equal('make = def', c.GetMake())
685
686 var c2 = MyCar.new("123")
687 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000688
689 def CheckCar()
690 assert_equal("make = def", c.GetMake())
691 assert_equal(5, c.GetAge())
692 enddef
693 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000694 END
695 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000696
697 lines =<< trim END
698 vim9script
699
700 class MyCar
701 this.make: string
702
703 def new(make_arg: string)
704 this.make = make_arg
705 enddef
706 endclass
707
708 var c = MyCar.new("abc")
709 var c = MyCar.new("def")
710 END
711 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000712
713 lines =<< trim END
714 vim9script
715
716 class Foo
717 this.x: list<number> = []
718
719 def Add(n: number): any
720 this.x->add(n)
721 return this
722 enddef
723 endclass
724
725 echo Foo.new().Add(1).Add(2).x
726 echo Foo.new().Add(1).Add(2)
727 .x
728 echo Foo.new().Add(1)
729 .Add(2).x
730 echo Foo.new()
731 .Add(1).Add(2).x
732 echo Foo.new()
733 .Add(1)
734 .Add(2)
735 .x
736 END
737 v9.CheckScriptSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +0000738enddef
739
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000740def Test_class_object_compare()
741 var class_lines =<< trim END
742 vim9script
743 class Item
744 this.nr = 0
745 this.name = 'xx'
746 endclass
747 END
748
749 # used at the script level and in a compiled function
750 var test_lines =<< trim END
751 var i1 = Item.new()
752 assert_equal(i1, i1)
753 assert_true(i1 is i1)
754 var i2 = Item.new()
755 assert_equal(i1, i2)
756 assert_false(i1 is i2)
757 var i3 = Item.new(0, 'xx')
758 assert_equal(i1, i3)
759
760 var io1 = Item.new(1, 'xx')
761 assert_notequal(i1, io1)
762 var io2 = Item.new(0, 'yy')
763 assert_notequal(i1, io2)
764 END
765
766 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000767 v9.CheckScriptSuccess(
768 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000769
770 for op in ['>', '>=', '<', '<=', '=~', '!~']
771 var op_lines = [
772 'var i1 = Item.new()',
773 'var i2 = Item.new()',
774 'echo i1 ' .. op .. ' i2',
775 ]
776 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000777 v9.CheckScriptFailure(class_lines
778 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000779 endfor
780enddef
781
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000782def Test_object_type()
783 var lines =<< trim END
784 vim9script
785
786 class One
787 this.one = 1
788 endclass
789 class Two
790 this.two = 2
791 endclass
792 class TwoMore extends Two
793 this.more = 9
794 endclass
795
796 var o: One = One.new()
797 var t: Two = Two.new()
798 var m: TwoMore = TwoMore.new()
799 var tm: Two = TwoMore.new()
800
801 t = m
802 END
803 v9.CheckScriptSuccess(lines)
804
805 lines =<< trim END
806 vim9script
807
808 class One
809 this.one = 1
810 endclass
811 class Two
812 this.two = 2
813 endclass
814
815 var o: One = Two.new()
816 END
817 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000818
819 lines =<< trim END
820 vim9script
821
822 interface One
823 def GetMember(): number
824 endinterface
825 class Two implements One
826 this.one = 1
827 def GetMember(): number
828 return this.one
829 enddef
830 endclass
831
832 var o: One = Two.new(5)
833 assert_equal(5, o.GetMember())
834 END
835 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +0000836
837 lines =<< trim END
838 vim9script
839
840 class Num
841 this.n: number = 0
842 endclass
843
844 def Ref(name: string): func(Num): Num
845 return (arg: Num): Num => {
846 return eval(name)(arg)
847 }
848 enddef
849
850 const Fn = Ref('Double')
851 var Double = (m: Num): Num => Num.new(m.n * 2)
852
853 echo Fn(Num.new(4))
854 END
855 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000856enddef
857
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000858def Test_class_member()
859 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +0000860 var lines =<< trim END
861 vim9script
862 class TextPos
863 this.lnum = 1
864 this.col = 1
865 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000866 static _secret = 7
867 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +0000868
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000869 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +0000870 counter += nr
871 enddef
872 endclass
873
874 assert_equal(0, TextPos.counter)
875 TextPos.AddToCounter(3)
876 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000877 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000878
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000879 def GetCounter(): number
880 return TextPos.counter
881 enddef
882 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +0000883
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000884 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000885 assert_fails('TextPos.counter = 5', 'E1335:')
886 assert_fails('TextPos.counter += 5', 'E1335:')
887
888 assert_fails('echo TextPos._secret', 'E1333:')
889 assert_fails('TextPos._secret = 8', 'E1333:')
890
891 assert_equal(42, TextPos.anybody)
892 TextPos.anybody = 12
893 assert_equal(12, TextPos.anybody)
894 TextPos.anybody += 5
895 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000896 END
897 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000898
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000899 # example in the help
900 lines =<< trim END
901 vim9script
902 class OtherThing
903 this.size: number
904 static totalSize: number
905
906 def new(this.size)
907 totalSize += this.size
908 enddef
909 endclass
910 assert_equal(0, OtherThing.totalSize)
911 var to3 = OtherThing.new(3)
912 assert_equal(3, OtherThing.totalSize)
913 var to7 = OtherThing.new(7)
914 assert_equal(10, OtherThing.totalSize)
915 END
916 v9.CheckScriptSuccess(lines)
917
Bram Moolenaar4e2406c2023-06-24 19:22:21 +0100918 # using static class member twice
919 lines =<< trim END
920 vim9script
921
922 class HTML
923 static author: string = 'John Doe'
924
925 static def MacroSubstitute(s: string): string
926 return substitute(s, '{{author}}', author, 'gi')
927 enddef
928 endclass
929
930 assert_equal('some text', HTML.MacroSubstitute('some text'))
931 assert_equal('some text', HTML.MacroSubstitute('some text'))
932 END
933 v9.CheckScriptSuccess(lines)
934
Bram Moolenaar62a69232023-01-24 15:07:04 +0000935 # access private member in lambda
936 lines =<< trim END
937 vim9script
938
939 class Foo
940 this._x: number = 0
941
942 def Add(n: number): number
943 const F = (): number => this._x + n
944 return F()
945 enddef
946 endclass
947
948 var foo = Foo.new()
949 assert_equal(5, foo.Add(5))
950 END
951 v9.CheckScriptSuccess(lines)
952
h-east2bd6a092023-05-19 19:01:17 +0100953 # access private member in lambda body
954 lines =<< trim END
955 vim9script
956
957 class Foo
958 this._x: number = 6
959
960 def Add(n: number): number
961 var Lam = () => {
962 this._x = this._x + n
963 }
964 Lam()
965 return this._x
966 enddef
967 endclass
968
969 var foo = Foo.new()
970 assert_equal(13, foo.Add(7))
971 END
972 v9.CheckScriptSuccess(lines)
973
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000974 # check shadowing
975 lines =<< trim END
976 vim9script
977
978 class Some
979 static count = 0
980 def Method(count: number)
981 echo count
982 enddef
983 endclass
984
985 var s = Some.new()
986 s.Method(7)
987 END
988 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
989
990 lines =<< trim END
991 vim9script
992
993 class Some
994 static count = 0
995 def Method(arg: number)
996 var count = 3
997 echo arg count
998 enddef
999 endclass
1000
1001 var s = Some.new()
1002 s.Method(7)
1003 END
1004 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001005enddef
1006
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001007func Test_class_garbagecollect()
1008 let lines =<< trim END
1009 vim9script
1010
1011 class Point
1012 this.p = [2, 3]
1013 static pl = ['a', 'b']
1014 static pd = {a: 'a', b: 'b'}
1015 endclass
1016
1017 echo Point.pl Point.pd
1018 call test_garbagecollect_now()
1019 echo Point.pl Point.pd
1020 END
1021 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001022
1023 let lines =<< trim END
1024 vim9script
1025
1026 interface View
1027 endinterface
1028
1029 class Widget
1030 this.view: View
1031 endclass
1032
1033 class MyView implements View
1034 this.widget: Widget
1035
1036 def new()
1037 # this will result in a circular reference to this object
1038 this.widget = Widget.new(this)
1039 enddef
1040 endclass
1041
1042 var view = MyView.new()
1043
1044 # overwrite "view", will be garbage-collected next
1045 view = MyView.new()
1046 test_garbagecollect_now()
1047 END
1048 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001049endfunc
1050
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001051def Test_class_function()
1052 var lines =<< trim END
1053 vim9script
1054 class Value
1055 this.value = 0
1056 static objects = 0
1057
1058 def new(v: number)
1059 this.value = v
1060 ++objects
1061 enddef
1062
1063 static def GetCount(): number
1064 return objects
1065 enddef
1066 endclass
1067
1068 assert_equal(0, Value.GetCount())
1069 var v1 = Value.new(2)
1070 assert_equal(1, Value.GetCount())
1071 var v2 = Value.new(7)
1072 assert_equal(2, Value.GetCount())
1073 END
1074 v9.CheckScriptSuccess(lines)
1075enddef
1076
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001077def Test_class_defcompile()
1078 var lines =<< trim END
1079 vim9script
1080
1081 class C
1082 def Fo(i: number): string
1083 return i
1084 enddef
1085 endclass
1086
1087 defcompile C.Fo
1088 END
1089 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1090
1091 lines =<< trim END
1092 vim9script
1093
1094 class C
1095 static def Fc(): number
1096 return 'x'
1097 enddef
1098 endclass
1099
1100 defcompile C.Fc
1101 END
1102 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
1103enddef
1104
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001105def Test_class_object_to_string()
1106 var lines =<< trim END
1107 vim9script
1108 class TextPosition
1109 this.lnum = 1
1110 this.col = 22
1111 endclass
1112
1113 assert_equal("class TextPosition", string(TextPosition))
1114
1115 var pos = TextPosition.new()
1116 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1117 END
1118 v9.CheckScriptSuccess(lines)
1119enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001120
Bram Moolenaar554d0312023-01-05 19:59:18 +00001121def Test_interface_basics()
1122 var lines =<< trim END
1123 vim9script
1124 interface Something
1125 this.value: string
1126 static count: number
1127 def GetCount(): number
1128 endinterface
1129 END
1130 v9.CheckScriptSuccess(lines)
1131
1132 lines =<< trim END
1133 interface SomethingWrong
1134 static count = 7
1135 endinterface
1136 END
1137 v9.CheckScriptFailure(lines, 'E1342:')
1138
1139 lines =<< trim END
1140 vim9script
1141
1142 interface Some
1143 static count: number
1144 def Method(count: number)
1145 endinterface
1146 END
h-east61378a12023-04-18 19:07:29 +01001147 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001148
1149 lines =<< trim END
1150 vim9script
1151
1152 interface Some
1153 this.value: number
1154 def Method(value: number)
1155 endinterface
1156 END
h-east61378a12023-04-18 19:07:29 +01001157 # The argument name and the object member name are the same, but this is not a
1158 # problem because object members are always accessed with the "this." prefix.
1159 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001160
1161 lines =<< trim END
1162 vim9script
1163 interface somethingWrong
1164 static count = 7
1165 endinterface
1166 END
1167 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1168
1169 lines =<< trim END
1170 vim9script
1171 interface SomethingWrong
1172 this.value: string
1173 static count = 7
1174 def GetCount(): number
1175 endinterface
1176 END
1177 v9.CheckScriptFailure(lines, 'E1344:')
1178
1179 lines =<< trim END
1180 vim9script
1181 interface SomethingWrong
1182 this.value: string
1183 static count: number
1184 def GetCount(): number
1185 return 5
1186 enddef
1187 endinterface
1188 END
1189 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001190
1191 lines =<< trim END
1192 vim9script
1193 export interface EnterExit
1194 def Enter(): void
1195 def Exit(): void
1196 endinterface
1197 END
1198 writefile(lines, 'XdefIntf.vim', 'D')
1199
1200 lines =<< trim END
1201 vim9script
1202 import './XdefIntf.vim' as defIntf
1203 export def With(ee: defIntf.EnterExit, F: func)
1204 ee.Enter()
1205 try
1206 F()
1207 finally
1208 ee.Exit()
1209 endtry
1210 enddef
1211 END
1212 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001213
1214 var imported =<< trim END
1215 vim9script
1216 export abstract class EnterExit
1217 def Enter(): void
1218 enddef
1219 def Exit(): void
1220 enddef
1221 endclass
1222 END
1223 writefile(imported, 'XdefIntf2.vim', 'D')
1224
1225 lines[1] = " import './XdefIntf2.vim' as defIntf"
1226 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001227enddef
1228
Bram Moolenaar94674f22023-01-06 18:42:20 +00001229def Test_class_implements_interface()
1230 var lines =<< trim END
1231 vim9script
1232
1233 interface Some
1234 static count: number
1235 def Method(nr: number)
1236 endinterface
1237
1238 class SomeImpl implements Some
1239 static count: number
1240 def Method(nr: number)
1241 echo nr
1242 enddef
1243 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001244
1245 interface Another
1246 this.member: string
1247 endinterface
1248
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001249 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001250 this.member = 'abc'
1251 static count: number
1252 def Method(nr: number)
1253 echo nr
1254 enddef
1255 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001256 END
1257 v9.CheckScriptSuccess(lines)
1258
1259 lines =<< trim END
1260 vim9script
1261
1262 interface Some
1263 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001264 endinterface
1265
1266 class SomeImpl implements Some implements Some
1267 static count: number
1268 endclass
1269 END
1270 v9.CheckScriptFailure(lines, 'E1350:')
1271
1272 lines =<< trim END
1273 vim9script
1274
1275 interface Some
1276 static counter: number
1277 endinterface
1278
1279 class SomeImpl implements Some, Some
1280 static count: number
1281 endclass
1282 END
1283 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1284
1285 lines =<< trim END
1286 vim9script
1287
1288 interface Some
1289 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001290 def Method(nr: number)
1291 endinterface
1292
1293 class SomeImpl implements Some
1294 static count: number
1295 def Method(nr: number)
1296 echo nr
1297 enddef
1298 endclass
1299 END
1300 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1301
1302 lines =<< trim END
1303 vim9script
1304
1305 interface Some
1306 static count: number
1307 def Methods(nr: number)
1308 endinterface
1309
1310 class SomeImpl implements Some
1311 static count: number
1312 def Method(nr: number)
1313 echo nr
1314 enddef
1315 endclass
1316 END
1317 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001318
1319 # Check different order of members in class and interface works.
1320 lines =<< trim END
1321 vim9script
1322
1323 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001324 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001325 this.errpos: number
1326 endinterface
1327
1328 # order of members is opposite of interface
1329 class Failure implements Result
1330 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001331 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001332 endclass
1333
1334 def Test()
1335 var result: Result = Failure.new()
1336
1337 assert_equal('label', result.label)
1338 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001339
1340 result.label = 'different'
1341 assert_equal('different', result.label)
1342 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001343 enddef
1344
1345 Test()
1346 END
1347 v9.CheckScriptSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00001348enddef
1349
Bram Moolenaard0200c82023-01-28 15:19:40 +00001350def Test_call_interface_method()
1351 var lines =<< trim END
1352 vim9script
1353 interface Base
1354 def Enter(): void
1355 endinterface
1356
1357 class Child implements Base
1358 def Enter(): void
1359 g:result ..= 'child'
1360 enddef
1361 endclass
1362
1363 def F(obj: Base)
1364 obj.Enter()
1365 enddef
1366
1367 g:result = ''
1368 F(Child.new())
1369 assert_equal('child', g:result)
1370 unlet g:result
1371 END
1372 v9.CheckScriptSuccess(lines)
1373
1374 lines =<< trim END
1375 vim9script
1376 class Base
1377 def Enter(): void
1378 g:result ..= 'base'
1379 enddef
1380 endclass
1381
1382 class Child extends Base
1383 def Enter(): void
1384 g:result ..= 'child'
1385 enddef
1386 endclass
1387
1388 def F(obj: Base)
1389 obj.Enter()
1390 enddef
1391
1392 g:result = ''
1393 F(Child.new())
1394 assert_equal('child', g:result)
1395 unlet g:result
1396 END
1397 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001398
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001399 # method of interface returns a value
1400 lines =<< trim END
1401 vim9script
1402 interface Base
1403 def Enter(): string
1404 endinterface
1405
1406 class Child implements Base
1407 def Enter(): string
1408 g:result ..= 'child'
1409 return "/resource"
1410 enddef
1411 endclass
1412
1413 def F(obj: Base)
1414 var r = obj.Enter()
1415 g:result ..= r
1416 enddef
1417
1418 g:result = ''
1419 F(Child.new())
1420 assert_equal('child/resource', g:result)
1421 unlet g:result
1422 END
1423 v9.CheckScriptSuccess(lines)
1424
1425 lines =<< trim END
1426 vim9script
1427 class Base
1428 def Enter(): string
1429 return null_string
1430 enddef
1431 endclass
1432
1433 class Child extends Base
1434 def Enter(): string
1435 g:result ..= 'child'
1436 return "/resource"
1437 enddef
1438 endclass
1439
1440 def F(obj: Base)
1441 var r = obj.Enter()
1442 g:result ..= r
1443 enddef
1444
1445 g:result = ''
1446 F(Child.new())
1447 assert_equal('child/resource', g:result)
1448 unlet g:result
1449 END
1450 v9.CheckScriptSuccess(lines)
1451
1452
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001453 # No class that implements the interface.
1454 lines =<< trim END
1455 vim9script
1456
1457 interface IWithEE
1458 def Enter(): any
1459 def Exit(): void
1460 endinterface
1461
1462 def With1(ee: IWithEE, F: func)
1463 var r = ee.Enter()
1464 enddef
1465
1466 defcompile
1467 END
1468 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001469enddef
1470
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001471def Test_class_used_as_type()
1472 var lines =<< trim END
1473 vim9script
1474
1475 class Point
1476 this.x = 0
1477 this.y = 0
1478 endclass
1479
1480 var p: Point
1481 p = Point.new(2, 33)
1482 assert_equal(2, p.x)
1483 assert_equal(33, p.y)
1484 END
1485 v9.CheckScriptSuccess(lines)
1486
1487 lines =<< trim END
1488 vim9script
1489
1490 interface HasX
1491 this.x: number
1492 endinterface
1493
1494 class Point implements HasX
1495 this.x = 0
1496 this.y = 0
1497 endclass
1498
1499 var p: Point
1500 p = Point.new(2, 33)
1501 var hx = p
1502 assert_equal(2, hx.x)
1503 END
1504 v9.CheckScriptSuccess(lines)
1505
1506 lines =<< trim END
1507 vim9script
1508
1509 class Point
1510 this.x = 0
1511 this.y = 0
1512 endclass
1513
1514 var p: Point
1515 p = 'text'
1516 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001517 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001518enddef
1519
Bram Moolenaar83677162023-01-08 19:54:10 +00001520def Test_class_extends()
1521 var lines =<< trim END
1522 vim9script
1523 class Base
1524 this.one = 1
1525 def GetOne(): number
1526 return this.one
1527 enddef
1528 endclass
1529 class Child extends Base
1530 this.two = 2
1531 def GetTotal(): number
1532 return this.one + this.two
1533 enddef
1534 endclass
1535 var o = Child.new()
1536 assert_equal(1, o.one)
1537 assert_equal(2, o.two)
1538 assert_equal(1, o.GetOne())
1539 assert_equal(3, o.GetTotal())
1540 END
1541 v9.CheckScriptSuccess(lines)
1542
1543 lines =<< trim END
1544 vim9script
1545 class Base
1546 this.one = 1
1547 endclass
1548 class Child extends Base
1549 this.two = 2
1550 endclass
1551 var o = Child.new(3, 44)
1552 assert_equal(3, o.one)
1553 assert_equal(44, o.two)
1554 END
1555 v9.CheckScriptSuccess(lines)
1556
1557 lines =<< trim END
1558 vim9script
1559 class Base
1560 this.one = 1
1561 endclass
1562 class Child extends Base extends Base
1563 this.two = 2
1564 endclass
1565 END
1566 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1567
1568 lines =<< trim END
1569 vim9script
1570 class Child extends BaseClass
1571 this.two = 2
1572 endclass
1573 END
1574 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1575
1576 lines =<< trim END
1577 vim9script
1578 var SomeVar = 99
1579 class Child extends SomeVar
1580 this.two = 2
1581 endclass
1582 END
1583 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001584
1585 lines =<< trim END
1586 vim9script
1587 class Base
1588 this.name: string
1589 def ToString(): string
1590 return this.name
1591 enddef
1592 endclass
1593
1594 class Child extends Base
1595 this.age: number
1596 def ToString(): string
1597 return super.ToString() .. ': ' .. this.age
1598 enddef
1599 endclass
1600
1601 var o = Child.new('John', 42)
1602 assert_equal('John: 42', o.ToString())
1603 END
1604 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001605
1606 lines =<< trim END
1607 vim9script
1608 class Child
1609 this.age: number
1610 def ToString(): number
1611 return this.age
1612 enddef
1613 def ToString(): string
1614 return this.age
1615 enddef
1616 endclass
1617 END
1618 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1619
1620 lines =<< trim END
1621 vim9script
1622 class Child
1623 this.age: number
1624 def ToString(): string
1625 return super .ToString() .. ': ' .. this.age
1626 enddef
1627 endclass
1628 var o = Child.new(42)
1629 echo o.ToString()
1630 END
1631 v9.CheckScriptFailure(lines, 'E1356:')
1632
1633 lines =<< trim END
1634 vim9script
1635 class Base
1636 this.name: string
1637 def ToString(): string
1638 return this.name
1639 enddef
1640 endclass
1641
1642 var age = 42
1643 def ToString(): string
1644 return super.ToString() .. ': ' .. age
1645 enddef
1646 echo ToString()
1647 END
1648 v9.CheckScriptFailure(lines, 'E1357:')
1649
1650 lines =<< trim END
1651 vim9script
1652 class Child
1653 this.age: number
1654 def ToString(): string
1655 return super.ToString() .. ': ' .. this.age
1656 enddef
1657 endclass
1658 var o = Child.new(42)
1659 echo o.ToString()
1660 END
1661 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001662
1663 lines =<< trim END
1664 vim9script
1665 class Base
1666 this.name: string
1667 static def ToString(): string
1668 return 'Base class'
1669 enddef
1670 endclass
1671
1672 class Child extends Base
1673 this.age: number
1674 def ToString(): string
1675 return Base.ToString() .. ': ' .. this.age
1676 enddef
1677 endclass
1678
1679 var o = Child.new('John', 42)
1680 assert_equal('Base class: 42', o.ToString())
1681 END
1682 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001683
1684 lines =<< trim END
1685 vim9script
1686 class Base
1687 this.value = 1
1688 def new(init: number)
1689 this.value = number + 1
1690 enddef
1691 endclass
1692 class Child extends Base
1693 def new()
1694 this.new(3)
1695 enddef
1696 endclass
1697 var c = Child.new()
1698 END
1699 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00001700
1701 # base class with more than one object member
1702 lines =<< trim END
1703 vim9script
1704
1705 class Result
1706 this.success: bool
1707 this.value: any = null
1708 endclass
1709
1710 class Success extends Result
1711 def new(this.value = v:none)
1712 this.success = true
1713 enddef
1714 endclass
1715
1716 var v = Success.new('asdf')
1717 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
1718 END
1719 v9.CheckScriptSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00001720enddef
1721
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00001722def Test_using_base_class()
1723 var lines =<< trim END
1724 vim9script
1725
1726 class BaseEE
1727 def Enter(): any
1728 return null
1729 enddef
1730 def Exit(resource: any): void
1731 enddef
1732 endclass
1733
1734 class ChildEE extends BaseEE
1735 def Enter(): any
1736 return 42
1737 enddef
1738
1739 def Exit(resource: number): void
1740 g:result ..= '/exit'
1741 enddef
1742 endclass
1743
1744 def With(ee: BaseEE)
1745 var r = ee.Enter()
1746 try
1747 g:result ..= r
1748 finally
1749 g:result ..= '/finally'
1750 ee.Exit(r)
1751 endtry
1752 enddef
1753
1754 g:result = ''
1755 With(ChildEE.new())
1756 assert_equal('42/finally/exit', g:result)
1757 END
1758 v9.CheckScriptSuccess(lines)
1759 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01001760
1761 # Using super, Child invokes Base method which has optional arg. #12471
1762 lines =<< trim END
1763 vim9script
1764
1765 class Base
1766 this.success: bool = false
1767 def Method(arg = 0)
1768 this.success = true
1769 enddef
1770 endclass
1771
1772 class Child extends Base
1773 def new()
1774 super.Method()
1775 enddef
1776 endclass
1777
1778 var obj = Child.new()
1779 assert_equal(true, obj.success)
1780 END
1781 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00001782enddef
1783
1784
Bram Moolenaara86655a2023-01-12 17:06:27 +00001785def Test_class_import()
1786 var lines =<< trim END
1787 vim9script
1788 export class Animal
1789 this.kind: string
1790 this.name: string
1791 endclass
1792 END
1793 writefile(lines, 'Xanimal.vim', 'D')
1794
1795 lines =<< trim END
1796 vim9script
1797 import './Xanimal.vim' as animal
1798
1799 var a: animal.Animal
1800 a = animal.Animal.new('fish', 'Eric')
1801 assert_equal('fish', a.kind)
1802 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00001803
1804 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
1805 assert_equal('cat', b.kind)
1806 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00001807 END
1808 v9.CheckScriptSuccess(lines)
1809enddef
1810
Bram Moolenaar24a8d062023-01-14 13:12:06 +00001811def Test_abstract_class()
1812 var lines =<< trim END
1813 vim9script
1814 abstract class Base
1815 this.name: string
1816 endclass
1817 class Person extends Base
1818 this.age: number
1819 endclass
1820 var p: Base = Person.new('Peter', 42)
1821 assert_equal('Peter', p.name)
1822 assert_equal(42, p.age)
1823 END
1824 v9.CheckScriptSuccess(lines)
1825
1826 lines =<< trim END
1827 vim9script
1828 abstract class Base
1829 this.name: string
1830 endclass
1831 class Person extends Base
1832 this.age: number
1833 endclass
1834 var p = Base.new('Peter')
1835 END
1836 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
1837
1838 lines =<< trim END
1839 abstract class Base
1840 this.name: string
1841 endclass
1842 END
1843 v9.CheckScriptFailure(lines, 'E1316:')
1844enddef
1845
Bram Moolenaar486fc252023-01-18 14:51:07 +00001846def Test_closure_in_class()
1847 var lines =<< trim END
1848 vim9script
1849
1850 class Foo
1851 this.y: list<string> = ['B']
1852
1853 def new()
1854 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
1855 enddef
1856 endclass
1857
1858 Foo.new()
1859 assert_equal(['A'], g:result)
1860 END
1861 v9.CheckScriptSuccess(lines)
1862enddef
1863
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01001864def Test_call_constructor_from_legacy()
1865 var lines =<< trim END
1866 vim9script
1867
1868 var newCalled = 'false'
1869
1870 class A
1871 def new()
1872 newCalled = 'true'
1873 enddef
1874 endclass
1875
1876 export def F(options = {}): any
1877 return A
1878 enddef
1879
1880 g:p = F()
1881 legacy call p.new()
1882 assert_equal('true', newCalled)
1883 END
1884 v9.CheckScriptSuccess(lines)
1885enddef
1886
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001887def Test_defer_with_object()
1888 var lines =<< trim END
1889 vim9script
1890
1891 class CWithEE
1892 def Enter()
1893 g:result ..= "entered/"
1894 enddef
1895 def Exit()
1896 g:result ..= "exited"
1897 enddef
1898 endclass
1899
1900 def With(ee: CWithEE, F: func)
1901 ee.Enter()
1902 defer ee.Exit()
1903 F()
1904 enddef
1905
1906 g:result = ''
1907 var obj = CWithEE.new()
1908 obj->With(() => {
1909 g:result ..= "called/"
1910 })
1911 assert_equal('entered/called/exited', g:result)
1912 END
1913 v9.CheckScriptSuccess(lines)
1914 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00001915
1916 lines =<< trim END
1917 vim9script
1918
1919 class BaseWithEE
1920 def Enter()
1921 g:result ..= "entered-base/"
1922 enddef
1923 def Exit()
1924 g:result ..= "exited-base"
1925 enddef
1926 endclass
1927
1928 class CWithEE extends BaseWithEE
1929 def Enter()
1930 g:result ..= "entered-child/"
1931 enddef
1932 def Exit()
1933 g:result ..= "exited-child"
1934 enddef
1935 endclass
1936
1937 def With(ee: BaseWithEE, F: func)
1938 ee.Enter()
1939 defer ee.Exit()
1940 F()
1941 enddef
1942
1943 g:result = ''
1944 var obj = CWithEE.new()
1945 obj->With(() => {
1946 g:result ..= "called/"
1947 })
1948 assert_equal('entered-child/called/exited-child', g:result)
1949 END
1950 v9.CheckScriptSuccess(lines)
1951 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001952enddef
1953
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02001954" The following test used to crash Vim (Github issue #12676)
1955def Test_extends_method_crashes_vim()
1956 var lines =<< trim END
1957 vim9script
1958
1959 class Observer
1960 endclass
1961
1962 class Property
1963 this.value: any
1964
1965 def Set(v: any)
1966 if v != this.value
1967 this.value = v
1968 endif
1969 enddef
1970
1971 def Register(observer: Observer)
1972 enddef
1973 endclass
1974
1975 class Bool extends Property
1976 this.value: bool
1977 endclass
1978
1979 def Observe(obj: Property, who: Observer)
1980 obj.Register(who)
1981 enddef
1982
1983 var p = Bool.new(false)
1984 var myObserver = Observer.new()
1985
1986 Observe(p, myObserver)
1987
1988 p.Set(true)
1989 END
1990 v9.CheckScriptSuccess(lines)
1991enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001992
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02001993" Test for calling a method in a class that is extended
1994def Test_call_method_in_extended_class()
1995 var lines =<< trim END
1996 vim9script
1997
1998 var prop_init_called = false
1999 var prop_register_called = false
2000
2001 class Property
2002 def Init()
2003 prop_init_called = true
2004 enddef
2005
2006 def Register()
2007 prop_register_called = true
2008 enddef
2009 endclass
2010
2011 class Bool extends Property
2012 endclass
2013
2014 def Observe(obj: Property)
2015 obj.Register()
2016 enddef
2017
2018 var p = Property.new()
2019 Observe(p)
2020
2021 p.Init()
2022 assert_true(prop_init_called)
2023 assert_true(prop_register_called)
2024 END
2025 v9.CheckScriptSuccess(lines)
2026enddef
2027
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002028" Test for calling a method in the parent class that is extended partially.
2029" This used to fail with the 'E118: Too many arguments for function: Text' error
2030" message (Github issue #12524).
2031def Test_call_method_in_parent_class()
2032 var lines =<< trim END
2033 vim9script
2034
2035 class Widget
2036 this._lnum: number = 1
2037
2038 def SetY(lnum: number)
2039 this._lnum = lnum
2040 enddef
2041
2042 def Text(): string
2043 return ''
2044 enddef
2045 endclass
2046
2047 class Foo extends Widget
2048 def Text(): string
2049 return '<Foo>'
2050 enddef
2051 endclass
2052
2053 def Stack(w1: Widget, w2: Widget): list<Widget>
2054 w1.SetY(1)
2055 w2.SetY(2)
2056 return [w1, w2]
2057 enddef
2058
2059 var foo1 = Foo.new()
2060 var foo2 = Foo.new()
2061 var l = Stack(foo1, foo2)
2062 END
2063 v9.CheckScriptSuccess(lines)
2064enddef
2065
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002066" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker