blob: a8c95a74da1ad604ceda5f283de3e3861474be90 [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
1887 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1888
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
1900 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1901
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
1913 v9.CheckScriptFailure(lines, 'E1407: Member "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
1958 def F1(i: I1): list<number>
1959 return [ i.svar1, i.svar2 ]
1960 enddef
1961
1962 def F2(i: I1): list<number>
1963 return [ i.mvar1, i.mvar2 ]
1964 enddef
1965
1966 var oa = A.new()
1967 var ob = B.new()
1968 var oc = C.new()
1969
1970 assert_equal([11, 12], F1(oa))
1971 assert_equal([21, 22], F1(ob))
1972 assert_equal([31, 32], F1(oc))
1973
1974 assert_equal([111, 112], F2(oa))
1975 assert_equal([121, 122], F2(ob))
1976 assert_equal([131, 132], F2(oc))
1977 END
1978 v9.CheckScriptSuccess(lines)
1979
1980 # Access superclass interface members from subclass, mix variable order.
1981 # Two interfaces, one on A, one on B; each has both kinds of variables
1982 lines =<< trim END
1983 vim9script
1984
1985 interface I1
1986 public static svar1: number
1987 public static svar2: number
1988 public this.mvar1: number
1989 public this.mvar2: number
1990 endinterface
1991
1992 interface I2
1993 public static svar3: number
1994 public static svar4: number
1995 public this.mvar3: number
1996 public this.mvar4: number
1997 endinterface
1998
1999 class A implements I1
2000 public static svar1: number
2001 public static svar2: number
2002 public this.mvar1: number
2003 public this.mvar2: number
2004 def new()
2005 svar1 = 11
2006 svar2 = 12
2007 this.mvar1 = 111
2008 this.mvar2 = 112
2009 enddef
2010 endclass
2011
2012 class B extends A implements I2
2013 public static svar3: number
2014 public static svar4: number
2015 public this.mvar3: number
2016 public this.mvar4: number
2017 def new()
2018 svar1 = 21
2019 svar2 = 22
2020 svar3 = 23
2021 svar4 = 24
2022 this.mvar1 = 121
2023 this.mvar2 = 122
2024 this.mvar3 = 123
2025 this.mvar4 = 124
2026 enddef
2027 endclass
2028
2029 class C extends B
2030 public static svar5: number
2031 def new()
2032 svar1 = 31
2033 svar2 = 32
2034 svar3 = 33
2035 svar4 = 34
2036 svar5 = 1001
2037 this.mvar1 = 131
2038 this.mvar2 = 132
2039 this.mvar3 = 133
2040 this.mvar4 = 134
2041 enddef
2042 endclass
2043
2044 def F1(i: I1): list<number>
2045 return [ i.svar1, i.svar2 ]
2046 enddef
2047
2048 def F2(i: I1): list<number>
2049 return [ i.mvar1, i.mvar2 ]
2050 enddef
2051
2052 def F3(i: I2): list<number>
2053 return [ i.svar3, i.svar4 ]
2054 enddef
2055
2056 def F4(i: I2): list<number>
2057 return [ i.mvar3, i.mvar4 ]
2058 enddef
2059
2060 def F5(o: C): number
2061 return o.svar5
2062 enddef
2063
2064 var oa = A.new()
2065 var ob = B.new()
2066 var oc = C.new()
2067
2068 assert_equal([[11, 12]], [F1(oa)])
2069 assert_equal([[21, 22], [23, 24]], [F1(ob), F3(ob)])
2070 assert_equal([[31, 32], [33, 34]], [F1(oc), F3(oc)])
2071
2072 assert_equal([[111, 112]], [F2(oa)])
2073 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2074 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
2075
2076 assert_equal(1001, F5(oc))
2077 END
2078 v9.CheckScriptSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002079enddef
2080
Bram Moolenaard0200c82023-01-28 15:19:40 +00002081def Test_call_interface_method()
2082 var lines =<< trim END
2083 vim9script
2084 interface Base
2085 def Enter(): void
2086 endinterface
2087
2088 class Child implements Base
2089 def Enter(): void
2090 g:result ..= 'child'
2091 enddef
2092 endclass
2093
2094 def F(obj: Base)
2095 obj.Enter()
2096 enddef
2097
2098 g:result = ''
2099 F(Child.new())
2100 assert_equal('child', g:result)
2101 unlet g:result
2102 END
2103 v9.CheckScriptSuccess(lines)
2104
2105 lines =<< trim END
2106 vim9script
2107 class Base
2108 def Enter(): void
2109 g:result ..= 'base'
2110 enddef
2111 endclass
2112
2113 class Child extends Base
2114 def Enter(): void
2115 g:result ..= 'child'
2116 enddef
2117 endclass
2118
2119 def F(obj: Base)
2120 obj.Enter()
2121 enddef
2122
2123 g:result = ''
2124 F(Child.new())
2125 assert_equal('child', g:result)
2126 unlet g:result
2127 END
2128 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002129
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002130 # method of interface returns a value
2131 lines =<< trim END
2132 vim9script
2133 interface Base
2134 def Enter(): string
2135 endinterface
2136
2137 class Child implements Base
2138 def Enter(): string
2139 g:result ..= 'child'
2140 return "/resource"
2141 enddef
2142 endclass
2143
2144 def F(obj: Base)
2145 var r = obj.Enter()
2146 g:result ..= r
2147 enddef
2148
2149 g:result = ''
2150 F(Child.new())
2151 assert_equal('child/resource', g:result)
2152 unlet g:result
2153 END
2154 v9.CheckScriptSuccess(lines)
2155
2156 lines =<< trim END
2157 vim9script
2158 class Base
2159 def Enter(): string
2160 return null_string
2161 enddef
2162 endclass
2163
2164 class Child extends Base
2165 def Enter(): string
2166 g:result ..= 'child'
2167 return "/resource"
2168 enddef
2169 endclass
2170
2171 def F(obj: Base)
2172 var r = obj.Enter()
2173 g:result ..= r
2174 enddef
2175
2176 g:result = ''
2177 F(Child.new())
2178 assert_equal('child/resource', g:result)
2179 unlet g:result
2180 END
2181 v9.CheckScriptSuccess(lines)
2182
2183
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002184 # No class that implements the interface.
2185 lines =<< trim END
2186 vim9script
2187
2188 interface IWithEE
2189 def Enter(): any
2190 def Exit(): void
2191 endinterface
2192
2193 def With1(ee: IWithEE, F: func)
2194 var r = ee.Enter()
2195 enddef
2196
2197 defcompile
2198 END
2199 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002200enddef
2201
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002202def Test_class_used_as_type()
2203 var lines =<< trim END
2204 vim9script
2205
2206 class Point
2207 this.x = 0
2208 this.y = 0
2209 endclass
2210
2211 var p: Point
2212 p = Point.new(2, 33)
2213 assert_equal(2, p.x)
2214 assert_equal(33, p.y)
2215 END
2216 v9.CheckScriptSuccess(lines)
2217
2218 lines =<< trim END
2219 vim9script
2220
2221 interface HasX
2222 this.x: number
2223 endinterface
2224
2225 class Point implements HasX
2226 this.x = 0
2227 this.y = 0
2228 endclass
2229
2230 var p: Point
2231 p = Point.new(2, 33)
2232 var hx = p
2233 assert_equal(2, hx.x)
2234 END
2235 v9.CheckScriptSuccess(lines)
2236
2237 lines =<< trim END
2238 vim9script
2239
2240 class Point
2241 this.x = 0
2242 this.y = 0
2243 endclass
2244
2245 var p: Point
2246 p = 'text'
2247 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002248 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002249enddef
2250
Bram Moolenaar83677162023-01-08 19:54:10 +00002251def Test_class_extends()
2252 var lines =<< trim END
2253 vim9script
2254 class Base
2255 this.one = 1
2256 def GetOne(): number
2257 return this.one
2258 enddef
2259 endclass
2260 class Child extends Base
2261 this.two = 2
2262 def GetTotal(): number
2263 return this.one + this.two
2264 enddef
2265 endclass
2266 var o = Child.new()
2267 assert_equal(1, o.one)
2268 assert_equal(2, o.two)
2269 assert_equal(1, o.GetOne())
2270 assert_equal(3, o.GetTotal())
2271 END
2272 v9.CheckScriptSuccess(lines)
2273
2274 lines =<< trim END
2275 vim9script
2276 class Base
2277 this.one = 1
2278 endclass
2279 class Child extends Base
2280 this.two = 2
2281 endclass
2282 var o = Child.new(3, 44)
2283 assert_equal(3, o.one)
2284 assert_equal(44, o.two)
2285 END
2286 v9.CheckScriptSuccess(lines)
2287
2288 lines =<< trim END
2289 vim9script
2290 class Base
2291 this.one = 1
2292 endclass
2293 class Child extends Base extends Base
2294 this.two = 2
2295 endclass
2296 END
2297 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
2298
2299 lines =<< trim END
2300 vim9script
2301 class Child extends BaseClass
2302 this.two = 2
2303 endclass
2304 END
2305 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
2306
2307 lines =<< trim END
2308 vim9script
2309 var SomeVar = 99
2310 class Child extends SomeVar
2311 this.two = 2
2312 endclass
2313 END
2314 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002315
2316 lines =<< trim END
2317 vim9script
2318 class Base
2319 this.name: string
2320 def ToString(): string
2321 return this.name
2322 enddef
2323 endclass
2324
2325 class Child extends Base
2326 this.age: number
2327 def ToString(): string
2328 return super.ToString() .. ': ' .. this.age
2329 enddef
2330 endclass
2331
2332 var o = Child.new('John', 42)
2333 assert_equal('John: 42', o.ToString())
2334 END
2335 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002336
2337 lines =<< trim END
2338 vim9script
2339 class Child
2340 this.age: number
2341 def ToString(): number
2342 return this.age
2343 enddef
2344 def ToString(): string
2345 return this.age
2346 enddef
2347 endclass
2348 END
2349 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
2350
2351 lines =<< trim END
2352 vim9script
2353 class Child
2354 this.age: number
2355 def ToString(): string
2356 return super .ToString() .. ': ' .. this.age
2357 enddef
2358 endclass
2359 var o = Child.new(42)
2360 echo o.ToString()
2361 END
2362 v9.CheckScriptFailure(lines, 'E1356:')
2363
2364 lines =<< trim END
2365 vim9script
2366 class Base
2367 this.name: string
2368 def ToString(): string
2369 return this.name
2370 enddef
2371 endclass
2372
2373 var age = 42
2374 def ToString(): string
2375 return super.ToString() .. ': ' .. age
2376 enddef
2377 echo ToString()
2378 END
2379 v9.CheckScriptFailure(lines, 'E1357:')
2380
2381 lines =<< trim END
2382 vim9script
2383 class Child
2384 this.age: number
2385 def ToString(): string
2386 return super.ToString() .. ': ' .. this.age
2387 enddef
2388 endclass
2389 var o = Child.new(42)
2390 echo o.ToString()
2391 END
2392 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002393
2394 lines =<< trim END
2395 vim9script
2396 class Base
2397 this.name: string
2398 static def ToString(): string
2399 return 'Base class'
2400 enddef
2401 endclass
2402
2403 class Child extends Base
2404 this.age: number
2405 def ToString(): string
2406 return Base.ToString() .. ': ' .. this.age
2407 enddef
2408 endclass
2409
2410 var o = Child.new('John', 42)
2411 assert_equal('Base class: 42', o.ToString())
2412 END
2413 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002414
2415 lines =<< trim END
2416 vim9script
2417 class Base
2418 this.value = 1
2419 def new(init: number)
2420 this.value = number + 1
2421 enddef
2422 endclass
2423 class Child extends Base
2424 def new()
2425 this.new(3)
2426 enddef
2427 endclass
2428 var c = Child.new()
2429 END
2430 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002431
2432 # base class with more than one object member
2433 lines =<< trim END
2434 vim9script
2435
2436 class Result
2437 this.success: bool
2438 this.value: any = null
2439 endclass
2440
2441 class Success extends Result
2442 def new(this.value = v:none)
2443 this.success = true
2444 enddef
2445 endclass
2446
2447 var v = Success.new('asdf')
2448 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2449 END
2450 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002451
2452 # class name after "extends" doesn't end in a space or NUL character
2453 lines =<< trim END
2454 vim9script
2455 class A
2456 endclass
2457 class B extends A"
2458 endclass
2459 END
2460 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002461enddef
2462
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002463def Test_using_base_class()
2464 var lines =<< trim END
2465 vim9script
2466
2467 class BaseEE
2468 def Enter(): any
2469 return null
2470 enddef
2471 def Exit(resource: any): void
2472 enddef
2473 endclass
2474
2475 class ChildEE extends BaseEE
2476 def Enter(): any
2477 return 42
2478 enddef
2479
2480 def Exit(resource: number): void
2481 g:result ..= '/exit'
2482 enddef
2483 endclass
2484
2485 def With(ee: BaseEE)
2486 var r = ee.Enter()
2487 try
2488 g:result ..= r
2489 finally
2490 g:result ..= '/finally'
2491 ee.Exit(r)
2492 endtry
2493 enddef
2494
2495 g:result = ''
2496 With(ChildEE.new())
2497 assert_equal('42/finally/exit', g:result)
2498 END
2499 v9.CheckScriptSuccess(lines)
2500 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002501
2502 # Using super, Child invokes Base method which has optional arg. #12471
2503 lines =<< trim END
2504 vim9script
2505
2506 class Base
2507 this.success: bool = false
2508 def Method(arg = 0)
2509 this.success = true
2510 enddef
2511 endclass
2512
2513 class Child extends Base
2514 def new()
2515 super.Method()
2516 enddef
2517 endclass
2518
2519 var obj = Child.new()
2520 assert_equal(true, obj.success)
2521 END
2522 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002523enddef
2524
2525
Bram Moolenaara86655a2023-01-12 17:06:27 +00002526def Test_class_import()
2527 var lines =<< trim END
2528 vim9script
2529 export class Animal
2530 this.kind: string
2531 this.name: string
2532 endclass
2533 END
2534 writefile(lines, 'Xanimal.vim', 'D')
2535
2536 lines =<< trim END
2537 vim9script
2538 import './Xanimal.vim' as animal
2539
2540 var a: animal.Animal
2541 a = animal.Animal.new('fish', 'Eric')
2542 assert_equal('fish', a.kind)
2543 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002544
2545 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2546 assert_equal('cat', b.kind)
2547 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002548 END
2549 v9.CheckScriptSuccess(lines)
2550enddef
2551
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002552def Test_abstract_class()
2553 var lines =<< trim END
2554 vim9script
2555 abstract class Base
2556 this.name: string
2557 endclass
2558 class Person extends Base
2559 this.age: number
2560 endclass
2561 var p: Base = Person.new('Peter', 42)
2562 assert_equal('Peter', p.name)
2563 assert_equal(42, p.age)
2564 END
2565 v9.CheckScriptSuccess(lines)
2566
2567 lines =<< trim END
2568 vim9script
2569 abstract class Base
2570 this.name: string
2571 endclass
2572 class Person extends Base
2573 this.age: number
2574 endclass
2575 var p = Base.new('Peter')
2576 END
2577 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2578
2579 lines =<< trim END
2580 abstract class Base
2581 this.name: string
2582 endclass
2583 END
2584 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002585
2586 # Abstract class cannot have a "new" function
2587 lines =<< trim END
2588 vim9script
2589 abstract class Base
2590 def new()
2591 enddef
2592 endclass
2593 END
2594 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002595enddef
2596
Bram Moolenaar486fc252023-01-18 14:51:07 +00002597def Test_closure_in_class()
2598 var lines =<< trim END
2599 vim9script
2600
2601 class Foo
2602 this.y: list<string> = ['B']
2603
2604 def new()
2605 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2606 enddef
2607 endclass
2608
2609 Foo.new()
2610 assert_equal(['A'], g:result)
2611 END
2612 v9.CheckScriptSuccess(lines)
2613enddef
2614
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002615def Test_call_constructor_from_legacy()
2616 var lines =<< trim END
2617 vim9script
2618
2619 var newCalled = 'false'
2620
2621 class A
2622 def new()
2623 newCalled = 'true'
2624 enddef
2625 endclass
2626
2627 export def F(options = {}): any
2628 return A
2629 enddef
2630
2631 g:p = F()
2632 legacy call p.new()
2633 assert_equal('true', newCalled)
2634 END
2635 v9.CheckScriptSuccess(lines)
2636enddef
2637
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002638def Test_defer_with_object()
2639 var lines =<< trim END
2640 vim9script
2641
2642 class CWithEE
2643 def Enter()
2644 g:result ..= "entered/"
2645 enddef
2646 def Exit()
2647 g:result ..= "exited"
2648 enddef
2649 endclass
2650
2651 def With(ee: CWithEE, F: func)
2652 ee.Enter()
2653 defer ee.Exit()
2654 F()
2655 enddef
2656
2657 g:result = ''
2658 var obj = CWithEE.new()
2659 obj->With(() => {
2660 g:result ..= "called/"
2661 })
2662 assert_equal('entered/called/exited', g:result)
2663 END
2664 v9.CheckScriptSuccess(lines)
2665 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002666
2667 lines =<< trim END
2668 vim9script
2669
2670 class BaseWithEE
2671 def Enter()
2672 g:result ..= "entered-base/"
2673 enddef
2674 def Exit()
2675 g:result ..= "exited-base"
2676 enddef
2677 endclass
2678
2679 class CWithEE extends BaseWithEE
2680 def Enter()
2681 g:result ..= "entered-child/"
2682 enddef
2683 def Exit()
2684 g:result ..= "exited-child"
2685 enddef
2686 endclass
2687
2688 def With(ee: BaseWithEE, F: func)
2689 ee.Enter()
2690 defer ee.Exit()
2691 F()
2692 enddef
2693
2694 g:result = ''
2695 var obj = CWithEE.new()
2696 obj->With(() => {
2697 g:result ..= "called/"
2698 })
2699 assert_equal('entered-child/called/exited-child', g:result)
2700 END
2701 v9.CheckScriptSuccess(lines)
2702 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002703enddef
2704
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002705" The following test used to crash Vim (Github issue #12676)
2706def Test_extends_method_crashes_vim()
2707 var lines =<< trim END
2708 vim9script
2709
2710 class Observer
2711 endclass
2712
2713 class Property
2714 this.value: any
2715
2716 def Set(v: any)
2717 if v != this.value
2718 this.value = v
2719 endif
2720 enddef
2721
2722 def Register(observer: Observer)
2723 enddef
2724 endclass
2725
2726 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002727 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002728 endclass
2729
2730 def Observe(obj: Property, who: Observer)
2731 obj.Register(who)
2732 enddef
2733
2734 var p = Bool.new(false)
2735 var myObserver = Observer.new()
2736
2737 Observe(p, myObserver)
2738
2739 p.Set(true)
2740 END
2741 v9.CheckScriptSuccess(lines)
2742enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002743
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002744" Test for calling a method in a class that is extended
2745def Test_call_method_in_extended_class()
2746 var lines =<< trim END
2747 vim9script
2748
2749 var prop_init_called = false
2750 var prop_register_called = false
2751
2752 class Property
2753 def Init()
2754 prop_init_called = true
2755 enddef
2756
2757 def Register()
2758 prop_register_called = true
2759 enddef
2760 endclass
2761
2762 class Bool extends Property
2763 endclass
2764
2765 def Observe(obj: Property)
2766 obj.Register()
2767 enddef
2768
2769 var p = Property.new()
2770 Observe(p)
2771
2772 p.Init()
2773 assert_true(prop_init_called)
2774 assert_true(prop_register_called)
2775 END
2776 v9.CheckScriptSuccess(lines)
2777enddef
2778
LemonBoyafe04662023-08-23 21:08:11 +02002779def Test_instanceof()
2780 var lines =<< trim END
2781 vim9script
2782
2783 class Base1
2784 endclass
2785
2786 class Base2 extends Base1
2787 endclass
2788
2789 interface Intf1
2790 endinterface
2791
2792 class Mix1 implements Intf1
2793 endclass
2794
2795 class Base3 extends Mix1
2796 endclass
2797
2798 var b1 = Base1.new()
2799 var b2 = Base2.new()
2800 var b3 = Base3.new()
2801
2802 assert_true(instanceof(b1, Base1))
2803 assert_true(instanceof(b2, Base1))
2804 assert_false(instanceof(b1, Base2))
2805 assert_true(instanceof(b3, Mix1))
2806 assert_false(instanceof(b3, []))
2807 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002808
2809 def Foo()
2810 var a1 = Base1.new()
2811 var a2 = Base2.new()
2812 var a3 = Base3.new()
2813
2814 assert_true(instanceof(a1, Base1))
2815 assert_true(instanceof(a2, Base1))
2816 assert_false(instanceof(a1, Base2))
2817 assert_true(instanceof(a3, Mix1))
2818 assert_false(instanceof(a3, []))
2819 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2820 enddef
2821 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002822 END
2823 v9.CheckScriptSuccess(lines)
2824enddef
2825
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002826" Test for calling a method in the parent class that is extended partially.
2827" This used to fail with the 'E118: Too many arguments for function: Text' error
2828" message (Github issue #12524).
2829def Test_call_method_in_parent_class()
2830 var lines =<< trim END
2831 vim9script
2832
2833 class Widget
2834 this._lnum: number = 1
2835
2836 def SetY(lnum: number)
2837 this._lnum = lnum
2838 enddef
2839
2840 def Text(): string
2841 return ''
2842 enddef
2843 endclass
2844
2845 class Foo extends Widget
2846 def Text(): string
2847 return '<Foo>'
2848 enddef
2849 endclass
2850
2851 def Stack(w1: Widget, w2: Widget): list<Widget>
2852 w1.SetY(1)
2853 w2.SetY(2)
2854 return [w1, w2]
2855 enddef
2856
2857 var foo1 = Foo.new()
2858 var foo2 = Foo.new()
2859 var l = Stack(foo1, foo2)
2860 END
2861 v9.CheckScriptSuccess(lines)
2862enddef
2863
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002864" Test for calling methods from three levels of classes
2865def Test_multi_level_method_call()
2866 var lines =<< trim END
2867 vim9script
2868
2869 var A_func1: number = 0
2870 var A_func2: number = 0
2871 var A_func3: number = 0
2872 var B_func2: number = 0
2873 var B_func3: number = 0
2874 var C_func3: number = 0
2875
2876 class A
2877 def Func1()
2878 A_func1 += 1
2879 enddef
2880
2881 def Func2()
2882 A_func2 += 1
2883 enddef
2884
2885 def Func3()
2886 A_func3 += 1
2887 enddef
2888 endclass
2889
2890 class B extends A
2891 def Func2()
2892 B_func2 += 1
2893 enddef
2894
2895 def Func3()
2896 B_func3 += 1
2897 enddef
2898 endclass
2899
2900 class C extends B
2901 def Func3()
2902 C_func3 += 1
2903 enddef
2904 endclass
2905
2906 def A_CallFuncs(a: A)
2907 a.Func1()
2908 a.Func2()
2909 a.Func3()
2910 enddef
2911
2912 def B_CallFuncs(b: B)
2913 b.Func1()
2914 b.Func2()
2915 b.Func3()
2916 enddef
2917
2918 def C_CallFuncs(c: C)
2919 c.Func1()
2920 c.Func2()
2921 c.Func3()
2922 enddef
2923
2924 var cobj = C.new()
2925 A_CallFuncs(cobj)
2926 B_CallFuncs(cobj)
2927 C_CallFuncs(cobj)
2928 assert_equal(3, A_func1)
2929 assert_equal(0, A_func2)
2930 assert_equal(0, A_func3)
2931 assert_equal(3, B_func2)
2932 assert_equal(0, B_func3)
2933 assert_equal(3, C_func3)
2934 END
2935 v9.CheckScriptSuccess(lines)
2936enddef
2937
2938" Test for using members from three levels of classes
2939def Test_multi_level_member_access()
2940 var lines =<< trim END
2941 vim9script
2942
2943 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002944 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002945 endclass
2946
2947 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002948 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002949 endclass
2950
2951 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002952 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002953 endclass
2954
2955 def A_members(a: A)
2956 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002957 enddef
2958
2959 def B_members(b: B)
2960 b.val1 += 1
2961 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002962 enddef
2963
2964 def C_members(c: C)
2965 c.val1 += 1
2966 c.val2 += 1
2967 c.val3 += 1
2968 enddef
2969
2970 var cobj = C.new()
2971 A_members(cobj)
2972 B_members(cobj)
2973 C_members(cobj)
2974 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002975 assert_equal(2, cobj.val2)
2976 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002977 END
2978 v9.CheckScriptSuccess(lines)
2979enddef
2980
LemonBoy0ffc17a2023-08-20 18:09:11 +02002981" Test expansion of <stack> with class methods.
2982def Test_stack_expansion_with_methods()
2983 var lines =<< trim END
2984 vim9script
2985
2986 class C
2987 def M1()
2988 F0()
2989 enddef
2990 endclass
2991
2992 def F0()
2993 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2994 enddef
2995
2996 def F()
2997 C.new().M1()
2998 enddef
2999
3000 F()
3001 END
3002 v9.CheckScriptSuccess(lines)
3003enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003004
3005" Test the return type of the new() constructor
3006def Test_new_return_type()
3007 # new() uses the default return type and there is no return statement
3008 var lines =<< trim END
3009 vim9script
3010
3011 class C
3012 this._bufnr: number
3013
3014 def new(this._bufnr)
3015 if !bufexists(this._bufnr)
3016 this._bufnr = -1
3017 endif
3018 enddef
3019 endclass
3020
3021 var c = C.new(12345)
3022 assert_equal('object<C>', typename(c))
3023
3024 var v1: C
3025 v1 = C.new(12345)
3026 assert_equal('object<C>', typename(v1))
3027
3028 def F()
3029 var v2: C
3030 v2 = C.new(12345)
3031 assert_equal('object<C>', typename(v2))
3032 enddef
3033 F()
3034 END
3035 v9.CheckScriptSuccess(lines)
3036
3037 # new() uses the default return type and an empty 'return' statement
3038 lines =<< trim END
3039 vim9script
3040
3041 class C
3042 this._bufnr: number
3043
3044 def new(this._bufnr)
3045 if !bufexists(this._bufnr)
3046 this._bufnr = -1
3047 return
3048 endif
3049 enddef
3050 endclass
3051
3052 var c = C.new(12345)
3053 assert_equal('object<C>', typename(c))
3054
3055 var v1: C
3056 v1 = C.new(12345)
3057 assert_equal('object<C>', typename(v1))
3058
3059 def F()
3060 var v2: C
3061 v2 = C.new(12345)
3062 assert_equal('object<C>', typename(v2))
3063 enddef
3064 F()
3065 END
3066 v9.CheckScriptSuccess(lines)
3067
3068 # new() uses "any" return type and returns "this"
3069 lines =<< trim END
3070 vim9script
3071
3072 class C
3073 this._bufnr: number
3074
3075 def new(this._bufnr): any
3076 if !bufexists(this._bufnr)
3077 this._bufnr = -1
3078 return this
3079 endif
3080 enddef
3081 endclass
3082 END
3083 v9.CheckScriptFailure(lines, 'E1365:')
3084
3085 # new() uses 'Dict' return type and returns a Dict
3086 lines =<< trim END
3087 vim9script
3088
3089 class C
3090 this._state: dict<any>
3091
3092 def new(): dict<any>
3093 this._state = {}
3094 return this._state
3095 enddef
3096 endclass
3097
3098 var c = C.new()
3099 assert_equal('object<C>', typename(c))
3100 END
3101 v9.CheckScriptFailure(lines, 'E1365:')
3102enddef
3103
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003104" Test for checking a member initialization type at run time.
3105def Test_runtime_type_check_for_member_init()
3106 var lines =<< trim END
3107 vim9script
3108
3109 var retnum: bool = false
3110
3111 def F(): any
3112 retnum = !retnum
3113 if retnum
3114 return 1
3115 else
3116 return "hello"
3117 endif
3118 enddef
3119
3120 class C
3121 this._foo: bool = F()
3122 endclass
3123
3124 var c1 = C.new()
3125 var c2 = C.new()
3126 END
3127 v9.CheckScriptFailure(lines, 'E1012:')
3128enddef
3129
3130" Test for locking a variable referring to an object and reassigning to another
3131" object.
3132def Test_object_lockvar()
3133 var lines =<< trim END
3134 vim9script
3135
3136 class C
3137 this.val: number
3138 def new(this.val)
3139 enddef
3140 endclass
3141
3142 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3143 lockvar 2 some_dict
3144
3145 var current: C
3146 current = some_dict['c']
3147 assert_equal(3, current.val)
3148 current = some_dict['b']
3149 assert_equal(2, current.val)
3150
3151 def F()
3152 current = some_dict['c']
3153 enddef
3154
3155 def G()
3156 current = some_dict['b']
3157 enddef
3158
3159 F()
3160 assert_equal(3, current.val)
3161 G()
3162 assert_equal(2, current.val)
3163 END
3164 v9.CheckScriptSuccess(lines)
3165enddef
3166
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003167" Test for a private object method
3168def Test_private_object_method()
3169 # Try calling a private method using an object (at the script level)
3170 var lines =<< trim END
3171 vim9script
3172
3173 class A
3174 def _Foo(): number
3175 return 1234
3176 enddef
3177 endclass
3178 var a = A.new()
3179 a._Foo()
3180 END
3181 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3182
3183 # Try calling a private method using an object (from a def function)
3184 lines =<< trim END
3185 vim9script
3186
3187 class A
3188 def _Foo(): number
3189 return 1234
3190 enddef
3191 endclass
3192 def T()
3193 var a = A.new()
3194 a._Foo()
3195 enddef
3196 T()
3197 END
3198 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3199
3200 # Use a private method from another object method (in script context)
3201 lines =<< trim END
3202 vim9script
3203
3204 class A
3205 def _Foo(): number
3206 return 1234
3207 enddef
3208 def Bar(): number
3209 return this._Foo()
3210 enddef
3211 endclass
3212 var a = A.new()
3213 assert_equal(1234, a.Bar())
3214 END
3215 v9.CheckScriptSuccess(lines)
3216
3217 # Use a private method from another object method (def function context)
3218 lines =<< trim END
3219 vim9script
3220
3221 class A
3222 def _Foo(): number
3223 return 1234
3224 enddef
3225 def Bar(): number
3226 return this._Foo()
3227 enddef
3228 endclass
3229 def T()
3230 var a = A.new()
3231 assert_equal(1234, a.Bar())
3232 enddef
3233 T()
3234 END
3235 v9.CheckScriptSuccess(lines)
3236
3237 # Try calling a private method without the "this" prefix
3238 lines =<< trim END
3239 vim9script
3240
3241 class A
3242 def _Foo(): number
3243 return 1234
3244 enddef
3245 def Bar(): number
3246 return _Foo()
3247 enddef
3248 endclass
3249 var a = A.new()
3250 a.Bar()
3251 END
3252 v9.CheckScriptFailure(lines, 'E117: Unknown function: _Foo')
3253
3254 # Try calling a private method using the class name
3255 lines =<< trim END
3256 vim9script
3257
3258 class A
3259 def _Foo(): number
3260 return 1234
3261 enddef
3262 endclass
3263 A._Foo()
3264 END
3265 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3266
3267 # Try to use "public" keyword when defining a private method
3268 lines =<< trim END
3269 vim9script
3270
3271 class A
3272 public def _Foo()
3273 enddef
3274 endclass
3275 var a = A.new()
3276 a._Foo()
3277 END
3278 v9.CheckScriptFailure(lines, 'E1331: Public must be followed by "this" or "static"')
3279
3280 # Define two private methods with the same name
3281 lines =<< trim END
3282 vim9script
3283
3284 class A
3285 def _Foo()
3286 enddef
3287 def _Foo()
3288 enddef
3289 endclass
3290 var a = A.new()
3291 END
3292 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3293
3294 # Define a private method and a object method with the same name
3295 lines =<< trim END
3296 vim9script
3297
3298 class A
3299 def _Foo()
3300 enddef
3301 def Foo()
3302 enddef
3303 endclass
3304 var a = A.new()
3305 END
3306 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3307
3308 # Define an object method and a private method with the same name
3309 lines =<< trim END
3310 vim9script
3311
3312 class A
3313 def Foo()
3314 enddef
3315 def _Foo()
3316 enddef
3317 endclass
3318 var a = A.new()
3319 END
3320 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3321
3322 # Call a public method and a private method from a private method
3323 lines =<< trim END
3324 vim9script
3325
3326 class A
3327 def Foo(): number
3328 return 100
3329 enddef
3330 def _Bar(): number
3331 return 200
3332 enddef
3333 def _Baz()
3334 assert_equal(100, this.Foo())
3335 assert_equal(200, this._Bar())
3336 enddef
3337 def T()
3338 this._Baz()
3339 enddef
3340 endclass
3341 var a = A.new()
3342 a.T()
3343 END
3344 v9.CheckScriptSuccess(lines)
3345
3346 # Try calling a private method from another class
3347 lines =<< trim END
3348 vim9script
3349
3350 class A
3351 def _Foo(): number
3352 return 100
3353 enddef
3354 endclass
3355 class B
3356 def Foo(): number
3357 var a = A.new()
3358 a._Foo()
3359 enddef
3360 endclass
3361 var b = B.new()
3362 b.Foo()
3363 END
3364 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3365
3366 # Call a private object method from a child class object method
3367 lines =<< trim END
3368 vim9script
3369 class A
3370 def _Foo(): number
3371 return 1234
3372 enddef
3373 endclass
3374 class B extends A
3375 def Bar()
3376 enddef
3377 endclass
3378 class C extends B
3379 def Baz(): number
3380 return this._Foo()
3381 enddef
3382 endclass
3383 var c = C.new()
3384 assert_equal(1234, c.Baz())
3385 END
3386 v9.CheckScriptSuccess(lines)
3387
3388 # Call a private object method from a child class object
3389 lines =<< trim END
3390 vim9script
3391 class A
3392 def _Foo(): number
3393 return 1234
3394 enddef
3395 endclass
3396 class B extends A
3397 def Bar()
3398 enddef
3399 endclass
3400 class C extends B
3401 def Baz(): number
3402 enddef
3403 endclass
3404 var c = C.new()
3405 assert_equal(1234, c._Foo())
3406 END
3407 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3408
3409 # Using "_" prefix in a method name should fail outside of a class
3410 lines =<< trim END
3411 vim9script
3412 def _Foo(): number
3413 return 1234
3414 enddef
3415 var a = _Foo()
3416 END
3417 v9.CheckScriptFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
3418enddef
3419
3420" Test for an private class method
3421def Test_private_class_method()
3422 # Try calling a class private method (at the script level)
3423 var lines =<< trim END
3424 vim9script
3425
3426 class A
3427 static def _Foo(): number
3428 return 1234
3429 enddef
3430 endclass
3431 A._Foo()
3432 END
3433 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3434
3435 # Try calling a class private method (from a def function)
3436 lines =<< trim END
3437 vim9script
3438
3439 class A
3440 static def _Foo(): number
3441 return 1234
3442 enddef
3443 endclass
3444 def T()
3445 A._Foo()
3446 enddef
3447 T()
3448 END
3449 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3450
3451 # Try calling a class private method using an object (at the script level)
3452 lines =<< trim END
3453 vim9script
3454
3455 class A
3456 static def _Foo(): number
3457 return 1234
3458 enddef
3459 endclass
3460 var a = A.new()
3461 a._Foo()
3462 END
3463 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3464
3465 # Try calling a class private method using an object (from a def function)
3466 lines =<< trim END
3467 vim9script
3468
3469 class A
3470 static def _Foo(): number
3471 return 1234
3472 enddef
3473 endclass
3474 def T()
3475 var a = A.new()
3476 a._Foo()
3477 enddef
3478 T()
3479 END
3480 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3481
3482 # Use a class private method from an object method
3483 lines =<< trim END
3484 vim9script
3485
3486 class A
3487 static def _Foo(): number
3488 return 1234
3489 enddef
3490 def Bar()
3491 assert_equal(1234, A._Foo())
3492 enddef
3493 endclass
3494 var a = A.new()
3495 a.Bar()
3496 END
3497 v9.CheckScriptSuccess(lines)
3498
3499 # Use a class private method from another class private method
3500 lines =<< trim END
3501 vim9script
3502
3503 class A
3504 static def _Foo1(): number
3505 return 1234
3506 enddef
3507 static def _Foo2()
3508 assert_equal(1234, A._Foo1())
3509 enddef
3510 def Bar()
3511 A._Foo2()
3512 enddef
3513 endclass
3514 var a = A.new()
3515 a.Bar()
3516 END
3517 v9.CheckScriptSuccess(lines)
3518
3519 # Declare a class method and a class private method with the same name
3520 lines =<< trim END
3521 vim9script
3522
3523 class A
3524 static def _Foo()
3525 enddef
3526 static def Foo()
3527 enddef
3528 endclass
3529 var a = A.new()
3530 END
3531 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3532
3533 # Try calling a class private method from another class
3534 lines =<< trim END
3535 vim9script
3536
3537 class A
3538 static def _Foo(): number
3539 return 1234
3540 enddef
3541 endclass
3542 class B
3543 def Foo(): number
3544 return A._Foo()
3545 enddef
3546 endclass
3547 var b = B.new()
3548 assert_equal(1234, b.Foo())
3549 END
3550 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3551
3552 # Call a private class method from a child class object method
3553 lines =<< trim END
3554 vim9script
3555 class A
3556 static def _Foo(): number
3557 return 1234
3558 enddef
3559 endclass
3560 class B extends A
3561 def Bar()
3562 enddef
3563 endclass
3564 class C extends B
3565 def Baz(): number
3566 return A._Foo()
3567 enddef
3568 endclass
3569 var c = C.new()
3570 assert_equal(1234, c.Baz())
3571 END
3572 v9.CheckScriptSuccess(lines)
3573
3574 # Call a private class method from a child class private class method
3575 lines =<< trim END
3576 vim9script
3577 class A
3578 static def _Foo(): number
3579 return 1234
3580 enddef
3581 endclass
3582 class B extends A
3583 def Bar()
3584 enddef
3585 endclass
3586 class C extends B
3587 static def Baz(): number
3588 return A._Foo()
3589 enddef
3590 endclass
3591 assert_equal(1234, C.Baz())
3592 END
3593 v9.CheckScriptSuccess(lines)
3594
3595 # Call a private class method from a child class object
3596 lines =<< trim END
3597 vim9script
3598 class A
3599 static def _Foo(): number
3600 return 1234
3601 enddef
3602 endclass
3603 class B extends A
3604 def Bar()
3605 enddef
3606 endclass
3607 class C extends B
3608 def Baz(): number
3609 enddef
3610 endclass
3611 var c = C.new()
3612 assert_equal(1234, C._Foo())
3613 END
3614 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3615enddef
3616
3617" Test for an interface private object_method
3618def Test_interface_private_object_method()
3619 # Implement an interface private method and use it from a public method
3620 var lines =<< trim END
3621 vim9script
3622 interface Intf
3623 def _Foo(): number
3624 endinterface
3625 class A implements Intf
3626 def _Foo(): number
3627 return 1234
3628 enddef
3629 def Bar(): number
3630 return this._Foo()
3631 enddef
3632 endclass
3633 var a = A.new()
3634 assert_equal(1234, a.Bar())
3635 END
3636 v9.CheckScriptSuccess(lines)
3637
3638 # Call an interface private class method (script context)
3639 lines =<< trim END
3640 vim9script
3641 interface Intf
3642 def _Foo(): number
3643 endinterface
3644 class A implements Intf
3645 def _Foo(): number
3646 return 1234
3647 enddef
3648 endclass
3649 var a = A.new()
3650 assert_equal(1234, a._Foo())
3651 END
3652 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3653
3654 # Call an interface private class method (def context)
3655 lines =<< trim END
3656 vim9script
3657 interface Intf
3658 def _Foo(): number
3659 endinterface
3660 class A implements Intf
3661 def _Foo(): number
3662 return 1234
3663 enddef
3664 endclass
3665 def T()
3666 var a = A.new()
3667 assert_equal(1234, a._Foo())
3668 enddef
3669 T()
3670 END
3671 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3672
3673 # Implement an interface private object method as a private class method
3674 lines =<< trim END
3675 vim9script
3676 interface Intf
3677 def _Foo(): number
3678 endinterface
3679 class A implements Intf
3680 static def _Foo(): number
3681 return 1234
3682 enddef
3683 endclass
3684 END
3685 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3686enddef
3687
3688" Test for an interface private class method
3689def Test_interface_private_class_method()
3690 # Implement an interface private class method and use it from a public method
3691 var lines =<< trim END
3692 vim9script
3693 interface Intf
3694 static def _Foo(): number
3695 endinterface
3696 class A implements Intf
3697 static def _Foo(): number
3698 return 1234
3699 enddef
3700 def Bar(): number
3701 return A._Foo()
3702 enddef
3703 endclass
3704 var a = A.new()
3705 assert_equal(1234, a.Bar())
3706 END
3707 v9.CheckScriptSuccess(lines)
3708
3709 # Call an interface private class method (script context)
3710 lines =<< trim END
3711 vim9script
3712 interface Intf
3713 static def _Foo(): number
3714 endinterface
3715 class A implements Intf
3716 static def _Foo(): number
3717 return 1234
3718 enddef
3719 endclass
3720 assert_equal(1234, A._Foo())
3721 END
3722 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3723
3724 # Call an interface private class method (def context)
3725 lines =<< trim END
3726 vim9script
3727 interface Intf
3728 static def _Foo(): number
3729 endinterface
3730 class A implements Intf
3731 static def _Foo(): number
3732 return 1234
3733 enddef
3734 endclass
3735 def T()
3736 assert_equal(1234, A._Foo())
3737 enddef
3738 T()
3739 END
3740 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3741
3742 # Implement an interface private class method as a private object method
3743 lines =<< trim END
3744 vim9script
3745 interface Intf
3746 static def _Foo(): number
3747 endinterface
3748 class A implements Intf
3749 def _Foo(): number
3750 return 1234
3751 enddef
3752 endclass
3753 END
3754 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3755enddef
3756
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003757" Test for using the return value of a class/object method as a function
3758" argument.
3759def Test_objmethod_funcarg()
3760 var lines =<< trim END
3761 vim9script
3762
3763 class C
3764 def Foo(): string
3765 return 'foo'
3766 enddef
3767 endclass
3768
3769 def Bar(a: number, s: string): string
3770 return s
3771 enddef
3772
3773 def Baz(c: C)
3774 assert_equal('foo', Bar(10, c.Foo()))
3775 enddef
3776
3777 var t = C.new()
3778 Baz(t)
3779 END
3780 v9.CheckScriptSuccess(lines)
3781
3782 lines =<< trim END
3783 vim9script
3784
3785 class C
3786 static def Foo(): string
3787 return 'foo'
3788 enddef
3789 endclass
3790
3791 def Bar(a: number, s: string): string
3792 return s
3793 enddef
3794
3795 def Baz()
3796 assert_equal('foo', Bar(10, C.Foo()))
3797 enddef
3798
3799 Baz()
3800 END
3801 v9.CheckScriptSuccess(lines)
3802enddef
3803
Ernie Raelcf138d42023-09-06 20:45:03 +02003804def Test_static_inheritence()
3805 # subclasses get their own static copy
3806 var lines =<< trim END
3807 vim9script
3808
3809 class A
3810 static _svar: number
3811 this._mvar: number
3812 def new()
3813 _svar = 1
3814 this._mvar = 101
3815 enddef
3816 def AccessObject(): number
3817 return this._mvar
3818 enddef
3819 def AccessStaticThroughObject(): number
3820 return _svar
3821 enddef
3822 endclass
3823
3824 class B extends A
3825 def new()
3826 _svar = 2
3827 this._mvar = 102
3828 enddef
3829 endclass
3830
3831 class C extends B
3832 def new()
3833 _svar = 3
3834 this._mvar = 103
3835 enddef
3836
3837 def AccessPrivateStaticThroughClassName(): number
3838 assert_equal(1, A._svar)
3839 assert_equal(2, B._svar)
3840 assert_equal(3, C._svar)
3841 return 444
3842 enddef
3843 endclass
3844
3845 var oa = A.new()
3846 var ob = B.new()
3847 var oc = C.new()
3848 assert_equal(101, oa.AccessObject())
3849 assert_equal(102, ob.AccessObject())
3850 assert_equal(103, oc.AccessObject())
3851
3852 assert_equal(444, oc.AccessPrivateStaticThroughClassName())
3853
3854 # verify object properly resolves to correct static
3855 assert_equal(1, oa.AccessStaticThroughObject())
3856 assert_equal(2, ob.AccessStaticThroughObject())
3857 assert_equal(3, oc.AccessStaticThroughObject())
3858 END
3859 v9.CheckScriptSuccess(lines)
3860enddef
3861
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003862" Test for declaring duplicate object and class members
3863def Test_dup_member_variable()
3864 # Duplicate member variable
3865 var lines =<< trim END
3866 vim9script
3867 class C
3868 this.val = 10
3869 this.val = 20
3870 endclass
3871 END
3872 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3873
3874 # Duplicate private member variable
3875 lines =<< trim END
3876 vim9script
3877 class C
3878 this._val = 10
3879 this._val = 20
3880 endclass
3881 END
3882 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3883
3884 # Duplicate public member variable
3885 lines =<< trim END
3886 vim9script
3887 class C
3888 public this.val = 10
3889 public this.val = 20
3890 endclass
3891 END
3892 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3893
3894 # Duplicate private member variable
3895 lines =<< trim END
3896 vim9script
3897 class C
3898 this.val = 10
3899 this._val = 20
3900 endclass
3901 END
3902 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3903
3904 # Duplicate public and private member variable
3905 lines =<< trim END
3906 vim9script
3907 class C
3908 this._val = 20
3909 public this.val = 10
3910 endclass
3911 END
3912 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3913
3914 # Duplicate class member variable
3915 lines =<< trim END
3916 vim9script
3917 class C
3918 static s: string = "abc"
3919 static _s: string = "def"
3920 endclass
3921 END
3922 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3923
3924 # Duplicate public and private class member variable
3925 lines =<< trim END
3926 vim9script
3927 class C
3928 public static s: string = "abc"
3929 static _s: string = "def"
3930 endclass
3931 END
3932 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3933
3934 # Duplicate class and object member variable
3935 lines =<< trim END
3936 vim9script
3937 class C
3938 static val = 10
3939 this.val = 20
3940 def new()
3941 enddef
3942 endclass
3943 var c = C.new()
3944 assert_equal(10, C.val)
3945 assert_equal(20, c.val)
3946 END
3947 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003948
3949 # Duplicate object member variable in a derived class
3950 lines =<< trim END
3951 vim9script
3952 class A
3953 this.val = 10
3954 endclass
3955 class B extends A
3956 endclass
3957 class C extends B
3958 this.val = 20
3959 endclass
3960 END
3961 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3962
3963 # Duplicate object private member variable in a derived class
3964 lines =<< trim END
3965 vim9script
3966 class A
3967 this._val = 10
3968 endclass
3969 class B extends A
3970 endclass
3971 class C extends B
3972 this._val = 20
3973 endclass
3974 END
3975 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3976
3977 # Duplicate object private member variable in a derived class
3978 lines =<< trim END
3979 vim9script
3980 class A
3981 this.val = 10
3982 endclass
3983 class B extends A
3984 endclass
3985 class C extends B
3986 this._val = 20
3987 endclass
3988 END
3989 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3990
3991 # Duplicate object member variable in a derived class
3992 lines =<< trim END
3993 vim9script
3994 class A
3995 this._val = 10
3996 endclass
3997 class B extends A
3998 endclass
3999 class C extends B
4000 this.val = 20
4001 endclass
4002 END
4003 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
4004
4005 # Duplicate class member variable in a derived class
4006 lines =<< trim END
4007 vim9script
4008 class A
4009 static val = 10
4010 endclass
4011 class B extends A
4012 endclass
4013 class C extends B
4014 static val = 20
4015 endclass
4016 END
4017 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
4018
4019 # Duplicate private class member variable in a derived class
4020 lines =<< trim END
4021 vim9script
4022 class A
4023 static _val = 10
4024 endclass
4025 class B extends A
4026 endclass
4027 class C extends B
4028 static _val = 20
4029 endclass
4030 END
4031 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
4032
4033 # Duplicate private class member variable in a derived class
4034 lines =<< trim END
4035 vim9script
4036 class A
4037 static val = 10
4038 endclass
4039 class B extends A
4040 endclass
4041 class C extends B
4042 static _val = 20
4043 endclass
4044 END
4045 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
4046
4047 # Duplicate class member variable in a derived class
4048 lines =<< trim END
4049 vim9script
4050 class A
4051 static _val = 10
4052 endclass
4053 class B extends A
4054 endclass
4055 class C extends B
4056 static val = 20
4057 endclass
4058 END
4059 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004060
4061 # Two member variables with a common prefix
4062 lines =<< trim END
4063 vim9script
4064 class A
4065 public static svar2: number
4066 public static svar: number
4067 endclass
4068 END
4069 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004070enddef
4071
Ernie Rael18143d32023-09-04 22:30:41 +02004072def Test_interface_static_member_access()
4073 # In a class cannot read from interface static
4074 var lines =<< trim END
4075 vim9script
4076 interface I
4077 public static num: number
4078 endinterface
4079 class C implements I
4080 public static num = 3
4081 def F()
4082 var x = I.num
4083 enddef
4084 endclass
4085 C.new().F()
4086 END
4087 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4088
4089 # In a class cannot write to interface static
4090 lines =<< trim END
4091 vim9script
4092 interface I
4093 public static num: number
4094 endinterface
4095 class C implements I
4096 public static num = 3
4097 def F()
4098 I.num = 7
4099 enddef
4100 endclass
4101 C.new().F()
4102 END
4103 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4104
4105 # In a def cannot read from interface static
4106 lines =<< trim END
4107 vim9script
4108 interface I
4109 public static num: number
4110 endinterface
4111 def F()
4112 var x = I.num
4113 enddef
4114 F()
4115 END
4116 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4117
4118 # In a def cannot write to interface static
4119 lines =<< trim END
4120 vim9script
4121 interface I
4122 public static num: number
4123 endinterface
4124 def F()
4125 I.num = 7
4126 enddef
4127 F()
4128 END
4129 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
4130
4131 # script level cannot read interface static
4132 lines =<< trim END
4133 vim9script
4134 interface I
4135 public static s_var1: number
4136 endinterface
4137
4138 var x = I.s_var1
4139 END
4140 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "s_var1"')
4141
4142 # script level cannot write interface static
4143 lines =<< trim END
4144 vim9script
4145 interface I
4146 public static s_var1: number
4147 endinterface
4148
4149 I.s_var1 = 3
4150 END
4151 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "I.s_var1 = 3"')
4152
4153enddef
4154
4155def Test_static_member_access_outside_class()
4156 # Verify access of statics implemented from interface
4157 # in a :def (outside of a class)
4158 # Note the order of the static is different
4159 # between the interface and the class,
4160 # since they are allocated in order in each interface/class;
4161 # so the static index is mapped from interfaced to class as needed.
4162
4163 # Check reading statics
4164 var lines =<< trim END
4165 vim9script
4166
4167 interface I
4168 public static s_var1: number
4169 public static s_var2: number
4170 endinterface
4171
4172 class C implements I
4173 public static s_var2 = 2
4174 public static x_static = 7
4175 public static s_var1 = 1
4176 endclass
4177
4178 def F1(): number
4179 assert_equal(1, C.s_var1)
4180 assert_equal(2, C.s_var2)
4181 assert_equal(7, C.x_static)
4182 return 11
4183 enddef
4184
4185 # access the class static through an interface argument
4186 def F2(i: I): number
4187 assert_equal(1, i.s_var1)
4188 assert_equal(2, i.s_var2)
4189 return 22
4190 enddef
4191
4192 # access the class static through an object interface
4193 def F3(o: C): number
4194 assert_equal(1, o.s_var1)
4195 assert_equal(2, o.s_var2)
4196 assert_equal(7, o.x_static)
4197 return 33
4198 enddef
4199
4200 assert_equal(11, F1())
4201 var c = C.new()
4202 assert_equal(22, F2(c))
4203 assert_equal(33, F3(c))
4204 END
4205 v9.CheckScriptSuccess(lines)
4206enddef
4207
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004208" Test for accessing a private member outside a class in a def function
4209def Test_private_member_access_outside_class()
4210 # private object member variable
4211 var lines =<< trim END
4212 vim9script
4213 class A
4214 this._val = 10
4215 def GetVal(): number
4216 return this._val
4217 enddef
4218 endclass
4219 def T()
4220 var a = A.new()
4221 a._val = 20
4222 enddef
4223 T()
4224 END
4225 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4226
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004227 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004228 lines =<< trim END
4229 vim9script
4230 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004231 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004232 endclass
4233 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004234 var a = A.new()
4235 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004236 enddef
4237 T()
4238 END
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004239 v9.CheckScriptFailure(lines, 'E1089: Unknown variable: _a = 1')
Ernie Rael18143d32023-09-04 22:30:41 +02004240
4241 # private static member variable
4242 lines =<< trim END
4243 vim9script
4244 class A
4245 static _val = 10
4246 endclass
4247 def T()
4248 var a = A.new()
4249 var x = a._val
4250 enddef
4251 T()
4252 END
4253 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4254
4255 # private static member variable
4256 lines =<< trim END
4257 vim9script
4258 class A
4259 static _val = 10
4260 endclass
4261 def T()
4262 var a = A.new()
4263 a._val = 3
4264 enddef
4265 T()
4266 END
4267 # TODO: wrong error, should be about private member
4268 v9.CheckScriptFailure(lines, 'E1089: Unknown variable')
4269
4270 # private static class variable
4271 lines =<< trim END
4272 vim9script
4273 class A
4274 static _val = 10
4275 endclass
4276 def T()
4277 var x = A._val
4278 enddef
4279 T()
4280 END
4281 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4282
4283 # private static class variable
4284 lines =<< trim END
4285 vim9script
4286 class A
4287 static _val = 10
4288 endclass
4289 def T()
4290 A._val = 3
4291 enddef
4292 T()
4293 END
4294 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4295
4296
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004297enddef
4298
4299" Test for changing the member access of an interface in a implementation class
4300def Test_change_interface_member_access()
4301 var lines =<< trim END
4302 vim9script
4303 interface A
4304 public this.val: number
4305 endinterface
4306 class B implements A
4307 this.val = 10
4308 endclass
4309 END
4310 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
4311
4312 lines =<< trim END
4313 vim9script
4314 interface A
4315 this.val: number
4316 endinterface
4317 class B implements A
4318 public this.val = 10
4319 endclass
4320 END
4321 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
4322enddef
4323
4324" Test for trying to change a readonly member from a def function
4325def Test_readonly_member_change_in_def_func()
4326 var lines =<< trim END
4327 vim9script
4328 class A
4329 this.val: number
4330 endclass
4331 def T()
4332 var a = A.new()
4333 a.val = 20
4334 enddef
4335 T()
4336 END
4337 v9.CheckScriptFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004338enddef
4339
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004340" Test for reading and writing a class member from a def function
4341def Test_modify_class_member_from_def_function()
4342 var lines =<< trim END
4343 vim9script
4344 class A
4345 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004346 public static var2: list<number> = [1, 2]
4347 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004348 static _priv_var4: number = 40
4349 endclass
4350 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004351 assert_equal([1, 2], A.var2)
4352 assert_equal({a: 1, b: 2}, A.var3)
4353 A.var2 = [3, 4]
4354 A.var3 = {c: 3, d: 4}
4355 assert_equal([3, 4], A.var2)
4356 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004357 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4358 enddef
4359 T()
4360 END
4361 v9.CheckScriptSuccess(lines)
4362enddef
4363
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004364" Test for accessing a class member variable using an object
4365def Test_class_member_access_using_object()
4366 var lines =<< trim END
4367 vim9script
4368 class A
4369 public static svar1: list<number> = [1]
4370 public static svar2: list<number> = [2]
4371 endclass
4372
4373 A.svar1->add(3)
4374 A.svar2->add(4)
4375 assert_equal([1, 3], A.svar1)
4376 assert_equal([2, 4], A.svar2)
4377 var a1 = A.new()
4378 a1.svar1->add(5)
4379 a1.svar2->add(6)
4380 assert_equal([1, 3, 5], a1.svar1)
4381 assert_equal([2, 4, 6], a1.svar2)
4382
4383 def Foo()
4384 A.svar1->add(7)
4385 A.svar2->add(8)
4386 assert_equal([1, 3, 5, 7], A.svar1)
4387 assert_equal([2, 4, 6, 8], A.svar2)
4388 var a2 = A.new()
4389 a2.svar1->add(9)
4390 a2.svar2->add(10)
4391 assert_equal([1, 3, 5, 7, 9], a2.svar1)
4392 assert_equal([2, 4, 6, 8, 10], a2.svar2)
4393 enddef
4394 Foo()
4395 END
4396 v9.CheckScriptSuccess(lines)
4397enddef
4398
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004399" Test for using a interface method using a child object
4400def Test_interface_method_from_child()
4401 var lines =<< trim END
4402 vim9script
4403
4404 interface A
4405 def Foo(): string
4406 endinterface
4407
4408 class B implements A
4409 def Foo(): string
4410 return 'foo'
4411 enddef
4412 endclass
4413
4414 class C extends B
4415 def Bar(): string
4416 return 'bar'
4417 enddef
4418 endclass
4419
4420 def T1(a: A)
4421 assert_equal('foo', a.Foo())
4422 enddef
4423
4424 def T2(b: B)
4425 assert_equal('foo', b.Foo())
4426 enddef
4427
4428 var c = C.new()
4429 T1(c)
4430 T2(c)
4431 END
4432 v9.CheckScriptSuccess(lines)
4433enddef
4434
4435" Test for using an interface method using a child object when it is overridden
4436" by the child class.
4437" FIXME: This test fails.
4438" def Test_interface_overridden_method_from_child()
4439" var lines =<< trim END
4440" vim9script
4441"
4442" interface A
4443" def Foo(): string
4444" endinterface
4445"
4446" class B implements A
4447" def Foo(): string
4448" return 'b-foo'
4449" enddef
4450" endclass
4451"
4452" class C extends B
4453" def Bar(): string
4454" return 'bar'
4455" enddef
4456" def Foo(): string
4457" return 'c-foo'
4458" enddef
4459" endclass
4460"
4461" def T1(a: A)
4462" assert_equal('c-foo', a.Foo())
4463" enddef
4464"
4465" def T2(b: B)
4466" assert_equal('c-foo', b.Foo())
4467" enddef
4468"
4469" var c = C.new()
4470" T1(c)
4471" T2(c)
4472" END
4473" v9.CheckScriptSuccess(lines)
4474" enddef
4475
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004476" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker