blob: a79ccc8f5361279b30085d1adf4646b7ad25f329 [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
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200138 # Test for unsupported comment specifier
139 lines =<< trim END
140 vim9script
141 class Something
142 # comment
143 #{
144 endclass
145 END
146 v9.CheckScriptFailure(lines, 'E1170:')
147
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000148 lines =<< trim END
149 vim9script
150
151 class TextPosition
152 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000153 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000154
Bram Moolenaar418b5472022-12-20 13:38:22 +0000155 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000156 def ToString(): string
157 return $'({this.lnum}, {this.col})'
158 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000159 endclass
160
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000161 # use the automatically generated new() method
162 var pos = TextPosition.new(2, 12)
163 assert_equal(2, pos.lnum)
164 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000165
166 # call an object method
167 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000168
169 assert_equal(v:t_class, type(TextPosition))
170 assert_equal(v:t_object, type(pos))
171 assert_equal('class<TextPosition>', typename(TextPosition))
172 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000173 END
174 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200175
176 # When referencing object methods, space cannot be used after a "."
177 lines =<< trim END
178 vim9script
179 class A
180 def Foo(): number
181 return 10
182 enddef
183 endclass
184 var a = A.new()
185 var v = a. Foo()
186 END
187 v9.CheckScriptFailure(lines, 'E1202:')
188
189 # Using an object without specifying a method or a member variable
190 lines =<< trim END
191 vim9script
192 class A
193 def Foo(): number
194 return 10
195 enddef
196 endclass
197 var a = A.new()
198 var v = a.
199 END
200 v9.CheckScriptFailure(lines, 'E15:')
201
202 # Error when parsing the arguments of an object method.
203 lines =<< trim END
204 vim9script
205 class A
206 def Foo()
207 enddef
208 endclass
209 var a = A.new()
210 var v = a.Foo(,)
211 END
212 v9.CheckScriptFailure(lines, 'E15:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000213enddef
214
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000215def Test_class_defined_twice()
216 # class defined twice should fail
217 var lines =<< trim END
218 vim9script
219 class There
220 endclass
221 class There
222 endclass
223 END
224 v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "There"')
225
226 # one class, reload same script twice is OK
227 lines =<< trim END
228 vim9script
229 class There
230 endclass
231 END
232 writefile(lines, 'XclassTwice.vim', 'D')
233 source XclassTwice.vim
234 source XclassTwice.vim
235enddef
236
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000237def Test_returning_null_object()
238 # this was causing an internal error
239 var lines =<< trim END
240 vim9script
241
242 class BufferList
243 def Current(): any
244 return null_object
245 enddef
246 endclass
247
248 var buffers = BufferList.new()
249 echo buffers.Current()
250 END
251 v9.CheckScriptSuccess(lines)
252enddef
253
Bram Moolenaard13dd302023-03-11 20:56:35 +0000254def Test_using_null_class()
255 var lines =<< trim END
256 @_ = null_class.member
257 END
258 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
259enddef
260
Bram Moolenaar657aea72023-01-27 13:16:19 +0000261def Test_class_interface_wrong_end()
262 var lines =<< trim END
263 vim9script
264 abstract class SomeName
265 this.member = 'text'
266 endinterface
267 END
268 v9.CheckScriptFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
269
270 lines =<< trim END
271 vim9script
272 export interface AnotherName
273 this.member: string
274 endclass
275 END
276 v9.CheckScriptFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
277enddef
278
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000279def Test_object_not_set()
280 var lines =<< trim END
281 vim9script
282
283 class State
284 this.value = 'xyz'
285 endclass
286
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000287 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000288 var db = {'xyz': 789}
289 echo db[state.value]
290 END
291 v9.CheckScriptFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000292
293 lines =<< trim END
294 vim9script
295
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000296 class Class
297 this.id: string
298 def Method1()
299 echo 'Method1' .. this.id
300 enddef
301 endclass
302
303 var obj: Class
304 def Func()
305 obj.Method1()
306 enddef
307 Func()
308 END
309 v9.CheckScriptFailure(lines, 'E1360:')
310
311 lines =<< trim END
312 vim9script
313
Bram Moolenaar0917e862023-02-18 14:42:44 +0000314 class Background
315 this.background = 'dark'
316 endclass
317
318 class Colorscheme
319 this._bg: Background
320
321 def GetBackground(): string
322 return this._bg.background
323 enddef
324 endclass
325
326 var bg: Background # UNINITIALIZED
327 echo Colorscheme.new(bg).GetBackground()
328 END
329 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Background> but got object<Unknown>')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000330
331 # TODO: this should not give an error but be handled at runtime
332 lines =<< trim END
333 vim9script
334
335 class Class
336 this.id: string
337 def Method1()
338 echo 'Method1' .. this.id
339 enddef
340 endclass
341
342 var obj = null_object
343 def Func()
344 obj.Method1()
345 enddef
346 Func()
347 END
348 v9.CheckScriptFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000349enddef
350
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000351def Test_class_member_initializer()
352 var lines =<< trim END
353 vim9script
354
355 class TextPosition
356 this.lnum: number = 1
357 this.col: number = 1
358
Bram Moolenaar418b5472022-12-20 13:38:22 +0000359 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000360 def new(lnum: number)
361 this.lnum = lnum
362 enddef
363 endclass
364
365 var pos = TextPosition.new(3)
366 assert_equal(3, pos.lnum)
367 assert_equal(1, pos.col)
368
369 var instr = execute('disassemble TextPosition.new')
370 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000371 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000372 '\d PUSHNR 1\_s*' ..
373 '\d STORE_THIS 0\_s*' ..
374 '\d PUSHNR 1\_s*' ..
375 '\d STORE_THIS 1\_s*' ..
376 'this.lnum = lnum\_s*' ..
377 '\d LOAD arg\[-1]\_s*' ..
378 '\d PUSHNR 0\_s*' ..
379 '\d LOAD $0\_s*' ..
380 '\d\+ STOREINDEX object\_s*' ..
381 '\d\+ RETURN object.*',
382 instr)
383 END
384 v9.CheckScriptSuccess(lines)
385enddef
386
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000387def Test_member_any_used_as_object()
388 var lines =<< trim END
389 vim9script
390
391 class Inner
392 this.value: number = 0
393 endclass
394
395 class Outer
396 this.inner: any
397 endclass
398
399 def F(outer: Outer)
400 outer.inner.value = 1
401 enddef
402
403 var inner_obj = Inner.new(0)
404 var outer_obj = Outer.new(inner_obj)
405 F(outer_obj)
406 assert_equal(1, inner_obj.value)
407 END
408 v9.CheckScriptSuccess(lines)
409
410 lines =<< trim END
411 vim9script
412
413 class Inner
414 this.value: number = 0
415 endclass
416
417 class Outer
418 this.inner: Inner
419 endclass
420
421 def F(outer: Outer)
422 outer.inner.value = 1
423 enddef
424
425 def Test_assign_to_nested_typed_member()
426 var inner = Inner.new(0)
427 var outer = Outer.new(inner)
428 F(outer)
429 assert_equal(1, inner.value)
430 enddef
431
432 Test_assign_to_nested_typed_member()
433 END
434 v9.CheckScriptSuccess(lines)
435enddef
436
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000437def Test_assignment_with_operator()
438 var lines =<< trim END
439 vim9script
440
441 class Foo
442 this.x: number
443
444 def Add(n: number)
445 this.x += n
446 enddef
447 endclass
448
449 var f = Foo.new(3)
450 f.Add(17)
451 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100452
453 def AddToFoo(obj: Foo)
454 obj.x += 3
455 enddef
456
457 AddToFoo(f)
458 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000459 END
460 v9.CheckScriptSuccess(lines)
461enddef
462
Bram Moolenaarf4508042023-01-15 16:54:57 +0000463def Test_list_of_objects()
464 var lines =<< trim END
465 vim9script
466
467 class Foo
468 def Add()
469 enddef
470 endclass
471
472 def ProcessList(fooList: list<Foo>)
473 for foo in fooList
474 foo.Add()
475 endfor
476 enddef
477
478 var l: list<Foo> = [Foo.new()]
479 ProcessList(l)
480 END
481 v9.CheckScriptSuccess(lines)
482enddef
483
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000484def Test_expr_after_using_object()
485 var lines =<< trim END
486 vim9script
487
488 class Something
489 this.label: string = ''
490 endclass
491
492 def Foo(): Something
493 var v = Something.new()
494 echo 'in Foo(): ' .. typename(v)
495 return v
496 enddef
497
498 Foo()
499 END
500 v9.CheckScriptSuccess(lines)
501enddef
502
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000503def Test_class_default_new()
504 var lines =<< trim END
505 vim9script
506
507 class TextPosition
508 this.lnum: number = 1
509 this.col: number = 1
510 endclass
511
512 var pos = TextPosition.new()
513 assert_equal(1, pos.lnum)
514 assert_equal(1, pos.col)
515
516 pos = TextPosition.new(v:none, v:none)
517 assert_equal(1, pos.lnum)
518 assert_equal(1, pos.col)
519
520 pos = TextPosition.new(3, 22)
521 assert_equal(3, pos.lnum)
522 assert_equal(22, pos.col)
523
524 pos = TextPosition.new(v:none, 33)
525 assert_equal(1, pos.lnum)
526 assert_equal(33, pos.col)
527 END
528 v9.CheckScriptSuccess(lines)
529
530 lines =<< trim END
531 vim9script
532 class Person
533 this.name: string
534 this.age: number = 42
535 this.education: string = "unknown"
536
537 def new(this.name, this.age = v:none, this.education = v:none)
538 enddef
539 endclass
540
541 var piet = Person.new("Piet")
542 assert_equal("Piet", piet.name)
543 assert_equal(42, piet.age)
544 assert_equal("unknown", piet.education)
545
546 var chris = Person.new("Chris", 4, "none")
547 assert_equal("Chris", chris.name)
548 assert_equal(4, chris.age)
549 assert_equal("none", chris.education)
550 END
551 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000552
553 lines =<< trim END
554 vim9script
555 class Person
556 this.name: string
557 this.age: number = 42
558 this.education: string = "unknown"
559
560 def new(this.name, this.age = v:none, this.education = v:none)
561 enddef
562 endclass
563
564 var missing = Person.new()
565 END
566 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000567enddef
568
h-east2261c892023-08-16 21:49:54 +0900569
570def Test_class_new_with_object_member()
571 var lines =<< trim END
572 vim9script
573
574 class C
575 this.str: string
576 this.num: number
577 def new(this.str, this.num)
578 enddef
579 def newVals(this.str, this.num)
580 enddef
581 endclass
582
583 def Check()
584 try
585 var c = C.new('cats', 2)
586 assert_equal('cats', c.str)
587 assert_equal(2, c.num)
588
589 c = C.newVals('dogs', 4)
590 assert_equal('dogs', c.str)
591 assert_equal(4, c.num)
592 catch
593 assert_report($'Unexpected exception was caught: {v:exception}')
594 endtry
595 enddef
596
597 Check()
598 END
599 v9.CheckScriptSuccess(lines)
600
601 lines =<< trim END
602 vim9script
603
604 class C
605 this.str: string
606 this.num: number
607 def new(this.str, this.num)
608 enddef
609 endclass
610
611 def Check()
612 try
613 var c = C.new(1, 2)
614 catch
615 assert_report($'Unexpected exception was caught: {v:exception}')
616 endtry
617 enddef
618
619 Check()
620 END
621 v9.CheckScriptFailure(lines, 'E1013:')
622
623 lines =<< trim END
624 vim9script
625
626 class C
627 this.str: string
628 this.num: number
629 def newVals(this.str, this.num)
630 enddef
631 endclass
632
633 def Check()
634 try
635 var c = C.newVals('dogs', 'apes')
636 catch
637 assert_report($'Unexpected exception was caught: {v:exception}')
638 endtry
639 enddef
640
641 Check()
642 END
643 v9.CheckScriptFailure(lines, 'E1013:')
644enddef
645
Bram Moolenaar74e12742022-12-13 21:14:28 +0000646def Test_class_object_member_inits()
647 var lines =<< trim END
648 vim9script
649 class TextPosition
650 this.lnum: number
651 this.col = 1
652 this.addcol: number = 2
653 endclass
654
655 var pos = TextPosition.new()
656 assert_equal(0, pos.lnum)
657 assert_equal(1, pos.col)
658 assert_equal(2, pos.addcol)
659 END
660 v9.CheckScriptSuccess(lines)
661
662 lines =<< trim END
663 vim9script
664 class TextPosition
665 this.lnum
666 this.col = 1
667 endclass
668 END
669 v9.CheckScriptFailure(lines, 'E1022:')
670
671 lines =<< trim END
672 vim9script
673 class TextPosition
674 this.lnum = v:none
675 this.col = 1
676 endclass
677 END
678 v9.CheckScriptFailure(lines, 'E1330:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200679
680 # Test for initializing an object member with an unknown variable/type
681 lines =<< trim END
682 vim9script
683 class A
684 this.value = init_val
685 endclass
686 END
687 v9.CheckScriptFailureList(lines, ['E121:', 'E1329:'])
Bram Moolenaar74e12742022-12-13 21:14:28 +0000688enddef
689
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000690def Test_class_object_member_access()
691 var lines =<< trim END
692 vim9script
693 class Triple
694 this._one = 1
695 this.two = 2
696 public this.three = 3
697
698 def GetOne(): number
699 return this._one
700 enddef
701 endclass
702
703 var trip = Triple.new()
704 assert_equal(1, trip.GetOne())
705 assert_equal(2, trip.two)
706 assert_equal(3, trip.three)
707 assert_fails('echo trip._one', 'E1333')
708
709 assert_fails('trip._one = 11', 'E1333')
710 assert_fails('trip.two = 22', 'E1335')
711 trip.three = 33
712 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000713
714 assert_fails('trip.four = 4', 'E1334')
715 END
716 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000717
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200718 # Test for a public member variable name beginning with an underscore
719 lines =<< trim END
720 vim9script
721 class A
722 public this._val = 10
723 endclass
724 END
725 v9.CheckScriptFailure(lines, 'E1332:')
726
Bram Moolenaar590162c2022-12-24 21:24:06 +0000727 lines =<< trim END
728 vim9script
729
730 class MyCar
731 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000732 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000733
734 def new(make_arg: string)
735 this.make = make_arg
736 enddef
737
738 def GetMake(): string
739 return $"make = {this.make}"
740 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000741 def GetAge(): number
742 return this.age
743 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000744 endclass
745
746 var c = MyCar.new("abc")
747 assert_equal('make = abc', c.GetMake())
748
749 c = MyCar.new("def")
750 assert_equal('make = def', c.GetMake())
751
752 var c2 = MyCar.new("123")
753 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000754
755 def CheckCar()
756 assert_equal("make = def", c.GetMake())
757 assert_equal(5, c.GetAge())
758 enddef
759 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000760 END
761 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000762
763 lines =<< trim END
764 vim9script
765
766 class MyCar
767 this.make: string
768
769 def new(make_arg: string)
770 this.make = make_arg
771 enddef
772 endclass
773
774 var c = MyCar.new("abc")
775 var c = MyCar.new("def")
776 END
777 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000778
779 lines =<< trim END
780 vim9script
781
782 class Foo
783 this.x: list<number> = []
784
785 def Add(n: number): any
786 this.x->add(n)
787 return this
788 enddef
789 endclass
790
791 echo Foo.new().Add(1).Add(2).x
792 echo Foo.new().Add(1).Add(2)
793 .x
794 echo Foo.new().Add(1)
795 .Add(2).x
796 echo Foo.new()
797 .Add(1).Add(2).x
798 echo Foo.new()
799 .Add(1)
800 .Add(2)
801 .x
802 END
803 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200804
805 # Test for "public" cannot be abbreviated
806 lines =<< trim END
807 vim9script
808 class Something
809 pub this.val = 1
810 endclass
811 END
812 v9.CheckScriptFailure(lines, 'E1065:')
813
814 # Test for "public" keyword must be followed by "this" or "static".
815 lines =<< trim END
816 vim9script
817 class Something
818 public val = 1
819 endclass
820 END
821 v9.CheckScriptFailure(lines, 'E1331:')
822
823 # Test for "static" cannot be abbreviated
824 lines =<< trim END
825 vim9script
826 class Something
827 stat this.val = 1
828 endclass
829 END
830 v9.CheckScriptFailure(lines, 'E1065:')
Bram Moolenaard505d172022-12-18 21:42:55 +0000831enddef
832
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000833def Test_class_object_compare()
834 var class_lines =<< trim END
835 vim9script
836 class Item
837 this.nr = 0
838 this.name = 'xx'
839 endclass
840 END
841
842 # used at the script level and in a compiled function
843 var test_lines =<< trim END
844 var i1 = Item.new()
845 assert_equal(i1, i1)
846 assert_true(i1 is i1)
847 var i2 = Item.new()
848 assert_equal(i1, i2)
849 assert_false(i1 is i2)
850 var i3 = Item.new(0, 'xx')
851 assert_equal(i1, i3)
852
853 var io1 = Item.new(1, 'xx')
854 assert_notequal(i1, io1)
855 var io2 = Item.new(0, 'yy')
856 assert_notequal(i1, io2)
857 END
858
859 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000860 v9.CheckScriptSuccess(
861 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000862
863 for op in ['>', '>=', '<', '<=', '=~', '!~']
864 var op_lines = [
865 'var i1 = Item.new()',
866 'var i2 = Item.new()',
867 'echo i1 ' .. op .. ' i2',
868 ]
869 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000870 v9.CheckScriptFailure(class_lines
871 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000872 endfor
873enddef
874
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000875def Test_object_type()
876 var lines =<< trim END
877 vim9script
878
879 class One
880 this.one = 1
881 endclass
882 class Two
883 this.two = 2
884 endclass
885 class TwoMore extends Two
886 this.more = 9
887 endclass
888
889 var o: One = One.new()
890 var t: Two = Two.new()
891 var m: TwoMore = TwoMore.new()
892 var tm: Two = TwoMore.new()
893
894 t = m
895 END
896 v9.CheckScriptSuccess(lines)
897
898 lines =<< trim END
899 vim9script
900
901 class One
902 this.one = 1
903 endclass
904 class Two
905 this.two = 2
906 endclass
907
908 var o: One = Two.new()
909 END
910 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000911
912 lines =<< trim END
913 vim9script
914
915 interface One
916 def GetMember(): number
917 endinterface
918 class Two implements One
919 this.one = 1
920 def GetMember(): number
921 return this.one
922 enddef
923 endclass
924
925 var o: One = Two.new(5)
926 assert_equal(5, o.GetMember())
927 END
928 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +0000929
930 lines =<< trim END
931 vim9script
932
933 class Num
934 this.n: number = 0
935 endclass
936
937 def Ref(name: string): func(Num): Num
938 return (arg: Num): Num => {
939 return eval(name)(arg)
940 }
941 enddef
942
943 const Fn = Ref('Double')
944 var Double = (m: Num): Num => Num.new(m.n * 2)
945
946 echo Fn(Num.new(4))
947 END
948 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000949enddef
950
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000951def Test_class_member()
952 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +0000953 var lines =<< trim END
954 vim9script
955 class TextPos
956 this.lnum = 1
957 this.col = 1
958 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000959 static _secret = 7
960 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +0000961
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000962 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +0000963 counter += nr
964 enddef
965 endclass
966
967 assert_equal(0, TextPos.counter)
968 TextPos.AddToCounter(3)
969 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000970 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000971
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000972 def GetCounter(): number
973 return TextPos.counter
974 enddef
975 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +0000976
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000977 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000978 assert_fails('TextPos.counter = 5', 'E1335:')
979 assert_fails('TextPos.counter += 5', 'E1335:')
980
981 assert_fails('echo TextPos._secret', 'E1333:')
982 assert_fails('TextPos._secret = 8', 'E1333:')
983
984 assert_equal(42, TextPos.anybody)
985 TextPos.anybody = 12
986 assert_equal(12, TextPos.anybody)
987 TextPos.anybody += 5
988 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000989 END
990 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000991
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000992 # example in the help
993 lines =<< trim END
994 vim9script
995 class OtherThing
996 this.size: number
997 static totalSize: number
998
999 def new(this.size)
1000 totalSize += this.size
1001 enddef
1002 endclass
1003 assert_equal(0, OtherThing.totalSize)
1004 var to3 = OtherThing.new(3)
1005 assert_equal(3, OtherThing.totalSize)
1006 var to7 = OtherThing.new(7)
1007 assert_equal(10, OtherThing.totalSize)
1008 END
1009 v9.CheckScriptSuccess(lines)
1010
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001011 # using static class member twice
1012 lines =<< trim END
1013 vim9script
1014
1015 class HTML
1016 static author: string = 'John Doe'
1017
1018 static def MacroSubstitute(s: string): string
1019 return substitute(s, '{{author}}', author, 'gi')
1020 enddef
1021 endclass
1022
1023 assert_equal('some text', HTML.MacroSubstitute('some text'))
1024 assert_equal('some text', HTML.MacroSubstitute('some text'))
1025 END
1026 v9.CheckScriptSuccess(lines)
1027
Bram Moolenaar62a69232023-01-24 15:07:04 +00001028 # access private member in lambda
1029 lines =<< trim END
1030 vim9script
1031
1032 class Foo
1033 this._x: number = 0
1034
1035 def Add(n: number): number
1036 const F = (): number => this._x + n
1037 return F()
1038 enddef
1039 endclass
1040
1041 var foo = Foo.new()
1042 assert_equal(5, foo.Add(5))
1043 END
1044 v9.CheckScriptSuccess(lines)
1045
h-east2bd6a092023-05-19 19:01:17 +01001046 # access private member in lambda body
1047 lines =<< trim END
1048 vim9script
1049
1050 class Foo
1051 this._x: number = 6
1052
1053 def Add(n: number): number
1054 var Lam = () => {
1055 this._x = this._x + n
1056 }
1057 Lam()
1058 return this._x
1059 enddef
1060 endclass
1061
1062 var foo = Foo.new()
1063 assert_equal(13, foo.Add(7))
1064 END
1065 v9.CheckScriptSuccess(lines)
1066
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001067 # check shadowing
1068 lines =<< trim END
1069 vim9script
1070
1071 class Some
1072 static count = 0
1073 def Method(count: number)
1074 echo count
1075 enddef
1076 endclass
1077
1078 var s = Some.new()
1079 s.Method(7)
1080 END
1081 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
1082
1083 lines =<< trim END
1084 vim9script
1085
1086 class Some
1087 static count = 0
1088 def Method(arg: number)
1089 var count = 3
1090 echo arg count
1091 enddef
1092 endclass
1093
1094 var s = Some.new()
1095 s.Method(7)
1096 END
1097 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001098
1099 # Test for using an invalid type for a member variable
1100 lines =<< trim END
1101 vim9script
1102 class A
1103 this.val: xxx
1104 endclass
1105 END
1106 v9.CheckScriptFailure(lines, 'E1010:')
1107
1108 # Test for no space before or after the '=' when initializing a member
1109 # variable
1110 lines =<< trim END
1111 vim9script
1112 class A
1113 this.val: number= 10
1114 endclass
1115 END
1116 v9.CheckScriptFailure(lines, 'E1004:')
1117 lines =<< trim END
1118 vim9script
1119 class A
1120 this.val: number =10
1121 endclass
1122 END
1123 v9.CheckScriptFailure(lines, 'E1004:')
1124
1125 # Access a non-existing member
1126 lines =<< trim END
1127 vim9script
1128 class A
1129 endclass
1130 var a = A.new()
1131 var v = a.bar
1132 END
1133 v9.CheckScriptFailure(lines, 'E1326:')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001134enddef
1135
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001136func Test_class_garbagecollect()
1137 let lines =<< trim END
1138 vim9script
1139
1140 class Point
1141 this.p = [2, 3]
1142 static pl = ['a', 'b']
1143 static pd = {a: 'a', b: 'b'}
1144 endclass
1145
1146 echo Point.pl Point.pd
1147 call test_garbagecollect_now()
1148 echo Point.pl Point.pd
1149 END
1150 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001151
1152 let lines =<< trim END
1153 vim9script
1154
1155 interface View
1156 endinterface
1157
1158 class Widget
1159 this.view: View
1160 endclass
1161
1162 class MyView implements View
1163 this.widget: Widget
1164
1165 def new()
1166 # this will result in a circular reference to this object
1167 this.widget = Widget.new(this)
1168 enddef
1169 endclass
1170
1171 var view = MyView.new()
1172
1173 # overwrite "view", will be garbage-collected next
1174 view = MyView.new()
1175 test_garbagecollect_now()
1176 END
1177 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001178endfunc
1179
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001180def Test_class_function()
1181 var lines =<< trim END
1182 vim9script
1183 class Value
1184 this.value = 0
1185 static objects = 0
1186
1187 def new(v: number)
1188 this.value = v
1189 ++objects
1190 enddef
1191
1192 static def GetCount(): number
1193 return objects
1194 enddef
1195 endclass
1196
1197 assert_equal(0, Value.GetCount())
1198 var v1 = Value.new(2)
1199 assert_equal(1, Value.GetCount())
1200 var v2 = Value.new(7)
1201 assert_equal(2, Value.GetCount())
1202 END
1203 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001204
1205 # Test for cleaning up after a class definition failure when using class
1206 # functions.
1207 lines =<< trim END
1208 vim9script
1209 class A
1210 static def Foo()
1211 enddef
1212 aaa
1213 endclass
1214 END
1215 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001216enddef
1217
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001218def Test_class_defcompile()
1219 var lines =<< trim END
1220 vim9script
1221
1222 class C
1223 def Fo(i: number): string
1224 return i
1225 enddef
1226 endclass
1227
1228 defcompile C.Fo
1229 END
1230 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1231
1232 lines =<< trim END
1233 vim9script
1234
1235 class C
1236 static def Fc(): number
1237 return 'x'
1238 enddef
1239 endclass
1240
1241 defcompile C.Fc
1242 END
1243 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001244
1245 # Trying to compile a function using a non-existing class variable
1246 lines =<< trim END
1247 vim9script
1248 defcompile x.Foo()
1249 END
1250 v9.CheckScriptFailure(lines, 'E475:')
1251
1252 # Trying to compile a function using a variable which is not a class
1253 lines =<< trim END
1254 vim9script
1255 var x: number
1256 defcompile x.Foo()
1257 END
1258 v9.CheckScriptFailure(lines, 'E475:')
1259
1260 # Trying to compile a function without specifying the name
1261 lines =<< trim END
1262 vim9script
1263 class A
1264 endclass
1265 defcompile A.
1266 END
1267 v9.CheckScriptFailure(lines, 'E475:')
1268
1269 # Trying to compile a non-existing class object member function
1270 lines =<< trim END
1271 vim9script
1272 class A
1273 endclass
1274 var a = A.new()
1275 defcompile a.Foo()
1276 END
1277 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001278enddef
1279
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001280def Test_class_object_to_string()
1281 var lines =<< trim END
1282 vim9script
1283 class TextPosition
1284 this.lnum = 1
1285 this.col = 22
1286 endclass
1287
1288 assert_equal("class TextPosition", string(TextPosition))
1289
1290 var pos = TextPosition.new()
1291 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1292 END
1293 v9.CheckScriptSuccess(lines)
1294enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001295
Bram Moolenaar554d0312023-01-05 19:59:18 +00001296def Test_interface_basics()
1297 var lines =<< trim END
1298 vim9script
1299 interface Something
1300 this.value: string
1301 static count: number
1302 def GetCount(): number
1303 endinterface
1304 END
1305 v9.CheckScriptSuccess(lines)
1306
1307 lines =<< trim END
1308 interface SomethingWrong
1309 static count = 7
1310 endinterface
1311 END
1312 v9.CheckScriptFailure(lines, 'E1342:')
1313
1314 lines =<< trim END
1315 vim9script
1316
1317 interface Some
1318 static count: number
1319 def Method(count: number)
1320 endinterface
1321 END
h-east61378a12023-04-18 19:07:29 +01001322 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001323
1324 lines =<< trim END
1325 vim9script
1326
1327 interface Some
1328 this.value: number
1329 def Method(value: number)
1330 endinterface
1331 END
h-east61378a12023-04-18 19:07:29 +01001332 # The argument name and the object member name are the same, but this is not a
1333 # problem because object members are always accessed with the "this." prefix.
1334 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001335
1336 lines =<< trim END
1337 vim9script
1338 interface somethingWrong
1339 static count = 7
1340 endinterface
1341 END
1342 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1343
1344 lines =<< trim END
1345 vim9script
1346 interface SomethingWrong
1347 this.value: string
1348 static count = 7
1349 def GetCount(): number
1350 endinterface
1351 END
1352 v9.CheckScriptFailure(lines, 'E1344:')
1353
1354 lines =<< trim END
1355 vim9script
1356 interface SomethingWrong
1357 this.value: string
1358 static count: number
1359 def GetCount(): number
1360 return 5
1361 enddef
1362 endinterface
1363 END
1364 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001365
1366 lines =<< trim END
1367 vim9script
1368 export interface EnterExit
1369 def Enter(): void
1370 def Exit(): void
1371 endinterface
1372 END
1373 writefile(lines, 'XdefIntf.vim', 'D')
1374
1375 lines =<< trim END
1376 vim9script
1377 import './XdefIntf.vim' as defIntf
1378 export def With(ee: defIntf.EnterExit, F: func)
1379 ee.Enter()
1380 try
1381 F()
1382 finally
1383 ee.Exit()
1384 endtry
1385 enddef
1386 END
1387 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001388
1389 var imported =<< trim END
1390 vim9script
1391 export abstract class EnterExit
1392 def Enter(): void
1393 enddef
1394 def Exit(): void
1395 enddef
1396 endclass
1397 END
1398 writefile(imported, 'XdefIntf2.vim', 'D')
1399
1400 lines[1] = " import './XdefIntf2.vim' as defIntf"
1401 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001402enddef
1403
Bram Moolenaar94674f22023-01-06 18:42:20 +00001404def Test_class_implements_interface()
1405 var lines =<< trim END
1406 vim9script
1407
1408 interface Some
1409 static count: number
1410 def Method(nr: number)
1411 endinterface
1412
1413 class SomeImpl implements Some
1414 static count: number
1415 def Method(nr: number)
1416 echo nr
1417 enddef
1418 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001419
1420 interface Another
1421 this.member: string
1422 endinterface
1423
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001424 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001425 this.member = 'abc'
1426 static count: number
1427 def Method(nr: number)
1428 echo nr
1429 enddef
1430 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001431 END
1432 v9.CheckScriptSuccess(lines)
1433
1434 lines =<< trim END
1435 vim9script
1436
1437 interface Some
1438 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001439 endinterface
1440
1441 class SomeImpl implements Some implements Some
1442 static count: number
1443 endclass
1444 END
1445 v9.CheckScriptFailure(lines, 'E1350:')
1446
1447 lines =<< trim END
1448 vim9script
1449
1450 interface Some
1451 static counter: number
1452 endinterface
1453
1454 class SomeImpl implements Some, Some
1455 static count: number
1456 endclass
1457 END
1458 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1459
1460 lines =<< trim END
1461 vim9script
1462
1463 interface Some
1464 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001465 def Method(nr: number)
1466 endinterface
1467
1468 class SomeImpl implements Some
1469 static count: number
1470 def Method(nr: number)
1471 echo nr
1472 enddef
1473 endclass
1474 END
1475 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1476
1477 lines =<< trim END
1478 vim9script
1479
1480 interface Some
1481 static count: number
1482 def Methods(nr: number)
1483 endinterface
1484
1485 class SomeImpl implements Some
1486 static count: number
1487 def Method(nr: number)
1488 echo nr
1489 enddef
1490 endclass
1491 END
1492 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001493
1494 # Check different order of members in class and interface works.
1495 lines =<< trim END
1496 vim9script
1497
1498 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001499 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001500 this.errpos: number
1501 endinterface
1502
1503 # order of members is opposite of interface
1504 class Failure implements Result
1505 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001506 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001507 endclass
1508
1509 def Test()
1510 var result: Result = Failure.new()
1511
1512 assert_equal('label', result.label)
1513 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001514
1515 result.label = 'different'
1516 assert_equal('different', result.label)
1517 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001518 enddef
1519
1520 Test()
1521 END
1522 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001523
1524 # Interface name after "extends" doesn't end in a space or NUL character
1525 lines =<< trim END
1526 vim9script
1527 interface A
1528 endinterface
1529 class B extends A"
1530 endclass
1531 END
1532 v9.CheckScriptFailure(lines, 'E1315:')
1533
1534 # Trailing characters after a class name
1535 lines =<< trim END
1536 vim9script
1537 class A bbb
1538 endclass
1539 END
1540 v9.CheckScriptFailure(lines, 'E488:')
1541
1542 # using "implements" with a non-existing class
1543 lines =<< trim END
1544 vim9script
1545 class A implements B
1546 endclass
1547 END
1548 v9.CheckScriptFailure(lines, 'E1346:')
1549
1550 # using "implements" with a regular class
1551 lines =<< trim END
1552 vim9script
1553 class A
1554 endclass
1555 class B implements A
1556 endclass
1557 END
1558 v9.CheckScriptFailure(lines, 'E1347:')
1559
1560 # using "implements" with a variable
1561 lines =<< trim END
1562 vim9script
1563 var T: number = 10
1564 class A implements T
1565 endclass
1566 END
1567 v9.CheckScriptFailure(lines, 'E1347:')
1568
1569 # all the class methods in an "interface" should be implemented
1570 lines =<< trim END
1571 vim9script
1572 interface A
1573 static def Foo()
1574 endinterface
1575 class B implements A
1576 endclass
1577 END
1578 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001579
1580 lines =<< trim END
1581 vim9script
1582
1583 interface One
1584 static matching: bool
1585 static as_any: any
1586 static not_matching: number
1587 endinterface
1588 class Two implements One
1589 static not_matching: string
1590 static as_any: string
1591 static matching: bool
1592 endclass
1593 END
1594 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1595
1596 lines =<< trim END
1597 vim9script
1598
1599 interface One
1600 def IsEven(nr: number): bool
1601 endinterface
1602 class Two implements One
1603 def IsEven(nr: number): string
1604 enddef
1605 endclass
1606 END
1607 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1608
1609 lines =<< trim END
1610 vim9script
1611
1612 interface One
1613 def IsEven(nr: number): bool
1614 endinterface
1615 class Two implements One
1616 def IsEven(nr: bool): bool
1617 enddef
1618 endclass
1619 END
1620 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1621
1622 lines =<< trim END
1623 vim9script
1624
1625 interface One
1626 def IsEven(nr: number): bool
1627 endinterface
1628 class Two implements One
1629 def IsEven(nr: number, ...extra: list<number>): bool
1630 enddef
1631 endclass
1632 END
1633 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
Bram Moolenaar94674f22023-01-06 18:42:20 +00001634enddef
1635
Bram Moolenaard0200c82023-01-28 15:19:40 +00001636def Test_call_interface_method()
1637 var lines =<< trim END
1638 vim9script
1639 interface Base
1640 def Enter(): void
1641 endinterface
1642
1643 class Child implements Base
1644 def Enter(): void
1645 g:result ..= 'child'
1646 enddef
1647 endclass
1648
1649 def F(obj: Base)
1650 obj.Enter()
1651 enddef
1652
1653 g:result = ''
1654 F(Child.new())
1655 assert_equal('child', g:result)
1656 unlet g:result
1657 END
1658 v9.CheckScriptSuccess(lines)
1659
1660 lines =<< trim END
1661 vim9script
1662 class Base
1663 def Enter(): void
1664 g:result ..= 'base'
1665 enddef
1666 endclass
1667
1668 class Child extends Base
1669 def Enter(): void
1670 g:result ..= 'child'
1671 enddef
1672 endclass
1673
1674 def F(obj: Base)
1675 obj.Enter()
1676 enddef
1677
1678 g:result = ''
1679 F(Child.new())
1680 assert_equal('child', g:result)
1681 unlet g:result
1682 END
1683 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001684
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001685 # method of interface returns a value
1686 lines =<< trim END
1687 vim9script
1688 interface Base
1689 def Enter(): string
1690 endinterface
1691
1692 class Child implements Base
1693 def Enter(): string
1694 g:result ..= 'child'
1695 return "/resource"
1696 enddef
1697 endclass
1698
1699 def F(obj: Base)
1700 var r = obj.Enter()
1701 g:result ..= r
1702 enddef
1703
1704 g:result = ''
1705 F(Child.new())
1706 assert_equal('child/resource', g:result)
1707 unlet g:result
1708 END
1709 v9.CheckScriptSuccess(lines)
1710
1711 lines =<< trim END
1712 vim9script
1713 class Base
1714 def Enter(): string
1715 return null_string
1716 enddef
1717 endclass
1718
1719 class Child extends Base
1720 def Enter(): string
1721 g:result ..= 'child'
1722 return "/resource"
1723 enddef
1724 endclass
1725
1726 def F(obj: Base)
1727 var r = obj.Enter()
1728 g:result ..= r
1729 enddef
1730
1731 g:result = ''
1732 F(Child.new())
1733 assert_equal('child/resource', g:result)
1734 unlet g:result
1735 END
1736 v9.CheckScriptSuccess(lines)
1737
1738
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001739 # No class that implements the interface.
1740 lines =<< trim END
1741 vim9script
1742
1743 interface IWithEE
1744 def Enter(): any
1745 def Exit(): void
1746 endinterface
1747
1748 def With1(ee: IWithEE, F: func)
1749 var r = ee.Enter()
1750 enddef
1751
1752 defcompile
1753 END
1754 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001755enddef
1756
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001757def Test_class_used_as_type()
1758 var lines =<< trim END
1759 vim9script
1760
1761 class Point
1762 this.x = 0
1763 this.y = 0
1764 endclass
1765
1766 var p: Point
1767 p = Point.new(2, 33)
1768 assert_equal(2, p.x)
1769 assert_equal(33, p.y)
1770 END
1771 v9.CheckScriptSuccess(lines)
1772
1773 lines =<< trim END
1774 vim9script
1775
1776 interface HasX
1777 this.x: number
1778 endinterface
1779
1780 class Point implements HasX
1781 this.x = 0
1782 this.y = 0
1783 endclass
1784
1785 var p: Point
1786 p = Point.new(2, 33)
1787 var hx = p
1788 assert_equal(2, hx.x)
1789 END
1790 v9.CheckScriptSuccess(lines)
1791
1792 lines =<< trim END
1793 vim9script
1794
1795 class Point
1796 this.x = 0
1797 this.y = 0
1798 endclass
1799
1800 var p: Point
1801 p = 'text'
1802 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001803 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001804enddef
1805
Bram Moolenaar83677162023-01-08 19:54:10 +00001806def Test_class_extends()
1807 var lines =<< trim END
1808 vim9script
1809 class Base
1810 this.one = 1
1811 def GetOne(): number
1812 return this.one
1813 enddef
1814 endclass
1815 class Child extends Base
1816 this.two = 2
1817 def GetTotal(): number
1818 return this.one + this.two
1819 enddef
1820 endclass
1821 var o = Child.new()
1822 assert_equal(1, o.one)
1823 assert_equal(2, o.two)
1824 assert_equal(1, o.GetOne())
1825 assert_equal(3, o.GetTotal())
1826 END
1827 v9.CheckScriptSuccess(lines)
1828
1829 lines =<< trim END
1830 vim9script
1831 class Base
1832 this.one = 1
1833 endclass
1834 class Child extends Base
1835 this.two = 2
1836 endclass
1837 var o = Child.new(3, 44)
1838 assert_equal(3, o.one)
1839 assert_equal(44, o.two)
1840 END
1841 v9.CheckScriptSuccess(lines)
1842
1843 lines =<< trim END
1844 vim9script
1845 class Base
1846 this.one = 1
1847 endclass
1848 class Child extends Base extends Base
1849 this.two = 2
1850 endclass
1851 END
1852 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1853
1854 lines =<< trim END
1855 vim9script
1856 class Child extends BaseClass
1857 this.two = 2
1858 endclass
1859 END
1860 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1861
1862 lines =<< trim END
1863 vim9script
1864 var SomeVar = 99
1865 class Child extends SomeVar
1866 this.two = 2
1867 endclass
1868 END
1869 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001870
1871 lines =<< trim END
1872 vim9script
1873 class Base
1874 this.name: string
1875 def ToString(): string
1876 return this.name
1877 enddef
1878 endclass
1879
1880 class Child extends Base
1881 this.age: number
1882 def ToString(): string
1883 return super.ToString() .. ': ' .. this.age
1884 enddef
1885 endclass
1886
1887 var o = Child.new('John', 42)
1888 assert_equal('John: 42', o.ToString())
1889 END
1890 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001891
1892 lines =<< trim END
1893 vim9script
1894 class Child
1895 this.age: number
1896 def ToString(): number
1897 return this.age
1898 enddef
1899 def ToString(): string
1900 return this.age
1901 enddef
1902 endclass
1903 END
1904 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1905
1906 lines =<< trim END
1907 vim9script
1908 class Child
1909 this.age: number
1910 def ToString(): string
1911 return super .ToString() .. ': ' .. this.age
1912 enddef
1913 endclass
1914 var o = Child.new(42)
1915 echo o.ToString()
1916 END
1917 v9.CheckScriptFailure(lines, 'E1356:')
1918
1919 lines =<< trim END
1920 vim9script
1921 class Base
1922 this.name: string
1923 def ToString(): string
1924 return this.name
1925 enddef
1926 endclass
1927
1928 var age = 42
1929 def ToString(): string
1930 return super.ToString() .. ': ' .. age
1931 enddef
1932 echo ToString()
1933 END
1934 v9.CheckScriptFailure(lines, 'E1357:')
1935
1936 lines =<< trim END
1937 vim9script
1938 class Child
1939 this.age: number
1940 def ToString(): string
1941 return super.ToString() .. ': ' .. this.age
1942 enddef
1943 endclass
1944 var o = Child.new(42)
1945 echo o.ToString()
1946 END
1947 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001948
1949 lines =<< trim END
1950 vim9script
1951 class Base
1952 this.name: string
1953 static def ToString(): string
1954 return 'Base class'
1955 enddef
1956 endclass
1957
1958 class Child extends Base
1959 this.age: number
1960 def ToString(): string
1961 return Base.ToString() .. ': ' .. this.age
1962 enddef
1963 endclass
1964
1965 var o = Child.new('John', 42)
1966 assert_equal('Base class: 42', o.ToString())
1967 END
1968 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001969
1970 lines =<< trim END
1971 vim9script
1972 class Base
1973 this.value = 1
1974 def new(init: number)
1975 this.value = number + 1
1976 enddef
1977 endclass
1978 class Child extends Base
1979 def new()
1980 this.new(3)
1981 enddef
1982 endclass
1983 var c = Child.new()
1984 END
1985 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00001986
1987 # base class with more than one object member
1988 lines =<< trim END
1989 vim9script
1990
1991 class Result
1992 this.success: bool
1993 this.value: any = null
1994 endclass
1995
1996 class Success extends Result
1997 def new(this.value = v:none)
1998 this.success = true
1999 enddef
2000 endclass
2001
2002 var v = Success.new('asdf')
2003 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2004 END
2005 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002006
2007 # class name after "extends" doesn't end in a space or NUL character
2008 lines =<< trim END
2009 vim9script
2010 class A
2011 endclass
2012 class B extends A"
2013 endclass
2014 END
2015 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002016enddef
2017
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002018def Test_using_base_class()
2019 var lines =<< trim END
2020 vim9script
2021
2022 class BaseEE
2023 def Enter(): any
2024 return null
2025 enddef
2026 def Exit(resource: any): void
2027 enddef
2028 endclass
2029
2030 class ChildEE extends BaseEE
2031 def Enter(): any
2032 return 42
2033 enddef
2034
2035 def Exit(resource: number): void
2036 g:result ..= '/exit'
2037 enddef
2038 endclass
2039
2040 def With(ee: BaseEE)
2041 var r = ee.Enter()
2042 try
2043 g:result ..= r
2044 finally
2045 g:result ..= '/finally'
2046 ee.Exit(r)
2047 endtry
2048 enddef
2049
2050 g:result = ''
2051 With(ChildEE.new())
2052 assert_equal('42/finally/exit', g:result)
2053 END
2054 v9.CheckScriptSuccess(lines)
2055 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002056
2057 # Using super, Child invokes Base method which has optional arg. #12471
2058 lines =<< trim END
2059 vim9script
2060
2061 class Base
2062 this.success: bool = false
2063 def Method(arg = 0)
2064 this.success = true
2065 enddef
2066 endclass
2067
2068 class Child extends Base
2069 def new()
2070 super.Method()
2071 enddef
2072 endclass
2073
2074 var obj = Child.new()
2075 assert_equal(true, obj.success)
2076 END
2077 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002078enddef
2079
2080
Bram Moolenaara86655a2023-01-12 17:06:27 +00002081def Test_class_import()
2082 var lines =<< trim END
2083 vim9script
2084 export class Animal
2085 this.kind: string
2086 this.name: string
2087 endclass
2088 END
2089 writefile(lines, 'Xanimal.vim', 'D')
2090
2091 lines =<< trim END
2092 vim9script
2093 import './Xanimal.vim' as animal
2094
2095 var a: animal.Animal
2096 a = animal.Animal.new('fish', 'Eric')
2097 assert_equal('fish', a.kind)
2098 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002099
2100 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2101 assert_equal('cat', b.kind)
2102 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002103 END
2104 v9.CheckScriptSuccess(lines)
2105enddef
2106
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002107def Test_abstract_class()
2108 var lines =<< trim END
2109 vim9script
2110 abstract class Base
2111 this.name: string
2112 endclass
2113 class Person extends Base
2114 this.age: number
2115 endclass
2116 var p: Base = Person.new('Peter', 42)
2117 assert_equal('Peter', p.name)
2118 assert_equal(42, p.age)
2119 END
2120 v9.CheckScriptSuccess(lines)
2121
2122 lines =<< trim END
2123 vim9script
2124 abstract class Base
2125 this.name: string
2126 endclass
2127 class Person extends Base
2128 this.age: number
2129 endclass
2130 var p = Base.new('Peter')
2131 END
2132 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2133
2134 lines =<< trim END
2135 abstract class Base
2136 this.name: string
2137 endclass
2138 END
2139 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002140
2141 # Abstract class cannot have a "new" function
2142 lines =<< trim END
2143 vim9script
2144 abstract class Base
2145 def new()
2146 enddef
2147 endclass
2148 END
2149 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002150enddef
2151
Bram Moolenaar486fc252023-01-18 14:51:07 +00002152def Test_closure_in_class()
2153 var lines =<< trim END
2154 vim9script
2155
2156 class Foo
2157 this.y: list<string> = ['B']
2158
2159 def new()
2160 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2161 enddef
2162 endclass
2163
2164 Foo.new()
2165 assert_equal(['A'], g:result)
2166 END
2167 v9.CheckScriptSuccess(lines)
2168enddef
2169
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002170def Test_call_constructor_from_legacy()
2171 var lines =<< trim END
2172 vim9script
2173
2174 var newCalled = 'false'
2175
2176 class A
2177 def new()
2178 newCalled = 'true'
2179 enddef
2180 endclass
2181
2182 export def F(options = {}): any
2183 return A
2184 enddef
2185
2186 g:p = F()
2187 legacy call p.new()
2188 assert_equal('true', newCalled)
2189 END
2190 v9.CheckScriptSuccess(lines)
2191enddef
2192
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002193def Test_defer_with_object()
2194 var lines =<< trim END
2195 vim9script
2196
2197 class CWithEE
2198 def Enter()
2199 g:result ..= "entered/"
2200 enddef
2201 def Exit()
2202 g:result ..= "exited"
2203 enddef
2204 endclass
2205
2206 def With(ee: CWithEE, F: func)
2207 ee.Enter()
2208 defer ee.Exit()
2209 F()
2210 enddef
2211
2212 g:result = ''
2213 var obj = CWithEE.new()
2214 obj->With(() => {
2215 g:result ..= "called/"
2216 })
2217 assert_equal('entered/called/exited', g:result)
2218 END
2219 v9.CheckScriptSuccess(lines)
2220 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002221
2222 lines =<< trim END
2223 vim9script
2224
2225 class BaseWithEE
2226 def Enter()
2227 g:result ..= "entered-base/"
2228 enddef
2229 def Exit()
2230 g:result ..= "exited-base"
2231 enddef
2232 endclass
2233
2234 class CWithEE extends BaseWithEE
2235 def Enter()
2236 g:result ..= "entered-child/"
2237 enddef
2238 def Exit()
2239 g:result ..= "exited-child"
2240 enddef
2241 endclass
2242
2243 def With(ee: BaseWithEE, F: func)
2244 ee.Enter()
2245 defer ee.Exit()
2246 F()
2247 enddef
2248
2249 g:result = ''
2250 var obj = CWithEE.new()
2251 obj->With(() => {
2252 g:result ..= "called/"
2253 })
2254 assert_equal('entered-child/called/exited-child', g:result)
2255 END
2256 v9.CheckScriptSuccess(lines)
2257 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002258enddef
2259
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002260" The following test used to crash Vim (Github issue #12676)
2261def Test_extends_method_crashes_vim()
2262 var lines =<< trim END
2263 vim9script
2264
2265 class Observer
2266 endclass
2267
2268 class Property
2269 this.value: any
2270
2271 def Set(v: any)
2272 if v != this.value
2273 this.value = v
2274 endif
2275 enddef
2276
2277 def Register(observer: Observer)
2278 enddef
2279 endclass
2280
2281 class Bool extends Property
2282 this.value: bool
2283 endclass
2284
2285 def Observe(obj: Property, who: Observer)
2286 obj.Register(who)
2287 enddef
2288
2289 var p = Bool.new(false)
2290 var myObserver = Observer.new()
2291
2292 Observe(p, myObserver)
2293
2294 p.Set(true)
2295 END
2296 v9.CheckScriptSuccess(lines)
2297enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002298
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002299" Test for calling a method in a class that is extended
2300def Test_call_method_in_extended_class()
2301 var lines =<< trim END
2302 vim9script
2303
2304 var prop_init_called = false
2305 var prop_register_called = false
2306
2307 class Property
2308 def Init()
2309 prop_init_called = true
2310 enddef
2311
2312 def Register()
2313 prop_register_called = true
2314 enddef
2315 endclass
2316
2317 class Bool extends Property
2318 endclass
2319
2320 def Observe(obj: Property)
2321 obj.Register()
2322 enddef
2323
2324 var p = Property.new()
2325 Observe(p)
2326
2327 p.Init()
2328 assert_true(prop_init_called)
2329 assert_true(prop_register_called)
2330 END
2331 v9.CheckScriptSuccess(lines)
2332enddef
2333
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002334" Test for calling a method in the parent class that is extended partially.
2335" This used to fail with the 'E118: Too many arguments for function: Text' error
2336" message (Github issue #12524).
2337def Test_call_method_in_parent_class()
2338 var lines =<< trim END
2339 vim9script
2340
2341 class Widget
2342 this._lnum: number = 1
2343
2344 def SetY(lnum: number)
2345 this._lnum = lnum
2346 enddef
2347
2348 def Text(): string
2349 return ''
2350 enddef
2351 endclass
2352
2353 class Foo extends Widget
2354 def Text(): string
2355 return '<Foo>'
2356 enddef
2357 endclass
2358
2359 def Stack(w1: Widget, w2: Widget): list<Widget>
2360 w1.SetY(1)
2361 w2.SetY(2)
2362 return [w1, w2]
2363 enddef
2364
2365 var foo1 = Foo.new()
2366 var foo2 = Foo.new()
2367 var l = Stack(foo1, foo2)
2368 END
2369 v9.CheckScriptSuccess(lines)
2370enddef
2371
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002372" Test for calling methods from three levels of classes
2373def Test_multi_level_method_call()
2374 var lines =<< trim END
2375 vim9script
2376
2377 var A_func1: number = 0
2378 var A_func2: number = 0
2379 var A_func3: number = 0
2380 var B_func2: number = 0
2381 var B_func3: number = 0
2382 var C_func3: number = 0
2383
2384 class A
2385 def Func1()
2386 A_func1 += 1
2387 enddef
2388
2389 def Func2()
2390 A_func2 += 1
2391 enddef
2392
2393 def Func3()
2394 A_func3 += 1
2395 enddef
2396 endclass
2397
2398 class B extends A
2399 def Func2()
2400 B_func2 += 1
2401 enddef
2402
2403 def Func3()
2404 B_func3 += 1
2405 enddef
2406 endclass
2407
2408 class C extends B
2409 def Func3()
2410 C_func3 += 1
2411 enddef
2412 endclass
2413
2414 def A_CallFuncs(a: A)
2415 a.Func1()
2416 a.Func2()
2417 a.Func3()
2418 enddef
2419
2420 def B_CallFuncs(b: B)
2421 b.Func1()
2422 b.Func2()
2423 b.Func3()
2424 enddef
2425
2426 def C_CallFuncs(c: C)
2427 c.Func1()
2428 c.Func2()
2429 c.Func3()
2430 enddef
2431
2432 var cobj = C.new()
2433 A_CallFuncs(cobj)
2434 B_CallFuncs(cobj)
2435 C_CallFuncs(cobj)
2436 assert_equal(3, A_func1)
2437 assert_equal(0, A_func2)
2438 assert_equal(0, A_func3)
2439 assert_equal(3, B_func2)
2440 assert_equal(0, B_func3)
2441 assert_equal(3, C_func3)
2442 END
2443 v9.CheckScriptSuccess(lines)
2444enddef
2445
2446" Test for using members from three levels of classes
2447def Test_multi_level_member_access()
2448 var lines =<< trim END
2449 vim9script
2450
2451 class A
2452 this.val1: number = 0
2453 this.val2: number = 0
2454 this.val3: number = 0
2455 endclass
2456
2457 class B extends A
2458 this.val2: number = 0
2459 this.val3: number = 0
2460 endclass
2461
2462 class C extends B
2463 this.val3: number = 0
2464 endclass
2465
2466 def A_members(a: A)
2467 a.val1 += 1
2468 a.val2 += 1
2469 a.val3 += 1
2470 enddef
2471
2472 def B_members(b: B)
2473 b.val1 += 1
2474 b.val2 += 1
2475 b.val3 += 1
2476 enddef
2477
2478 def C_members(c: C)
2479 c.val1 += 1
2480 c.val2 += 1
2481 c.val3 += 1
2482 enddef
2483
2484 var cobj = C.new()
2485 A_members(cobj)
2486 B_members(cobj)
2487 C_members(cobj)
2488 assert_equal(3, cobj.val1)
2489 assert_equal(3, cobj.val2)
2490 assert_equal(3, cobj.val3)
2491 END
2492 v9.CheckScriptSuccess(lines)
2493enddef
2494
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002495" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker