blob: 5f5528aebd1d3f04cb9d35c63a64d978977371a5 [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:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200213
214 lines =<< trim END
215 vim9script
216 class A
217 this.y = {
218 X: 1
219 }
220 endclass
221 var a = A.new()
222 END
223 v9.CheckScriptSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000224enddef
225
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000226def Test_class_defined_twice()
227 # class defined twice should fail
228 var lines =<< trim END
229 vim9script
230 class There
231 endclass
232 class There
233 endclass
234 END
235 v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "There"')
236
237 # one class, reload same script twice is OK
238 lines =<< trim END
239 vim9script
240 class There
241 endclass
242 END
243 writefile(lines, 'XclassTwice.vim', 'D')
244 source XclassTwice.vim
245 source XclassTwice.vim
246enddef
247
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000248def Test_returning_null_object()
249 # this was causing an internal error
250 var lines =<< trim END
251 vim9script
252
253 class BufferList
254 def Current(): any
255 return null_object
256 enddef
257 endclass
258
259 var buffers = BufferList.new()
260 echo buffers.Current()
261 END
262 v9.CheckScriptSuccess(lines)
263enddef
264
Bram Moolenaard13dd302023-03-11 20:56:35 +0000265def Test_using_null_class()
266 var lines =<< trim END
267 @_ = null_class.member
268 END
269 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
270enddef
271
Bram Moolenaar657aea72023-01-27 13:16:19 +0000272def Test_class_interface_wrong_end()
273 var lines =<< trim END
274 vim9script
275 abstract class SomeName
276 this.member = 'text'
277 endinterface
278 END
279 v9.CheckScriptFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
280
281 lines =<< trim END
282 vim9script
283 export interface AnotherName
284 this.member: string
285 endclass
286 END
287 v9.CheckScriptFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
288enddef
289
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000290def Test_object_not_set()
291 var lines =<< trim END
292 vim9script
293
294 class State
295 this.value = 'xyz'
296 endclass
297
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000298 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000299 var db = {'xyz': 789}
300 echo db[state.value]
301 END
302 v9.CheckScriptFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000303
304 lines =<< trim END
305 vim9script
306
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000307 class Class
308 this.id: string
309 def Method1()
310 echo 'Method1' .. this.id
311 enddef
312 endclass
313
314 var obj: Class
315 def Func()
316 obj.Method1()
317 enddef
318 Func()
319 END
320 v9.CheckScriptFailure(lines, 'E1360:')
321
322 lines =<< trim END
323 vim9script
324
Bram Moolenaar0917e862023-02-18 14:42:44 +0000325 class Background
326 this.background = 'dark'
327 endclass
328
329 class Colorscheme
330 this._bg: Background
331
332 def GetBackground(): string
333 return this._bg.background
334 enddef
335 endclass
336
337 var bg: Background # UNINITIALIZED
338 echo Colorscheme.new(bg).GetBackground()
339 END
Ernie Rael5c018be2023-08-27 18:40:26 +0200340 v9.CheckScriptFailure(lines, 'E1360:')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000341
342 # TODO: this should not give an error but be handled at runtime
343 lines =<< trim END
344 vim9script
345
346 class Class
347 this.id: string
348 def Method1()
349 echo 'Method1' .. this.id
350 enddef
351 endclass
352
353 var obj = null_object
354 def Func()
355 obj.Method1()
356 enddef
357 Func()
358 END
359 v9.CheckScriptFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000360enddef
361
Ernie Rael5c018be2023-08-27 18:40:26 +0200362def Test_null_object_assign_compare()
363 var lines =<< trim END
364 vim9script
365
366 var nullo = null_object
367 def F(): any
368 return nullo
369 enddef
370 assert_equal('object<Unknown>', typename(F()))
371
372 var o0 = F()
373 assert_true(o0 == null_object)
374 assert_true(o0 == null)
375
376 var o1: any = nullo
377 assert_true(o1 == null_object)
378 assert_true(o1 == null)
379
380 def G()
381 var x = null_object
382 enddef
383
384 class C
385 endclass
386 var o2: C
387 assert_true(o2 == null_object)
388 assert_true(o2 == null)
389
390 o2 = null_object
391 assert_true(o2 == null)
392
393 o2 = C.new()
394 assert_true(o2 != null)
395
396 o2 = null_object
397 assert_true(o2 == null)
398 END
399 v9.CheckScriptSuccess(lines)
400enddef
401
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000402def Test_class_member_initializer()
403 var lines =<< trim END
404 vim9script
405
406 class TextPosition
407 this.lnum: number = 1
408 this.col: number = 1
409
Bram Moolenaar418b5472022-12-20 13:38:22 +0000410 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000411 def new(lnum: number)
412 this.lnum = lnum
413 enddef
414 endclass
415
416 var pos = TextPosition.new(3)
417 assert_equal(3, pos.lnum)
418 assert_equal(1, pos.col)
419
420 var instr = execute('disassemble TextPosition.new')
421 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000422 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000423 '\d PUSHNR 1\_s*' ..
424 '\d STORE_THIS 0\_s*' ..
425 '\d PUSHNR 1\_s*' ..
426 '\d STORE_THIS 1\_s*' ..
427 'this.lnum = lnum\_s*' ..
428 '\d LOAD arg\[-1]\_s*' ..
429 '\d PUSHNR 0\_s*' ..
430 '\d LOAD $0\_s*' ..
431 '\d\+ STOREINDEX object\_s*' ..
432 '\d\+ RETURN object.*',
433 instr)
434 END
435 v9.CheckScriptSuccess(lines)
436enddef
437
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000438def Test_member_any_used_as_object()
439 var lines =<< trim END
440 vim9script
441
442 class Inner
443 this.value: number = 0
444 endclass
445
446 class Outer
447 this.inner: any
448 endclass
449
450 def F(outer: Outer)
451 outer.inner.value = 1
452 enddef
453
454 var inner_obj = Inner.new(0)
455 var outer_obj = Outer.new(inner_obj)
456 F(outer_obj)
457 assert_equal(1, inner_obj.value)
458 END
459 v9.CheckScriptSuccess(lines)
460
461 lines =<< trim END
462 vim9script
463
464 class Inner
465 this.value: number = 0
466 endclass
467
468 class Outer
469 this.inner: Inner
470 endclass
471
472 def F(outer: Outer)
473 outer.inner.value = 1
474 enddef
475
476 def Test_assign_to_nested_typed_member()
477 var inner = Inner.new(0)
478 var outer = Outer.new(inner)
479 F(outer)
480 assert_equal(1, inner.value)
481 enddef
482
483 Test_assign_to_nested_typed_member()
484 END
485 v9.CheckScriptSuccess(lines)
486enddef
487
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000488def Test_assignment_with_operator()
489 var lines =<< trim END
490 vim9script
491
492 class Foo
493 this.x: number
494
495 def Add(n: number)
496 this.x += n
497 enddef
498 endclass
499
500 var f = Foo.new(3)
501 f.Add(17)
502 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100503
504 def AddToFoo(obj: Foo)
505 obj.x += 3
506 enddef
507
508 AddToFoo(f)
509 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000510 END
511 v9.CheckScriptSuccess(lines)
512enddef
513
Bram Moolenaarf4508042023-01-15 16:54:57 +0000514def Test_list_of_objects()
515 var lines =<< trim END
516 vim9script
517
518 class Foo
519 def Add()
520 enddef
521 endclass
522
523 def ProcessList(fooList: list<Foo>)
524 for foo in fooList
525 foo.Add()
526 endfor
527 enddef
528
529 var l: list<Foo> = [Foo.new()]
530 ProcessList(l)
531 END
532 v9.CheckScriptSuccess(lines)
533enddef
534
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000535def Test_expr_after_using_object()
536 var lines =<< trim END
537 vim9script
538
539 class Something
540 this.label: string = ''
541 endclass
542
543 def Foo(): Something
544 var v = Something.new()
545 echo 'in Foo(): ' .. typename(v)
546 return v
547 enddef
548
549 Foo()
550 END
551 v9.CheckScriptSuccess(lines)
552enddef
553
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000554def Test_class_default_new()
555 var lines =<< trim END
556 vim9script
557
558 class TextPosition
559 this.lnum: number = 1
560 this.col: number = 1
561 endclass
562
563 var pos = TextPosition.new()
564 assert_equal(1, pos.lnum)
565 assert_equal(1, pos.col)
566
567 pos = TextPosition.new(v:none, v:none)
568 assert_equal(1, pos.lnum)
569 assert_equal(1, pos.col)
570
571 pos = TextPosition.new(3, 22)
572 assert_equal(3, pos.lnum)
573 assert_equal(22, pos.col)
574
575 pos = TextPosition.new(v:none, 33)
576 assert_equal(1, pos.lnum)
577 assert_equal(33, pos.col)
578 END
579 v9.CheckScriptSuccess(lines)
580
581 lines =<< trim END
582 vim9script
583 class Person
584 this.name: string
585 this.age: number = 42
586 this.education: string = "unknown"
587
588 def new(this.name, this.age = v:none, this.education = v:none)
589 enddef
590 endclass
591
592 var piet = Person.new("Piet")
593 assert_equal("Piet", piet.name)
594 assert_equal(42, piet.age)
595 assert_equal("unknown", piet.education)
596
597 var chris = Person.new("Chris", 4, "none")
598 assert_equal("Chris", chris.name)
599 assert_equal(4, chris.age)
600 assert_equal("none", chris.education)
601 END
602 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000603
604 lines =<< trim END
605 vim9script
606 class Person
607 this.name: string
608 this.age: number = 42
609 this.education: string = "unknown"
610
611 def new(this.name, this.age = v:none, this.education = v:none)
612 enddef
613 endclass
614
615 var missing = Person.new()
616 END
617 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000618enddef
619
h-east2261c892023-08-16 21:49:54 +0900620
621def Test_class_new_with_object_member()
622 var lines =<< trim END
623 vim9script
624
625 class C
626 this.str: string
627 this.num: number
628 def new(this.str, this.num)
629 enddef
630 def newVals(this.str, this.num)
631 enddef
632 endclass
633
634 def Check()
635 try
636 var c = C.new('cats', 2)
637 assert_equal('cats', c.str)
638 assert_equal(2, c.num)
639
640 c = C.newVals('dogs', 4)
641 assert_equal('dogs', c.str)
642 assert_equal(4, c.num)
643 catch
644 assert_report($'Unexpected exception was caught: {v:exception}')
645 endtry
646 enddef
647
648 Check()
649 END
650 v9.CheckScriptSuccess(lines)
651
652 lines =<< trim END
653 vim9script
654
655 class C
656 this.str: string
657 this.num: number
658 def new(this.str, this.num)
659 enddef
660 endclass
661
662 def Check()
663 try
664 var c = C.new(1, 2)
665 catch
666 assert_report($'Unexpected exception was caught: {v:exception}')
667 endtry
668 enddef
669
670 Check()
671 END
672 v9.CheckScriptFailure(lines, 'E1013:')
673
674 lines =<< trim END
675 vim9script
676
677 class C
678 this.str: string
679 this.num: number
680 def newVals(this.str, this.num)
681 enddef
682 endclass
683
684 def Check()
685 try
686 var c = C.newVals('dogs', 'apes')
687 catch
688 assert_report($'Unexpected exception was caught: {v:exception}')
689 endtry
690 enddef
691
692 Check()
693 END
694 v9.CheckScriptFailure(lines, 'E1013:')
695enddef
696
Bram Moolenaar74e12742022-12-13 21:14:28 +0000697def Test_class_object_member_inits()
698 var lines =<< trim END
699 vim9script
700 class TextPosition
701 this.lnum: number
702 this.col = 1
703 this.addcol: number = 2
704 endclass
705
706 var pos = TextPosition.new()
707 assert_equal(0, pos.lnum)
708 assert_equal(1, pos.col)
709 assert_equal(2, pos.addcol)
710 END
711 v9.CheckScriptSuccess(lines)
712
713 lines =<< trim END
714 vim9script
715 class TextPosition
716 this.lnum
717 this.col = 1
718 endclass
719 END
720 v9.CheckScriptFailure(lines, 'E1022:')
721
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200722 # If the type is not specified for a member, then it should be set during
723 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000724 lines =<< trim END
725 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200726
727 var init_count = 0
728 def Init(): string
729 init_count += 1
730 return 'foo'
731 enddef
732
733 class A
734 this.str1 = Init()
735 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000736 this.col = 1
737 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200738
739 assert_equal(init_count, 0)
740 var a = A.new()
741 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000742 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200743 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200744
745 # Test for initializing an object member with an unknown variable/type
746 lines =<< trim END
747 vim9script
748 class A
749 this.value = init_val
750 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200751 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200752 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200753 v9.CheckScriptFailure(lines, 'E1001:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000754enddef
755
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000756def Test_class_object_member_access()
757 var lines =<< trim END
758 vim9script
759 class Triple
760 this._one = 1
761 this.two = 2
762 public this.three = 3
763
764 def GetOne(): number
765 return this._one
766 enddef
767 endclass
768
769 var trip = Triple.new()
770 assert_equal(1, trip.GetOne())
771 assert_equal(2, trip.two)
772 assert_equal(3, trip.three)
773 assert_fails('echo trip._one', 'E1333')
774
775 assert_fails('trip._one = 11', 'E1333')
776 assert_fails('trip.two = 22', 'E1335')
777 trip.three = 33
778 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000779
780 assert_fails('trip.four = 4', 'E1334')
781 END
782 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000783
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200784 # Test for a public member variable name beginning with an underscore
785 lines =<< trim END
786 vim9script
787 class A
788 public this._val = 10
789 endclass
790 END
791 v9.CheckScriptFailure(lines, 'E1332:')
792
Bram Moolenaar590162c2022-12-24 21:24:06 +0000793 lines =<< trim END
794 vim9script
795
796 class MyCar
797 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000798 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000799
800 def new(make_arg: string)
801 this.make = make_arg
802 enddef
803
804 def GetMake(): string
805 return $"make = {this.make}"
806 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000807 def GetAge(): number
808 return this.age
809 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000810 endclass
811
812 var c = MyCar.new("abc")
813 assert_equal('make = abc', c.GetMake())
814
815 c = MyCar.new("def")
816 assert_equal('make = def', c.GetMake())
817
818 var c2 = MyCar.new("123")
819 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000820
821 def CheckCar()
822 assert_equal("make = def", c.GetMake())
823 assert_equal(5, c.GetAge())
824 enddef
825 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000826 END
827 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000828
829 lines =<< trim END
830 vim9script
831
832 class MyCar
833 this.make: string
834
835 def new(make_arg: string)
836 this.make = make_arg
837 enddef
838 endclass
839
840 var c = MyCar.new("abc")
841 var c = MyCar.new("def")
842 END
843 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000844
845 lines =<< trim END
846 vim9script
847
848 class Foo
849 this.x: list<number> = []
850
851 def Add(n: number): any
852 this.x->add(n)
853 return this
854 enddef
855 endclass
856
857 echo Foo.new().Add(1).Add(2).x
858 echo Foo.new().Add(1).Add(2)
859 .x
860 echo Foo.new().Add(1)
861 .Add(2).x
862 echo Foo.new()
863 .Add(1).Add(2).x
864 echo Foo.new()
865 .Add(1)
866 .Add(2)
867 .x
868 END
869 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200870
871 # Test for "public" cannot be abbreviated
872 lines =<< trim END
873 vim9script
874 class Something
875 pub this.val = 1
876 endclass
877 END
878 v9.CheckScriptFailure(lines, 'E1065:')
879
880 # Test for "public" keyword must be followed by "this" or "static".
881 lines =<< trim END
882 vim9script
883 class Something
884 public val = 1
885 endclass
886 END
887 v9.CheckScriptFailure(lines, 'E1331:')
888
889 # Test for "static" cannot be abbreviated
890 lines =<< trim END
891 vim9script
892 class Something
893 stat this.val = 1
894 endclass
895 END
896 v9.CheckScriptFailure(lines, 'E1065:')
Bram Moolenaard505d172022-12-18 21:42:55 +0000897enddef
898
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000899def Test_class_object_compare()
900 var class_lines =<< trim END
901 vim9script
902 class Item
903 this.nr = 0
904 this.name = 'xx'
905 endclass
906 END
907
908 # used at the script level and in a compiled function
909 var test_lines =<< trim END
910 var i1 = Item.new()
911 assert_equal(i1, i1)
912 assert_true(i1 is i1)
913 var i2 = Item.new()
914 assert_equal(i1, i2)
915 assert_false(i1 is i2)
916 var i3 = Item.new(0, 'xx')
917 assert_equal(i1, i3)
918
919 var io1 = Item.new(1, 'xx')
920 assert_notequal(i1, io1)
921 var io2 = Item.new(0, 'yy')
922 assert_notequal(i1, io2)
923 END
924
925 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000926 v9.CheckScriptSuccess(
927 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000928
929 for op in ['>', '>=', '<', '<=', '=~', '!~']
930 var op_lines = [
931 'var i1 = Item.new()',
932 'var i2 = Item.new()',
933 'echo i1 ' .. op .. ' i2',
934 ]
935 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000936 v9.CheckScriptFailure(class_lines
937 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000938 endfor
939enddef
940
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000941def Test_object_type()
942 var lines =<< trim END
943 vim9script
944
945 class One
946 this.one = 1
947 endclass
948 class Two
949 this.two = 2
950 endclass
951 class TwoMore extends Two
952 this.more = 9
953 endclass
954
955 var o: One = One.new()
956 var t: Two = Two.new()
957 var m: TwoMore = TwoMore.new()
958 var tm: Two = TwoMore.new()
959
960 t = m
961 END
962 v9.CheckScriptSuccess(lines)
963
964 lines =<< trim END
965 vim9script
966
967 class One
968 this.one = 1
969 endclass
970 class Two
971 this.two = 2
972 endclass
973
974 var o: One = Two.new()
975 END
976 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000977
978 lines =<< trim END
979 vim9script
980
981 interface One
982 def GetMember(): number
983 endinterface
984 class Two implements One
985 this.one = 1
986 def GetMember(): number
987 return this.one
988 enddef
989 endclass
990
991 var o: One = Two.new(5)
992 assert_equal(5, o.GetMember())
993 END
994 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +0000995
996 lines =<< trim END
997 vim9script
998
999 class Num
1000 this.n: number = 0
1001 endclass
1002
1003 def Ref(name: string): func(Num): Num
1004 return (arg: Num): Num => {
1005 return eval(name)(arg)
1006 }
1007 enddef
1008
1009 const Fn = Ref('Double')
1010 var Double = (m: Num): Num => Num.new(m.n * 2)
1011
1012 echo Fn(Num.new(4))
1013 END
1014 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001015enddef
1016
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001017def Test_class_member()
1018 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001019 var lines =<< trim END
1020 vim9script
1021 class TextPos
1022 this.lnum = 1
1023 this.col = 1
1024 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001025 static _secret = 7
1026 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001027
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001028 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001029 counter += nr
1030 enddef
1031 endclass
1032
1033 assert_equal(0, TextPos.counter)
1034 TextPos.AddToCounter(3)
1035 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001036 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001037
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001038 def GetCounter(): number
1039 return TextPos.counter
1040 enddef
1041 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001042
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001043 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001044 assert_fails('TextPos.counter = 5', 'E1335:')
1045 assert_fails('TextPos.counter += 5', 'E1335:')
1046
1047 assert_fails('echo TextPos._secret', 'E1333:')
1048 assert_fails('TextPos._secret = 8', 'E1333:')
1049
1050 assert_equal(42, TextPos.anybody)
1051 TextPos.anybody = 12
1052 assert_equal(12, TextPos.anybody)
1053 TextPos.anybody += 5
1054 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001055 END
1056 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001057
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001058 # example in the help
1059 lines =<< trim END
1060 vim9script
1061 class OtherThing
1062 this.size: number
1063 static totalSize: number
1064
1065 def new(this.size)
1066 totalSize += this.size
1067 enddef
1068 endclass
1069 assert_equal(0, OtherThing.totalSize)
1070 var to3 = OtherThing.new(3)
1071 assert_equal(3, OtherThing.totalSize)
1072 var to7 = OtherThing.new(7)
1073 assert_equal(10, OtherThing.totalSize)
1074 END
1075 v9.CheckScriptSuccess(lines)
1076
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001077 # using static class member twice
1078 lines =<< trim END
1079 vim9script
1080
1081 class HTML
1082 static author: string = 'John Doe'
1083
1084 static def MacroSubstitute(s: string): string
1085 return substitute(s, '{{author}}', author, 'gi')
1086 enddef
1087 endclass
1088
1089 assert_equal('some text', HTML.MacroSubstitute('some text'))
1090 assert_equal('some text', HTML.MacroSubstitute('some text'))
1091 END
1092 v9.CheckScriptSuccess(lines)
1093
Bram Moolenaar62a69232023-01-24 15:07:04 +00001094 # access private member in lambda
1095 lines =<< trim END
1096 vim9script
1097
1098 class Foo
1099 this._x: number = 0
1100
1101 def Add(n: number): number
1102 const F = (): number => this._x + n
1103 return F()
1104 enddef
1105 endclass
1106
1107 var foo = Foo.new()
1108 assert_equal(5, foo.Add(5))
1109 END
1110 v9.CheckScriptSuccess(lines)
1111
h-east2bd6a092023-05-19 19:01:17 +01001112 # access private member in lambda body
1113 lines =<< trim END
1114 vim9script
1115
1116 class Foo
1117 this._x: number = 6
1118
1119 def Add(n: number): number
1120 var Lam = () => {
1121 this._x = this._x + n
1122 }
1123 Lam()
1124 return this._x
1125 enddef
1126 endclass
1127
1128 var foo = Foo.new()
1129 assert_equal(13, foo.Add(7))
1130 END
1131 v9.CheckScriptSuccess(lines)
1132
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001133 # check shadowing
1134 lines =<< trim END
1135 vim9script
1136
1137 class Some
1138 static count = 0
1139 def Method(count: number)
1140 echo count
1141 enddef
1142 endclass
1143
1144 var s = Some.new()
1145 s.Method(7)
1146 END
1147 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
1148
1149 lines =<< trim END
1150 vim9script
1151
1152 class Some
1153 static count = 0
1154 def Method(arg: number)
1155 var count = 3
1156 echo arg count
1157 enddef
1158 endclass
1159
1160 var s = Some.new()
1161 s.Method(7)
1162 END
1163 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001164
1165 # Test for using an invalid type for a member variable
1166 lines =<< trim END
1167 vim9script
1168 class A
1169 this.val: xxx
1170 endclass
1171 END
1172 v9.CheckScriptFailure(lines, 'E1010:')
1173
1174 # Test for no space before or after the '=' when initializing a member
1175 # variable
1176 lines =<< trim END
1177 vim9script
1178 class A
1179 this.val: number= 10
1180 endclass
1181 END
1182 v9.CheckScriptFailure(lines, 'E1004:')
1183 lines =<< trim END
1184 vim9script
1185 class A
1186 this.val: number =10
1187 endclass
1188 END
1189 v9.CheckScriptFailure(lines, 'E1004:')
1190
1191 # Access a non-existing member
1192 lines =<< trim END
1193 vim9script
1194 class A
1195 endclass
1196 var a = A.new()
1197 var v = a.bar
1198 END
1199 v9.CheckScriptFailure(lines, 'E1326:')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001200enddef
1201
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001202func Test_class_garbagecollect()
1203 let lines =<< trim END
1204 vim9script
1205
1206 class Point
1207 this.p = [2, 3]
1208 static pl = ['a', 'b']
1209 static pd = {a: 'a', b: 'b'}
1210 endclass
1211
1212 echo Point.pl Point.pd
1213 call test_garbagecollect_now()
1214 echo Point.pl Point.pd
1215 END
1216 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001217
1218 let lines =<< trim END
1219 vim9script
1220
1221 interface View
1222 endinterface
1223
1224 class Widget
1225 this.view: View
1226 endclass
1227
1228 class MyView implements View
1229 this.widget: Widget
1230
1231 def new()
1232 # this will result in a circular reference to this object
1233 this.widget = Widget.new(this)
1234 enddef
1235 endclass
1236
1237 var view = MyView.new()
1238
1239 # overwrite "view", will be garbage-collected next
1240 view = MyView.new()
1241 test_garbagecollect_now()
1242 END
1243 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001244endfunc
1245
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001246def Test_class_function()
1247 var lines =<< trim END
1248 vim9script
1249 class Value
1250 this.value = 0
1251 static objects = 0
1252
1253 def new(v: number)
1254 this.value = v
1255 ++objects
1256 enddef
1257
1258 static def GetCount(): number
1259 return objects
1260 enddef
1261 endclass
1262
1263 assert_equal(0, Value.GetCount())
1264 var v1 = Value.new(2)
1265 assert_equal(1, Value.GetCount())
1266 var v2 = Value.new(7)
1267 assert_equal(2, Value.GetCount())
1268 END
1269 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001270
1271 # Test for cleaning up after a class definition failure when using class
1272 # functions.
1273 lines =<< trim END
1274 vim9script
1275 class A
1276 static def Foo()
1277 enddef
1278 aaa
1279 endclass
1280 END
1281 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001282enddef
1283
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001284def Test_class_defcompile()
1285 var lines =<< trim END
1286 vim9script
1287
1288 class C
1289 def Fo(i: number): string
1290 return i
1291 enddef
1292 endclass
1293
1294 defcompile C.Fo
1295 END
1296 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1297
1298 lines =<< trim END
1299 vim9script
1300
1301 class C
1302 static def Fc(): number
1303 return 'x'
1304 enddef
1305 endclass
1306
1307 defcompile C.Fc
1308 END
1309 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001310
1311 # Trying to compile a function using a non-existing class variable
1312 lines =<< trim END
1313 vim9script
1314 defcompile x.Foo()
1315 END
1316 v9.CheckScriptFailure(lines, 'E475:')
1317
1318 # Trying to compile a function using a variable which is not a class
1319 lines =<< trim END
1320 vim9script
1321 var x: number
1322 defcompile x.Foo()
1323 END
1324 v9.CheckScriptFailure(lines, 'E475:')
1325
1326 # Trying to compile a function without specifying the name
1327 lines =<< trim END
1328 vim9script
1329 class A
1330 endclass
1331 defcompile A.
1332 END
1333 v9.CheckScriptFailure(lines, 'E475:')
1334
1335 # Trying to compile a non-existing class object member function
1336 lines =<< trim END
1337 vim9script
1338 class A
1339 endclass
1340 var a = A.new()
1341 defcompile a.Foo()
1342 END
1343 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001344enddef
1345
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001346def Test_class_object_to_string()
1347 var lines =<< trim END
1348 vim9script
1349 class TextPosition
1350 this.lnum = 1
1351 this.col = 22
1352 endclass
1353
1354 assert_equal("class TextPosition", string(TextPosition))
1355
1356 var pos = TextPosition.new()
1357 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1358 END
1359 v9.CheckScriptSuccess(lines)
1360enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001361
Bram Moolenaar554d0312023-01-05 19:59:18 +00001362def Test_interface_basics()
1363 var lines =<< trim END
1364 vim9script
1365 interface Something
1366 this.value: string
1367 static count: number
1368 def GetCount(): number
1369 endinterface
1370 END
1371 v9.CheckScriptSuccess(lines)
1372
1373 lines =<< trim END
1374 interface SomethingWrong
1375 static count = 7
1376 endinterface
1377 END
1378 v9.CheckScriptFailure(lines, 'E1342:')
1379
1380 lines =<< trim END
1381 vim9script
1382
1383 interface Some
1384 static count: number
1385 def Method(count: number)
1386 endinterface
1387 END
h-east61378a12023-04-18 19:07:29 +01001388 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001389
1390 lines =<< trim END
1391 vim9script
1392
1393 interface Some
1394 this.value: number
1395 def Method(value: number)
1396 endinterface
1397 END
h-east61378a12023-04-18 19:07:29 +01001398 # The argument name and the object member name are the same, but this is not a
1399 # problem because object members are always accessed with the "this." prefix.
1400 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001401
1402 lines =<< trim END
1403 vim9script
1404 interface somethingWrong
1405 static count = 7
1406 endinterface
1407 END
1408 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1409
1410 lines =<< trim END
1411 vim9script
1412 interface SomethingWrong
1413 this.value: string
1414 static count = 7
1415 def GetCount(): number
1416 endinterface
1417 END
1418 v9.CheckScriptFailure(lines, 'E1344:')
1419
1420 lines =<< trim END
1421 vim9script
1422 interface SomethingWrong
1423 this.value: string
1424 static count: number
1425 def GetCount(): number
1426 return 5
1427 enddef
1428 endinterface
1429 END
1430 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001431
1432 lines =<< trim END
1433 vim9script
1434 export interface EnterExit
1435 def Enter(): void
1436 def Exit(): void
1437 endinterface
1438 END
1439 writefile(lines, 'XdefIntf.vim', 'D')
1440
1441 lines =<< trim END
1442 vim9script
1443 import './XdefIntf.vim' as defIntf
1444 export def With(ee: defIntf.EnterExit, F: func)
1445 ee.Enter()
1446 try
1447 F()
1448 finally
1449 ee.Exit()
1450 endtry
1451 enddef
1452 END
1453 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001454
1455 var imported =<< trim END
1456 vim9script
1457 export abstract class EnterExit
1458 def Enter(): void
1459 enddef
1460 def Exit(): void
1461 enddef
1462 endclass
1463 END
1464 writefile(imported, 'XdefIntf2.vim', 'D')
1465
1466 lines[1] = " import './XdefIntf2.vim' as defIntf"
1467 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001468enddef
1469
Bram Moolenaar94674f22023-01-06 18:42:20 +00001470def Test_class_implements_interface()
1471 var lines =<< trim END
1472 vim9script
1473
1474 interface Some
1475 static count: number
1476 def Method(nr: number)
1477 endinterface
1478
1479 class SomeImpl implements Some
1480 static count: number
1481 def Method(nr: number)
1482 echo nr
1483 enddef
1484 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001485
1486 interface Another
1487 this.member: string
1488 endinterface
1489
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001490 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001491 this.member = 'abc'
1492 static count: number
1493 def Method(nr: number)
1494 echo nr
1495 enddef
1496 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001497 END
1498 v9.CheckScriptSuccess(lines)
1499
1500 lines =<< trim END
1501 vim9script
1502
1503 interface Some
1504 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001505 endinterface
1506
1507 class SomeImpl implements Some implements Some
1508 static count: number
1509 endclass
1510 END
1511 v9.CheckScriptFailure(lines, 'E1350:')
1512
1513 lines =<< trim END
1514 vim9script
1515
1516 interface Some
1517 static counter: number
1518 endinterface
1519
1520 class SomeImpl implements Some, Some
1521 static count: number
1522 endclass
1523 END
1524 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1525
1526 lines =<< trim END
1527 vim9script
1528
1529 interface Some
1530 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001531 def Method(nr: number)
1532 endinterface
1533
1534 class SomeImpl implements Some
1535 static count: number
1536 def Method(nr: number)
1537 echo nr
1538 enddef
1539 endclass
1540 END
1541 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1542
1543 lines =<< trim END
1544 vim9script
1545
1546 interface Some
1547 static count: number
1548 def Methods(nr: number)
1549 endinterface
1550
1551 class SomeImpl implements Some
1552 static count: number
1553 def Method(nr: number)
1554 echo nr
1555 enddef
1556 endclass
1557 END
1558 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001559
1560 # Check different order of members in class and interface works.
1561 lines =<< trim END
1562 vim9script
1563
1564 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001565 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001566 this.errpos: number
1567 endinterface
1568
1569 # order of members is opposite of interface
1570 class Failure implements Result
1571 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001572 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001573 endclass
1574
1575 def Test()
1576 var result: Result = Failure.new()
1577
1578 assert_equal('label', result.label)
1579 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001580
1581 result.label = 'different'
1582 assert_equal('different', result.label)
1583 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001584 enddef
1585
1586 Test()
1587 END
1588 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001589
1590 # Interface name after "extends" doesn't end in a space or NUL character
1591 lines =<< trim END
1592 vim9script
1593 interface A
1594 endinterface
1595 class B extends A"
1596 endclass
1597 END
1598 v9.CheckScriptFailure(lines, 'E1315:')
1599
1600 # Trailing characters after a class name
1601 lines =<< trim END
1602 vim9script
1603 class A bbb
1604 endclass
1605 END
1606 v9.CheckScriptFailure(lines, 'E488:')
1607
1608 # using "implements" with a non-existing class
1609 lines =<< trim END
1610 vim9script
1611 class A implements B
1612 endclass
1613 END
1614 v9.CheckScriptFailure(lines, 'E1346:')
1615
1616 # using "implements" with a regular class
1617 lines =<< trim END
1618 vim9script
1619 class A
1620 endclass
1621 class B implements A
1622 endclass
1623 END
1624 v9.CheckScriptFailure(lines, 'E1347:')
1625
1626 # using "implements" with a variable
1627 lines =<< trim END
1628 vim9script
1629 var T: number = 10
1630 class A implements T
1631 endclass
1632 END
1633 v9.CheckScriptFailure(lines, 'E1347:')
1634
1635 # all the class methods in an "interface" should be implemented
1636 lines =<< trim END
1637 vim9script
1638 interface A
1639 static def Foo()
1640 endinterface
1641 class B implements A
1642 endclass
1643 END
1644 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001645
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02001646 # implements should be followed by a white space
1647 lines =<< trim END
1648 vim9script
1649 interface A
1650 endinterface
1651 class B implements A;
1652 endclass
1653 END
1654 v9.CheckScriptFailure(lines, 'E1315:')
1655
LemonBoyc5d27442023-08-19 13:02:35 +02001656 lines =<< trim END
1657 vim9script
1658
1659 interface One
1660 static matching: bool
1661 static as_any: any
1662 static not_matching: number
1663 endinterface
1664 class Two implements One
1665 static not_matching: string
1666 static as_any: string
1667 static matching: bool
1668 endclass
1669 END
1670 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1671
1672 lines =<< trim END
1673 vim9script
1674
1675 interface One
1676 def IsEven(nr: number): bool
1677 endinterface
1678 class Two implements One
1679 def IsEven(nr: number): string
1680 enddef
1681 endclass
1682 END
1683 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1684
1685 lines =<< trim END
1686 vim9script
1687
1688 interface One
1689 def IsEven(nr: number): bool
1690 endinterface
1691 class Two implements One
1692 def IsEven(nr: bool): bool
1693 enddef
1694 endclass
1695 END
1696 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1697
1698 lines =<< trim END
1699 vim9script
1700
1701 interface One
1702 def IsEven(nr: number): bool
1703 endinterface
1704 class Two implements One
1705 def IsEven(nr: number, ...extra: list<number>): bool
1706 enddef
1707 endclass
1708 END
1709 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 +00001710enddef
1711
Bram Moolenaard0200c82023-01-28 15:19:40 +00001712def Test_call_interface_method()
1713 var lines =<< trim END
1714 vim9script
1715 interface Base
1716 def Enter(): void
1717 endinterface
1718
1719 class Child implements Base
1720 def Enter(): void
1721 g:result ..= 'child'
1722 enddef
1723 endclass
1724
1725 def F(obj: Base)
1726 obj.Enter()
1727 enddef
1728
1729 g:result = ''
1730 F(Child.new())
1731 assert_equal('child', g:result)
1732 unlet g:result
1733 END
1734 v9.CheckScriptSuccess(lines)
1735
1736 lines =<< trim END
1737 vim9script
1738 class Base
1739 def Enter(): void
1740 g:result ..= 'base'
1741 enddef
1742 endclass
1743
1744 class Child extends Base
1745 def Enter(): void
1746 g:result ..= 'child'
1747 enddef
1748 endclass
1749
1750 def F(obj: Base)
1751 obj.Enter()
1752 enddef
1753
1754 g:result = ''
1755 F(Child.new())
1756 assert_equal('child', g:result)
1757 unlet g:result
1758 END
1759 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001760
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001761 # method of interface returns a value
1762 lines =<< trim END
1763 vim9script
1764 interface Base
1765 def Enter(): string
1766 endinterface
1767
1768 class Child implements Base
1769 def Enter(): string
1770 g:result ..= 'child'
1771 return "/resource"
1772 enddef
1773 endclass
1774
1775 def F(obj: Base)
1776 var r = obj.Enter()
1777 g:result ..= r
1778 enddef
1779
1780 g:result = ''
1781 F(Child.new())
1782 assert_equal('child/resource', g:result)
1783 unlet g:result
1784 END
1785 v9.CheckScriptSuccess(lines)
1786
1787 lines =<< trim END
1788 vim9script
1789 class Base
1790 def Enter(): string
1791 return null_string
1792 enddef
1793 endclass
1794
1795 class Child extends Base
1796 def Enter(): string
1797 g:result ..= 'child'
1798 return "/resource"
1799 enddef
1800 endclass
1801
1802 def F(obj: Base)
1803 var r = obj.Enter()
1804 g:result ..= r
1805 enddef
1806
1807 g:result = ''
1808 F(Child.new())
1809 assert_equal('child/resource', g:result)
1810 unlet g:result
1811 END
1812 v9.CheckScriptSuccess(lines)
1813
1814
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001815 # No class that implements the interface.
1816 lines =<< trim END
1817 vim9script
1818
1819 interface IWithEE
1820 def Enter(): any
1821 def Exit(): void
1822 endinterface
1823
1824 def With1(ee: IWithEE, F: func)
1825 var r = ee.Enter()
1826 enddef
1827
1828 defcompile
1829 END
1830 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001831enddef
1832
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001833def Test_class_used_as_type()
1834 var lines =<< trim END
1835 vim9script
1836
1837 class Point
1838 this.x = 0
1839 this.y = 0
1840 endclass
1841
1842 var p: Point
1843 p = Point.new(2, 33)
1844 assert_equal(2, p.x)
1845 assert_equal(33, p.y)
1846 END
1847 v9.CheckScriptSuccess(lines)
1848
1849 lines =<< trim END
1850 vim9script
1851
1852 interface HasX
1853 this.x: number
1854 endinterface
1855
1856 class Point implements HasX
1857 this.x = 0
1858 this.y = 0
1859 endclass
1860
1861 var p: Point
1862 p = Point.new(2, 33)
1863 var hx = p
1864 assert_equal(2, hx.x)
1865 END
1866 v9.CheckScriptSuccess(lines)
1867
1868 lines =<< trim END
1869 vim9script
1870
1871 class Point
1872 this.x = 0
1873 this.y = 0
1874 endclass
1875
1876 var p: Point
1877 p = 'text'
1878 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001879 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001880enddef
1881
Bram Moolenaar83677162023-01-08 19:54:10 +00001882def Test_class_extends()
1883 var lines =<< trim END
1884 vim9script
1885 class Base
1886 this.one = 1
1887 def GetOne(): number
1888 return this.one
1889 enddef
1890 endclass
1891 class Child extends Base
1892 this.two = 2
1893 def GetTotal(): number
1894 return this.one + this.two
1895 enddef
1896 endclass
1897 var o = Child.new()
1898 assert_equal(1, o.one)
1899 assert_equal(2, o.two)
1900 assert_equal(1, o.GetOne())
1901 assert_equal(3, o.GetTotal())
1902 END
1903 v9.CheckScriptSuccess(lines)
1904
1905 lines =<< trim END
1906 vim9script
1907 class Base
1908 this.one = 1
1909 endclass
1910 class Child extends Base
1911 this.two = 2
1912 endclass
1913 var o = Child.new(3, 44)
1914 assert_equal(3, o.one)
1915 assert_equal(44, o.two)
1916 END
1917 v9.CheckScriptSuccess(lines)
1918
1919 lines =<< trim END
1920 vim9script
1921 class Base
1922 this.one = 1
1923 endclass
1924 class Child extends Base extends Base
1925 this.two = 2
1926 endclass
1927 END
1928 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1929
1930 lines =<< trim END
1931 vim9script
1932 class Child extends BaseClass
1933 this.two = 2
1934 endclass
1935 END
1936 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1937
1938 lines =<< trim END
1939 vim9script
1940 var SomeVar = 99
1941 class Child extends SomeVar
1942 this.two = 2
1943 endclass
1944 END
1945 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001946
1947 lines =<< trim END
1948 vim9script
1949 class Base
1950 this.name: string
1951 def ToString(): string
1952 return this.name
1953 enddef
1954 endclass
1955
1956 class Child extends Base
1957 this.age: number
1958 def ToString(): string
1959 return super.ToString() .. ': ' .. this.age
1960 enddef
1961 endclass
1962
1963 var o = Child.new('John', 42)
1964 assert_equal('John: 42', o.ToString())
1965 END
1966 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001967
1968 lines =<< trim END
1969 vim9script
1970 class Child
1971 this.age: number
1972 def ToString(): number
1973 return this.age
1974 enddef
1975 def ToString(): string
1976 return this.age
1977 enddef
1978 endclass
1979 END
1980 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1981
1982 lines =<< trim END
1983 vim9script
1984 class Child
1985 this.age: number
1986 def ToString(): string
1987 return super .ToString() .. ': ' .. this.age
1988 enddef
1989 endclass
1990 var o = Child.new(42)
1991 echo o.ToString()
1992 END
1993 v9.CheckScriptFailure(lines, 'E1356:')
1994
1995 lines =<< trim END
1996 vim9script
1997 class Base
1998 this.name: string
1999 def ToString(): string
2000 return this.name
2001 enddef
2002 endclass
2003
2004 var age = 42
2005 def ToString(): string
2006 return super.ToString() .. ': ' .. age
2007 enddef
2008 echo ToString()
2009 END
2010 v9.CheckScriptFailure(lines, 'E1357:')
2011
2012 lines =<< trim END
2013 vim9script
2014 class Child
2015 this.age: number
2016 def ToString(): string
2017 return super.ToString() .. ': ' .. this.age
2018 enddef
2019 endclass
2020 var o = Child.new(42)
2021 echo o.ToString()
2022 END
2023 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002024
2025 lines =<< trim END
2026 vim9script
2027 class Base
2028 this.name: string
2029 static def ToString(): string
2030 return 'Base class'
2031 enddef
2032 endclass
2033
2034 class Child extends Base
2035 this.age: number
2036 def ToString(): string
2037 return Base.ToString() .. ': ' .. this.age
2038 enddef
2039 endclass
2040
2041 var o = Child.new('John', 42)
2042 assert_equal('Base class: 42', o.ToString())
2043 END
2044 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002045
2046 lines =<< trim END
2047 vim9script
2048 class Base
2049 this.value = 1
2050 def new(init: number)
2051 this.value = number + 1
2052 enddef
2053 endclass
2054 class Child extends Base
2055 def new()
2056 this.new(3)
2057 enddef
2058 endclass
2059 var c = Child.new()
2060 END
2061 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002062
2063 # base class with more than one object member
2064 lines =<< trim END
2065 vim9script
2066
2067 class Result
2068 this.success: bool
2069 this.value: any = null
2070 endclass
2071
2072 class Success extends Result
2073 def new(this.value = v:none)
2074 this.success = true
2075 enddef
2076 endclass
2077
2078 var v = Success.new('asdf')
2079 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2080 END
2081 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002082
2083 # class name after "extends" doesn't end in a space or NUL character
2084 lines =<< trim END
2085 vim9script
2086 class A
2087 endclass
2088 class B extends A"
2089 endclass
2090 END
2091 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002092enddef
2093
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002094def Test_using_base_class()
2095 var lines =<< trim END
2096 vim9script
2097
2098 class BaseEE
2099 def Enter(): any
2100 return null
2101 enddef
2102 def Exit(resource: any): void
2103 enddef
2104 endclass
2105
2106 class ChildEE extends BaseEE
2107 def Enter(): any
2108 return 42
2109 enddef
2110
2111 def Exit(resource: number): void
2112 g:result ..= '/exit'
2113 enddef
2114 endclass
2115
2116 def With(ee: BaseEE)
2117 var r = ee.Enter()
2118 try
2119 g:result ..= r
2120 finally
2121 g:result ..= '/finally'
2122 ee.Exit(r)
2123 endtry
2124 enddef
2125
2126 g:result = ''
2127 With(ChildEE.new())
2128 assert_equal('42/finally/exit', g:result)
2129 END
2130 v9.CheckScriptSuccess(lines)
2131 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002132
2133 # Using super, Child invokes Base method which has optional arg. #12471
2134 lines =<< trim END
2135 vim9script
2136
2137 class Base
2138 this.success: bool = false
2139 def Method(arg = 0)
2140 this.success = true
2141 enddef
2142 endclass
2143
2144 class Child extends Base
2145 def new()
2146 super.Method()
2147 enddef
2148 endclass
2149
2150 var obj = Child.new()
2151 assert_equal(true, obj.success)
2152 END
2153 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002154enddef
2155
2156
Bram Moolenaara86655a2023-01-12 17:06:27 +00002157def Test_class_import()
2158 var lines =<< trim END
2159 vim9script
2160 export class Animal
2161 this.kind: string
2162 this.name: string
2163 endclass
2164 END
2165 writefile(lines, 'Xanimal.vim', 'D')
2166
2167 lines =<< trim END
2168 vim9script
2169 import './Xanimal.vim' as animal
2170
2171 var a: animal.Animal
2172 a = animal.Animal.new('fish', 'Eric')
2173 assert_equal('fish', a.kind)
2174 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002175
2176 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2177 assert_equal('cat', b.kind)
2178 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002179 END
2180 v9.CheckScriptSuccess(lines)
2181enddef
2182
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002183def Test_abstract_class()
2184 var lines =<< trim END
2185 vim9script
2186 abstract class Base
2187 this.name: string
2188 endclass
2189 class Person extends Base
2190 this.age: number
2191 endclass
2192 var p: Base = Person.new('Peter', 42)
2193 assert_equal('Peter', p.name)
2194 assert_equal(42, p.age)
2195 END
2196 v9.CheckScriptSuccess(lines)
2197
2198 lines =<< trim END
2199 vim9script
2200 abstract class Base
2201 this.name: string
2202 endclass
2203 class Person extends Base
2204 this.age: number
2205 endclass
2206 var p = Base.new('Peter')
2207 END
2208 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2209
2210 lines =<< trim END
2211 abstract class Base
2212 this.name: string
2213 endclass
2214 END
2215 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002216
2217 # Abstract class cannot have a "new" function
2218 lines =<< trim END
2219 vim9script
2220 abstract class Base
2221 def new()
2222 enddef
2223 endclass
2224 END
2225 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002226enddef
2227
Bram Moolenaar486fc252023-01-18 14:51:07 +00002228def Test_closure_in_class()
2229 var lines =<< trim END
2230 vim9script
2231
2232 class Foo
2233 this.y: list<string> = ['B']
2234
2235 def new()
2236 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2237 enddef
2238 endclass
2239
2240 Foo.new()
2241 assert_equal(['A'], g:result)
2242 END
2243 v9.CheckScriptSuccess(lines)
2244enddef
2245
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002246def Test_call_constructor_from_legacy()
2247 var lines =<< trim END
2248 vim9script
2249
2250 var newCalled = 'false'
2251
2252 class A
2253 def new()
2254 newCalled = 'true'
2255 enddef
2256 endclass
2257
2258 export def F(options = {}): any
2259 return A
2260 enddef
2261
2262 g:p = F()
2263 legacy call p.new()
2264 assert_equal('true', newCalled)
2265 END
2266 v9.CheckScriptSuccess(lines)
2267enddef
2268
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002269def Test_defer_with_object()
2270 var lines =<< trim END
2271 vim9script
2272
2273 class CWithEE
2274 def Enter()
2275 g:result ..= "entered/"
2276 enddef
2277 def Exit()
2278 g:result ..= "exited"
2279 enddef
2280 endclass
2281
2282 def With(ee: CWithEE, F: func)
2283 ee.Enter()
2284 defer ee.Exit()
2285 F()
2286 enddef
2287
2288 g:result = ''
2289 var obj = CWithEE.new()
2290 obj->With(() => {
2291 g:result ..= "called/"
2292 })
2293 assert_equal('entered/called/exited', g:result)
2294 END
2295 v9.CheckScriptSuccess(lines)
2296 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002297
2298 lines =<< trim END
2299 vim9script
2300
2301 class BaseWithEE
2302 def Enter()
2303 g:result ..= "entered-base/"
2304 enddef
2305 def Exit()
2306 g:result ..= "exited-base"
2307 enddef
2308 endclass
2309
2310 class CWithEE extends BaseWithEE
2311 def Enter()
2312 g:result ..= "entered-child/"
2313 enddef
2314 def Exit()
2315 g:result ..= "exited-child"
2316 enddef
2317 endclass
2318
2319 def With(ee: BaseWithEE, F: func)
2320 ee.Enter()
2321 defer ee.Exit()
2322 F()
2323 enddef
2324
2325 g:result = ''
2326 var obj = CWithEE.new()
2327 obj->With(() => {
2328 g:result ..= "called/"
2329 })
2330 assert_equal('entered-child/called/exited-child', g:result)
2331 END
2332 v9.CheckScriptSuccess(lines)
2333 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002334enddef
2335
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002336" The following test used to crash Vim (Github issue #12676)
2337def Test_extends_method_crashes_vim()
2338 var lines =<< trim END
2339 vim9script
2340
2341 class Observer
2342 endclass
2343
2344 class Property
2345 this.value: any
2346
2347 def Set(v: any)
2348 if v != this.value
2349 this.value = v
2350 endif
2351 enddef
2352
2353 def Register(observer: Observer)
2354 enddef
2355 endclass
2356
2357 class Bool extends Property
2358 this.value: bool
2359 endclass
2360
2361 def Observe(obj: Property, who: Observer)
2362 obj.Register(who)
2363 enddef
2364
2365 var p = Bool.new(false)
2366 var myObserver = Observer.new()
2367
2368 Observe(p, myObserver)
2369
2370 p.Set(true)
2371 END
2372 v9.CheckScriptSuccess(lines)
2373enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002374
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002375" Test for calling a method in a class that is extended
2376def Test_call_method_in_extended_class()
2377 var lines =<< trim END
2378 vim9script
2379
2380 var prop_init_called = false
2381 var prop_register_called = false
2382
2383 class Property
2384 def Init()
2385 prop_init_called = true
2386 enddef
2387
2388 def Register()
2389 prop_register_called = true
2390 enddef
2391 endclass
2392
2393 class Bool extends Property
2394 endclass
2395
2396 def Observe(obj: Property)
2397 obj.Register()
2398 enddef
2399
2400 var p = Property.new()
2401 Observe(p)
2402
2403 p.Init()
2404 assert_true(prop_init_called)
2405 assert_true(prop_register_called)
2406 END
2407 v9.CheckScriptSuccess(lines)
2408enddef
2409
LemonBoyafe04662023-08-23 21:08:11 +02002410def Test_instanceof()
2411 var lines =<< trim END
2412 vim9script
2413
2414 class Base1
2415 endclass
2416
2417 class Base2 extends Base1
2418 endclass
2419
2420 interface Intf1
2421 endinterface
2422
2423 class Mix1 implements Intf1
2424 endclass
2425
2426 class Base3 extends Mix1
2427 endclass
2428
2429 var b1 = Base1.new()
2430 var b2 = Base2.new()
2431 var b3 = Base3.new()
2432
2433 assert_true(instanceof(b1, Base1))
2434 assert_true(instanceof(b2, Base1))
2435 assert_false(instanceof(b1, Base2))
2436 assert_true(instanceof(b3, Mix1))
2437 assert_false(instanceof(b3, []))
2438 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002439
2440 def Foo()
2441 var a1 = Base1.new()
2442 var a2 = Base2.new()
2443 var a3 = Base3.new()
2444
2445 assert_true(instanceof(a1, Base1))
2446 assert_true(instanceof(a2, Base1))
2447 assert_false(instanceof(a1, Base2))
2448 assert_true(instanceof(a3, Mix1))
2449 assert_false(instanceof(a3, []))
2450 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2451 enddef
2452 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002453 END
2454 v9.CheckScriptSuccess(lines)
2455enddef
2456
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002457" Test for calling a method in the parent class that is extended partially.
2458" This used to fail with the 'E118: Too many arguments for function: Text' error
2459" message (Github issue #12524).
2460def Test_call_method_in_parent_class()
2461 var lines =<< trim END
2462 vim9script
2463
2464 class Widget
2465 this._lnum: number = 1
2466
2467 def SetY(lnum: number)
2468 this._lnum = lnum
2469 enddef
2470
2471 def Text(): string
2472 return ''
2473 enddef
2474 endclass
2475
2476 class Foo extends Widget
2477 def Text(): string
2478 return '<Foo>'
2479 enddef
2480 endclass
2481
2482 def Stack(w1: Widget, w2: Widget): list<Widget>
2483 w1.SetY(1)
2484 w2.SetY(2)
2485 return [w1, w2]
2486 enddef
2487
2488 var foo1 = Foo.new()
2489 var foo2 = Foo.new()
2490 var l = Stack(foo1, foo2)
2491 END
2492 v9.CheckScriptSuccess(lines)
2493enddef
2494
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002495" Test for calling methods from three levels of classes
2496def Test_multi_level_method_call()
2497 var lines =<< trim END
2498 vim9script
2499
2500 var A_func1: number = 0
2501 var A_func2: number = 0
2502 var A_func3: number = 0
2503 var B_func2: number = 0
2504 var B_func3: number = 0
2505 var C_func3: number = 0
2506
2507 class A
2508 def Func1()
2509 A_func1 += 1
2510 enddef
2511
2512 def Func2()
2513 A_func2 += 1
2514 enddef
2515
2516 def Func3()
2517 A_func3 += 1
2518 enddef
2519 endclass
2520
2521 class B extends A
2522 def Func2()
2523 B_func2 += 1
2524 enddef
2525
2526 def Func3()
2527 B_func3 += 1
2528 enddef
2529 endclass
2530
2531 class C extends B
2532 def Func3()
2533 C_func3 += 1
2534 enddef
2535 endclass
2536
2537 def A_CallFuncs(a: A)
2538 a.Func1()
2539 a.Func2()
2540 a.Func3()
2541 enddef
2542
2543 def B_CallFuncs(b: B)
2544 b.Func1()
2545 b.Func2()
2546 b.Func3()
2547 enddef
2548
2549 def C_CallFuncs(c: C)
2550 c.Func1()
2551 c.Func2()
2552 c.Func3()
2553 enddef
2554
2555 var cobj = C.new()
2556 A_CallFuncs(cobj)
2557 B_CallFuncs(cobj)
2558 C_CallFuncs(cobj)
2559 assert_equal(3, A_func1)
2560 assert_equal(0, A_func2)
2561 assert_equal(0, A_func3)
2562 assert_equal(3, B_func2)
2563 assert_equal(0, B_func3)
2564 assert_equal(3, C_func3)
2565 END
2566 v9.CheckScriptSuccess(lines)
2567enddef
2568
2569" Test for using members from three levels of classes
2570def Test_multi_level_member_access()
2571 var lines =<< trim END
2572 vim9script
2573
2574 class A
2575 this.val1: number = 0
2576 this.val2: number = 0
2577 this.val3: number = 0
2578 endclass
2579
2580 class B extends A
2581 this.val2: number = 0
2582 this.val3: number = 0
2583 endclass
2584
2585 class C extends B
2586 this.val3: number = 0
2587 endclass
2588
2589 def A_members(a: A)
2590 a.val1 += 1
2591 a.val2 += 1
2592 a.val3 += 1
2593 enddef
2594
2595 def B_members(b: B)
2596 b.val1 += 1
2597 b.val2 += 1
2598 b.val3 += 1
2599 enddef
2600
2601 def C_members(c: C)
2602 c.val1 += 1
2603 c.val2 += 1
2604 c.val3 += 1
2605 enddef
2606
2607 var cobj = C.new()
2608 A_members(cobj)
2609 B_members(cobj)
2610 C_members(cobj)
2611 assert_equal(3, cobj.val1)
2612 assert_equal(3, cobj.val2)
2613 assert_equal(3, cobj.val3)
2614 END
2615 v9.CheckScriptSuccess(lines)
2616enddef
2617
LemonBoy0ffc17a2023-08-20 18:09:11 +02002618" Test expansion of <stack> with class methods.
2619def Test_stack_expansion_with_methods()
2620 var lines =<< trim END
2621 vim9script
2622
2623 class C
2624 def M1()
2625 F0()
2626 enddef
2627 endclass
2628
2629 def F0()
2630 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2631 enddef
2632
2633 def F()
2634 C.new().M1()
2635 enddef
2636
2637 F()
2638 END
2639 v9.CheckScriptSuccess(lines)
2640enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002641
2642" Test the return type of the new() constructor
2643def Test_new_return_type()
2644 # new() uses the default return type and there is no return statement
2645 var lines =<< trim END
2646 vim9script
2647
2648 class C
2649 this._bufnr: number
2650
2651 def new(this._bufnr)
2652 if !bufexists(this._bufnr)
2653 this._bufnr = -1
2654 endif
2655 enddef
2656 endclass
2657
2658 var c = C.new(12345)
2659 assert_equal('object<C>', typename(c))
2660
2661 var v1: C
2662 v1 = C.new(12345)
2663 assert_equal('object<C>', typename(v1))
2664
2665 def F()
2666 var v2: C
2667 v2 = C.new(12345)
2668 assert_equal('object<C>', typename(v2))
2669 enddef
2670 F()
2671 END
2672 v9.CheckScriptSuccess(lines)
2673
2674 # new() uses the default return type and an empty 'return' statement
2675 lines =<< trim END
2676 vim9script
2677
2678 class C
2679 this._bufnr: number
2680
2681 def new(this._bufnr)
2682 if !bufexists(this._bufnr)
2683 this._bufnr = -1
2684 return
2685 endif
2686 enddef
2687 endclass
2688
2689 var c = C.new(12345)
2690 assert_equal('object<C>', typename(c))
2691
2692 var v1: C
2693 v1 = C.new(12345)
2694 assert_equal('object<C>', typename(v1))
2695
2696 def F()
2697 var v2: C
2698 v2 = C.new(12345)
2699 assert_equal('object<C>', typename(v2))
2700 enddef
2701 F()
2702 END
2703 v9.CheckScriptSuccess(lines)
2704
2705 # new() uses "any" return type and returns "this"
2706 lines =<< trim END
2707 vim9script
2708
2709 class C
2710 this._bufnr: number
2711
2712 def new(this._bufnr): any
2713 if !bufexists(this._bufnr)
2714 this._bufnr = -1
2715 return this
2716 endif
2717 enddef
2718 endclass
2719 END
2720 v9.CheckScriptFailure(lines, 'E1365:')
2721
2722 # new() uses 'Dict' return type and returns a Dict
2723 lines =<< trim END
2724 vim9script
2725
2726 class C
2727 this._state: dict<any>
2728
2729 def new(): dict<any>
2730 this._state = {}
2731 return this._state
2732 enddef
2733 endclass
2734
2735 var c = C.new()
2736 assert_equal('object<C>', typename(c))
2737 END
2738 v9.CheckScriptFailure(lines, 'E1365:')
2739enddef
2740
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02002741" Test for checking a member initialization type at run time.
2742def Test_runtime_type_check_for_member_init()
2743 var lines =<< trim END
2744 vim9script
2745
2746 var retnum: bool = false
2747
2748 def F(): any
2749 retnum = !retnum
2750 if retnum
2751 return 1
2752 else
2753 return "hello"
2754 endif
2755 enddef
2756
2757 class C
2758 this._foo: bool = F()
2759 endclass
2760
2761 var c1 = C.new()
2762 var c2 = C.new()
2763 END
2764 v9.CheckScriptFailure(lines, 'E1012:')
2765enddef
2766
2767" Test for locking a variable referring to an object and reassigning to another
2768" object.
2769def Test_object_lockvar()
2770 var lines =<< trim END
2771 vim9script
2772
2773 class C
2774 this.val: number
2775 def new(this.val)
2776 enddef
2777 endclass
2778
2779 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
2780 lockvar 2 some_dict
2781
2782 var current: C
2783 current = some_dict['c']
2784 assert_equal(3, current.val)
2785 current = some_dict['b']
2786 assert_equal(2, current.val)
2787
2788 def F()
2789 current = some_dict['c']
2790 enddef
2791
2792 def G()
2793 current = some_dict['b']
2794 enddef
2795
2796 F()
2797 assert_equal(3, current.val)
2798 G()
2799 assert_equal(2, current.val)
2800 END
2801 v9.CheckScriptSuccess(lines)
2802enddef
2803
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002804" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker