blob: bf8f649d6e33a589cd8c0ae302a1e485a074a1ad [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')
Bram Moolenaard505d172022-12-18 21:42:55 +0000936enddef
937
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000938def Test_class_object_compare()
939 var class_lines =<< trim END
940 vim9script
941 class Item
942 this.nr = 0
943 this.name = 'xx'
944 endclass
945 END
946
947 # used at the script level and in a compiled function
948 var test_lines =<< trim END
949 var i1 = Item.new()
950 assert_equal(i1, i1)
951 assert_true(i1 is i1)
952 var i2 = Item.new()
953 assert_equal(i1, i2)
954 assert_false(i1 is i2)
955 var i3 = Item.new(0, 'xx')
956 assert_equal(i1, i3)
957
958 var io1 = Item.new(1, 'xx')
959 assert_notequal(i1, io1)
960 var io2 = Item.new(0, 'yy')
961 assert_notequal(i1, io2)
962 END
963
964 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000965 v9.CheckScriptSuccess(
966 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000967
968 for op in ['>', '>=', '<', '<=', '=~', '!~']
969 var op_lines = [
970 'var i1 = Item.new()',
971 'var i2 = Item.new()',
972 'echo i1 ' .. op .. ' i2',
973 ]
974 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000975 v9.CheckScriptFailure(class_lines
976 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000977 endfor
978enddef
979
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000980def Test_object_type()
981 var lines =<< trim END
982 vim9script
983
984 class One
985 this.one = 1
986 endclass
987 class Two
988 this.two = 2
989 endclass
990 class TwoMore extends Two
991 this.more = 9
992 endclass
993
994 var o: One = One.new()
995 var t: Two = Two.new()
996 var m: TwoMore = TwoMore.new()
997 var tm: Two = TwoMore.new()
998
999 t = m
1000 END
1001 v9.CheckScriptSuccess(lines)
1002
1003 lines =<< trim END
1004 vim9script
1005
1006 class One
1007 this.one = 1
1008 endclass
1009 class Two
1010 this.two = 2
1011 endclass
1012
1013 var o: One = Two.new()
1014 END
1015 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001016
1017 lines =<< trim END
1018 vim9script
1019
1020 interface One
1021 def GetMember(): number
1022 endinterface
1023 class Two implements One
1024 this.one = 1
1025 def GetMember(): number
1026 return this.one
1027 enddef
1028 endclass
1029
1030 var o: One = Two.new(5)
1031 assert_equal(5, o.GetMember())
1032 END
1033 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001034
1035 lines =<< trim END
1036 vim9script
1037
1038 class Num
1039 this.n: number = 0
1040 endclass
1041
1042 def Ref(name: string): func(Num): Num
1043 return (arg: Num): Num => {
1044 return eval(name)(arg)
1045 }
1046 enddef
1047
1048 const Fn = Ref('Double')
1049 var Double = (m: Num): Num => Num.new(m.n * 2)
1050
1051 echo Fn(Num.new(4))
1052 END
1053 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001054enddef
1055
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001056def Test_class_member()
1057 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001058 var lines =<< trim END
1059 vim9script
1060 class TextPos
1061 this.lnum = 1
1062 this.col = 1
1063 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001064 static _secret = 7
1065 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001066
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001067 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001068 counter += nr
1069 enddef
1070 endclass
1071
1072 assert_equal(0, TextPos.counter)
1073 TextPos.AddToCounter(3)
1074 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001075 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001076
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001077 def GetCounter(): number
1078 return TextPos.counter
1079 enddef
1080 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001081
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001082 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001083 assert_fails('TextPos.counter = 5', 'E1335:')
1084 assert_fails('TextPos.counter += 5', 'E1335:')
1085
1086 assert_fails('echo TextPos._secret', 'E1333:')
1087 assert_fails('TextPos._secret = 8', 'E1333:')
1088
1089 assert_equal(42, TextPos.anybody)
1090 TextPos.anybody = 12
1091 assert_equal(12, TextPos.anybody)
1092 TextPos.anybody += 5
1093 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001094 END
1095 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001096
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001097 # example in the help
1098 lines =<< trim END
1099 vim9script
1100 class OtherThing
1101 this.size: number
1102 static totalSize: number
1103
1104 def new(this.size)
1105 totalSize += this.size
1106 enddef
1107 endclass
1108 assert_equal(0, OtherThing.totalSize)
1109 var to3 = OtherThing.new(3)
1110 assert_equal(3, OtherThing.totalSize)
1111 var to7 = OtherThing.new(7)
1112 assert_equal(10, OtherThing.totalSize)
1113 END
1114 v9.CheckScriptSuccess(lines)
1115
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001116 # using static class member twice
1117 lines =<< trim END
1118 vim9script
1119
1120 class HTML
1121 static author: string = 'John Doe'
1122
1123 static def MacroSubstitute(s: string): string
1124 return substitute(s, '{{author}}', author, 'gi')
1125 enddef
1126 endclass
1127
1128 assert_equal('some text', HTML.MacroSubstitute('some text'))
1129 assert_equal('some text', HTML.MacroSubstitute('some text'))
1130 END
1131 v9.CheckScriptSuccess(lines)
1132
Bram Moolenaar62a69232023-01-24 15:07:04 +00001133 # access private member in lambda
1134 lines =<< trim END
1135 vim9script
1136
1137 class Foo
1138 this._x: number = 0
1139
1140 def Add(n: number): number
1141 const F = (): number => this._x + n
1142 return F()
1143 enddef
1144 endclass
1145
1146 var foo = Foo.new()
1147 assert_equal(5, foo.Add(5))
1148 END
1149 v9.CheckScriptSuccess(lines)
1150
h-east2bd6a092023-05-19 19:01:17 +01001151 # access private member in lambda body
1152 lines =<< trim END
1153 vim9script
1154
1155 class Foo
1156 this._x: number = 6
1157
1158 def Add(n: number): number
1159 var Lam = () => {
1160 this._x = this._x + n
1161 }
1162 Lam()
1163 return this._x
1164 enddef
1165 endclass
1166
1167 var foo = Foo.new()
1168 assert_equal(13, foo.Add(7))
1169 END
1170 v9.CheckScriptSuccess(lines)
1171
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001172 # check shadowing
1173 lines =<< trim END
1174 vim9script
1175
1176 class Some
1177 static count = 0
1178 def Method(count: number)
1179 echo count
1180 enddef
1181 endclass
1182
1183 var s = Some.new()
1184 s.Method(7)
1185 END
1186 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
1187
1188 lines =<< trim END
1189 vim9script
1190
1191 class Some
1192 static count = 0
1193 def Method(arg: number)
1194 var count = 3
1195 echo arg count
1196 enddef
1197 endclass
1198
1199 var s = Some.new()
1200 s.Method(7)
1201 END
1202 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001203
1204 # Test for using an invalid type for a member variable
1205 lines =<< trim END
1206 vim9script
1207 class A
1208 this.val: xxx
1209 endclass
1210 END
1211 v9.CheckScriptFailure(lines, 'E1010:')
1212
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001213 # Test for setting a member on a null object
1214 lines =<< trim END
1215 vim9script
1216 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001217 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001218 endclass
1219
1220 def F()
1221 var obj: A
1222 obj.val = ""
1223 enddef
1224 F()
1225 END
1226 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1227
1228 # Test for accessing a member on a null object
1229 lines =<< trim END
1230 vim9script
1231 class A
1232 this.val: string
1233 endclass
1234
1235 def F()
1236 var obj: A
1237 echo obj.val
1238 enddef
1239 F()
1240 END
1241 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1242
1243 # Test for setting a member on a null object, at script level
1244 lines =<< trim END
1245 vim9script
1246 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001247 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001248 endclass
1249
1250 var obj: A
1251 obj.val = ""
1252 END
1253 # FIXME(in source): this should give E1360 as well!
1254 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
1255
1256 # Test for accessing a member on a null object, at script level
1257 lines =<< trim END
1258 vim9script
1259 class A
1260 this.val: string
1261 endclass
1262
1263 var obj: A
1264 echo obj.val
1265 END
1266 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1267
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001268 # Test for no space before or after the '=' when initializing a member
1269 # variable
1270 lines =<< trim END
1271 vim9script
1272 class A
1273 this.val: number= 10
1274 endclass
1275 END
1276 v9.CheckScriptFailure(lines, 'E1004:')
1277 lines =<< trim END
1278 vim9script
1279 class A
1280 this.val: number =10
1281 endclass
1282 END
1283 v9.CheckScriptFailure(lines, 'E1004:')
1284
1285 # Access a non-existing member
1286 lines =<< trim END
1287 vim9script
1288 class A
1289 endclass
1290 var a = A.new()
1291 var v = a.bar
1292 END
1293 v9.CheckScriptFailure(lines, 'E1326:')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001294enddef
1295
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001296func Test_class_garbagecollect()
1297 let lines =<< trim END
1298 vim9script
1299
1300 class Point
1301 this.p = [2, 3]
1302 static pl = ['a', 'b']
1303 static pd = {a: 'a', b: 'b'}
1304 endclass
1305
1306 echo Point.pl Point.pd
1307 call test_garbagecollect_now()
1308 echo Point.pl Point.pd
1309 END
1310 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001311
1312 let lines =<< trim END
1313 vim9script
1314
1315 interface View
1316 endinterface
1317
1318 class Widget
1319 this.view: View
1320 endclass
1321
1322 class MyView implements View
1323 this.widget: Widget
1324
1325 def new()
1326 # this will result in a circular reference to this object
1327 this.widget = Widget.new(this)
1328 enddef
1329 endclass
1330
1331 var view = MyView.new()
1332
1333 # overwrite "view", will be garbage-collected next
1334 view = MyView.new()
1335 test_garbagecollect_now()
1336 END
1337 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001338endfunc
1339
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001340" Test interface garbage collection
1341func Test_interface_garbagecollect()
1342 let lines =<< trim END
1343 vim9script
1344
1345 interface I
1346 static ro_class_var: number
1347 public static rw_class_var: number
1348 static _priv_class_var: number
1349 this.ro_obj_var: number
1350 public this.rw_obj_var: number
1351 this._priv_obj_var: number
1352
1353 static def ClassFoo(): number
1354 static def _ClassBar(): number
1355 def ObjFoo(): number
1356 def _ObjBar(): number
1357 endinterface
1358
1359 class A implements I
1360 static ro_class_var: number = 10
1361 public static rw_class_var: number = 20
1362 static _priv_class_var: number = 30
1363 this.ro_obj_var: number = 40
1364 public this.rw_obj_var: number = 50
1365 this._priv_obj_var: number = 60
1366
1367 static def _ClassBar(): number
1368 return _priv_class_var
1369 enddef
1370
1371 static def ClassFoo(): number
1372 return ro_class_var + rw_class_var + A._ClassBar()
1373 enddef
1374
1375 def _ObjBar(): number
1376 return this._priv_obj_var
1377 enddef
1378
1379 def ObjFoo(): number
1380 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1381 enddef
1382 endclass
1383
1384 assert_equal(60, A.ClassFoo())
1385 var o = A.new()
1386 assert_equal(150, o.ObjFoo())
1387 test_garbagecollect_now()
1388 assert_equal(60, A.ClassFoo())
1389 assert_equal(150, o.ObjFoo())
1390 END
1391 call v9.CheckScriptSuccess(lines)
1392endfunc
1393
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001394def Test_class_function()
1395 var lines =<< trim END
1396 vim9script
1397 class Value
1398 this.value = 0
1399 static objects = 0
1400
1401 def new(v: number)
1402 this.value = v
1403 ++objects
1404 enddef
1405
1406 static def GetCount(): number
1407 return objects
1408 enddef
1409 endclass
1410
1411 assert_equal(0, Value.GetCount())
1412 var v1 = Value.new(2)
1413 assert_equal(1, Value.GetCount())
1414 var v2 = Value.new(7)
1415 assert_equal(2, Value.GetCount())
1416 END
1417 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001418
1419 # Test for cleaning up after a class definition failure when using class
1420 # functions.
1421 lines =<< trim END
1422 vim9script
1423 class A
1424 static def Foo()
1425 enddef
1426 aaa
1427 endclass
1428 END
1429 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001430enddef
1431
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001432def Test_class_defcompile()
1433 var lines =<< trim END
1434 vim9script
1435
1436 class C
1437 def Fo(i: number): string
1438 return i
1439 enddef
1440 endclass
1441
1442 defcompile C.Fo
1443 END
1444 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1445
1446 lines =<< trim END
1447 vim9script
1448
1449 class C
1450 static def Fc(): number
1451 return 'x'
1452 enddef
1453 endclass
1454
1455 defcompile C.Fc
1456 END
1457 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001458
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001459 lines =<< trim END
1460 vim9script
1461
1462 class C
1463 static def new()
1464 enddef
1465 endclass
1466
1467 defcompile C.new
1468 END
1469 v9.CheckScriptFailure(lines, 'E1370: Cannot define a "new" function as static')
1470
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001471 # Trying to compile a function using a non-existing class variable
1472 lines =<< trim END
1473 vim9script
1474 defcompile x.Foo()
1475 END
1476 v9.CheckScriptFailure(lines, 'E475:')
1477
1478 # Trying to compile a function using a variable which is not a class
1479 lines =<< trim END
1480 vim9script
1481 var x: number
1482 defcompile x.Foo()
1483 END
1484 v9.CheckScriptFailure(lines, 'E475:')
1485
1486 # Trying to compile a function without specifying the name
1487 lines =<< trim END
1488 vim9script
1489 class A
1490 endclass
1491 defcompile A.
1492 END
1493 v9.CheckScriptFailure(lines, 'E475:')
1494
1495 # Trying to compile a non-existing class object member function
1496 lines =<< trim END
1497 vim9script
1498 class A
1499 endclass
1500 var a = A.new()
1501 defcompile a.Foo()
1502 END
1503 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001504enddef
1505
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001506def Test_class_object_to_string()
1507 var lines =<< trim END
1508 vim9script
1509 class TextPosition
1510 this.lnum = 1
1511 this.col = 22
1512 endclass
1513
1514 assert_equal("class TextPosition", string(TextPosition))
1515
1516 var pos = TextPosition.new()
1517 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1518 END
1519 v9.CheckScriptSuccess(lines)
1520enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001521
Bram Moolenaar554d0312023-01-05 19:59:18 +00001522def Test_interface_basics()
1523 var lines =<< trim END
1524 vim9script
1525 interface Something
1526 this.value: string
1527 static count: number
1528 def GetCount(): number
1529 endinterface
1530 END
1531 v9.CheckScriptSuccess(lines)
1532
1533 lines =<< trim END
1534 interface SomethingWrong
1535 static count = 7
1536 endinterface
1537 END
1538 v9.CheckScriptFailure(lines, 'E1342:')
1539
1540 lines =<< trim END
1541 vim9script
1542
1543 interface Some
1544 static count: number
1545 def Method(count: number)
1546 endinterface
1547 END
h-east61378a12023-04-18 19:07:29 +01001548 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001549
1550 lines =<< trim END
1551 vim9script
1552
1553 interface Some
1554 this.value: number
1555 def Method(value: number)
1556 endinterface
1557 END
h-east61378a12023-04-18 19:07:29 +01001558 # The argument name and the object member name are the same, but this is not a
1559 # problem because object members are always accessed with the "this." prefix.
1560 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001561
1562 lines =<< trim END
1563 vim9script
1564 interface somethingWrong
1565 static count = 7
1566 endinterface
1567 END
1568 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1569
1570 lines =<< trim END
1571 vim9script
1572 interface SomethingWrong
1573 this.value: string
1574 static count = 7
1575 def GetCount(): number
1576 endinterface
1577 END
1578 v9.CheckScriptFailure(lines, 'E1344:')
1579
1580 lines =<< trim END
1581 vim9script
1582 interface SomethingWrong
1583 this.value: string
1584 static count: number
1585 def GetCount(): number
1586 return 5
1587 enddef
1588 endinterface
1589 END
1590 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001591
1592 lines =<< trim END
1593 vim9script
1594 export interface EnterExit
1595 def Enter(): void
1596 def Exit(): void
1597 endinterface
1598 END
1599 writefile(lines, 'XdefIntf.vim', 'D')
1600
1601 lines =<< trim END
1602 vim9script
1603 import './XdefIntf.vim' as defIntf
1604 export def With(ee: defIntf.EnterExit, F: func)
1605 ee.Enter()
1606 try
1607 F()
1608 finally
1609 ee.Exit()
1610 endtry
1611 enddef
1612 END
1613 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001614
1615 var imported =<< trim END
1616 vim9script
1617 export abstract class EnterExit
1618 def Enter(): void
1619 enddef
1620 def Exit(): void
1621 enddef
1622 endclass
1623 END
1624 writefile(imported, 'XdefIntf2.vim', 'D')
1625
1626 lines[1] = " import './XdefIntf2.vim' as defIntf"
1627 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001628enddef
1629
Bram Moolenaar94674f22023-01-06 18:42:20 +00001630def Test_class_implements_interface()
1631 var lines =<< trim END
1632 vim9script
1633
1634 interface Some
1635 static count: number
1636 def Method(nr: number)
1637 endinterface
1638
1639 class SomeImpl implements Some
1640 static count: number
1641 def Method(nr: number)
1642 echo nr
1643 enddef
1644 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001645
1646 interface Another
1647 this.member: string
1648 endinterface
1649
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001650 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001651 this.member = 'abc'
1652 static count: number
1653 def Method(nr: number)
1654 echo nr
1655 enddef
1656 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001657 END
1658 v9.CheckScriptSuccess(lines)
1659
1660 lines =<< trim END
1661 vim9script
1662
1663 interface Some
1664 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001665 endinterface
1666
1667 class SomeImpl implements Some implements Some
1668 static count: number
1669 endclass
1670 END
1671 v9.CheckScriptFailure(lines, 'E1350:')
1672
1673 lines =<< trim END
1674 vim9script
1675
1676 interface Some
1677 static counter: number
1678 endinterface
1679
1680 class SomeImpl implements Some, Some
1681 static count: number
1682 endclass
1683 END
1684 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1685
1686 lines =<< trim END
1687 vim9script
1688
1689 interface Some
1690 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001691 def Method(nr: number)
1692 endinterface
1693
1694 class SomeImpl implements Some
1695 static count: number
1696 def Method(nr: number)
1697 echo nr
1698 enddef
1699 endclass
1700 END
1701 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1702
1703 lines =<< trim END
1704 vim9script
1705
1706 interface Some
1707 static count: number
1708 def Methods(nr: number)
1709 endinterface
1710
1711 class SomeImpl implements Some
1712 static count: number
1713 def Method(nr: number)
1714 echo nr
1715 enddef
1716 endclass
1717 END
1718 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001719
1720 # Check different order of members in class and interface works.
1721 lines =<< trim END
1722 vim9script
1723
1724 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001725 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001726 this.errpos: number
1727 endinterface
1728
1729 # order of members is opposite of interface
1730 class Failure implements Result
1731 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001732 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001733 endclass
1734
1735 def Test()
1736 var result: Result = Failure.new()
1737
1738 assert_equal('label', result.label)
1739 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001740
1741 result.label = 'different'
1742 assert_equal('different', result.label)
1743 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001744 enddef
1745
1746 Test()
1747 END
1748 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001749
1750 # Interface name after "extends" doesn't end in a space or NUL character
1751 lines =<< trim END
1752 vim9script
1753 interface A
1754 endinterface
1755 class B extends A"
1756 endclass
1757 END
1758 v9.CheckScriptFailure(lines, 'E1315:')
1759
1760 # Trailing characters after a class name
1761 lines =<< trim END
1762 vim9script
1763 class A bbb
1764 endclass
1765 END
1766 v9.CheckScriptFailure(lines, 'E488:')
1767
1768 # using "implements" with a non-existing class
1769 lines =<< trim END
1770 vim9script
1771 class A implements B
1772 endclass
1773 END
1774 v9.CheckScriptFailure(lines, 'E1346:')
1775
1776 # using "implements" with a regular class
1777 lines =<< trim END
1778 vim9script
1779 class A
1780 endclass
1781 class B implements A
1782 endclass
1783 END
1784 v9.CheckScriptFailure(lines, 'E1347:')
1785
1786 # using "implements" with a variable
1787 lines =<< trim END
1788 vim9script
1789 var T: number = 10
1790 class A implements T
1791 endclass
1792 END
1793 v9.CheckScriptFailure(lines, 'E1347:')
1794
1795 # all the class methods in an "interface" should be implemented
1796 lines =<< trim END
1797 vim9script
1798 interface A
1799 static def Foo()
1800 endinterface
1801 class B implements A
1802 endclass
1803 END
1804 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001805
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02001806 # implements should be followed by a white space
1807 lines =<< trim END
1808 vim9script
1809 interface A
1810 endinterface
1811 class B implements A;
1812 endclass
1813 END
1814 v9.CheckScriptFailure(lines, 'E1315:')
1815
LemonBoyc5d27442023-08-19 13:02:35 +02001816 lines =<< trim END
1817 vim9script
1818
1819 interface One
1820 static matching: bool
1821 static as_any: any
1822 static not_matching: number
1823 endinterface
1824 class Two implements One
1825 static not_matching: string
1826 static as_any: string
1827 static matching: bool
1828 endclass
1829 END
1830 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1831
1832 lines =<< trim END
1833 vim9script
1834
1835 interface One
1836 def IsEven(nr: number): bool
1837 endinterface
1838 class Two implements One
1839 def IsEven(nr: number): string
1840 enddef
1841 endclass
1842 END
1843 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1844
1845 lines =<< trim END
1846 vim9script
1847
1848 interface One
1849 def IsEven(nr: number): bool
1850 endinterface
1851 class Two implements One
1852 def IsEven(nr: bool): bool
1853 enddef
1854 endclass
1855 END
1856 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1857
1858 lines =<< trim END
1859 vim9script
1860
1861 interface One
1862 def IsEven(nr: number): bool
1863 endinterface
1864 class Two implements One
1865 def IsEven(nr: number, ...extra: list<number>): bool
1866 enddef
1867 endclass
1868 END
1869 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
Bram Moolenaar94674f22023-01-06 18:42:20 +00001870enddef
1871
Bram Moolenaard0200c82023-01-28 15:19:40 +00001872def Test_call_interface_method()
1873 var lines =<< trim END
1874 vim9script
1875 interface Base
1876 def Enter(): void
1877 endinterface
1878
1879 class Child implements Base
1880 def Enter(): void
1881 g:result ..= 'child'
1882 enddef
1883 endclass
1884
1885 def F(obj: Base)
1886 obj.Enter()
1887 enddef
1888
1889 g:result = ''
1890 F(Child.new())
1891 assert_equal('child', g:result)
1892 unlet g:result
1893 END
1894 v9.CheckScriptSuccess(lines)
1895
1896 lines =<< trim END
1897 vim9script
1898 class Base
1899 def Enter(): void
1900 g:result ..= 'base'
1901 enddef
1902 endclass
1903
1904 class Child extends Base
1905 def Enter(): void
1906 g:result ..= 'child'
1907 enddef
1908 endclass
1909
1910 def F(obj: Base)
1911 obj.Enter()
1912 enddef
1913
1914 g:result = ''
1915 F(Child.new())
1916 assert_equal('child', g:result)
1917 unlet g:result
1918 END
1919 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001920
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001921 # method of interface returns a value
1922 lines =<< trim END
1923 vim9script
1924 interface Base
1925 def Enter(): string
1926 endinterface
1927
1928 class Child implements Base
1929 def Enter(): string
1930 g:result ..= 'child'
1931 return "/resource"
1932 enddef
1933 endclass
1934
1935 def F(obj: Base)
1936 var r = obj.Enter()
1937 g:result ..= r
1938 enddef
1939
1940 g:result = ''
1941 F(Child.new())
1942 assert_equal('child/resource', g:result)
1943 unlet g:result
1944 END
1945 v9.CheckScriptSuccess(lines)
1946
1947 lines =<< trim END
1948 vim9script
1949 class Base
1950 def Enter(): string
1951 return null_string
1952 enddef
1953 endclass
1954
1955 class Child extends Base
1956 def Enter(): string
1957 g:result ..= 'child'
1958 return "/resource"
1959 enddef
1960 endclass
1961
1962 def F(obj: Base)
1963 var r = obj.Enter()
1964 g:result ..= r
1965 enddef
1966
1967 g:result = ''
1968 F(Child.new())
1969 assert_equal('child/resource', g:result)
1970 unlet g:result
1971 END
1972 v9.CheckScriptSuccess(lines)
1973
1974
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001975 # No class that implements the interface.
1976 lines =<< trim END
1977 vim9script
1978
1979 interface IWithEE
1980 def Enter(): any
1981 def Exit(): void
1982 endinterface
1983
1984 def With1(ee: IWithEE, F: func)
1985 var r = ee.Enter()
1986 enddef
1987
1988 defcompile
1989 END
1990 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001991enddef
1992
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001993def Test_class_used_as_type()
1994 var lines =<< trim END
1995 vim9script
1996
1997 class Point
1998 this.x = 0
1999 this.y = 0
2000 endclass
2001
2002 var p: Point
2003 p = Point.new(2, 33)
2004 assert_equal(2, p.x)
2005 assert_equal(33, p.y)
2006 END
2007 v9.CheckScriptSuccess(lines)
2008
2009 lines =<< trim END
2010 vim9script
2011
2012 interface HasX
2013 this.x: number
2014 endinterface
2015
2016 class Point implements HasX
2017 this.x = 0
2018 this.y = 0
2019 endclass
2020
2021 var p: Point
2022 p = Point.new(2, 33)
2023 var hx = p
2024 assert_equal(2, hx.x)
2025 END
2026 v9.CheckScriptSuccess(lines)
2027
2028 lines =<< trim END
2029 vim9script
2030
2031 class Point
2032 this.x = 0
2033 this.y = 0
2034 endclass
2035
2036 var p: Point
2037 p = 'text'
2038 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002039 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002040enddef
2041
Bram Moolenaar83677162023-01-08 19:54:10 +00002042def Test_class_extends()
2043 var lines =<< trim END
2044 vim9script
2045 class Base
2046 this.one = 1
2047 def GetOne(): number
2048 return this.one
2049 enddef
2050 endclass
2051 class Child extends Base
2052 this.two = 2
2053 def GetTotal(): number
2054 return this.one + this.two
2055 enddef
2056 endclass
2057 var o = Child.new()
2058 assert_equal(1, o.one)
2059 assert_equal(2, o.two)
2060 assert_equal(1, o.GetOne())
2061 assert_equal(3, o.GetTotal())
2062 END
2063 v9.CheckScriptSuccess(lines)
2064
2065 lines =<< trim END
2066 vim9script
2067 class Base
2068 this.one = 1
2069 endclass
2070 class Child extends Base
2071 this.two = 2
2072 endclass
2073 var o = Child.new(3, 44)
2074 assert_equal(3, o.one)
2075 assert_equal(44, o.two)
2076 END
2077 v9.CheckScriptSuccess(lines)
2078
2079 lines =<< trim END
2080 vim9script
2081 class Base
2082 this.one = 1
2083 endclass
2084 class Child extends Base extends Base
2085 this.two = 2
2086 endclass
2087 END
2088 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
2089
2090 lines =<< trim END
2091 vim9script
2092 class Child extends BaseClass
2093 this.two = 2
2094 endclass
2095 END
2096 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
2097
2098 lines =<< trim END
2099 vim9script
2100 var SomeVar = 99
2101 class Child extends SomeVar
2102 this.two = 2
2103 endclass
2104 END
2105 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002106
2107 lines =<< trim END
2108 vim9script
2109 class Base
2110 this.name: string
2111 def ToString(): string
2112 return this.name
2113 enddef
2114 endclass
2115
2116 class Child extends Base
2117 this.age: number
2118 def ToString(): string
2119 return super.ToString() .. ': ' .. this.age
2120 enddef
2121 endclass
2122
2123 var o = Child.new('John', 42)
2124 assert_equal('John: 42', o.ToString())
2125 END
2126 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002127
2128 lines =<< trim END
2129 vim9script
2130 class Child
2131 this.age: number
2132 def ToString(): number
2133 return this.age
2134 enddef
2135 def ToString(): string
2136 return this.age
2137 enddef
2138 endclass
2139 END
2140 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
2141
2142 lines =<< trim END
2143 vim9script
2144 class Child
2145 this.age: number
2146 def ToString(): string
2147 return super .ToString() .. ': ' .. this.age
2148 enddef
2149 endclass
2150 var o = Child.new(42)
2151 echo o.ToString()
2152 END
2153 v9.CheckScriptFailure(lines, 'E1356:')
2154
2155 lines =<< trim END
2156 vim9script
2157 class Base
2158 this.name: string
2159 def ToString(): string
2160 return this.name
2161 enddef
2162 endclass
2163
2164 var age = 42
2165 def ToString(): string
2166 return super.ToString() .. ': ' .. age
2167 enddef
2168 echo ToString()
2169 END
2170 v9.CheckScriptFailure(lines, 'E1357:')
2171
2172 lines =<< trim END
2173 vim9script
2174 class Child
2175 this.age: number
2176 def ToString(): string
2177 return super.ToString() .. ': ' .. this.age
2178 enddef
2179 endclass
2180 var o = Child.new(42)
2181 echo o.ToString()
2182 END
2183 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002184
2185 lines =<< trim END
2186 vim9script
2187 class Base
2188 this.name: string
2189 static def ToString(): string
2190 return 'Base class'
2191 enddef
2192 endclass
2193
2194 class Child extends Base
2195 this.age: number
2196 def ToString(): string
2197 return Base.ToString() .. ': ' .. this.age
2198 enddef
2199 endclass
2200
2201 var o = Child.new('John', 42)
2202 assert_equal('Base class: 42', o.ToString())
2203 END
2204 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002205
2206 lines =<< trim END
2207 vim9script
2208 class Base
2209 this.value = 1
2210 def new(init: number)
2211 this.value = number + 1
2212 enddef
2213 endclass
2214 class Child extends Base
2215 def new()
2216 this.new(3)
2217 enddef
2218 endclass
2219 var c = Child.new()
2220 END
2221 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002222
2223 # base class with more than one object member
2224 lines =<< trim END
2225 vim9script
2226
2227 class Result
2228 this.success: bool
2229 this.value: any = null
2230 endclass
2231
2232 class Success extends Result
2233 def new(this.value = v:none)
2234 this.success = true
2235 enddef
2236 endclass
2237
2238 var v = Success.new('asdf')
2239 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2240 END
2241 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002242
2243 # class name after "extends" doesn't end in a space or NUL character
2244 lines =<< trim END
2245 vim9script
2246 class A
2247 endclass
2248 class B extends A"
2249 endclass
2250 END
2251 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002252enddef
2253
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002254def Test_using_base_class()
2255 var lines =<< trim END
2256 vim9script
2257
2258 class BaseEE
2259 def Enter(): any
2260 return null
2261 enddef
2262 def Exit(resource: any): void
2263 enddef
2264 endclass
2265
2266 class ChildEE extends BaseEE
2267 def Enter(): any
2268 return 42
2269 enddef
2270
2271 def Exit(resource: number): void
2272 g:result ..= '/exit'
2273 enddef
2274 endclass
2275
2276 def With(ee: BaseEE)
2277 var r = ee.Enter()
2278 try
2279 g:result ..= r
2280 finally
2281 g:result ..= '/finally'
2282 ee.Exit(r)
2283 endtry
2284 enddef
2285
2286 g:result = ''
2287 With(ChildEE.new())
2288 assert_equal('42/finally/exit', g:result)
2289 END
2290 v9.CheckScriptSuccess(lines)
2291 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002292
2293 # Using super, Child invokes Base method which has optional arg. #12471
2294 lines =<< trim END
2295 vim9script
2296
2297 class Base
2298 this.success: bool = false
2299 def Method(arg = 0)
2300 this.success = true
2301 enddef
2302 endclass
2303
2304 class Child extends Base
2305 def new()
2306 super.Method()
2307 enddef
2308 endclass
2309
2310 var obj = Child.new()
2311 assert_equal(true, obj.success)
2312 END
2313 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002314enddef
2315
2316
Bram Moolenaara86655a2023-01-12 17:06:27 +00002317def Test_class_import()
2318 var lines =<< trim END
2319 vim9script
2320 export class Animal
2321 this.kind: string
2322 this.name: string
2323 endclass
2324 END
2325 writefile(lines, 'Xanimal.vim', 'D')
2326
2327 lines =<< trim END
2328 vim9script
2329 import './Xanimal.vim' as animal
2330
2331 var a: animal.Animal
2332 a = animal.Animal.new('fish', 'Eric')
2333 assert_equal('fish', a.kind)
2334 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002335
2336 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2337 assert_equal('cat', b.kind)
2338 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002339 END
2340 v9.CheckScriptSuccess(lines)
2341enddef
2342
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002343def Test_abstract_class()
2344 var lines =<< trim END
2345 vim9script
2346 abstract class Base
2347 this.name: string
2348 endclass
2349 class Person extends Base
2350 this.age: number
2351 endclass
2352 var p: Base = Person.new('Peter', 42)
2353 assert_equal('Peter', p.name)
2354 assert_equal(42, p.age)
2355 END
2356 v9.CheckScriptSuccess(lines)
2357
2358 lines =<< trim END
2359 vim9script
2360 abstract class Base
2361 this.name: string
2362 endclass
2363 class Person extends Base
2364 this.age: number
2365 endclass
2366 var p = Base.new('Peter')
2367 END
2368 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2369
2370 lines =<< trim END
2371 abstract class Base
2372 this.name: string
2373 endclass
2374 END
2375 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002376
2377 # Abstract class cannot have a "new" function
2378 lines =<< trim END
2379 vim9script
2380 abstract class Base
2381 def new()
2382 enddef
2383 endclass
2384 END
2385 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002386enddef
2387
Bram Moolenaar486fc252023-01-18 14:51:07 +00002388def Test_closure_in_class()
2389 var lines =<< trim END
2390 vim9script
2391
2392 class Foo
2393 this.y: list<string> = ['B']
2394
2395 def new()
2396 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2397 enddef
2398 endclass
2399
2400 Foo.new()
2401 assert_equal(['A'], g:result)
2402 END
2403 v9.CheckScriptSuccess(lines)
2404enddef
2405
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002406def Test_call_constructor_from_legacy()
2407 var lines =<< trim END
2408 vim9script
2409
2410 var newCalled = 'false'
2411
2412 class A
2413 def new()
2414 newCalled = 'true'
2415 enddef
2416 endclass
2417
2418 export def F(options = {}): any
2419 return A
2420 enddef
2421
2422 g:p = F()
2423 legacy call p.new()
2424 assert_equal('true', newCalled)
2425 END
2426 v9.CheckScriptSuccess(lines)
2427enddef
2428
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002429def Test_defer_with_object()
2430 var lines =<< trim END
2431 vim9script
2432
2433 class CWithEE
2434 def Enter()
2435 g:result ..= "entered/"
2436 enddef
2437 def Exit()
2438 g:result ..= "exited"
2439 enddef
2440 endclass
2441
2442 def With(ee: CWithEE, F: func)
2443 ee.Enter()
2444 defer ee.Exit()
2445 F()
2446 enddef
2447
2448 g:result = ''
2449 var obj = CWithEE.new()
2450 obj->With(() => {
2451 g:result ..= "called/"
2452 })
2453 assert_equal('entered/called/exited', g:result)
2454 END
2455 v9.CheckScriptSuccess(lines)
2456 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002457
2458 lines =<< trim END
2459 vim9script
2460
2461 class BaseWithEE
2462 def Enter()
2463 g:result ..= "entered-base/"
2464 enddef
2465 def Exit()
2466 g:result ..= "exited-base"
2467 enddef
2468 endclass
2469
2470 class CWithEE extends BaseWithEE
2471 def Enter()
2472 g:result ..= "entered-child/"
2473 enddef
2474 def Exit()
2475 g:result ..= "exited-child"
2476 enddef
2477 endclass
2478
2479 def With(ee: BaseWithEE, F: func)
2480 ee.Enter()
2481 defer ee.Exit()
2482 F()
2483 enddef
2484
2485 g:result = ''
2486 var obj = CWithEE.new()
2487 obj->With(() => {
2488 g:result ..= "called/"
2489 })
2490 assert_equal('entered-child/called/exited-child', g:result)
2491 END
2492 v9.CheckScriptSuccess(lines)
2493 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002494enddef
2495
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002496" The following test used to crash Vim (Github issue #12676)
2497def Test_extends_method_crashes_vim()
2498 var lines =<< trim END
2499 vim9script
2500
2501 class Observer
2502 endclass
2503
2504 class Property
2505 this.value: any
2506
2507 def Set(v: any)
2508 if v != this.value
2509 this.value = v
2510 endif
2511 enddef
2512
2513 def Register(observer: Observer)
2514 enddef
2515 endclass
2516
2517 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002518 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002519 endclass
2520
2521 def Observe(obj: Property, who: Observer)
2522 obj.Register(who)
2523 enddef
2524
2525 var p = Bool.new(false)
2526 var myObserver = Observer.new()
2527
2528 Observe(p, myObserver)
2529
2530 p.Set(true)
2531 END
2532 v9.CheckScriptSuccess(lines)
2533enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002534
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002535" Test for calling a method in a class that is extended
2536def Test_call_method_in_extended_class()
2537 var lines =<< trim END
2538 vim9script
2539
2540 var prop_init_called = false
2541 var prop_register_called = false
2542
2543 class Property
2544 def Init()
2545 prop_init_called = true
2546 enddef
2547
2548 def Register()
2549 prop_register_called = true
2550 enddef
2551 endclass
2552
2553 class Bool extends Property
2554 endclass
2555
2556 def Observe(obj: Property)
2557 obj.Register()
2558 enddef
2559
2560 var p = Property.new()
2561 Observe(p)
2562
2563 p.Init()
2564 assert_true(prop_init_called)
2565 assert_true(prop_register_called)
2566 END
2567 v9.CheckScriptSuccess(lines)
2568enddef
2569
LemonBoyafe04662023-08-23 21:08:11 +02002570def Test_instanceof()
2571 var lines =<< trim END
2572 vim9script
2573
2574 class Base1
2575 endclass
2576
2577 class Base2 extends Base1
2578 endclass
2579
2580 interface Intf1
2581 endinterface
2582
2583 class Mix1 implements Intf1
2584 endclass
2585
2586 class Base3 extends Mix1
2587 endclass
2588
2589 var b1 = Base1.new()
2590 var b2 = Base2.new()
2591 var b3 = Base3.new()
2592
2593 assert_true(instanceof(b1, Base1))
2594 assert_true(instanceof(b2, Base1))
2595 assert_false(instanceof(b1, Base2))
2596 assert_true(instanceof(b3, Mix1))
2597 assert_false(instanceof(b3, []))
2598 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002599
2600 def Foo()
2601 var a1 = Base1.new()
2602 var a2 = Base2.new()
2603 var a3 = Base3.new()
2604
2605 assert_true(instanceof(a1, Base1))
2606 assert_true(instanceof(a2, Base1))
2607 assert_false(instanceof(a1, Base2))
2608 assert_true(instanceof(a3, Mix1))
2609 assert_false(instanceof(a3, []))
2610 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2611 enddef
2612 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002613 END
2614 v9.CheckScriptSuccess(lines)
2615enddef
2616
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002617" Test for calling a method in the parent class that is extended partially.
2618" This used to fail with the 'E118: Too many arguments for function: Text' error
2619" message (Github issue #12524).
2620def Test_call_method_in_parent_class()
2621 var lines =<< trim END
2622 vim9script
2623
2624 class Widget
2625 this._lnum: number = 1
2626
2627 def SetY(lnum: number)
2628 this._lnum = lnum
2629 enddef
2630
2631 def Text(): string
2632 return ''
2633 enddef
2634 endclass
2635
2636 class Foo extends Widget
2637 def Text(): string
2638 return '<Foo>'
2639 enddef
2640 endclass
2641
2642 def Stack(w1: Widget, w2: Widget): list<Widget>
2643 w1.SetY(1)
2644 w2.SetY(2)
2645 return [w1, w2]
2646 enddef
2647
2648 var foo1 = Foo.new()
2649 var foo2 = Foo.new()
2650 var l = Stack(foo1, foo2)
2651 END
2652 v9.CheckScriptSuccess(lines)
2653enddef
2654
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002655" Test for calling methods from three levels of classes
2656def Test_multi_level_method_call()
2657 var lines =<< trim END
2658 vim9script
2659
2660 var A_func1: number = 0
2661 var A_func2: number = 0
2662 var A_func3: number = 0
2663 var B_func2: number = 0
2664 var B_func3: number = 0
2665 var C_func3: number = 0
2666
2667 class A
2668 def Func1()
2669 A_func1 += 1
2670 enddef
2671
2672 def Func2()
2673 A_func2 += 1
2674 enddef
2675
2676 def Func3()
2677 A_func3 += 1
2678 enddef
2679 endclass
2680
2681 class B extends A
2682 def Func2()
2683 B_func2 += 1
2684 enddef
2685
2686 def Func3()
2687 B_func3 += 1
2688 enddef
2689 endclass
2690
2691 class C extends B
2692 def Func3()
2693 C_func3 += 1
2694 enddef
2695 endclass
2696
2697 def A_CallFuncs(a: A)
2698 a.Func1()
2699 a.Func2()
2700 a.Func3()
2701 enddef
2702
2703 def B_CallFuncs(b: B)
2704 b.Func1()
2705 b.Func2()
2706 b.Func3()
2707 enddef
2708
2709 def C_CallFuncs(c: C)
2710 c.Func1()
2711 c.Func2()
2712 c.Func3()
2713 enddef
2714
2715 var cobj = C.new()
2716 A_CallFuncs(cobj)
2717 B_CallFuncs(cobj)
2718 C_CallFuncs(cobj)
2719 assert_equal(3, A_func1)
2720 assert_equal(0, A_func2)
2721 assert_equal(0, A_func3)
2722 assert_equal(3, B_func2)
2723 assert_equal(0, B_func3)
2724 assert_equal(3, C_func3)
2725 END
2726 v9.CheckScriptSuccess(lines)
2727enddef
2728
2729" Test for using members from three levels of classes
2730def Test_multi_level_member_access()
2731 var lines =<< trim END
2732 vim9script
2733
2734 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002735 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002736 endclass
2737
2738 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002739 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002740 endclass
2741
2742 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002743 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002744 endclass
2745
2746 def A_members(a: A)
2747 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002748 enddef
2749
2750 def B_members(b: B)
2751 b.val1 += 1
2752 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002753 enddef
2754
2755 def C_members(c: C)
2756 c.val1 += 1
2757 c.val2 += 1
2758 c.val3 += 1
2759 enddef
2760
2761 var cobj = C.new()
2762 A_members(cobj)
2763 B_members(cobj)
2764 C_members(cobj)
2765 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002766 assert_equal(2, cobj.val2)
2767 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002768 END
2769 v9.CheckScriptSuccess(lines)
2770enddef
2771
LemonBoy0ffc17a2023-08-20 18:09:11 +02002772" Test expansion of <stack> with class methods.
2773def Test_stack_expansion_with_methods()
2774 var lines =<< trim END
2775 vim9script
2776
2777 class C
2778 def M1()
2779 F0()
2780 enddef
2781 endclass
2782
2783 def F0()
2784 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2785 enddef
2786
2787 def F()
2788 C.new().M1()
2789 enddef
2790
2791 F()
2792 END
2793 v9.CheckScriptSuccess(lines)
2794enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002795
2796" Test the return type of the new() constructor
2797def Test_new_return_type()
2798 # new() uses the default return type and there is no return statement
2799 var lines =<< trim END
2800 vim9script
2801
2802 class C
2803 this._bufnr: number
2804
2805 def new(this._bufnr)
2806 if !bufexists(this._bufnr)
2807 this._bufnr = -1
2808 endif
2809 enddef
2810 endclass
2811
2812 var c = C.new(12345)
2813 assert_equal('object<C>', typename(c))
2814
2815 var v1: C
2816 v1 = C.new(12345)
2817 assert_equal('object<C>', typename(v1))
2818
2819 def F()
2820 var v2: C
2821 v2 = C.new(12345)
2822 assert_equal('object<C>', typename(v2))
2823 enddef
2824 F()
2825 END
2826 v9.CheckScriptSuccess(lines)
2827
2828 # new() uses the default return type and an empty 'return' statement
2829 lines =<< trim END
2830 vim9script
2831
2832 class C
2833 this._bufnr: number
2834
2835 def new(this._bufnr)
2836 if !bufexists(this._bufnr)
2837 this._bufnr = -1
2838 return
2839 endif
2840 enddef
2841 endclass
2842
2843 var c = C.new(12345)
2844 assert_equal('object<C>', typename(c))
2845
2846 var v1: C
2847 v1 = C.new(12345)
2848 assert_equal('object<C>', typename(v1))
2849
2850 def F()
2851 var v2: C
2852 v2 = C.new(12345)
2853 assert_equal('object<C>', typename(v2))
2854 enddef
2855 F()
2856 END
2857 v9.CheckScriptSuccess(lines)
2858
2859 # new() uses "any" return type and returns "this"
2860 lines =<< trim END
2861 vim9script
2862
2863 class C
2864 this._bufnr: number
2865
2866 def new(this._bufnr): any
2867 if !bufexists(this._bufnr)
2868 this._bufnr = -1
2869 return this
2870 endif
2871 enddef
2872 endclass
2873 END
2874 v9.CheckScriptFailure(lines, 'E1365:')
2875
2876 # new() uses 'Dict' return type and returns a Dict
2877 lines =<< trim END
2878 vim9script
2879
2880 class C
2881 this._state: dict<any>
2882
2883 def new(): dict<any>
2884 this._state = {}
2885 return this._state
2886 enddef
2887 endclass
2888
2889 var c = C.new()
2890 assert_equal('object<C>', typename(c))
2891 END
2892 v9.CheckScriptFailure(lines, 'E1365:')
2893enddef
2894
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02002895" Test for checking a member initialization type at run time.
2896def Test_runtime_type_check_for_member_init()
2897 var lines =<< trim END
2898 vim9script
2899
2900 var retnum: bool = false
2901
2902 def F(): any
2903 retnum = !retnum
2904 if retnum
2905 return 1
2906 else
2907 return "hello"
2908 endif
2909 enddef
2910
2911 class C
2912 this._foo: bool = F()
2913 endclass
2914
2915 var c1 = C.new()
2916 var c2 = C.new()
2917 END
2918 v9.CheckScriptFailure(lines, 'E1012:')
2919enddef
2920
2921" Test for locking a variable referring to an object and reassigning to another
2922" object.
2923def Test_object_lockvar()
2924 var lines =<< trim END
2925 vim9script
2926
2927 class C
2928 this.val: number
2929 def new(this.val)
2930 enddef
2931 endclass
2932
2933 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
2934 lockvar 2 some_dict
2935
2936 var current: C
2937 current = some_dict['c']
2938 assert_equal(3, current.val)
2939 current = some_dict['b']
2940 assert_equal(2, current.val)
2941
2942 def F()
2943 current = some_dict['c']
2944 enddef
2945
2946 def G()
2947 current = some_dict['b']
2948 enddef
2949
2950 F()
2951 assert_equal(3, current.val)
2952 G()
2953 assert_equal(2, current.val)
2954 END
2955 v9.CheckScriptSuccess(lines)
2956enddef
2957
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02002958" Test for a private object method
2959def Test_private_object_method()
2960 # Try calling a private method using an object (at the script level)
2961 var lines =<< trim END
2962 vim9script
2963
2964 class A
2965 def _Foo(): number
2966 return 1234
2967 enddef
2968 endclass
2969 var a = A.new()
2970 a._Foo()
2971 END
2972 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2973
2974 # Try calling a private method using an object (from a def function)
2975 lines =<< trim END
2976 vim9script
2977
2978 class A
2979 def _Foo(): number
2980 return 1234
2981 enddef
2982 endclass
2983 def T()
2984 var a = A.new()
2985 a._Foo()
2986 enddef
2987 T()
2988 END
2989 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2990
2991 # Use a private method from another object method (in script context)
2992 lines =<< trim END
2993 vim9script
2994
2995 class A
2996 def _Foo(): number
2997 return 1234
2998 enddef
2999 def Bar(): number
3000 return this._Foo()
3001 enddef
3002 endclass
3003 var a = A.new()
3004 assert_equal(1234, a.Bar())
3005 END
3006 v9.CheckScriptSuccess(lines)
3007
3008 # Use a private method from another object method (def function context)
3009 lines =<< trim END
3010 vim9script
3011
3012 class A
3013 def _Foo(): number
3014 return 1234
3015 enddef
3016 def Bar(): number
3017 return this._Foo()
3018 enddef
3019 endclass
3020 def T()
3021 var a = A.new()
3022 assert_equal(1234, a.Bar())
3023 enddef
3024 T()
3025 END
3026 v9.CheckScriptSuccess(lines)
3027
3028 # Try calling a private method without the "this" prefix
3029 lines =<< trim END
3030 vim9script
3031
3032 class A
3033 def _Foo(): number
3034 return 1234
3035 enddef
3036 def Bar(): number
3037 return _Foo()
3038 enddef
3039 endclass
3040 var a = A.new()
3041 a.Bar()
3042 END
3043 v9.CheckScriptFailure(lines, 'E117: Unknown function: _Foo')
3044
3045 # Try calling a private method using the class name
3046 lines =<< trim END
3047 vim9script
3048
3049 class A
3050 def _Foo(): number
3051 return 1234
3052 enddef
3053 endclass
3054 A._Foo()
3055 END
3056 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3057
3058 # Try to use "public" keyword when defining a private method
3059 lines =<< trim END
3060 vim9script
3061
3062 class A
3063 public def _Foo()
3064 enddef
3065 endclass
3066 var a = A.new()
3067 a._Foo()
3068 END
3069 v9.CheckScriptFailure(lines, 'E1331: Public must be followed by "this" or "static"')
3070
3071 # Define two private methods with the same name
3072 lines =<< trim END
3073 vim9script
3074
3075 class A
3076 def _Foo()
3077 enddef
3078 def _Foo()
3079 enddef
3080 endclass
3081 var a = A.new()
3082 END
3083 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3084
3085 # Define a private method and a object method with the same name
3086 lines =<< trim END
3087 vim9script
3088
3089 class A
3090 def _Foo()
3091 enddef
3092 def Foo()
3093 enddef
3094 endclass
3095 var a = A.new()
3096 END
3097 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3098
3099 # Define an object method and a private method with the same name
3100 lines =<< trim END
3101 vim9script
3102
3103 class A
3104 def Foo()
3105 enddef
3106 def _Foo()
3107 enddef
3108 endclass
3109 var a = A.new()
3110 END
3111 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3112
3113 # Call a public method and a private method from a private method
3114 lines =<< trim END
3115 vim9script
3116
3117 class A
3118 def Foo(): number
3119 return 100
3120 enddef
3121 def _Bar(): number
3122 return 200
3123 enddef
3124 def _Baz()
3125 assert_equal(100, this.Foo())
3126 assert_equal(200, this._Bar())
3127 enddef
3128 def T()
3129 this._Baz()
3130 enddef
3131 endclass
3132 var a = A.new()
3133 a.T()
3134 END
3135 v9.CheckScriptSuccess(lines)
3136
3137 # Try calling a private method from another class
3138 lines =<< trim END
3139 vim9script
3140
3141 class A
3142 def _Foo(): number
3143 return 100
3144 enddef
3145 endclass
3146 class B
3147 def Foo(): number
3148 var a = A.new()
3149 a._Foo()
3150 enddef
3151 endclass
3152 var b = B.new()
3153 b.Foo()
3154 END
3155 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3156
3157 # Call a private object method from a child class object method
3158 lines =<< trim END
3159 vim9script
3160 class A
3161 def _Foo(): number
3162 return 1234
3163 enddef
3164 endclass
3165 class B extends A
3166 def Bar()
3167 enddef
3168 endclass
3169 class C extends B
3170 def Baz(): number
3171 return this._Foo()
3172 enddef
3173 endclass
3174 var c = C.new()
3175 assert_equal(1234, c.Baz())
3176 END
3177 v9.CheckScriptSuccess(lines)
3178
3179 # Call a private object method from a child class object
3180 lines =<< trim END
3181 vim9script
3182 class A
3183 def _Foo(): number
3184 return 1234
3185 enddef
3186 endclass
3187 class B extends A
3188 def Bar()
3189 enddef
3190 endclass
3191 class C extends B
3192 def Baz(): number
3193 enddef
3194 endclass
3195 var c = C.new()
3196 assert_equal(1234, c._Foo())
3197 END
3198 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3199
3200 # Using "_" prefix in a method name should fail outside of a class
3201 lines =<< trim END
3202 vim9script
3203 def _Foo(): number
3204 return 1234
3205 enddef
3206 var a = _Foo()
3207 END
3208 v9.CheckScriptFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
3209enddef
3210
3211" Test for an private class method
3212def Test_private_class_method()
3213 # Try calling a class private method (at the script level)
3214 var lines =<< trim END
3215 vim9script
3216
3217 class A
3218 static def _Foo(): number
3219 return 1234
3220 enddef
3221 endclass
3222 A._Foo()
3223 END
3224 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3225
3226 # Try calling a class private method (from a def function)
3227 lines =<< trim END
3228 vim9script
3229
3230 class A
3231 static def _Foo(): number
3232 return 1234
3233 enddef
3234 endclass
3235 def T()
3236 A._Foo()
3237 enddef
3238 T()
3239 END
3240 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3241
3242 # Try calling a class private method using an object (at the script level)
3243 lines =<< trim END
3244 vim9script
3245
3246 class A
3247 static def _Foo(): number
3248 return 1234
3249 enddef
3250 endclass
3251 var a = A.new()
3252 a._Foo()
3253 END
3254 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3255
3256 # Try calling a class private method using an object (from a def function)
3257 lines =<< trim END
3258 vim9script
3259
3260 class A
3261 static def _Foo(): number
3262 return 1234
3263 enddef
3264 endclass
3265 def T()
3266 var a = A.new()
3267 a._Foo()
3268 enddef
3269 T()
3270 END
3271 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3272
3273 # Use a class private method from an object method
3274 lines =<< trim END
3275 vim9script
3276
3277 class A
3278 static def _Foo(): number
3279 return 1234
3280 enddef
3281 def Bar()
3282 assert_equal(1234, A._Foo())
3283 enddef
3284 endclass
3285 var a = A.new()
3286 a.Bar()
3287 END
3288 v9.CheckScriptSuccess(lines)
3289
3290 # Use a class private method from another class private method
3291 lines =<< trim END
3292 vim9script
3293
3294 class A
3295 static def _Foo1(): number
3296 return 1234
3297 enddef
3298 static def _Foo2()
3299 assert_equal(1234, A._Foo1())
3300 enddef
3301 def Bar()
3302 A._Foo2()
3303 enddef
3304 endclass
3305 var a = A.new()
3306 a.Bar()
3307 END
3308 v9.CheckScriptSuccess(lines)
3309
3310 # Declare a class method and a class private method with the same name
3311 lines =<< trim END
3312 vim9script
3313
3314 class A
3315 static def _Foo()
3316 enddef
3317 static def Foo()
3318 enddef
3319 endclass
3320 var a = A.new()
3321 END
3322 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3323
3324 # Try calling a class private method from another class
3325 lines =<< trim END
3326 vim9script
3327
3328 class A
3329 static def _Foo(): number
3330 return 1234
3331 enddef
3332 endclass
3333 class B
3334 def Foo(): number
3335 return A._Foo()
3336 enddef
3337 endclass
3338 var b = B.new()
3339 assert_equal(1234, b.Foo())
3340 END
3341 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3342
3343 # Call a private class method from a child class object method
3344 lines =<< trim END
3345 vim9script
3346 class A
3347 static def _Foo(): number
3348 return 1234
3349 enddef
3350 endclass
3351 class B extends A
3352 def Bar()
3353 enddef
3354 endclass
3355 class C extends B
3356 def Baz(): number
3357 return A._Foo()
3358 enddef
3359 endclass
3360 var c = C.new()
3361 assert_equal(1234, c.Baz())
3362 END
3363 v9.CheckScriptSuccess(lines)
3364
3365 # Call a private class method from a child class private class method
3366 lines =<< trim END
3367 vim9script
3368 class A
3369 static def _Foo(): number
3370 return 1234
3371 enddef
3372 endclass
3373 class B extends A
3374 def Bar()
3375 enddef
3376 endclass
3377 class C extends B
3378 static def Baz(): number
3379 return A._Foo()
3380 enddef
3381 endclass
3382 assert_equal(1234, C.Baz())
3383 END
3384 v9.CheckScriptSuccess(lines)
3385
3386 # Call a private class method from a child class object
3387 lines =<< trim END
3388 vim9script
3389 class A
3390 static def _Foo(): number
3391 return 1234
3392 enddef
3393 endclass
3394 class B extends A
3395 def Bar()
3396 enddef
3397 endclass
3398 class C extends B
3399 def Baz(): number
3400 enddef
3401 endclass
3402 var c = C.new()
3403 assert_equal(1234, C._Foo())
3404 END
3405 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3406enddef
3407
3408" Test for an interface private object_method
3409def Test_interface_private_object_method()
3410 # Implement an interface private method and use it from a public method
3411 var lines =<< trim END
3412 vim9script
3413 interface Intf
3414 def _Foo(): number
3415 endinterface
3416 class A implements Intf
3417 def _Foo(): number
3418 return 1234
3419 enddef
3420 def Bar(): number
3421 return this._Foo()
3422 enddef
3423 endclass
3424 var a = A.new()
3425 assert_equal(1234, a.Bar())
3426 END
3427 v9.CheckScriptSuccess(lines)
3428
3429 # Call an interface private class method (script context)
3430 lines =<< trim END
3431 vim9script
3432 interface Intf
3433 def _Foo(): number
3434 endinterface
3435 class A implements Intf
3436 def _Foo(): number
3437 return 1234
3438 enddef
3439 endclass
3440 var a = A.new()
3441 assert_equal(1234, a._Foo())
3442 END
3443 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3444
3445 # Call an interface private class method (def context)
3446 lines =<< trim END
3447 vim9script
3448 interface Intf
3449 def _Foo(): number
3450 endinterface
3451 class A implements Intf
3452 def _Foo(): number
3453 return 1234
3454 enddef
3455 endclass
3456 def T()
3457 var a = A.new()
3458 assert_equal(1234, a._Foo())
3459 enddef
3460 T()
3461 END
3462 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3463
3464 # Implement an interface private object method as a private class method
3465 lines =<< trim END
3466 vim9script
3467 interface Intf
3468 def _Foo(): number
3469 endinterface
3470 class A implements Intf
3471 static def _Foo(): number
3472 return 1234
3473 enddef
3474 endclass
3475 END
3476 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3477enddef
3478
3479" Test for an interface private class method
3480def Test_interface_private_class_method()
3481 # Implement an interface private class method and use it from a public method
3482 var lines =<< trim END
3483 vim9script
3484 interface Intf
3485 static def _Foo(): number
3486 endinterface
3487 class A implements Intf
3488 static def _Foo(): number
3489 return 1234
3490 enddef
3491 def Bar(): number
3492 return A._Foo()
3493 enddef
3494 endclass
3495 var a = A.new()
3496 assert_equal(1234, a.Bar())
3497 END
3498 v9.CheckScriptSuccess(lines)
3499
3500 # Call an interface private class method (script context)
3501 lines =<< trim END
3502 vim9script
3503 interface Intf
3504 static def _Foo(): number
3505 endinterface
3506 class A implements Intf
3507 static def _Foo(): number
3508 return 1234
3509 enddef
3510 endclass
3511 assert_equal(1234, A._Foo())
3512 END
3513 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3514
3515 # Call an interface private class method (def context)
3516 lines =<< trim END
3517 vim9script
3518 interface Intf
3519 static def _Foo(): number
3520 endinterface
3521 class A implements Intf
3522 static def _Foo(): number
3523 return 1234
3524 enddef
3525 endclass
3526 def T()
3527 assert_equal(1234, A._Foo())
3528 enddef
3529 T()
3530 END
3531 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3532
3533 # Implement an interface private class method as a private object method
3534 lines =<< trim END
3535 vim9script
3536 interface Intf
3537 static def _Foo(): number
3538 endinterface
3539 class A implements Intf
3540 def _Foo(): number
3541 return 1234
3542 enddef
3543 endclass
3544 END
3545 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3546enddef
3547
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003548" Test for using the return value of a class/object method as a function
3549" argument.
3550def Test_objmethod_funcarg()
3551 var lines =<< trim END
3552 vim9script
3553
3554 class C
3555 def Foo(): string
3556 return 'foo'
3557 enddef
3558 endclass
3559
3560 def Bar(a: number, s: string): string
3561 return s
3562 enddef
3563
3564 def Baz(c: C)
3565 assert_equal('foo', Bar(10, c.Foo()))
3566 enddef
3567
3568 var t = C.new()
3569 Baz(t)
3570 END
3571 v9.CheckScriptSuccess(lines)
3572
3573 lines =<< trim END
3574 vim9script
3575
3576 class C
3577 static def Foo(): string
3578 return 'foo'
3579 enddef
3580 endclass
3581
3582 def Bar(a: number, s: string): string
3583 return s
3584 enddef
3585
3586 def Baz()
3587 assert_equal('foo', Bar(10, C.Foo()))
3588 enddef
3589
3590 Baz()
3591 END
3592 v9.CheckScriptSuccess(lines)
3593enddef
3594
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003595" Test for declaring duplicate object and class members
3596def Test_dup_member_variable()
3597 # Duplicate member variable
3598 var lines =<< trim END
3599 vim9script
3600 class C
3601 this.val = 10
3602 this.val = 20
3603 endclass
3604 END
3605 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3606
3607 # Duplicate private member variable
3608 lines =<< trim END
3609 vim9script
3610 class C
3611 this._val = 10
3612 this._val = 20
3613 endclass
3614 END
3615 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3616
3617 # Duplicate public member variable
3618 lines =<< trim END
3619 vim9script
3620 class C
3621 public this.val = 10
3622 public this.val = 20
3623 endclass
3624 END
3625 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3626
3627 # Duplicate private member variable
3628 lines =<< trim END
3629 vim9script
3630 class C
3631 this.val = 10
3632 this._val = 20
3633 endclass
3634 END
3635 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3636
3637 # Duplicate public and private member variable
3638 lines =<< trim END
3639 vim9script
3640 class C
3641 this._val = 20
3642 public this.val = 10
3643 endclass
3644 END
3645 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3646
3647 # Duplicate class member variable
3648 lines =<< trim END
3649 vim9script
3650 class C
3651 static s: string = "abc"
3652 static _s: string = "def"
3653 endclass
3654 END
3655 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3656
3657 # Duplicate public and private class member variable
3658 lines =<< trim END
3659 vim9script
3660 class C
3661 public static s: string = "abc"
3662 static _s: string = "def"
3663 endclass
3664 END
3665 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3666
3667 # Duplicate class and object member variable
3668 lines =<< trim END
3669 vim9script
3670 class C
3671 static val = 10
3672 this.val = 20
3673 def new()
3674 enddef
3675 endclass
3676 var c = C.new()
3677 assert_equal(10, C.val)
3678 assert_equal(20, c.val)
3679 END
3680 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003681
3682 # Duplicate object member variable in a derived class
3683 lines =<< trim END
3684 vim9script
3685 class A
3686 this.val = 10
3687 endclass
3688 class B extends A
3689 endclass
3690 class C extends B
3691 this.val = 20
3692 endclass
3693 END
3694 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3695
3696 # Duplicate object private member variable in a derived class
3697 lines =<< trim END
3698 vim9script
3699 class A
3700 this._val = 10
3701 endclass
3702 class B extends A
3703 endclass
3704 class C extends B
3705 this._val = 20
3706 endclass
3707 END
3708 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3709
3710 # Duplicate object private member variable in a derived class
3711 lines =<< trim END
3712 vim9script
3713 class A
3714 this.val = 10
3715 endclass
3716 class B extends A
3717 endclass
3718 class C extends B
3719 this._val = 20
3720 endclass
3721 END
3722 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3723
3724 # Duplicate object member variable in a derived class
3725 lines =<< trim END
3726 vim9script
3727 class A
3728 this._val = 10
3729 endclass
3730 class B extends A
3731 endclass
3732 class C extends B
3733 this.val = 20
3734 endclass
3735 END
3736 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3737
3738 # Duplicate class member variable in a derived class
3739 lines =<< trim END
3740 vim9script
3741 class A
3742 static val = 10
3743 endclass
3744 class B extends A
3745 endclass
3746 class C extends B
3747 static val = 20
3748 endclass
3749 END
3750 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3751
3752 # Duplicate private class member variable in a derived class
3753 lines =<< trim END
3754 vim9script
3755 class A
3756 static _val = 10
3757 endclass
3758 class B extends A
3759 endclass
3760 class C extends B
3761 static _val = 20
3762 endclass
3763 END
3764 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3765
3766 # Duplicate private class member variable in a derived class
3767 lines =<< trim END
3768 vim9script
3769 class A
3770 static val = 10
3771 endclass
3772 class B extends A
3773 endclass
3774 class C extends B
3775 static _val = 20
3776 endclass
3777 END
3778 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3779
3780 # Duplicate class member variable in a derived class
3781 lines =<< trim END
3782 vim9script
3783 class A
3784 static _val = 10
3785 endclass
3786 class B extends A
3787 endclass
3788 class C extends B
3789 static val = 20
3790 endclass
3791 END
3792 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02003793
3794 # Two member variables with a common prefix
3795 lines =<< trim END
3796 vim9script
3797 class A
3798 public static svar2: number
3799 public static svar: number
3800 endclass
3801 END
3802 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003803enddef
3804
Ernie Rael18143d32023-09-04 22:30:41 +02003805def Test_interface_static_member_access()
3806 # In a class cannot read from interface static
3807 var lines =<< trim END
3808 vim9script
3809 interface I
3810 public static num: number
3811 endinterface
3812 class C implements I
3813 public static num = 3
3814 def F()
3815 var x = I.num
3816 enddef
3817 endclass
3818 C.new().F()
3819 END
3820 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
3821
3822 # In a class cannot write to interface static
3823 lines =<< trim END
3824 vim9script
3825 interface I
3826 public static num: number
3827 endinterface
3828 class C implements I
3829 public static num = 3
3830 def F()
3831 I.num = 7
3832 enddef
3833 endclass
3834 C.new().F()
3835 END
3836 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
3837
3838 # In a def cannot read from interface static
3839 lines =<< trim END
3840 vim9script
3841 interface I
3842 public static num: number
3843 endinterface
3844 def F()
3845 var x = I.num
3846 enddef
3847 F()
3848 END
3849 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
3850
3851 # In a def cannot write to interface static
3852 lines =<< trim END
3853 vim9script
3854 interface I
3855 public static num: number
3856 endinterface
3857 def F()
3858 I.num = 7
3859 enddef
3860 F()
3861 END
3862 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
3863
3864 # script level cannot read interface static
3865 lines =<< trim END
3866 vim9script
3867 interface I
3868 public static s_var1: number
3869 endinterface
3870
3871 var x = I.s_var1
3872 END
3873 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "s_var1"')
3874
3875 # script level cannot write interface static
3876 lines =<< trim END
3877 vim9script
3878 interface I
3879 public static s_var1: number
3880 endinterface
3881
3882 I.s_var1 = 3
3883 END
3884 v9.CheckScriptFailure(lines, 'E1409: Cannot directly access interface "I" static member "I.s_var1 = 3"')
3885
3886enddef
3887
3888def Test_static_member_access_outside_class()
3889 # Verify access of statics implemented from interface
3890 # in a :def (outside of a class)
3891 # Note the order of the static is different
3892 # between the interface and the class,
3893 # since they are allocated in order in each interface/class;
3894 # so the static index is mapped from interfaced to class as needed.
3895
3896 # Check reading statics
3897 var lines =<< trim END
3898 vim9script
3899
3900 interface I
3901 public static s_var1: number
3902 public static s_var2: number
3903 endinterface
3904
3905 class C implements I
3906 public static s_var2 = 2
3907 public static x_static = 7
3908 public static s_var1 = 1
3909 endclass
3910
3911 def F1(): number
3912 assert_equal(1, C.s_var1)
3913 assert_equal(2, C.s_var2)
3914 assert_equal(7, C.x_static)
3915 return 11
3916 enddef
3917
3918 # access the class static through an interface argument
3919 def F2(i: I): number
3920 assert_equal(1, i.s_var1)
3921 assert_equal(2, i.s_var2)
3922 return 22
3923 enddef
3924
3925 # access the class static through an object interface
3926 def F3(o: C): number
3927 assert_equal(1, o.s_var1)
3928 assert_equal(2, o.s_var2)
3929 assert_equal(7, o.x_static)
3930 return 33
3931 enddef
3932
3933 assert_equal(11, F1())
3934 var c = C.new()
3935 assert_equal(22, F2(c))
3936 assert_equal(33, F3(c))
3937 END
3938 v9.CheckScriptSuccess(lines)
3939enddef
3940
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003941" Test for accessing a private member outside a class in a def function
3942def Test_private_member_access_outside_class()
3943 # private object member variable
3944 var lines =<< trim END
3945 vim9script
3946 class A
3947 this._val = 10
3948 def GetVal(): number
3949 return this._val
3950 enddef
3951 endclass
3952 def T()
3953 var a = A.new()
3954 a._val = 20
3955 enddef
3956 T()
3957 END
3958 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
3959
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003960 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003961 lines =<< trim END
3962 vim9script
3963 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003964 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003965 endclass
3966 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003967 var a = A.new()
3968 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003969 enddef
3970 T()
3971 END
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003972 v9.CheckScriptFailure(lines, 'E1089: Unknown variable: _a = 1')
Ernie Rael18143d32023-09-04 22:30:41 +02003973
3974 # private static member variable
3975 lines =<< trim END
3976 vim9script
3977 class A
3978 static _val = 10
3979 endclass
3980 def T()
3981 var a = A.new()
3982 var x = a._val
3983 enddef
3984 T()
3985 END
3986 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
3987
3988 # private static member variable
3989 lines =<< trim END
3990 vim9script
3991 class A
3992 static _val = 10
3993 endclass
3994 def T()
3995 var a = A.new()
3996 a._val = 3
3997 enddef
3998 T()
3999 END
4000 # TODO: wrong error, should be about private member
4001 v9.CheckScriptFailure(lines, 'E1089: Unknown variable')
4002
4003 # private static class variable
4004 lines =<< trim END
4005 vim9script
4006 class A
4007 static _val = 10
4008 endclass
4009 def T()
4010 var x = A._val
4011 enddef
4012 T()
4013 END
4014 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4015
4016 # private static class variable
4017 lines =<< trim END
4018 vim9script
4019 class A
4020 static _val = 10
4021 endclass
4022 def T()
4023 A._val = 3
4024 enddef
4025 T()
4026 END
4027 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
4028
4029
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004030enddef
4031
4032" Test for changing the member access of an interface in a implementation class
4033def Test_change_interface_member_access()
4034 var lines =<< trim END
4035 vim9script
4036 interface A
4037 public this.val: number
4038 endinterface
4039 class B implements A
4040 this.val = 10
4041 endclass
4042 END
4043 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
4044
4045 lines =<< trim END
4046 vim9script
4047 interface A
4048 this.val: number
4049 endinterface
4050 class B implements A
4051 public this.val = 10
4052 endclass
4053 END
4054 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
4055enddef
4056
4057" Test for trying to change a readonly member from a def function
4058def Test_readonly_member_change_in_def_func()
4059 var lines =<< trim END
4060 vim9script
4061 class A
4062 this.val: number
4063 endclass
4064 def T()
4065 var a = A.new()
4066 a.val = 20
4067 enddef
4068 T()
4069 END
4070 v9.CheckScriptFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004071enddef
4072
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004073" Test for reading and writing a class member from a def function
4074def Test_modify_class_member_from_def_function()
4075 var lines =<< trim END
4076 vim9script
4077 class A
4078 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004079 public static var2: list<number> = [1, 2]
4080 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004081 static _priv_var4: number = 40
4082 endclass
4083 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004084 assert_equal([1, 2], A.var2)
4085 assert_equal({a: 1, b: 2}, A.var3)
4086 A.var2 = [3, 4]
4087 A.var3 = {c: 3, d: 4}
4088 assert_equal([3, 4], A.var2)
4089 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004090 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4091 enddef
4092 T()
4093 END
4094 v9.CheckScriptSuccess(lines)
4095enddef
4096
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004097" Test for accessing a class member variable using an object
4098def Test_class_member_access_using_object()
4099 var lines =<< trim END
4100 vim9script
4101 class A
4102 public static svar1: list<number> = [1]
4103 public static svar2: list<number> = [2]
4104 endclass
4105
4106 A.svar1->add(3)
4107 A.svar2->add(4)
4108 assert_equal([1, 3], A.svar1)
4109 assert_equal([2, 4], A.svar2)
4110 var a1 = A.new()
4111 a1.svar1->add(5)
4112 a1.svar2->add(6)
4113 assert_equal([1, 3, 5], a1.svar1)
4114 assert_equal([2, 4, 6], a1.svar2)
4115
4116 def Foo()
4117 A.svar1->add(7)
4118 A.svar2->add(8)
4119 assert_equal([1, 3, 5, 7], A.svar1)
4120 assert_equal([2, 4, 6, 8], A.svar2)
4121 var a2 = A.new()
4122 a2.svar1->add(9)
4123 a2.svar2->add(10)
4124 assert_equal([1, 3, 5, 7, 9], a2.svar1)
4125 assert_equal([2, 4, 6, 8, 10], a2.svar2)
4126 enddef
4127 Foo()
4128 END
4129 v9.CheckScriptSuccess(lines)
4130enddef
4131
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004132" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker