blob: be4eb2eb8a0f9cb5ba7d26d84928e20ef7a7b2cd [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
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200493 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000494
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)
Ernie Rael18143d32023-09-04 22:30:41 +0200512
513 # do the same thing, but through an interface
514 lines =<< trim END
515 vim9script
516
517 interface I
518 public this.x: number
519 endinterface
520
521 class Foo implements I
522 public this.x: number
523
524 def Add(n: number)
525 var i: I = this
526 i.x += n
527 enddef
528 endclass
529
530 var f = Foo.new(3)
531 f.Add(17)
532 assert_equal(20, f.x)
533
534 def AddToFoo(i: I)
535 i.x += 3
536 enddef
537
538 AddToFoo(f)
539 assert_equal(23, f.x)
540 END
541 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000542enddef
543
Bram Moolenaarf4508042023-01-15 16:54:57 +0000544def Test_list_of_objects()
545 var lines =<< trim END
546 vim9script
547
548 class Foo
549 def Add()
550 enddef
551 endclass
552
553 def ProcessList(fooList: list<Foo>)
554 for foo in fooList
555 foo.Add()
556 endfor
557 enddef
558
559 var l: list<Foo> = [Foo.new()]
560 ProcessList(l)
561 END
562 v9.CheckScriptSuccess(lines)
563enddef
564
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000565def Test_expr_after_using_object()
566 var lines =<< trim END
567 vim9script
568
569 class Something
570 this.label: string = ''
571 endclass
572
573 def Foo(): Something
574 var v = Something.new()
575 echo 'in Foo(): ' .. typename(v)
576 return v
577 enddef
578
579 Foo()
580 END
581 v9.CheckScriptSuccess(lines)
582enddef
583
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000584def Test_class_default_new()
585 var lines =<< trim END
586 vim9script
587
588 class TextPosition
589 this.lnum: number = 1
590 this.col: number = 1
591 endclass
592
593 var pos = TextPosition.new()
594 assert_equal(1, pos.lnum)
595 assert_equal(1, pos.col)
596
597 pos = TextPosition.new(v:none, v:none)
598 assert_equal(1, pos.lnum)
599 assert_equal(1, pos.col)
600
601 pos = TextPosition.new(3, 22)
602 assert_equal(3, pos.lnum)
603 assert_equal(22, pos.col)
604
605 pos = TextPosition.new(v:none, 33)
606 assert_equal(1, pos.lnum)
607 assert_equal(33, pos.col)
608 END
609 v9.CheckScriptSuccess(lines)
610
611 lines =<< trim END
612 vim9script
613 class Person
614 this.name: string
615 this.age: number = 42
616 this.education: string = "unknown"
617
618 def new(this.name, this.age = v:none, this.education = v:none)
619 enddef
620 endclass
621
622 var piet = Person.new("Piet")
623 assert_equal("Piet", piet.name)
624 assert_equal(42, piet.age)
625 assert_equal("unknown", piet.education)
626
627 var chris = Person.new("Chris", 4, "none")
628 assert_equal("Chris", chris.name)
629 assert_equal(4, chris.age)
630 assert_equal("none", chris.education)
631 END
632 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000633
634 lines =<< trim END
635 vim9script
636 class Person
637 this.name: string
638 this.age: number = 42
639 this.education: string = "unknown"
640
641 def new(this.name, this.age = v:none, this.education = v:none)
642 enddef
643 endclass
644
645 var missing = Person.new()
646 END
647 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000648enddef
649
h-east2261c892023-08-16 21:49:54 +0900650
651def Test_class_new_with_object_member()
652 var 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 def newVals(this.str, this.num)
661 enddef
662 endclass
663
664 def Check()
665 try
666 var c = C.new('cats', 2)
667 assert_equal('cats', c.str)
668 assert_equal(2, c.num)
669
670 c = C.newVals('dogs', 4)
671 assert_equal('dogs', c.str)
672 assert_equal(4, c.num)
673 catch
674 assert_report($'Unexpected exception was caught: {v:exception}')
675 endtry
676 enddef
677
678 Check()
679 END
680 v9.CheckScriptSuccess(lines)
681
682 lines =<< trim END
683 vim9script
684
685 class C
686 this.str: string
687 this.num: number
688 def new(this.str, this.num)
689 enddef
690 endclass
691
692 def Check()
693 try
694 var c = C.new(1, 2)
695 catch
696 assert_report($'Unexpected exception was caught: {v:exception}')
697 endtry
698 enddef
699
700 Check()
701 END
702 v9.CheckScriptFailure(lines, 'E1013:')
703
704 lines =<< trim END
705 vim9script
706
707 class C
708 this.str: string
709 this.num: number
710 def newVals(this.str, this.num)
711 enddef
712 endclass
713
714 def Check()
715 try
716 var c = C.newVals('dogs', 'apes')
717 catch
718 assert_report($'Unexpected exception was caught: {v:exception}')
719 endtry
720 enddef
721
722 Check()
723 END
724 v9.CheckScriptFailure(lines, 'E1013:')
725enddef
726
Bram Moolenaar74e12742022-12-13 21:14:28 +0000727def Test_class_object_member_inits()
728 var lines =<< trim END
729 vim9script
730 class TextPosition
731 this.lnum: number
732 this.col = 1
733 this.addcol: number = 2
734 endclass
735
736 var pos = TextPosition.new()
737 assert_equal(0, pos.lnum)
738 assert_equal(1, pos.col)
739 assert_equal(2, pos.addcol)
740 END
741 v9.CheckScriptSuccess(lines)
742
743 lines =<< trim END
744 vim9script
745 class TextPosition
746 this.lnum
747 this.col = 1
748 endclass
749 END
750 v9.CheckScriptFailure(lines, 'E1022:')
751
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200752 # If the type is not specified for a member, then it should be set during
753 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000754 lines =<< trim END
755 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200756
757 var init_count = 0
758 def Init(): string
759 init_count += 1
760 return 'foo'
761 enddef
762
763 class A
764 this.str1 = Init()
765 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000766 this.col = 1
767 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200768
769 assert_equal(init_count, 0)
770 var a = A.new()
771 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000772 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200773 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200774
775 # Test for initializing an object member with an unknown variable/type
776 lines =<< trim END
777 vim9script
778 class A
779 this.value = init_val
780 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200781 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200782 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200783 v9.CheckScriptFailure(lines, 'E1001:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000784enddef
785
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000786def Test_class_object_member_access()
787 var lines =<< trim END
788 vim9script
789 class Triple
790 this._one = 1
791 this.two = 2
792 public this.three = 3
793
794 def GetOne(): number
795 return this._one
796 enddef
797 endclass
798
799 var trip = Triple.new()
800 assert_equal(1, trip.GetOne())
801 assert_equal(2, trip.two)
802 assert_equal(3, trip.three)
803 assert_fails('echo trip._one', 'E1333')
804
805 assert_fails('trip._one = 11', 'E1333')
806 assert_fails('trip.two = 22', 'E1335')
807 trip.three = 33
808 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000809
810 assert_fails('trip.four = 4', 'E1334')
811 END
812 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000813
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200814 # Test for a public member variable name beginning with an underscore
815 lines =<< trim END
816 vim9script
817 class A
818 public this._val = 10
819 endclass
820 END
821 v9.CheckScriptFailure(lines, 'E1332:')
822
Bram Moolenaar590162c2022-12-24 21:24:06 +0000823 lines =<< trim END
824 vim9script
825
826 class MyCar
827 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000828 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000829
830 def new(make_arg: string)
831 this.make = make_arg
832 enddef
833
834 def GetMake(): string
835 return $"make = {this.make}"
836 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000837 def GetAge(): number
838 return this.age
839 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000840 endclass
841
842 var c = MyCar.new("abc")
843 assert_equal('make = abc', c.GetMake())
844
845 c = MyCar.new("def")
846 assert_equal('make = def', c.GetMake())
847
848 var c2 = MyCar.new("123")
849 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000850
851 def CheckCar()
852 assert_equal("make = def", c.GetMake())
853 assert_equal(5, c.GetAge())
854 enddef
855 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000856 END
857 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000858
859 lines =<< trim END
860 vim9script
861
862 class MyCar
863 this.make: string
864
865 def new(make_arg: string)
866 this.make = make_arg
867 enddef
868 endclass
869
870 var c = MyCar.new("abc")
871 var c = MyCar.new("def")
872 END
873 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000874
875 lines =<< trim END
876 vim9script
877
878 class Foo
879 this.x: list<number> = []
880
881 def Add(n: number): any
882 this.x->add(n)
883 return this
884 enddef
885 endclass
886
887 echo Foo.new().Add(1).Add(2).x
888 echo Foo.new().Add(1).Add(2)
889 .x
890 echo Foo.new().Add(1)
891 .Add(2).x
892 echo Foo.new()
893 .Add(1).Add(2).x
894 echo Foo.new()
895 .Add(1)
896 .Add(2)
897 .x
898 END
899 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200900
901 # Test for "public" cannot be abbreviated
902 lines =<< trim END
903 vim9script
904 class Something
905 pub this.val = 1
906 endclass
907 END
908 v9.CheckScriptFailure(lines, 'E1065:')
909
910 # Test for "public" keyword must be followed by "this" or "static".
911 lines =<< trim END
912 vim9script
913 class Something
914 public val = 1
915 endclass
916 END
917 v9.CheckScriptFailure(lines, 'E1331:')
918
919 # Test for "static" cannot be abbreviated
920 lines =<< trim END
921 vim9script
922 class Something
923 stat this.val = 1
924 endclass
925 END
926 v9.CheckScriptFailure(lines, 'E1065:')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +0200927
928 # Test for "static" cannot be followed by "this".
929 lines =<< trim END
930 vim9script
931 class Something
932 static this.val = 1
933 endclass
934 END
935 v9.CheckScriptFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
Ernie Raelcf138d42023-09-06 20:45:03 +0200936
937 # Access from child class extending a class:
938 lines =<< trim END
939 vim9script
940 class A
941 this.ro_obj_var = 10
942 public this.rw_obj_var = 20
943 this._priv_obj_var = 30
944
945 static ro_class_var = 40
946 public static rw_class_var = 50
947 static _priv_class_var = 60
948 endclass
949
950 class B extends A
951 def Foo()
952 var x: number
953 x = this.ro_obj_var
954 this.ro_obj_var = 0
955 x = this.rw_obj_var
956 this.rw_obj_var = 0
957 x = this._priv_obj_var
958 this._priv_obj_var = 0
959
960 x = ro_class_var
961 ro_class_var = 0
962 x = rw_class_var
963 rw_class_var = 0
964 x = _priv_class_var
965 _priv_class_var = 0
966
967 x = A.ro_class_var
968 A.ro_class_var = 0
969 x = A.rw_class_var
970 A.rw_class_var = 0
971 x = A._priv_class_var
972 A._priv_class_var = 0
973 enddef
974 endclass
975
976 var b = B.new()
977 b.Foo()
978 END
979 v9.CheckScriptSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +0000980enddef
981
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000982def Test_class_object_compare()
983 var class_lines =<< trim END
984 vim9script
985 class Item
986 this.nr = 0
987 this.name = 'xx'
988 endclass
989 END
990
991 # used at the script level and in a compiled function
992 var test_lines =<< trim END
993 var i1 = Item.new()
994 assert_equal(i1, i1)
995 assert_true(i1 is i1)
996 var i2 = Item.new()
997 assert_equal(i1, i2)
998 assert_false(i1 is i2)
999 var i3 = Item.new(0, 'xx')
1000 assert_equal(i1, i3)
1001
1002 var io1 = Item.new(1, 'xx')
1003 assert_notequal(i1, io1)
1004 var io2 = Item.new(0, 'yy')
1005 assert_notequal(i1, io2)
1006 END
1007
1008 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001009 v9.CheckScriptSuccess(
1010 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001011
1012 for op in ['>', '>=', '<', '<=', '=~', '!~']
1013 var op_lines = [
1014 'var i1 = Item.new()',
1015 'var i2 = Item.new()',
1016 'echo i1 ' .. op .. ' i2',
1017 ]
1018 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001019 v9.CheckScriptFailure(class_lines
1020 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001021 endfor
1022enddef
1023
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001024def Test_object_type()
1025 var lines =<< trim END
1026 vim9script
1027
1028 class One
1029 this.one = 1
1030 endclass
1031 class Two
1032 this.two = 2
1033 endclass
1034 class TwoMore extends Two
1035 this.more = 9
1036 endclass
1037
1038 var o: One = One.new()
1039 var t: Two = Two.new()
1040 var m: TwoMore = TwoMore.new()
1041 var tm: Two = TwoMore.new()
1042
1043 t = m
1044 END
1045 v9.CheckScriptSuccess(lines)
1046
1047 lines =<< trim END
1048 vim9script
1049
1050 class One
1051 this.one = 1
1052 endclass
1053 class Two
1054 this.two = 2
1055 endclass
1056
1057 var o: One = Two.new()
1058 END
1059 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001060
1061 lines =<< trim END
1062 vim9script
1063
1064 interface One
1065 def GetMember(): number
1066 endinterface
1067 class Two implements One
1068 this.one = 1
1069 def GetMember(): number
1070 return this.one
1071 enddef
1072 endclass
1073
1074 var o: One = Two.new(5)
1075 assert_equal(5, o.GetMember())
1076 END
1077 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001078
1079 lines =<< trim END
1080 vim9script
1081
1082 class Num
1083 this.n: number = 0
1084 endclass
1085
1086 def Ref(name: string): func(Num): Num
1087 return (arg: Num): Num => {
1088 return eval(name)(arg)
1089 }
1090 enddef
1091
1092 const Fn = Ref('Double')
1093 var Double = (m: Num): Num => Num.new(m.n * 2)
1094
1095 echo Fn(Num.new(4))
1096 END
1097 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001098enddef
1099
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001100def Test_class_member()
1101 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001102 var lines =<< trim END
1103 vim9script
1104 class TextPos
1105 this.lnum = 1
1106 this.col = 1
1107 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001108 static _secret = 7
1109 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001110
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001111 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001112 counter += nr
1113 enddef
1114 endclass
1115
1116 assert_equal(0, TextPos.counter)
1117 TextPos.AddToCounter(3)
1118 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001119 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001120
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001121 def GetCounter(): number
1122 return TextPos.counter
1123 enddef
1124 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001125
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001126 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001127 assert_fails('TextPos.counter = 5', 'E1335:')
1128 assert_fails('TextPos.counter += 5', 'E1335:')
1129
1130 assert_fails('echo TextPos._secret', 'E1333:')
1131 assert_fails('TextPos._secret = 8', 'E1333:')
1132
1133 assert_equal(42, TextPos.anybody)
1134 TextPos.anybody = 12
1135 assert_equal(12, TextPos.anybody)
1136 TextPos.anybody += 5
1137 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001138 END
1139 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001140
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001141 # example in the help
1142 lines =<< trim END
1143 vim9script
1144 class OtherThing
1145 this.size: number
1146 static totalSize: number
1147
1148 def new(this.size)
1149 totalSize += this.size
1150 enddef
1151 endclass
1152 assert_equal(0, OtherThing.totalSize)
1153 var to3 = OtherThing.new(3)
1154 assert_equal(3, OtherThing.totalSize)
1155 var to7 = OtherThing.new(7)
1156 assert_equal(10, OtherThing.totalSize)
1157 END
1158 v9.CheckScriptSuccess(lines)
1159
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001160 # using static class member twice
1161 lines =<< trim END
1162 vim9script
1163
1164 class HTML
1165 static author: string = 'John Doe'
1166
1167 static def MacroSubstitute(s: string): string
1168 return substitute(s, '{{author}}', author, 'gi')
1169 enddef
1170 endclass
1171
1172 assert_equal('some text', HTML.MacroSubstitute('some text'))
1173 assert_equal('some text', HTML.MacroSubstitute('some text'))
1174 END
1175 v9.CheckScriptSuccess(lines)
1176
Bram Moolenaar62a69232023-01-24 15:07:04 +00001177 # access private member in lambda
1178 lines =<< trim END
1179 vim9script
1180
1181 class Foo
1182 this._x: number = 0
1183
1184 def Add(n: number): number
1185 const F = (): number => this._x + n
1186 return F()
1187 enddef
1188 endclass
1189
1190 var foo = Foo.new()
1191 assert_equal(5, foo.Add(5))
1192 END
1193 v9.CheckScriptSuccess(lines)
1194
h-east2bd6a092023-05-19 19:01:17 +01001195 # access private member in lambda body
1196 lines =<< trim END
1197 vim9script
1198
1199 class Foo
1200 this._x: number = 6
1201
1202 def Add(n: number): number
1203 var Lam = () => {
1204 this._x = this._x + n
1205 }
1206 Lam()
1207 return this._x
1208 enddef
1209 endclass
1210
1211 var foo = Foo.new()
1212 assert_equal(13, foo.Add(7))
1213 END
1214 v9.CheckScriptSuccess(lines)
1215
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001216 # check shadowing
1217 lines =<< trim END
1218 vim9script
1219
1220 class Some
1221 static count = 0
1222 def Method(count: number)
1223 echo count
1224 enddef
1225 endclass
1226
1227 var s = Some.new()
1228 s.Method(7)
1229 END
1230 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
1231
1232 lines =<< trim END
1233 vim9script
1234
1235 class Some
1236 static count = 0
1237 def Method(arg: number)
1238 var count = 3
1239 echo arg count
1240 enddef
1241 endclass
1242
1243 var s = Some.new()
1244 s.Method(7)
1245 END
1246 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001247
1248 # Test for using an invalid type for a member variable
1249 lines =<< trim END
1250 vim9script
1251 class A
1252 this.val: xxx
1253 endclass
1254 END
1255 v9.CheckScriptFailure(lines, 'E1010:')
1256
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001257 # Test for setting a member on a null object
1258 lines =<< trim END
1259 vim9script
1260 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001261 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001262 endclass
1263
1264 def F()
1265 var obj: A
1266 obj.val = ""
1267 enddef
1268 F()
1269 END
1270 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1271
1272 # Test for accessing a member on a null object
1273 lines =<< trim END
1274 vim9script
1275 class A
1276 this.val: string
1277 endclass
1278
1279 def F()
1280 var obj: A
1281 echo obj.val
1282 enddef
1283 F()
1284 END
1285 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1286
1287 # Test for setting a member on a null object, at script level
1288 lines =<< trim END
1289 vim9script
1290 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001291 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001292 endclass
1293
1294 var obj: A
1295 obj.val = ""
1296 END
1297 # FIXME(in source): this should give E1360 as well!
1298 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
1299
1300 # Test for accessing a member on a null object, at script level
1301 lines =<< trim END
1302 vim9script
1303 class A
1304 this.val: string
1305 endclass
1306
1307 var obj: A
1308 echo obj.val
1309 END
1310 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1311
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001312 # Test for no space before or after the '=' when initializing a member
1313 # variable
1314 lines =<< trim END
1315 vim9script
1316 class A
1317 this.val: number= 10
1318 endclass
1319 END
1320 v9.CheckScriptFailure(lines, 'E1004:')
1321 lines =<< trim END
1322 vim9script
1323 class A
1324 this.val: number =10
1325 endclass
1326 END
1327 v9.CheckScriptFailure(lines, 'E1004:')
1328
1329 # Access a non-existing member
1330 lines =<< trim END
1331 vim9script
1332 class A
1333 endclass
1334 var a = A.new()
1335 var v = a.bar
1336 END
1337 v9.CheckScriptFailure(lines, 'E1326:')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001338enddef
1339
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001340func Test_class_garbagecollect()
1341 let lines =<< trim END
1342 vim9script
1343
1344 class Point
1345 this.p = [2, 3]
1346 static pl = ['a', 'b']
1347 static pd = {a: 'a', b: 'b'}
1348 endclass
1349
1350 echo Point.pl Point.pd
1351 call test_garbagecollect_now()
1352 echo Point.pl Point.pd
1353 END
1354 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001355
1356 let lines =<< trim END
1357 vim9script
1358
1359 interface View
1360 endinterface
1361
1362 class Widget
1363 this.view: View
1364 endclass
1365
1366 class MyView implements View
1367 this.widget: Widget
1368
1369 def new()
1370 # this will result in a circular reference to this object
1371 this.widget = Widget.new(this)
1372 enddef
1373 endclass
1374
1375 var view = MyView.new()
1376
1377 # overwrite "view", will be garbage-collected next
1378 view = MyView.new()
1379 test_garbagecollect_now()
1380 END
1381 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001382endfunc
1383
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001384" Test interface garbage collection
1385func Test_interface_garbagecollect()
1386 let lines =<< trim END
1387 vim9script
1388
1389 interface I
1390 static ro_class_var: number
1391 public static rw_class_var: number
1392 static _priv_class_var: number
1393 this.ro_obj_var: number
1394 public this.rw_obj_var: number
1395 this._priv_obj_var: number
1396
1397 static def ClassFoo(): number
1398 static def _ClassBar(): number
1399 def ObjFoo(): number
1400 def _ObjBar(): number
1401 endinterface
1402
1403 class A implements I
1404 static ro_class_var: number = 10
1405 public static rw_class_var: number = 20
1406 static _priv_class_var: number = 30
1407 this.ro_obj_var: number = 40
1408 public this.rw_obj_var: number = 50
1409 this._priv_obj_var: number = 60
1410
1411 static def _ClassBar(): number
1412 return _priv_class_var
1413 enddef
1414
1415 static def ClassFoo(): number
1416 return ro_class_var + rw_class_var + A._ClassBar()
1417 enddef
1418
1419 def _ObjBar(): number
1420 return this._priv_obj_var
1421 enddef
1422
1423 def ObjFoo(): number
1424 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1425 enddef
1426 endclass
1427
1428 assert_equal(60, A.ClassFoo())
1429 var o = A.new()
1430 assert_equal(150, o.ObjFoo())
1431 test_garbagecollect_now()
1432 assert_equal(60, A.ClassFoo())
1433 assert_equal(150, o.ObjFoo())
1434 END
1435 call v9.CheckScriptSuccess(lines)
1436endfunc
1437
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001438def Test_class_function()
1439 var lines =<< trim END
1440 vim9script
1441 class Value
1442 this.value = 0
1443 static objects = 0
1444
1445 def new(v: number)
1446 this.value = v
1447 ++objects
1448 enddef
1449
1450 static def GetCount(): number
1451 return objects
1452 enddef
1453 endclass
1454
1455 assert_equal(0, Value.GetCount())
1456 var v1 = Value.new(2)
1457 assert_equal(1, Value.GetCount())
1458 var v2 = Value.new(7)
1459 assert_equal(2, Value.GetCount())
1460 END
1461 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001462
1463 # Test for cleaning up after a class definition failure when using class
1464 # functions.
1465 lines =<< trim END
1466 vim9script
1467 class A
1468 static def Foo()
1469 enddef
1470 aaa
1471 endclass
1472 END
1473 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001474enddef
1475
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001476def Test_class_defcompile()
1477 var lines =<< trim END
1478 vim9script
1479
1480 class C
1481 def Fo(i: number): string
1482 return i
1483 enddef
1484 endclass
1485
1486 defcompile C.Fo
1487 END
1488 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1489
1490 lines =<< trim END
1491 vim9script
1492
1493 class C
1494 static def Fc(): number
1495 return 'x'
1496 enddef
1497 endclass
1498
1499 defcompile C.Fc
1500 END
1501 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001502
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001503 lines =<< trim END
1504 vim9script
1505
1506 class C
1507 static def new()
1508 enddef
1509 endclass
1510
1511 defcompile C.new
1512 END
1513 v9.CheckScriptFailure(lines, 'E1370: Cannot define a "new" function as static')
1514
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001515 # Trying to compile a function using a non-existing class variable
1516 lines =<< trim END
1517 vim9script
1518 defcompile x.Foo()
1519 END
1520 v9.CheckScriptFailure(lines, 'E475:')
1521
1522 # Trying to compile a function using a variable which is not a class
1523 lines =<< trim END
1524 vim9script
1525 var x: number
1526 defcompile x.Foo()
1527 END
1528 v9.CheckScriptFailure(lines, 'E475:')
1529
1530 # Trying to compile a function without specifying the name
1531 lines =<< trim END
1532 vim9script
1533 class A
1534 endclass
1535 defcompile A.
1536 END
1537 v9.CheckScriptFailure(lines, 'E475:')
1538
1539 # Trying to compile a non-existing class object member function
1540 lines =<< trim END
1541 vim9script
1542 class A
1543 endclass
1544 var a = A.new()
1545 defcompile a.Foo()
1546 END
1547 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001548enddef
1549
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001550def Test_class_object_to_string()
1551 var lines =<< trim END
1552 vim9script
1553 class TextPosition
1554 this.lnum = 1
1555 this.col = 22
1556 endclass
1557
1558 assert_equal("class TextPosition", string(TextPosition))
1559
1560 var pos = TextPosition.new()
1561 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1562 END
1563 v9.CheckScriptSuccess(lines)
1564enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001565
Bram Moolenaar554d0312023-01-05 19:59:18 +00001566def Test_interface_basics()
1567 var lines =<< trim END
1568 vim9script
1569 interface Something
1570 this.value: string
1571 static count: number
1572 def GetCount(): number
1573 endinterface
1574 END
1575 v9.CheckScriptSuccess(lines)
1576
1577 lines =<< trim END
1578 interface SomethingWrong
1579 static count = 7
1580 endinterface
1581 END
1582 v9.CheckScriptFailure(lines, 'E1342:')
1583
1584 lines =<< trim END
1585 vim9script
1586
1587 interface Some
1588 static count: number
1589 def Method(count: number)
1590 endinterface
1591 END
h-east61378a12023-04-18 19:07:29 +01001592 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001593
1594 lines =<< trim END
1595 vim9script
1596
1597 interface Some
1598 this.value: number
1599 def Method(value: number)
1600 endinterface
1601 END
h-east61378a12023-04-18 19:07:29 +01001602 # The argument name and the object member name are the same, but this is not a
1603 # problem because object members are always accessed with the "this." prefix.
1604 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001605
1606 lines =<< trim END
1607 vim9script
1608 interface somethingWrong
1609 static count = 7
1610 endinterface
1611 END
1612 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1613
1614 lines =<< trim END
1615 vim9script
1616 interface SomethingWrong
1617 this.value: string
1618 static count = 7
1619 def GetCount(): number
1620 endinterface
1621 END
1622 v9.CheckScriptFailure(lines, 'E1344:')
1623
1624 lines =<< trim END
1625 vim9script
1626 interface SomethingWrong
1627 this.value: string
1628 static count: number
1629 def GetCount(): number
1630 return 5
1631 enddef
1632 endinterface
1633 END
1634 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001635
1636 lines =<< trim END
1637 vim9script
1638 export interface EnterExit
1639 def Enter(): void
1640 def Exit(): void
1641 endinterface
1642 END
1643 writefile(lines, 'XdefIntf.vim', 'D')
1644
1645 lines =<< trim END
1646 vim9script
1647 import './XdefIntf.vim' as defIntf
1648 export def With(ee: defIntf.EnterExit, F: func)
1649 ee.Enter()
1650 try
1651 F()
1652 finally
1653 ee.Exit()
1654 endtry
1655 enddef
1656 END
1657 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001658
1659 var imported =<< trim END
1660 vim9script
1661 export abstract class EnterExit
1662 def Enter(): void
1663 enddef
1664 def Exit(): void
1665 enddef
1666 endclass
1667 END
1668 writefile(imported, 'XdefIntf2.vim', 'D')
1669
1670 lines[1] = " import './XdefIntf2.vim' as defIntf"
1671 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001672enddef
1673
Bram Moolenaar94674f22023-01-06 18:42:20 +00001674def Test_class_implements_interface()
1675 var lines =<< trim END
1676 vim9script
1677
1678 interface Some
1679 static count: number
1680 def Method(nr: number)
1681 endinterface
1682
1683 class SomeImpl implements Some
1684 static count: number
1685 def Method(nr: number)
1686 echo nr
1687 enddef
1688 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001689
1690 interface Another
1691 this.member: string
1692 endinterface
1693
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001694 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001695 this.member = 'abc'
1696 static count: number
1697 def Method(nr: number)
1698 echo nr
1699 enddef
1700 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001701 END
1702 v9.CheckScriptSuccess(lines)
1703
1704 lines =<< trim END
1705 vim9script
1706
1707 interface Some
1708 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001709 endinterface
1710
1711 class SomeImpl implements Some implements Some
1712 static count: number
1713 endclass
1714 END
1715 v9.CheckScriptFailure(lines, 'E1350:')
1716
1717 lines =<< trim END
1718 vim9script
1719
1720 interface Some
1721 static counter: number
1722 endinterface
1723
1724 class SomeImpl implements Some, Some
1725 static count: number
1726 endclass
1727 END
1728 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1729
1730 lines =<< trim END
1731 vim9script
1732
1733 interface Some
1734 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001735 def Method(nr: number)
1736 endinterface
1737
1738 class SomeImpl implements Some
1739 static count: number
1740 def Method(nr: number)
1741 echo nr
1742 enddef
1743 endclass
1744 END
1745 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1746
1747 lines =<< trim END
1748 vim9script
1749
1750 interface Some
1751 static count: number
1752 def Methods(nr: number)
1753 endinterface
1754
1755 class SomeImpl implements Some
1756 static count: number
1757 def Method(nr: number)
1758 echo nr
1759 enddef
1760 endclass
1761 END
1762 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001763
1764 # Check different order of members in class and interface works.
1765 lines =<< trim END
1766 vim9script
1767
1768 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001769 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001770 this.errpos: number
1771 endinterface
1772
1773 # order of members is opposite of interface
1774 class Failure implements Result
1775 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001776 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001777 endclass
1778
1779 def Test()
1780 var result: Result = Failure.new()
1781
1782 assert_equal('label', result.label)
1783 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001784
1785 result.label = 'different'
1786 assert_equal('different', result.label)
1787 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001788 enddef
1789
1790 Test()
1791 END
1792 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001793
1794 # Interface name after "extends" doesn't end in a space or NUL character
1795 lines =<< trim END
1796 vim9script
1797 interface A
1798 endinterface
1799 class B extends A"
1800 endclass
1801 END
1802 v9.CheckScriptFailure(lines, 'E1315:')
1803
1804 # Trailing characters after a class name
1805 lines =<< trim END
1806 vim9script
1807 class A bbb
1808 endclass
1809 END
1810 v9.CheckScriptFailure(lines, 'E488:')
1811
1812 # using "implements" with a non-existing class
1813 lines =<< trim END
1814 vim9script
1815 class A implements B
1816 endclass
1817 END
1818 v9.CheckScriptFailure(lines, 'E1346:')
1819
1820 # using "implements" with a regular class
1821 lines =<< trim END
1822 vim9script
1823 class A
1824 endclass
1825 class B implements A
1826 endclass
1827 END
1828 v9.CheckScriptFailure(lines, 'E1347:')
1829
1830 # using "implements" with a variable
1831 lines =<< trim END
1832 vim9script
1833 var T: number = 10
1834 class A implements T
1835 endclass
1836 END
1837 v9.CheckScriptFailure(lines, 'E1347:')
1838
1839 # all the class methods in an "interface" should be implemented
1840 lines =<< trim END
1841 vim9script
1842 interface A
1843 static def Foo()
1844 endinterface
1845 class B implements A
1846 endclass
1847 END
1848 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001849
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02001850 # implements should be followed by a white space
1851 lines =<< trim END
1852 vim9script
1853 interface A
1854 endinterface
1855 class B implements A;
1856 endclass
1857 END
1858 v9.CheckScriptFailure(lines, 'E1315:')
1859
LemonBoyc5d27442023-08-19 13:02:35 +02001860 lines =<< trim END
1861 vim9script
1862
1863 interface One
1864 static matching: bool
1865 static as_any: any
1866 static not_matching: number
1867 endinterface
1868 class Two implements One
1869 static not_matching: string
1870 static as_any: string
1871 static matching: bool
1872 endclass
1873 END
1874 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1875
1876 lines =<< trim END
1877 vim9script
1878
1879 interface One
1880 def IsEven(nr: number): bool
1881 endinterface
1882 class Two implements One
1883 def IsEven(nr: number): string
1884 enddef
1885 endclass
1886 END
Christian Brabandtee17b6f2023-09-09 11:23:50 +02001887 v9.CheckScriptFailure(lines, 'E1407: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02001888
1889 lines =<< trim END
1890 vim9script
1891
1892 interface One
1893 def IsEven(nr: number): bool
1894 endinterface
1895 class Two implements One
1896 def IsEven(nr: bool): bool
1897 enddef
1898 endclass
1899 END
Christian Brabandtee17b6f2023-09-09 11:23:50 +02001900 v9.CheckScriptFailure(lines, 'E1407: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02001901
1902 lines =<< trim END
1903 vim9script
1904
1905 interface One
1906 def IsEven(nr: number): bool
1907 endinterface
1908 class Two implements One
1909 def IsEven(nr: number, ...extra: list<number>): bool
1910 enddef
1911 endclass
1912 END
Christian Brabandtee17b6f2023-09-09 11:23:50 +02001913 v9.CheckScriptFailure(lines, 'E1407: Method "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
Ernie Raelcf138d42023-09-06 20:45:03 +02001914
1915 # access superclass interface members from subclass, mix variable order
1916 lines =<< trim END
1917 vim9script
1918
1919 interface I1
1920 public static svar1: number
1921 public static svar2: number
1922 public this.mvar1: number
1923 public this.mvar2: number
1924 endinterface
1925
1926 # NOTE: the order is swapped
1927 class A implements I1
1928 public this.mvar2: number
1929 public this.mvar1: number
1930 public static svar2: number
1931 public static svar1: number
1932 def new()
1933 svar1 = 11
1934 svar2 = 12
1935 this.mvar1 = 111
1936 this.mvar2 = 112
1937 enddef
1938 endclass
1939
1940 class B extends A
1941 def new()
1942 svar1 = 21
1943 svar2 = 22
1944 this.mvar1 = 121
1945 this.mvar2 = 122
1946 enddef
1947 endclass
1948
1949 class C extends B
1950 def new()
1951 svar1 = 31
1952 svar2 = 32
1953 this.mvar1 = 131
1954 this.mvar2 = 132
1955 enddef
1956 endclass
1957
Ernie Raelcf138d42023-09-06 20:45:03 +02001958 def F2(i: I1): list<number>
1959 return [ i.mvar1, i.mvar2 ]
1960 enddef
1961
1962 var oa = A.new()
1963 var ob = B.new()
1964 var oc = C.new()
1965
Ernie Raelcf138d42023-09-06 20:45:03 +02001966 assert_equal([111, 112], F2(oa))
1967 assert_equal([121, 122], F2(ob))
1968 assert_equal([131, 132], F2(oc))
1969 END
1970 v9.CheckScriptSuccess(lines)
1971
1972 # Access superclass interface members from subclass, mix variable order.
1973 # Two interfaces, one on A, one on B; each has both kinds of variables
1974 lines =<< trim END
1975 vim9script
1976
1977 interface I1
1978 public static svar1: number
1979 public static svar2: number
1980 public this.mvar1: number
1981 public this.mvar2: number
1982 endinterface
1983
1984 interface I2
1985 public static svar3: number
1986 public static svar4: number
1987 public this.mvar3: number
1988 public this.mvar4: number
1989 endinterface
1990
1991 class A implements I1
1992 public static svar1: number
1993 public static svar2: number
1994 public this.mvar1: number
1995 public this.mvar2: number
1996 def new()
1997 svar1 = 11
1998 svar2 = 12
1999 this.mvar1 = 111
2000 this.mvar2 = 112
2001 enddef
2002 endclass
2003
2004 class B extends A implements I2
2005 public static svar3: number
2006 public static svar4: number
2007 public this.mvar3: number
2008 public this.mvar4: number
2009 def new()
2010 svar1 = 21
2011 svar2 = 22
2012 svar3 = 23
2013 svar4 = 24
2014 this.mvar1 = 121
2015 this.mvar2 = 122
2016 this.mvar3 = 123
2017 this.mvar4 = 124
2018 enddef
2019 endclass
2020
2021 class C extends B
2022 public static svar5: number
2023 def new()
2024 svar1 = 31
2025 svar2 = 32
2026 svar3 = 33
2027 svar4 = 34
2028 svar5 = 1001
2029 this.mvar1 = 131
2030 this.mvar2 = 132
2031 this.mvar3 = 133
2032 this.mvar4 = 134
2033 enddef
2034 endclass
2035
Ernie Raelcf138d42023-09-06 20:45:03 +02002036 def F2(i: I1): list<number>
2037 return [ i.mvar1, i.mvar2 ]
2038 enddef
2039
Ernie Raelcf138d42023-09-06 20:45:03 +02002040 def F4(i: I2): list<number>
2041 return [ i.mvar3, i.mvar4 ]
2042 enddef
2043
Ernie Raelcf138d42023-09-06 20:45:03 +02002044 var oa = A.new()
2045 var ob = B.new()
2046 var oc = C.new()
2047
Ernie Raelcf138d42023-09-06 20:45:03 +02002048 assert_equal([[111, 112]], [F2(oa)])
2049 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2050 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002051 END
2052 v9.CheckScriptSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002053enddef
2054
Bram Moolenaard0200c82023-01-28 15:19:40 +00002055def Test_call_interface_method()
2056 var lines =<< trim END
2057 vim9script
2058 interface Base
2059 def Enter(): void
2060 endinterface
2061
2062 class Child implements Base
2063 def Enter(): void
2064 g:result ..= 'child'
2065 enddef
2066 endclass
2067
2068 def F(obj: Base)
2069 obj.Enter()
2070 enddef
2071
2072 g:result = ''
2073 F(Child.new())
2074 assert_equal('child', g:result)
2075 unlet g:result
2076 END
2077 v9.CheckScriptSuccess(lines)
2078
2079 lines =<< trim END
2080 vim9script
2081 class Base
2082 def Enter(): void
2083 g:result ..= 'base'
2084 enddef
2085 endclass
2086
2087 class Child extends Base
2088 def Enter(): void
2089 g:result ..= 'child'
2090 enddef
2091 endclass
2092
2093 def F(obj: Base)
2094 obj.Enter()
2095 enddef
2096
2097 g:result = ''
2098 F(Child.new())
2099 assert_equal('child', g:result)
2100 unlet g:result
2101 END
2102 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002103
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002104 # method of interface returns a value
2105 lines =<< trim END
2106 vim9script
2107 interface Base
2108 def Enter(): string
2109 endinterface
2110
2111 class Child implements Base
2112 def Enter(): string
2113 g:result ..= 'child'
2114 return "/resource"
2115 enddef
2116 endclass
2117
2118 def F(obj: Base)
2119 var r = obj.Enter()
2120 g:result ..= r
2121 enddef
2122
2123 g:result = ''
2124 F(Child.new())
2125 assert_equal('child/resource', g:result)
2126 unlet g:result
2127 END
2128 v9.CheckScriptSuccess(lines)
2129
2130 lines =<< trim END
2131 vim9script
2132 class Base
2133 def Enter(): string
2134 return null_string
2135 enddef
2136 endclass
2137
2138 class Child extends Base
2139 def Enter(): string
2140 g:result ..= 'child'
2141 return "/resource"
2142 enddef
2143 endclass
2144
2145 def F(obj: Base)
2146 var r = obj.Enter()
2147 g:result ..= r
2148 enddef
2149
2150 g:result = ''
2151 F(Child.new())
2152 assert_equal('child/resource', g:result)
2153 unlet g:result
2154 END
2155 v9.CheckScriptSuccess(lines)
2156
2157
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002158 # No class that implements the interface.
2159 lines =<< trim END
2160 vim9script
2161
2162 interface IWithEE
2163 def Enter(): any
2164 def Exit(): void
2165 endinterface
2166
2167 def With1(ee: IWithEE, F: func)
2168 var r = ee.Enter()
2169 enddef
2170
2171 defcompile
2172 END
2173 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002174enddef
2175
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002176def Test_class_used_as_type()
2177 var lines =<< trim END
2178 vim9script
2179
2180 class Point
2181 this.x = 0
2182 this.y = 0
2183 endclass
2184
2185 var p: Point
2186 p = Point.new(2, 33)
2187 assert_equal(2, p.x)
2188 assert_equal(33, p.y)
2189 END
2190 v9.CheckScriptSuccess(lines)
2191
2192 lines =<< trim END
2193 vim9script
2194
2195 interface HasX
2196 this.x: number
2197 endinterface
2198
2199 class Point implements HasX
2200 this.x = 0
2201 this.y = 0
2202 endclass
2203
2204 var p: Point
2205 p = Point.new(2, 33)
2206 var hx = p
2207 assert_equal(2, hx.x)
2208 END
2209 v9.CheckScriptSuccess(lines)
2210
2211 lines =<< trim END
2212 vim9script
2213
2214 class Point
2215 this.x = 0
2216 this.y = 0
2217 endclass
2218
2219 var p: Point
2220 p = 'text'
2221 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002222 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002223enddef
2224
Bram Moolenaar83677162023-01-08 19:54:10 +00002225def Test_class_extends()
2226 var lines =<< trim END
2227 vim9script
2228 class Base
2229 this.one = 1
2230 def GetOne(): number
2231 return this.one
2232 enddef
2233 endclass
2234 class Child extends Base
2235 this.two = 2
2236 def GetTotal(): number
2237 return this.one + this.two
2238 enddef
2239 endclass
2240 var o = Child.new()
2241 assert_equal(1, o.one)
2242 assert_equal(2, o.two)
2243 assert_equal(1, o.GetOne())
2244 assert_equal(3, o.GetTotal())
2245 END
2246 v9.CheckScriptSuccess(lines)
2247
2248 lines =<< trim END
2249 vim9script
2250 class Base
2251 this.one = 1
2252 endclass
2253 class Child extends Base
2254 this.two = 2
2255 endclass
2256 var o = Child.new(3, 44)
2257 assert_equal(3, o.one)
2258 assert_equal(44, o.two)
2259 END
2260 v9.CheckScriptSuccess(lines)
2261
2262 lines =<< trim END
2263 vim9script
2264 class Base
2265 this.one = 1
2266 endclass
2267 class Child extends Base extends Base
2268 this.two = 2
2269 endclass
2270 END
2271 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
2272
2273 lines =<< trim END
2274 vim9script
2275 class Child extends BaseClass
2276 this.two = 2
2277 endclass
2278 END
2279 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
2280
2281 lines =<< trim END
2282 vim9script
2283 var SomeVar = 99
2284 class Child extends SomeVar
2285 this.two = 2
2286 endclass
2287 END
2288 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002289
2290 lines =<< trim END
2291 vim9script
2292 class Base
2293 this.name: string
2294 def ToString(): string
2295 return this.name
2296 enddef
2297 endclass
2298
2299 class Child extends Base
2300 this.age: number
2301 def ToString(): string
2302 return super.ToString() .. ': ' .. this.age
2303 enddef
2304 endclass
2305
2306 var o = Child.new('John', 42)
2307 assert_equal('John: 42', o.ToString())
2308 END
2309 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002310
2311 lines =<< trim END
2312 vim9script
2313 class Child
2314 this.age: number
2315 def ToString(): number
2316 return this.age
2317 enddef
2318 def ToString(): string
2319 return this.age
2320 enddef
2321 endclass
2322 END
2323 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
2324
2325 lines =<< trim END
2326 vim9script
2327 class Child
2328 this.age: number
2329 def ToString(): string
2330 return super .ToString() .. ': ' .. this.age
2331 enddef
2332 endclass
2333 var o = Child.new(42)
2334 echo o.ToString()
2335 END
2336 v9.CheckScriptFailure(lines, 'E1356:')
2337
2338 lines =<< trim END
2339 vim9script
2340 class Base
2341 this.name: string
2342 def ToString(): string
2343 return this.name
2344 enddef
2345 endclass
2346
2347 var age = 42
2348 def ToString(): string
2349 return super.ToString() .. ': ' .. age
2350 enddef
2351 echo ToString()
2352 END
2353 v9.CheckScriptFailure(lines, 'E1357:')
2354
2355 lines =<< trim END
2356 vim9script
2357 class Child
2358 this.age: number
2359 def ToString(): string
2360 return super.ToString() .. ': ' .. this.age
2361 enddef
2362 endclass
2363 var o = Child.new(42)
2364 echo o.ToString()
2365 END
2366 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002367
2368 lines =<< trim END
2369 vim9script
2370 class Base
2371 this.name: string
2372 static def ToString(): string
2373 return 'Base class'
2374 enddef
2375 endclass
2376
2377 class Child extends Base
2378 this.age: number
2379 def ToString(): string
2380 return Base.ToString() .. ': ' .. this.age
2381 enddef
2382 endclass
2383
2384 var o = Child.new('John', 42)
2385 assert_equal('Base class: 42', o.ToString())
2386 END
2387 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002388
2389 lines =<< trim END
2390 vim9script
2391 class Base
2392 this.value = 1
2393 def new(init: number)
2394 this.value = number + 1
2395 enddef
2396 endclass
2397 class Child extends Base
2398 def new()
2399 this.new(3)
2400 enddef
2401 endclass
2402 var c = Child.new()
2403 END
2404 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002405
2406 # base class with more than one object member
2407 lines =<< trim END
2408 vim9script
2409
2410 class Result
2411 this.success: bool
2412 this.value: any = null
2413 endclass
2414
2415 class Success extends Result
2416 def new(this.value = v:none)
2417 this.success = true
2418 enddef
2419 endclass
2420
2421 var v = Success.new('asdf')
2422 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2423 END
2424 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002425
2426 # class name after "extends" doesn't end in a space or NUL character
2427 lines =<< trim END
2428 vim9script
2429 class A
2430 endclass
2431 class B extends A"
2432 endclass
2433 END
2434 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002435enddef
2436
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002437def Test_using_base_class()
2438 var lines =<< trim END
2439 vim9script
2440
2441 class BaseEE
2442 def Enter(): any
2443 return null
2444 enddef
2445 def Exit(resource: any): void
2446 enddef
2447 endclass
2448
2449 class ChildEE extends BaseEE
2450 def Enter(): any
2451 return 42
2452 enddef
2453
2454 def Exit(resource: number): void
2455 g:result ..= '/exit'
2456 enddef
2457 endclass
2458
2459 def With(ee: BaseEE)
2460 var r = ee.Enter()
2461 try
2462 g:result ..= r
2463 finally
2464 g:result ..= '/finally'
2465 ee.Exit(r)
2466 endtry
2467 enddef
2468
2469 g:result = ''
2470 With(ChildEE.new())
2471 assert_equal('42/finally/exit', g:result)
2472 END
2473 v9.CheckScriptSuccess(lines)
2474 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002475
2476 # Using super, Child invokes Base method which has optional arg. #12471
2477 lines =<< trim END
2478 vim9script
2479
2480 class Base
2481 this.success: bool = false
2482 def Method(arg = 0)
2483 this.success = true
2484 enddef
2485 endclass
2486
2487 class Child extends Base
2488 def new()
2489 super.Method()
2490 enddef
2491 endclass
2492
2493 var obj = Child.new()
2494 assert_equal(true, obj.success)
2495 END
2496 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002497enddef
2498
2499
Bram Moolenaara86655a2023-01-12 17:06:27 +00002500def Test_class_import()
2501 var lines =<< trim END
2502 vim9script
2503 export class Animal
2504 this.kind: string
2505 this.name: string
2506 endclass
2507 END
2508 writefile(lines, 'Xanimal.vim', 'D')
2509
2510 lines =<< trim END
2511 vim9script
2512 import './Xanimal.vim' as animal
2513
2514 var a: animal.Animal
2515 a = animal.Animal.new('fish', 'Eric')
2516 assert_equal('fish', a.kind)
2517 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002518
2519 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2520 assert_equal('cat', b.kind)
2521 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002522 END
2523 v9.CheckScriptSuccess(lines)
2524enddef
2525
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002526def Test_abstract_class()
2527 var lines =<< trim END
2528 vim9script
2529 abstract class Base
2530 this.name: string
2531 endclass
2532 class Person extends Base
2533 this.age: number
2534 endclass
2535 var p: Base = Person.new('Peter', 42)
2536 assert_equal('Peter', p.name)
2537 assert_equal(42, p.age)
2538 END
2539 v9.CheckScriptSuccess(lines)
2540
2541 lines =<< trim END
2542 vim9script
2543 abstract class Base
2544 this.name: string
2545 endclass
2546 class Person extends Base
2547 this.age: number
2548 endclass
2549 var p = Base.new('Peter')
2550 END
2551 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2552
2553 lines =<< trim END
2554 abstract class Base
2555 this.name: string
2556 endclass
2557 END
2558 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002559
2560 # Abstract class cannot have a "new" function
2561 lines =<< trim END
2562 vim9script
2563 abstract class Base
2564 def new()
2565 enddef
2566 endclass
2567 END
2568 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002569enddef
2570
Bram Moolenaar486fc252023-01-18 14:51:07 +00002571def Test_closure_in_class()
2572 var lines =<< trim END
2573 vim9script
2574
2575 class Foo
2576 this.y: list<string> = ['B']
2577
2578 def new()
2579 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2580 enddef
2581 endclass
2582
2583 Foo.new()
2584 assert_equal(['A'], g:result)
2585 END
2586 v9.CheckScriptSuccess(lines)
2587enddef
2588
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002589def Test_call_constructor_from_legacy()
2590 var lines =<< trim END
2591 vim9script
2592
2593 var newCalled = 'false'
2594
2595 class A
2596 def new()
2597 newCalled = 'true'
2598 enddef
2599 endclass
2600
2601 export def F(options = {}): any
2602 return A
2603 enddef
2604
2605 g:p = F()
2606 legacy call p.new()
2607 assert_equal('true', newCalled)
2608 END
2609 v9.CheckScriptSuccess(lines)
2610enddef
2611
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002612def Test_defer_with_object()
2613 var lines =<< trim END
2614 vim9script
2615
2616 class CWithEE
2617 def Enter()
2618 g:result ..= "entered/"
2619 enddef
2620 def Exit()
2621 g:result ..= "exited"
2622 enddef
2623 endclass
2624
2625 def With(ee: CWithEE, F: func)
2626 ee.Enter()
2627 defer ee.Exit()
2628 F()
2629 enddef
2630
2631 g:result = ''
2632 var obj = CWithEE.new()
2633 obj->With(() => {
2634 g:result ..= "called/"
2635 })
2636 assert_equal('entered/called/exited', g:result)
2637 END
2638 v9.CheckScriptSuccess(lines)
2639 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002640
2641 lines =<< trim END
2642 vim9script
2643
2644 class BaseWithEE
2645 def Enter()
2646 g:result ..= "entered-base/"
2647 enddef
2648 def Exit()
2649 g:result ..= "exited-base"
2650 enddef
2651 endclass
2652
2653 class CWithEE extends BaseWithEE
2654 def Enter()
2655 g:result ..= "entered-child/"
2656 enddef
2657 def Exit()
2658 g:result ..= "exited-child"
2659 enddef
2660 endclass
2661
2662 def With(ee: BaseWithEE, F: func)
2663 ee.Enter()
2664 defer ee.Exit()
2665 F()
2666 enddef
2667
2668 g:result = ''
2669 var obj = CWithEE.new()
2670 obj->With(() => {
2671 g:result ..= "called/"
2672 })
2673 assert_equal('entered-child/called/exited-child', g:result)
2674 END
2675 v9.CheckScriptSuccess(lines)
2676 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002677enddef
2678
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002679" The following test used to crash Vim (Github issue #12676)
2680def Test_extends_method_crashes_vim()
2681 var lines =<< trim END
2682 vim9script
2683
2684 class Observer
2685 endclass
2686
2687 class Property
2688 this.value: any
2689
2690 def Set(v: any)
2691 if v != this.value
2692 this.value = v
2693 endif
2694 enddef
2695
2696 def Register(observer: Observer)
2697 enddef
2698 endclass
2699
2700 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002701 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002702 endclass
2703
2704 def Observe(obj: Property, who: Observer)
2705 obj.Register(who)
2706 enddef
2707
2708 var p = Bool.new(false)
2709 var myObserver = Observer.new()
2710
2711 Observe(p, myObserver)
2712
2713 p.Set(true)
2714 END
2715 v9.CheckScriptSuccess(lines)
2716enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002717
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002718" Test for calling a method in a class that is extended
2719def Test_call_method_in_extended_class()
2720 var lines =<< trim END
2721 vim9script
2722
2723 var prop_init_called = false
2724 var prop_register_called = false
2725
2726 class Property
2727 def Init()
2728 prop_init_called = true
2729 enddef
2730
2731 def Register()
2732 prop_register_called = true
2733 enddef
2734 endclass
2735
2736 class Bool extends Property
2737 endclass
2738
2739 def Observe(obj: Property)
2740 obj.Register()
2741 enddef
2742
2743 var p = Property.new()
2744 Observe(p)
2745
2746 p.Init()
2747 assert_true(prop_init_called)
2748 assert_true(prop_register_called)
2749 END
2750 v9.CheckScriptSuccess(lines)
2751enddef
2752
LemonBoyafe04662023-08-23 21:08:11 +02002753def Test_instanceof()
2754 var lines =<< trim END
2755 vim9script
2756
2757 class Base1
2758 endclass
2759
2760 class Base2 extends Base1
2761 endclass
2762
2763 interface Intf1
2764 endinterface
2765
2766 class Mix1 implements Intf1
2767 endclass
2768
2769 class Base3 extends Mix1
2770 endclass
2771
2772 var b1 = Base1.new()
2773 var b2 = Base2.new()
2774 var b3 = Base3.new()
2775
2776 assert_true(instanceof(b1, Base1))
2777 assert_true(instanceof(b2, Base1))
2778 assert_false(instanceof(b1, Base2))
2779 assert_true(instanceof(b3, Mix1))
2780 assert_false(instanceof(b3, []))
2781 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002782
2783 def Foo()
2784 var a1 = Base1.new()
2785 var a2 = Base2.new()
2786 var a3 = Base3.new()
2787
2788 assert_true(instanceof(a1, Base1))
2789 assert_true(instanceof(a2, Base1))
2790 assert_false(instanceof(a1, Base2))
2791 assert_true(instanceof(a3, Mix1))
2792 assert_false(instanceof(a3, []))
2793 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2794 enddef
2795 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002796 END
2797 v9.CheckScriptSuccess(lines)
2798enddef
2799
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002800" Test for calling a method in the parent class that is extended partially.
2801" This used to fail with the 'E118: Too many arguments for function: Text' error
2802" message (Github issue #12524).
2803def Test_call_method_in_parent_class()
2804 var lines =<< trim END
2805 vim9script
2806
2807 class Widget
2808 this._lnum: number = 1
2809
2810 def SetY(lnum: number)
2811 this._lnum = lnum
2812 enddef
2813
2814 def Text(): string
2815 return ''
2816 enddef
2817 endclass
2818
2819 class Foo extends Widget
2820 def Text(): string
2821 return '<Foo>'
2822 enddef
2823 endclass
2824
2825 def Stack(w1: Widget, w2: Widget): list<Widget>
2826 w1.SetY(1)
2827 w2.SetY(2)
2828 return [w1, w2]
2829 enddef
2830
2831 var foo1 = Foo.new()
2832 var foo2 = Foo.new()
2833 var l = Stack(foo1, foo2)
2834 END
2835 v9.CheckScriptSuccess(lines)
2836enddef
2837
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002838" Test for calling methods from three levels of classes
2839def Test_multi_level_method_call()
2840 var lines =<< trim END
2841 vim9script
2842
2843 var A_func1: number = 0
2844 var A_func2: number = 0
2845 var A_func3: number = 0
2846 var B_func2: number = 0
2847 var B_func3: number = 0
2848 var C_func3: number = 0
2849
2850 class A
2851 def Func1()
2852 A_func1 += 1
2853 enddef
2854
2855 def Func2()
2856 A_func2 += 1
2857 enddef
2858
2859 def Func3()
2860 A_func3 += 1
2861 enddef
2862 endclass
2863
2864 class B extends A
2865 def Func2()
2866 B_func2 += 1
2867 enddef
2868
2869 def Func3()
2870 B_func3 += 1
2871 enddef
2872 endclass
2873
2874 class C extends B
2875 def Func3()
2876 C_func3 += 1
2877 enddef
2878 endclass
2879
2880 def A_CallFuncs(a: A)
2881 a.Func1()
2882 a.Func2()
2883 a.Func3()
2884 enddef
2885
2886 def B_CallFuncs(b: B)
2887 b.Func1()
2888 b.Func2()
2889 b.Func3()
2890 enddef
2891
2892 def C_CallFuncs(c: C)
2893 c.Func1()
2894 c.Func2()
2895 c.Func3()
2896 enddef
2897
2898 var cobj = C.new()
2899 A_CallFuncs(cobj)
2900 B_CallFuncs(cobj)
2901 C_CallFuncs(cobj)
2902 assert_equal(3, A_func1)
2903 assert_equal(0, A_func2)
2904 assert_equal(0, A_func3)
2905 assert_equal(3, B_func2)
2906 assert_equal(0, B_func3)
2907 assert_equal(3, C_func3)
2908 END
2909 v9.CheckScriptSuccess(lines)
2910enddef
2911
2912" Test for using members from three levels of classes
2913def Test_multi_level_member_access()
2914 var lines =<< trim END
2915 vim9script
2916
2917 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002918 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002919 endclass
2920
2921 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002922 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002923 endclass
2924
2925 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002926 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002927 endclass
2928
2929 def A_members(a: A)
2930 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002931 enddef
2932
2933 def B_members(b: B)
2934 b.val1 += 1
2935 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002936 enddef
2937
2938 def C_members(c: C)
2939 c.val1 += 1
2940 c.val2 += 1
2941 c.val3 += 1
2942 enddef
2943
2944 var cobj = C.new()
2945 A_members(cobj)
2946 B_members(cobj)
2947 C_members(cobj)
2948 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002949 assert_equal(2, cobj.val2)
2950 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002951 END
2952 v9.CheckScriptSuccess(lines)
2953enddef
2954
LemonBoy0ffc17a2023-08-20 18:09:11 +02002955" Test expansion of <stack> with class methods.
2956def Test_stack_expansion_with_methods()
2957 var lines =<< trim END
2958 vim9script
2959
2960 class C
2961 def M1()
2962 F0()
2963 enddef
2964 endclass
2965
2966 def F0()
2967 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2968 enddef
2969
2970 def F()
2971 C.new().M1()
2972 enddef
2973
2974 F()
2975 END
2976 v9.CheckScriptSuccess(lines)
2977enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002978
2979" Test the return type of the new() constructor
2980def Test_new_return_type()
2981 # new() uses the default return type and there is no return statement
2982 var lines =<< trim END
2983 vim9script
2984
2985 class C
2986 this._bufnr: number
2987
2988 def new(this._bufnr)
2989 if !bufexists(this._bufnr)
2990 this._bufnr = -1
2991 endif
2992 enddef
2993 endclass
2994
2995 var c = C.new(12345)
2996 assert_equal('object<C>', typename(c))
2997
2998 var v1: C
2999 v1 = C.new(12345)
3000 assert_equal('object<C>', typename(v1))
3001
3002 def F()
3003 var v2: C
3004 v2 = C.new(12345)
3005 assert_equal('object<C>', typename(v2))
3006 enddef
3007 F()
3008 END
3009 v9.CheckScriptSuccess(lines)
3010
3011 # new() uses the default return type and an empty 'return' statement
3012 lines =<< trim END
3013 vim9script
3014
3015 class C
3016 this._bufnr: number
3017
3018 def new(this._bufnr)
3019 if !bufexists(this._bufnr)
3020 this._bufnr = -1
3021 return
3022 endif
3023 enddef
3024 endclass
3025
3026 var c = C.new(12345)
3027 assert_equal('object<C>', typename(c))
3028
3029 var v1: C
3030 v1 = C.new(12345)
3031 assert_equal('object<C>', typename(v1))
3032
3033 def F()
3034 var v2: C
3035 v2 = C.new(12345)
3036 assert_equal('object<C>', typename(v2))
3037 enddef
3038 F()
3039 END
3040 v9.CheckScriptSuccess(lines)
3041
3042 # new() uses "any" return type and returns "this"
3043 lines =<< trim END
3044 vim9script
3045
3046 class C
3047 this._bufnr: number
3048
3049 def new(this._bufnr): any
3050 if !bufexists(this._bufnr)
3051 this._bufnr = -1
3052 return this
3053 endif
3054 enddef
3055 endclass
3056 END
3057 v9.CheckScriptFailure(lines, 'E1365:')
3058
3059 # new() uses 'Dict' return type and returns a Dict
3060 lines =<< trim END
3061 vim9script
3062
3063 class C
3064 this._state: dict<any>
3065
3066 def new(): dict<any>
3067 this._state = {}
3068 return this._state
3069 enddef
3070 endclass
3071
3072 var c = C.new()
3073 assert_equal('object<C>', typename(c))
3074 END
3075 v9.CheckScriptFailure(lines, 'E1365:')
3076enddef
3077
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003078" Test for checking a member initialization type at run time.
3079def Test_runtime_type_check_for_member_init()
3080 var lines =<< trim END
3081 vim9script
3082
3083 var retnum: bool = false
3084
3085 def F(): any
3086 retnum = !retnum
3087 if retnum
3088 return 1
3089 else
3090 return "hello"
3091 endif
3092 enddef
3093
3094 class C
3095 this._foo: bool = F()
3096 endclass
3097
3098 var c1 = C.new()
3099 var c2 = C.new()
3100 END
3101 v9.CheckScriptFailure(lines, 'E1012:')
3102enddef
3103
3104" Test for locking a variable referring to an object and reassigning to another
3105" object.
3106def Test_object_lockvar()
3107 var lines =<< trim END
3108 vim9script
3109
3110 class C
3111 this.val: number
3112 def new(this.val)
3113 enddef
3114 endclass
3115
3116 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3117 lockvar 2 some_dict
3118
3119 var current: C
3120 current = some_dict['c']
3121 assert_equal(3, current.val)
3122 current = some_dict['b']
3123 assert_equal(2, current.val)
3124
3125 def F()
3126 current = some_dict['c']
3127 enddef
3128
3129 def G()
3130 current = some_dict['b']
3131 enddef
3132
3133 F()
3134 assert_equal(3, current.val)
3135 G()
3136 assert_equal(2, current.val)
3137 END
3138 v9.CheckScriptSuccess(lines)
3139enddef
3140
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003141" Test for a private object method
3142def Test_private_object_method()
3143 # Try calling a private method using an object (at the script level)
3144 var lines =<< trim END
3145 vim9script
3146
3147 class A
3148 def _Foo(): number
3149 return 1234
3150 enddef
3151 endclass
3152 var a = A.new()
3153 a._Foo()
3154 END
3155 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3156
3157 # Try calling a private method using an object (from a def function)
3158 lines =<< trim END
3159 vim9script
3160
3161 class A
3162 def _Foo(): number
3163 return 1234
3164 enddef
3165 endclass
3166 def T()
3167 var a = A.new()
3168 a._Foo()
3169 enddef
3170 T()
3171 END
3172 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3173
3174 # Use a private method from another object method (in script context)
3175 lines =<< trim END
3176 vim9script
3177
3178 class A
3179 def _Foo(): number
3180 return 1234
3181 enddef
3182 def Bar(): number
3183 return this._Foo()
3184 enddef
3185 endclass
3186 var a = A.new()
3187 assert_equal(1234, a.Bar())
3188 END
3189 v9.CheckScriptSuccess(lines)
3190
3191 # Use a private method from another object method (def function context)
3192 lines =<< trim END
3193 vim9script
3194
3195 class A
3196 def _Foo(): number
3197 return 1234
3198 enddef
3199 def Bar(): number
3200 return this._Foo()
3201 enddef
3202 endclass
3203 def T()
3204 var a = A.new()
3205 assert_equal(1234, a.Bar())
3206 enddef
3207 T()
3208 END
3209 v9.CheckScriptSuccess(lines)
3210
3211 # Try calling a private method without the "this" prefix
3212 lines =<< trim END
3213 vim9script
3214
3215 class A
3216 def _Foo(): number
3217 return 1234
3218 enddef
3219 def Bar(): number
3220 return _Foo()
3221 enddef
3222 endclass
3223 var a = A.new()
3224 a.Bar()
3225 END
3226 v9.CheckScriptFailure(lines, 'E117: Unknown function: _Foo')
3227
3228 # Try calling a private method using the class name
3229 lines =<< trim END
3230 vim9script
3231
3232 class A
3233 def _Foo(): number
3234 return 1234
3235 enddef
3236 endclass
3237 A._Foo()
3238 END
3239 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3240
3241 # Try to use "public" keyword when defining a private method
3242 lines =<< trim END
3243 vim9script
3244
3245 class A
3246 public def _Foo()
3247 enddef
3248 endclass
3249 var a = A.new()
3250 a._Foo()
3251 END
3252 v9.CheckScriptFailure(lines, 'E1331: Public must be followed by "this" or "static"')
3253
3254 # Define two private methods with the same name
3255 lines =<< trim END
3256 vim9script
3257
3258 class A
3259 def _Foo()
3260 enddef
3261 def _Foo()
3262 enddef
3263 endclass
3264 var a = A.new()
3265 END
3266 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3267
3268 # Define a private method and a object method with the same name
3269 lines =<< trim END
3270 vim9script
3271
3272 class A
3273 def _Foo()
3274 enddef
3275 def Foo()
3276 enddef
3277 endclass
3278 var a = A.new()
3279 END
3280 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3281
3282 # Define an object method and a private method with the same name
3283 lines =<< trim END
3284 vim9script
3285
3286 class A
3287 def Foo()
3288 enddef
3289 def _Foo()
3290 enddef
3291 endclass
3292 var a = A.new()
3293 END
3294 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3295
3296 # Call a public method and a private method from a private method
3297 lines =<< trim END
3298 vim9script
3299
3300 class A
3301 def Foo(): number
3302 return 100
3303 enddef
3304 def _Bar(): number
3305 return 200
3306 enddef
3307 def _Baz()
3308 assert_equal(100, this.Foo())
3309 assert_equal(200, this._Bar())
3310 enddef
3311 def T()
3312 this._Baz()
3313 enddef
3314 endclass
3315 var a = A.new()
3316 a.T()
3317 END
3318 v9.CheckScriptSuccess(lines)
3319
3320 # Try calling a private method from another class
3321 lines =<< trim END
3322 vim9script
3323
3324 class A
3325 def _Foo(): number
3326 return 100
3327 enddef
3328 endclass
3329 class B
3330 def Foo(): number
3331 var a = A.new()
3332 a._Foo()
3333 enddef
3334 endclass
3335 var b = B.new()
3336 b.Foo()
3337 END
3338 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3339
3340 # Call a private object method from a child class object method
3341 lines =<< trim END
3342 vim9script
3343 class A
3344 def _Foo(): number
3345 return 1234
3346 enddef
3347 endclass
3348 class B extends A
3349 def Bar()
3350 enddef
3351 endclass
3352 class C extends B
3353 def Baz(): number
3354 return this._Foo()
3355 enddef
3356 endclass
3357 var c = C.new()
3358 assert_equal(1234, c.Baz())
3359 END
3360 v9.CheckScriptSuccess(lines)
3361
3362 # Call a private object method from a child class object
3363 lines =<< trim END
3364 vim9script
3365 class A
3366 def _Foo(): number
3367 return 1234
3368 enddef
3369 endclass
3370 class B extends A
3371 def Bar()
3372 enddef
3373 endclass
3374 class C extends B
3375 def Baz(): number
3376 enddef
3377 endclass
3378 var c = C.new()
3379 assert_equal(1234, c._Foo())
3380 END
3381 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3382
3383 # Using "_" prefix in a method name should fail outside of a class
3384 lines =<< trim END
3385 vim9script
3386 def _Foo(): number
3387 return 1234
3388 enddef
3389 var a = _Foo()
3390 END
3391 v9.CheckScriptFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
3392enddef
3393
3394" Test for an private class method
3395def Test_private_class_method()
3396 # Try calling a class private method (at the script level)
3397 var lines =<< trim END
3398 vim9script
3399
3400 class A
3401 static def _Foo(): number
3402 return 1234
3403 enddef
3404 endclass
3405 A._Foo()
3406 END
3407 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3408
3409 # Try calling a class private method (from a def function)
3410 lines =<< trim END
3411 vim9script
3412
3413 class A
3414 static def _Foo(): number
3415 return 1234
3416 enddef
3417 endclass
3418 def T()
3419 A._Foo()
3420 enddef
3421 T()
3422 END
3423 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3424
3425 # Try calling a class private method using an object (at the script level)
3426 lines =<< trim END
3427 vim9script
3428
3429 class A
3430 static def _Foo(): number
3431 return 1234
3432 enddef
3433 endclass
3434 var a = A.new()
3435 a._Foo()
3436 END
3437 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3438
3439 # Try calling a class private method using an object (from a def function)
3440 lines =<< trim END
3441 vim9script
3442
3443 class A
3444 static def _Foo(): number
3445 return 1234
3446 enddef
3447 endclass
3448 def T()
3449 var a = A.new()
3450 a._Foo()
3451 enddef
3452 T()
3453 END
3454 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3455
3456 # Use a class private method from an object method
3457 lines =<< trim END
3458 vim9script
3459
3460 class A
3461 static def _Foo(): number
3462 return 1234
3463 enddef
3464 def Bar()
3465 assert_equal(1234, A._Foo())
3466 enddef
3467 endclass
3468 var a = A.new()
3469 a.Bar()
3470 END
3471 v9.CheckScriptSuccess(lines)
3472
3473 # Use a class private method from another class private method
3474 lines =<< trim END
3475 vim9script
3476
3477 class A
3478 static def _Foo1(): number
3479 return 1234
3480 enddef
3481 static def _Foo2()
3482 assert_equal(1234, A._Foo1())
3483 enddef
3484 def Bar()
3485 A._Foo2()
3486 enddef
3487 endclass
3488 var a = A.new()
3489 a.Bar()
3490 END
3491 v9.CheckScriptSuccess(lines)
3492
3493 # Declare a class method and a class private method with the same name
3494 lines =<< trim END
3495 vim9script
3496
3497 class A
3498 static def _Foo()
3499 enddef
3500 static def Foo()
3501 enddef
3502 endclass
3503 var a = A.new()
3504 END
3505 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3506
3507 # Try calling a class private method from another class
3508 lines =<< trim END
3509 vim9script
3510
3511 class A
3512 static def _Foo(): number
3513 return 1234
3514 enddef
3515 endclass
3516 class B
3517 def Foo(): number
3518 return A._Foo()
3519 enddef
3520 endclass
3521 var b = B.new()
3522 assert_equal(1234, b.Foo())
3523 END
3524 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3525
3526 # Call a private class method from a child class object method
3527 lines =<< trim END
3528 vim9script
3529 class A
3530 static def _Foo(): number
3531 return 1234
3532 enddef
3533 endclass
3534 class B extends A
3535 def Bar()
3536 enddef
3537 endclass
3538 class C extends B
3539 def Baz(): number
3540 return A._Foo()
3541 enddef
3542 endclass
3543 var c = C.new()
3544 assert_equal(1234, c.Baz())
3545 END
3546 v9.CheckScriptSuccess(lines)
3547
3548 # Call a private class method from a child class private class method
3549 lines =<< trim END
3550 vim9script
3551 class A
3552 static def _Foo(): number
3553 return 1234
3554 enddef
3555 endclass
3556 class B extends A
3557 def Bar()
3558 enddef
3559 endclass
3560 class C extends B
3561 static def Baz(): number
3562 return A._Foo()
3563 enddef
3564 endclass
3565 assert_equal(1234, C.Baz())
3566 END
3567 v9.CheckScriptSuccess(lines)
3568
3569 # Call a private class method from a child class object
3570 lines =<< trim END
3571 vim9script
3572 class A
3573 static def _Foo(): number
3574 return 1234
3575 enddef
3576 endclass
3577 class B extends A
3578 def Bar()
3579 enddef
3580 endclass
3581 class C extends B
3582 def Baz(): number
3583 enddef
3584 endclass
3585 var c = C.new()
3586 assert_equal(1234, C._Foo())
3587 END
3588 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3589enddef
3590
3591" Test for an interface private object_method
3592def Test_interface_private_object_method()
3593 # Implement an interface private method and use it from a public method
3594 var lines =<< trim END
3595 vim9script
3596 interface Intf
3597 def _Foo(): number
3598 endinterface
3599 class A implements Intf
3600 def _Foo(): number
3601 return 1234
3602 enddef
3603 def Bar(): number
3604 return this._Foo()
3605 enddef
3606 endclass
3607 var a = A.new()
3608 assert_equal(1234, a.Bar())
3609 END
3610 v9.CheckScriptSuccess(lines)
3611
3612 # Call an interface private class method (script context)
3613 lines =<< trim END
3614 vim9script
3615 interface Intf
3616 def _Foo(): number
3617 endinterface
3618 class A implements Intf
3619 def _Foo(): number
3620 return 1234
3621 enddef
3622 endclass
3623 var a = A.new()
3624 assert_equal(1234, a._Foo())
3625 END
3626 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3627
3628 # Call an interface private class method (def context)
3629 lines =<< trim END
3630 vim9script
3631 interface Intf
3632 def _Foo(): number
3633 endinterface
3634 class A implements Intf
3635 def _Foo(): number
3636 return 1234
3637 enddef
3638 endclass
3639 def T()
3640 var a = A.new()
3641 assert_equal(1234, a._Foo())
3642 enddef
3643 T()
3644 END
3645 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3646
3647 # Implement an interface private object method as a private class method
3648 lines =<< trim END
3649 vim9script
3650 interface Intf
3651 def _Foo(): number
3652 endinterface
3653 class A implements Intf
3654 static def _Foo(): number
3655 return 1234
3656 enddef
3657 endclass
3658 END
3659 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3660enddef
3661
3662" Test for an interface private class method
3663def Test_interface_private_class_method()
3664 # Implement an interface private class method and use it from a public method
3665 var lines =<< trim END
3666 vim9script
3667 interface Intf
3668 static def _Foo(): number
3669 endinterface
3670 class A implements Intf
3671 static def _Foo(): number
3672 return 1234
3673 enddef
3674 def Bar(): number
3675 return A._Foo()
3676 enddef
3677 endclass
3678 var a = A.new()
3679 assert_equal(1234, a.Bar())
3680 END
3681 v9.CheckScriptSuccess(lines)
3682
3683 # Call an interface private class method (script context)
3684 lines =<< trim END
3685 vim9script
3686 interface Intf
3687 static def _Foo(): number
3688 endinterface
3689 class A implements Intf
3690 static def _Foo(): number
3691 return 1234
3692 enddef
3693 endclass
3694 assert_equal(1234, A._Foo())
3695 END
3696 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3697
3698 # Call an interface private class method (def context)
3699 lines =<< trim END
3700 vim9script
3701 interface Intf
3702 static def _Foo(): number
3703 endinterface
3704 class A implements Intf
3705 static def _Foo(): number
3706 return 1234
3707 enddef
3708 endclass
3709 def T()
3710 assert_equal(1234, A._Foo())
3711 enddef
3712 T()
3713 END
3714 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3715
3716 # Implement an interface private class method as a private object method
3717 lines =<< trim END
3718 vim9script
3719 interface Intf
3720 static def _Foo(): number
3721 endinterface
3722 class A implements Intf
3723 def _Foo(): number
3724 return 1234
3725 enddef
3726 endclass
3727 END
3728 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3729enddef
3730
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003731" Test for using the return value of a class/object method as a function
3732" argument.
3733def Test_objmethod_funcarg()
3734 var lines =<< trim END
3735 vim9script
3736
3737 class C
3738 def Foo(): string
3739 return 'foo'
3740 enddef
3741 endclass
3742
3743 def Bar(a: number, s: string): string
3744 return s
3745 enddef
3746
3747 def Baz(c: C)
3748 assert_equal('foo', Bar(10, c.Foo()))
3749 enddef
3750
3751 var t = C.new()
3752 Baz(t)
3753 END
3754 v9.CheckScriptSuccess(lines)
3755
3756 lines =<< trim END
3757 vim9script
3758
3759 class C
3760 static def Foo(): string
3761 return 'foo'
3762 enddef
3763 endclass
3764
3765 def Bar(a: number, s: string): string
3766 return s
3767 enddef
3768
3769 def Baz()
3770 assert_equal('foo', Bar(10, C.Foo()))
3771 enddef
3772
3773 Baz()
3774 END
3775 v9.CheckScriptSuccess(lines)
3776enddef
3777
Ernie Raelcf138d42023-09-06 20:45:03 +02003778def Test_static_inheritence()
3779 # subclasses get their own static copy
3780 var lines =<< trim END
3781 vim9script
3782
3783 class A
3784 static _svar: number
3785 this._mvar: number
3786 def new()
3787 _svar = 1
3788 this._mvar = 101
3789 enddef
3790 def AccessObject(): number
3791 return this._mvar
3792 enddef
3793 def AccessStaticThroughObject(): number
3794 return _svar
3795 enddef
3796 endclass
3797
3798 class B extends A
3799 def new()
3800 _svar = 2
3801 this._mvar = 102
3802 enddef
3803 endclass
3804
3805 class C extends B
3806 def new()
3807 _svar = 3
3808 this._mvar = 103
3809 enddef
3810
3811 def AccessPrivateStaticThroughClassName(): number
3812 assert_equal(1, A._svar)
3813 assert_equal(2, B._svar)
3814 assert_equal(3, C._svar)
3815 return 444
3816 enddef
3817 endclass
3818
3819 var oa = A.new()
3820 var ob = B.new()
3821 var oc = C.new()
3822 assert_equal(101, oa.AccessObject())
3823 assert_equal(102, ob.AccessObject())
3824 assert_equal(103, oc.AccessObject())
3825
3826 assert_equal(444, oc.AccessPrivateStaticThroughClassName())
3827
3828 # verify object properly resolves to correct static
3829 assert_equal(1, oa.AccessStaticThroughObject())
3830 assert_equal(2, ob.AccessStaticThroughObject())
3831 assert_equal(3, oc.AccessStaticThroughObject())
3832 END
3833 v9.CheckScriptSuccess(lines)
3834enddef
3835
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003836" Test for declaring duplicate object and class members
3837def Test_dup_member_variable()
3838 # Duplicate member variable
3839 var lines =<< trim END
3840 vim9script
3841 class C
3842 this.val = 10
3843 this.val = 20
3844 endclass
3845 END
3846 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3847
3848 # Duplicate private member variable
3849 lines =<< trim END
3850 vim9script
3851 class C
3852 this._val = 10
3853 this._val = 20
3854 endclass
3855 END
3856 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3857
3858 # Duplicate public member variable
3859 lines =<< trim END
3860 vim9script
3861 class C
3862 public this.val = 10
3863 public this.val = 20
3864 endclass
3865 END
3866 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3867
3868 # Duplicate private member variable
3869 lines =<< trim END
3870 vim9script
3871 class C
3872 this.val = 10
3873 this._val = 20
3874 endclass
3875 END
3876 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3877
3878 # Duplicate public and private member variable
3879 lines =<< trim END
3880 vim9script
3881 class C
3882 this._val = 20
3883 public this.val = 10
3884 endclass
3885 END
3886 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3887
3888 # Duplicate class member variable
3889 lines =<< trim END
3890 vim9script
3891 class C
3892 static s: string = "abc"
3893 static _s: string = "def"
3894 endclass
3895 END
3896 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3897
3898 # Duplicate public and private class member variable
3899 lines =<< trim END
3900 vim9script
3901 class C
3902 public static s: string = "abc"
3903 static _s: string = "def"
3904 endclass
3905 END
3906 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3907
3908 # Duplicate class and object member variable
3909 lines =<< trim END
3910 vim9script
3911 class C
3912 static val = 10
3913 this.val = 20
3914 def new()
3915 enddef
3916 endclass
3917 var c = C.new()
3918 assert_equal(10, C.val)
3919 assert_equal(20, c.val)
3920 END
3921 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003922
3923 # Duplicate object member variable in a derived class
3924 lines =<< trim END
3925 vim9script
3926 class A
3927 this.val = 10
3928 endclass
3929 class B extends A
3930 endclass
3931 class C extends B
3932 this.val = 20
3933 endclass
3934 END
3935 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3936
3937 # Duplicate object private member variable in a derived class
3938 lines =<< trim END
3939 vim9script
3940 class A
3941 this._val = 10
3942 endclass
3943 class B extends A
3944 endclass
3945 class C extends B
3946 this._val = 20
3947 endclass
3948 END
3949 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3950
3951 # Duplicate object private member variable in a derived class
3952 lines =<< trim END
3953 vim9script
3954 class A
3955 this.val = 10
3956 endclass
3957 class B extends A
3958 endclass
3959 class C extends B
3960 this._val = 20
3961 endclass
3962 END
3963 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3964
3965 # Duplicate object member variable in a derived class
3966 lines =<< trim END
3967 vim9script
3968 class A
3969 this._val = 10
3970 endclass
3971 class B extends A
3972 endclass
3973 class C extends B
3974 this.val = 20
3975 endclass
3976 END
3977 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3978
3979 # Duplicate class member variable in a derived class
3980 lines =<< trim END
3981 vim9script
3982 class A
3983 static val = 10
3984 endclass
3985 class B extends A
3986 endclass
3987 class C extends B
3988 static val = 20
3989 endclass
3990 END
3991 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3992
3993 # Duplicate private class member variable in a derived class
3994 lines =<< trim END
3995 vim9script
3996 class A
3997 static _val = 10
3998 endclass
3999 class B extends A
4000 endclass
4001 class C extends B
4002 static _val = 20
4003 endclass
4004 END
4005 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
4006
4007 # Duplicate private class member variable in a derived class
4008 lines =<< trim END
4009 vim9script
4010 class A
4011 static val = 10
4012 endclass
4013 class B extends A
4014 endclass
4015 class C extends B
4016 static _val = 20
4017 endclass
4018 END
4019 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
4020
4021 # Duplicate class member variable in a derived class
4022 lines =<< trim END
4023 vim9script
4024 class A
4025 static _val = 10
4026 endclass
4027 class B extends A
4028 endclass
4029 class C extends B
4030 static val = 20
4031 endclass
4032 END
4033 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004034
4035 # Two member variables with a common prefix
4036 lines =<< trim END
4037 vim9script
4038 class A
4039 public static svar2: number
4040 public static svar: number
4041 endclass
4042 END
4043 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004044enddef
4045
Ernie Rael18143d32023-09-04 22:30:41 +02004046def Test_interface_static_member_access()
4047 # In a class cannot read from interface static
4048 var lines =<< trim END
4049 vim9script
4050 interface I
4051 public static num: number
4052 endinterface
4053 class C implements I
4054 public static num = 3
4055 def F()
4056 var x = I.num
4057 enddef
4058 endclass
4059 C.new().F()
4060 END
4061 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4062
4063 # In a class cannot write to interface static
4064 lines =<< trim END
4065 vim9script
4066 interface I
4067 public static num: number
4068 endinterface
4069 class C implements I
4070 public static num = 3
4071 def F()
4072 I.num = 7
4073 enddef
4074 endclass
4075 C.new().F()
4076 END
4077 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4078
4079 # In a def cannot read from interface static
4080 lines =<< trim END
4081 vim9script
4082 interface I
4083 public static num: number
4084 endinterface
4085 def F()
4086 var x = I.num
4087 enddef
4088 F()
4089 END
4090 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4091
4092 # In a def cannot write to interface static
4093 lines =<< trim END
4094 vim9script
4095 interface I
4096 public static num: number
4097 endinterface
4098 def F()
4099 I.num = 7
4100 enddef
4101 F()
4102 END
4103 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4104
4105 # script level cannot read interface static
4106 lines =<< trim END
4107 vim9script
4108 interface I
4109 public static s_var1: number
4110 endinterface
4111
4112 var x = I.s_var1
4113 END
4114 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "s_var1"')
4115
4116 # script level cannot write interface static
4117 lines =<< trim END
4118 vim9script
4119 interface I
4120 public static s_var1: number
4121 endinterface
4122
4123 I.s_var1 = 3
4124 END
4125 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "I.s_var1 = 3"')
4126
4127enddef
4128
4129def Test_static_member_access_outside_class()
4130 # Verify access of statics implemented from interface
4131 # in a :def (outside of a class)
4132 # Note the order of the static is different
4133 # between the interface and the class,
4134 # since they are allocated in order in each interface/class;
4135 # so the static index is mapped from interfaced to class as needed.
4136
4137 # Check reading statics
4138 var lines =<< trim END
4139 vim9script
4140
4141 interface I
4142 public static s_var1: number
4143 public static s_var2: number
4144 endinterface
4145
4146 class C implements I
4147 public static s_var2 = 2
4148 public static x_static = 7
4149 public static s_var1 = 1
4150 endclass
4151
4152 def F1(): number
4153 assert_equal(1, C.s_var1)
4154 assert_equal(2, C.s_var2)
4155 assert_equal(7, C.x_static)
4156 return 11
4157 enddef
4158
Ernie Rael18143d32023-09-04 22:30:41 +02004159 assert_equal(11, F1())
Ernie Rael18143d32023-09-04 22:30:41 +02004160 END
4161 v9.CheckScriptSuccess(lines)
4162enddef
4163
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004164" Test for accessing a private member outside a class in a def function
4165def Test_private_member_access_outside_class()
4166 # private object member variable
4167 var lines =<< trim END
4168 vim9script
4169 class A
4170 this._val = 10
4171 def GetVal(): number
4172 return this._val
4173 enddef
4174 endclass
4175 def T()
4176 var a = A.new()
4177 a._val = 20
4178 enddef
4179 T()
4180 END
4181 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4182
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004183 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004184 lines =<< trim END
4185 vim9script
4186 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004187 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004188 endclass
4189 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004190 var a = A.new()
4191 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004192 enddef
4193 T()
4194 END
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004195 v9.CheckScriptFailure(lines, 'E1089: Unknown variable: _a = 1')
Ernie Rael18143d32023-09-04 22:30:41 +02004196
4197 # private static member variable
4198 lines =<< trim END
4199 vim9script
4200 class A
4201 static _val = 10
4202 endclass
4203 def T()
4204 var a = A.new()
4205 var x = a._val
4206 enddef
4207 T()
4208 END
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004209 v9.CheckScriptFailure(lines, 'E1326: Member not found on object "A": _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004210
4211 # private static member variable
4212 lines =<< trim END
4213 vim9script
4214 class A
4215 static _val = 10
4216 endclass
4217 def T()
4218 var a = A.new()
4219 a._val = 3
4220 enddef
4221 T()
4222 END
4223 # TODO: wrong error, should be about private member
4224 v9.CheckScriptFailure(lines, 'E1089: Unknown variable')
4225
4226 # private static class variable
4227 lines =<< trim END
4228 vim9script
4229 class A
4230 static _val = 10
4231 endclass
4232 def T()
4233 var x = A._val
4234 enddef
4235 T()
4236 END
4237 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4238
4239 # private static class variable
4240 lines =<< trim END
4241 vim9script
4242 class A
4243 static _val = 10
4244 endclass
4245 def T()
4246 A._val = 3
4247 enddef
4248 T()
4249 END
4250 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004251enddef
4252
4253" Test for changing the member access of an interface in a implementation class
4254def Test_change_interface_member_access()
4255 var lines =<< trim END
4256 vim9script
4257 interface A
4258 public this.val: number
4259 endinterface
4260 class B implements A
4261 this.val = 10
4262 endclass
4263 END
4264 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
4265
4266 lines =<< trim END
4267 vim9script
4268 interface A
4269 this.val: number
4270 endinterface
4271 class B implements A
4272 public this.val = 10
4273 endclass
4274 END
4275 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
4276enddef
4277
4278" Test for trying to change a readonly member from a def function
4279def Test_readonly_member_change_in_def_func()
4280 var lines =<< trim END
4281 vim9script
4282 class A
4283 this.val: number
4284 endclass
4285 def T()
4286 var a = A.new()
4287 a.val = 20
4288 enddef
4289 T()
4290 END
4291 v9.CheckScriptFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004292enddef
4293
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004294" Test for reading and writing a class member from a def function
4295def Test_modify_class_member_from_def_function()
4296 var lines =<< trim END
4297 vim9script
4298 class A
4299 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004300 public static var2: list<number> = [1, 2]
4301 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004302 static _priv_var4: number = 40
4303 endclass
4304 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004305 assert_equal([1, 2], A.var2)
4306 assert_equal({a: 1, b: 2}, A.var3)
4307 A.var2 = [3, 4]
4308 A.var3 = {c: 3, d: 4}
4309 assert_equal([3, 4], A.var2)
4310 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004311 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4312 enddef
4313 T()
4314 END
4315 v9.CheckScriptSuccess(lines)
4316enddef
4317
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004318" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004319def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004320 var lines =<< trim END
4321 vim9script
4322 class A
4323 public static svar1: list<number> = [1]
4324 public static svar2: list<number> = [2]
4325 endclass
4326
4327 A.svar1->add(3)
4328 A.svar2->add(4)
4329 assert_equal([1, 3], A.svar1)
4330 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004331
4332 def Foo()
4333 A.svar1->add(7)
4334 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004335 assert_equal([1, 3, 7], A.svar1)
4336 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004337 enddef
4338 Foo()
4339 END
4340 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004341
4342 # Cannot read from a class variable using an object in script context
4343 lines =<< trim END
4344 vim9script
4345 class A
4346 public this.var1: number
4347 public static svar2: list<number> = [1]
4348 endclass
4349
4350 var a = A.new()
4351 echo a.svar2
4352 END
4353 v9.CheckScriptFailure(lines, 'E1326: Member not found on object "A": svar2')
4354
4355 # Cannot write to a class variable using an object in script context
4356 lines =<< trim END
4357 vim9script
4358 class A
4359 public this.var1: number
4360 public static svar2: list<number> = [1]
4361 endclass
4362
4363 var a = A.new()
4364 a.svar2 = [2]
4365 END
4366 v9.CheckScriptFailure(lines, 'E1334: Object member not found: svar2 = [2]')
4367
4368 # Cannot read from a class variable using an object in def method context
4369 lines =<< trim END
4370 vim9script
4371 class A
4372 public this.var1: number
4373 public static svar2: list<number> = [1]
4374 endclass
4375
4376 def T()
4377 var a = A.new()
4378 echo a.svar2
4379 enddef
4380 T()
4381 END
4382 v9.CheckScriptFailure(lines, 'E1326: Member not found on object "A": svar2')
4383
4384 # Cannot write to a class variable using an object in def method context
4385 lines =<< trim END
4386 vim9script
4387 class A
4388 public this.var1: number
4389 public static svar2: list<number> = [1]
4390 endclass
4391
4392 def T()
4393 var a = A.new()
4394 a.svar2 = [2]
4395 enddef
4396 T()
4397 END
4398 v9.CheckScriptFailure(lines, 'E1089: Unknown variable: svar2 = [2]')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004399enddef
4400
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004401" Test for using a interface method using a child object
4402def Test_interface_method_from_child()
4403 var lines =<< trim END
4404 vim9script
4405
4406 interface A
4407 def Foo(): string
4408 endinterface
4409
4410 class B implements A
4411 def Foo(): string
4412 return 'foo'
4413 enddef
4414 endclass
4415
4416 class C extends B
4417 def Bar(): string
4418 return 'bar'
4419 enddef
4420 endclass
4421
4422 def T1(a: A)
4423 assert_equal('foo', a.Foo())
4424 enddef
4425
4426 def T2(b: B)
4427 assert_equal('foo', b.Foo())
4428 enddef
4429
4430 var c = C.new()
4431 T1(c)
4432 T2(c)
4433 END
4434 v9.CheckScriptSuccess(lines)
4435enddef
4436
4437" Test for using an interface method using a child object when it is overridden
4438" by the child class.
4439" FIXME: This test fails.
4440" def Test_interface_overridden_method_from_child()
4441" var lines =<< trim END
4442" vim9script
4443"
4444" interface A
4445" def Foo(): string
4446" endinterface
4447"
4448" class B implements A
4449" def Foo(): string
4450" return 'b-foo'
4451" enddef
4452" endclass
4453"
4454" class C extends B
4455" def Bar(): string
4456" return 'bar'
4457" enddef
4458" def Foo(): string
4459" return 'c-foo'
4460" enddef
4461" endclass
4462"
4463" def T1(a: A)
4464" assert_equal('c-foo', a.Foo())
4465" enddef
4466"
4467" def T2(b: B)
4468" assert_equal('c-foo', b.Foo())
4469" enddef
4470"
4471" var c = C.new()
4472" T1(c)
4473" T2(c)
4474" END
4475" v9.CheckScriptSuccess(lines)
4476" enddef
4477
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004478" Test for abstract methods
4479def Test_abstract_method()
4480 # Use two abstract methods
4481 var lines =<< trim END
4482 vim9script
4483 abstract class A
4484 def M1(): number
4485 return 10
4486 enddef
4487 abstract def M2(): number
4488 abstract def M3(): number
4489 endclass
4490 class B extends A
4491 def M2(): number
4492 return 20
4493 enddef
4494 def M3(): number
4495 return 30
4496 enddef
4497 endclass
4498 var b = B.new()
4499 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4500 END
4501 v9.CheckScriptSuccess(lines)
4502
4503 # Don't define an abstract method
4504 lines =<< trim END
4505 vim9script
4506 abstract class A
4507 abstract def Foo()
4508 endclass
4509 class B extends A
4510 endclass
4511 END
4512 v9.CheckScriptFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
4513
4514 # Use abstract method in a concrete class
4515 lines =<< trim END
4516 vim9script
4517 class A
4518 abstract def Foo()
4519 endclass
4520 class B extends A
4521 endclass
4522 END
4523 v9.CheckScriptFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
4524
4525 # Use abstract method in an interface
4526 lines =<< trim END
4527 vim9script
4528 interface A
4529 abstract def Foo()
4530 endinterface
4531 class B implements A
4532 endclass
4533 END
4534 v9.CheckScriptFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
4535
4536 # Abbreviate the "abstract" keyword
4537 lines =<< trim END
4538 vim9script
4539 class A
4540 abs def Foo()
4541 endclass
4542 END
4543 v9.CheckScriptFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
4544
4545 # Use "abstract" with a member variable
4546 lines =<< trim END
4547 vim9script
4548 abstract class A
4549 abstract this.val = 10
4550 endclass
4551 END
4552 v9.CheckScriptFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
4553
4554 # Use a static abstract method
4555 lines =<< trim END
4556 vim9script
4557 abstract class A
4558 abstract static def Foo(): number
4559 endclass
4560 class B extends A
4561 static def Foo(): number
4562 return 4
4563 enddef
4564 endclass
4565 assert_equal(4, B.Foo())
4566 END
4567 v9.CheckScriptSuccess(lines)
4568
4569 # Type mismatch between abstract method and concrete method
4570 lines =<< trim END
4571 vim9script
4572 abstract class A
4573 abstract def Foo(a: string, b: number): list<number>
4574 endclass
4575 class B extends A
4576 def Foo(a: number, b: string): list<string>
4577 return []
4578 enddef
4579 endclass
4580 END
Christian Brabandtee17b6f2023-09-09 11:23:50 +02004581 v9.CheckScriptFailure(lines, 'E1407: Method "Foo": type mismatch, expected func(string, number): list<number> but got func(number, string): list<string>')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004582
4583 # Use an abstract class to invoke an abstract method
4584 # FIXME: This should fail
4585 lines =<< trim END
4586 vim9script
4587 abstract class A
4588 abstract static def Foo()
4589 endclass
4590 A.Foo()
4591 END
4592 v9.CheckScriptSuccess(lines)
4593
4594 # Invoke an abstract method from a def function
4595 lines =<< trim END
4596 vim9script
4597 abstract class A
4598 abstract def Foo(): list<number>
4599 endclass
4600 class B extends A
4601 def Foo(): list<number>
4602 return [3, 5]
4603 enddef
4604 endclass
4605 def Bar(c: B)
4606 assert_equal([3, 5], c.Foo())
4607 enddef
4608 var b = B.new()
4609 Bar(b)
4610 END
4611 v9.CheckScriptSuccess(lines)
4612enddef
4613
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004614" Test for calling a class method using an object in a def function context and
4615" script context.
4616def Test_class_method_call_using_object()
4617 # script context
4618 var lines =<< trim END
4619 vim9script
4620 class A
4621 static def Foo(): list<string>
4622 return ['a', 'b']
4623 enddef
4624 def Bar()
4625 assert_equal(['a', 'b'], A.Foo())
4626 assert_equal(['a', 'b'], Foo())
4627 enddef
4628 endclass
4629
4630 def T()
4631 assert_equal(['a', 'b'], A.Foo())
4632 var t_a = A.new()
4633 t_a.Bar()
4634 enddef
4635
4636 assert_equal(['a', 'b'], A.Foo())
4637 var a = A.new()
4638 a.Bar()
4639 T()
4640 END
4641 v9.CheckScriptSuccess(lines)
4642
4643 # script context
4644 lines =<< trim END
4645 vim9script
4646 class A
4647 static def Foo(): string
4648 return 'foo'
4649 enddef
4650 endclass
4651
4652 var a = A.new()
4653 assert_equal('foo', a.Foo())
4654 END
4655 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": Foo()')
4656
4657 # def function context
4658 lines =<< trim END
4659 vim9script
4660 class A
4661 static def Foo(): string
4662 return 'foo'
4663 enddef
4664 endclass
4665
4666 def T()
4667 var a = A.new()
4668 assert_equal('foo', a.Foo())
4669 enddef
4670 T()
4671 END
4672 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": Foo()')
4673enddef
4674
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004675" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker