blob: 8ae136f283f50e6382210846d79feb75c55bee83 [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)
512enddef
513
Bram Moolenaarf4508042023-01-15 16:54:57 +0000514def Test_list_of_objects()
515 var lines =<< trim END
516 vim9script
517
518 class Foo
519 def Add()
520 enddef
521 endclass
522
523 def ProcessList(fooList: list<Foo>)
524 for foo in fooList
525 foo.Add()
526 endfor
527 enddef
528
529 var l: list<Foo> = [Foo.new()]
530 ProcessList(l)
531 END
532 v9.CheckScriptSuccess(lines)
533enddef
534
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000535def Test_expr_after_using_object()
536 var lines =<< trim END
537 vim9script
538
539 class Something
540 this.label: string = ''
541 endclass
542
543 def Foo(): Something
544 var v = Something.new()
545 echo 'in Foo(): ' .. typename(v)
546 return v
547 enddef
548
549 Foo()
550 END
551 v9.CheckScriptSuccess(lines)
552enddef
553
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000554def Test_class_default_new()
555 var lines =<< trim END
556 vim9script
557
558 class TextPosition
559 this.lnum: number = 1
560 this.col: number = 1
561 endclass
562
563 var pos = TextPosition.new()
564 assert_equal(1, pos.lnum)
565 assert_equal(1, pos.col)
566
567 pos = TextPosition.new(v:none, v:none)
568 assert_equal(1, pos.lnum)
569 assert_equal(1, pos.col)
570
571 pos = TextPosition.new(3, 22)
572 assert_equal(3, pos.lnum)
573 assert_equal(22, pos.col)
574
575 pos = TextPosition.new(v:none, 33)
576 assert_equal(1, pos.lnum)
577 assert_equal(33, pos.col)
578 END
579 v9.CheckScriptSuccess(lines)
580
581 lines =<< trim END
582 vim9script
583 class Person
584 this.name: string
585 this.age: number = 42
586 this.education: string = "unknown"
587
588 def new(this.name, this.age = v:none, this.education = v:none)
589 enddef
590 endclass
591
592 var piet = Person.new("Piet")
593 assert_equal("Piet", piet.name)
594 assert_equal(42, piet.age)
595 assert_equal("unknown", piet.education)
596
597 var chris = Person.new("Chris", 4, "none")
598 assert_equal("Chris", chris.name)
599 assert_equal(4, chris.age)
600 assert_equal("none", chris.education)
601 END
602 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000603
604 lines =<< trim END
605 vim9script
606 class Person
607 this.name: string
608 this.age: number = 42
609 this.education: string = "unknown"
610
611 def new(this.name, this.age = v:none, this.education = v:none)
612 enddef
613 endclass
614
615 var missing = Person.new()
616 END
617 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000618enddef
619
h-east2261c892023-08-16 21:49:54 +0900620
621def Test_class_new_with_object_member()
622 var lines =<< trim END
623 vim9script
624
625 class C
626 this.str: string
627 this.num: number
628 def new(this.str, this.num)
629 enddef
630 def newVals(this.str, this.num)
631 enddef
632 endclass
633
634 def Check()
635 try
636 var c = C.new('cats', 2)
637 assert_equal('cats', c.str)
638 assert_equal(2, c.num)
639
640 c = C.newVals('dogs', 4)
641 assert_equal('dogs', c.str)
642 assert_equal(4, c.num)
643 catch
644 assert_report($'Unexpected exception was caught: {v:exception}')
645 endtry
646 enddef
647
648 Check()
649 END
650 v9.CheckScriptSuccess(lines)
651
652 lines =<< trim END
653 vim9script
654
655 class C
656 this.str: string
657 this.num: number
658 def new(this.str, this.num)
659 enddef
660 endclass
661
662 def Check()
663 try
664 var c = C.new(1, 2)
665 catch
666 assert_report($'Unexpected exception was caught: {v:exception}')
667 endtry
668 enddef
669
670 Check()
671 END
672 v9.CheckScriptFailure(lines, 'E1013:')
673
674 lines =<< trim END
675 vim9script
676
677 class C
678 this.str: string
679 this.num: number
680 def newVals(this.str, this.num)
681 enddef
682 endclass
683
684 def Check()
685 try
686 var c = C.newVals('dogs', 'apes')
687 catch
688 assert_report($'Unexpected exception was caught: {v:exception}')
689 endtry
690 enddef
691
692 Check()
693 END
694 v9.CheckScriptFailure(lines, 'E1013:')
695enddef
696
Bram Moolenaar74e12742022-12-13 21:14:28 +0000697def Test_class_object_member_inits()
698 var lines =<< trim END
699 vim9script
700 class TextPosition
701 this.lnum: number
702 this.col = 1
703 this.addcol: number = 2
704 endclass
705
706 var pos = TextPosition.new()
707 assert_equal(0, pos.lnum)
708 assert_equal(1, pos.col)
709 assert_equal(2, pos.addcol)
710 END
711 v9.CheckScriptSuccess(lines)
712
713 lines =<< trim END
714 vim9script
715 class TextPosition
716 this.lnum
717 this.col = 1
718 endclass
719 END
720 v9.CheckScriptFailure(lines, 'E1022:')
721
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200722 # If the type is not specified for a member, then it should be set during
723 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000724 lines =<< trim END
725 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200726
727 var init_count = 0
728 def Init(): string
729 init_count += 1
730 return 'foo'
731 enddef
732
733 class A
734 this.str1 = Init()
735 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000736 this.col = 1
737 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200738
739 assert_equal(init_count, 0)
740 var a = A.new()
741 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000742 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200743 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200744
745 # Test for initializing an object member with an unknown variable/type
746 lines =<< trim END
747 vim9script
748 class A
749 this.value = init_val
750 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200751 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200752 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200753 v9.CheckScriptFailure(lines, 'E1001:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000754enddef
755
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000756def Test_class_object_member_access()
757 var lines =<< trim END
758 vim9script
759 class Triple
760 this._one = 1
761 this.two = 2
762 public this.three = 3
763
764 def GetOne(): number
765 return this._one
766 enddef
767 endclass
768
769 var trip = Triple.new()
770 assert_equal(1, trip.GetOne())
771 assert_equal(2, trip.two)
772 assert_equal(3, trip.three)
773 assert_fails('echo trip._one', 'E1333')
774
775 assert_fails('trip._one = 11', 'E1333')
776 assert_fails('trip.two = 22', 'E1335')
777 trip.three = 33
778 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000779
780 assert_fails('trip.four = 4', 'E1334')
781 END
782 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000783
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200784 # Test for a public member variable name beginning with an underscore
785 lines =<< trim END
786 vim9script
787 class A
788 public this._val = 10
789 endclass
790 END
791 v9.CheckScriptFailure(lines, 'E1332:')
792
Bram Moolenaar590162c2022-12-24 21:24:06 +0000793 lines =<< trim END
794 vim9script
795
796 class MyCar
797 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000798 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000799
800 def new(make_arg: string)
801 this.make = make_arg
802 enddef
803
804 def GetMake(): string
805 return $"make = {this.make}"
806 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000807 def GetAge(): number
808 return this.age
809 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000810 endclass
811
812 var c = MyCar.new("abc")
813 assert_equal('make = abc', c.GetMake())
814
815 c = MyCar.new("def")
816 assert_equal('make = def', c.GetMake())
817
818 var c2 = MyCar.new("123")
819 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000820
821 def CheckCar()
822 assert_equal("make = def", c.GetMake())
823 assert_equal(5, c.GetAge())
824 enddef
825 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000826 END
827 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000828
829 lines =<< trim END
830 vim9script
831
832 class MyCar
833 this.make: string
834
835 def new(make_arg: string)
836 this.make = make_arg
837 enddef
838 endclass
839
840 var c = MyCar.new("abc")
841 var c = MyCar.new("def")
842 END
843 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000844
845 lines =<< trim END
846 vim9script
847
848 class Foo
849 this.x: list<number> = []
850
851 def Add(n: number): any
852 this.x->add(n)
853 return this
854 enddef
855 endclass
856
857 echo Foo.new().Add(1).Add(2).x
858 echo Foo.new().Add(1).Add(2)
859 .x
860 echo Foo.new().Add(1)
861 .Add(2).x
862 echo Foo.new()
863 .Add(1).Add(2).x
864 echo Foo.new()
865 .Add(1)
866 .Add(2)
867 .x
868 END
869 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200870
871 # Test for "public" cannot be abbreviated
872 lines =<< trim END
873 vim9script
874 class Something
875 pub this.val = 1
876 endclass
877 END
878 v9.CheckScriptFailure(lines, 'E1065:')
879
880 # Test for "public" keyword must be followed by "this" or "static".
881 lines =<< trim END
882 vim9script
883 class Something
884 public val = 1
885 endclass
886 END
887 v9.CheckScriptFailure(lines, 'E1331:')
888
889 # Test for "static" cannot be abbreviated
890 lines =<< trim END
891 vim9script
892 class Something
893 stat this.val = 1
894 endclass
895 END
896 v9.CheckScriptFailure(lines, 'E1065:')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +0200897
898 # Test for "static" cannot be followed by "this".
899 lines =<< trim END
900 vim9script
901 class Something
902 static this.val = 1
903 endclass
904 END
905 v9.CheckScriptFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
Bram Moolenaard505d172022-12-18 21:42:55 +0000906enddef
907
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000908def Test_class_object_compare()
909 var class_lines =<< trim END
910 vim9script
911 class Item
912 this.nr = 0
913 this.name = 'xx'
914 endclass
915 END
916
917 # used at the script level and in a compiled function
918 var test_lines =<< trim END
919 var i1 = Item.new()
920 assert_equal(i1, i1)
921 assert_true(i1 is i1)
922 var i2 = Item.new()
923 assert_equal(i1, i2)
924 assert_false(i1 is i2)
925 var i3 = Item.new(0, 'xx')
926 assert_equal(i1, i3)
927
928 var io1 = Item.new(1, 'xx')
929 assert_notequal(i1, io1)
930 var io2 = Item.new(0, 'yy')
931 assert_notequal(i1, io2)
932 END
933
934 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000935 v9.CheckScriptSuccess(
936 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000937
938 for op in ['>', '>=', '<', '<=', '=~', '!~']
939 var op_lines = [
940 'var i1 = Item.new()',
941 'var i2 = Item.new()',
942 'echo i1 ' .. op .. ' i2',
943 ]
944 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000945 v9.CheckScriptFailure(class_lines
946 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000947 endfor
948enddef
949
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000950def Test_object_type()
951 var lines =<< trim END
952 vim9script
953
954 class One
955 this.one = 1
956 endclass
957 class Two
958 this.two = 2
959 endclass
960 class TwoMore extends Two
961 this.more = 9
962 endclass
963
964 var o: One = One.new()
965 var t: Two = Two.new()
966 var m: TwoMore = TwoMore.new()
967 var tm: Two = TwoMore.new()
968
969 t = m
970 END
971 v9.CheckScriptSuccess(lines)
972
973 lines =<< trim END
974 vim9script
975
976 class One
977 this.one = 1
978 endclass
979 class Two
980 this.two = 2
981 endclass
982
983 var o: One = Two.new()
984 END
985 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000986
987 lines =<< trim END
988 vim9script
989
990 interface One
991 def GetMember(): number
992 endinterface
993 class Two implements One
994 this.one = 1
995 def GetMember(): number
996 return this.one
997 enddef
998 endclass
999
1000 var o: One = Two.new(5)
1001 assert_equal(5, o.GetMember())
1002 END
1003 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001004
1005 lines =<< trim END
1006 vim9script
1007
1008 class Num
1009 this.n: number = 0
1010 endclass
1011
1012 def Ref(name: string): func(Num): Num
1013 return (arg: Num): Num => {
1014 return eval(name)(arg)
1015 }
1016 enddef
1017
1018 const Fn = Ref('Double')
1019 var Double = (m: Num): Num => Num.new(m.n * 2)
1020
1021 echo Fn(Num.new(4))
1022 END
1023 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001024enddef
1025
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001026def Test_class_member()
1027 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001028 var lines =<< trim END
1029 vim9script
1030 class TextPos
1031 this.lnum = 1
1032 this.col = 1
1033 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001034 static _secret = 7
1035 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001036
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001037 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001038 counter += nr
1039 enddef
1040 endclass
1041
1042 assert_equal(0, TextPos.counter)
1043 TextPos.AddToCounter(3)
1044 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001045 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001046
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001047 def GetCounter(): number
1048 return TextPos.counter
1049 enddef
1050 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001051
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001052 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001053 assert_fails('TextPos.counter = 5', 'E1335:')
1054 assert_fails('TextPos.counter += 5', 'E1335:')
1055
1056 assert_fails('echo TextPos._secret', 'E1333:')
1057 assert_fails('TextPos._secret = 8', 'E1333:')
1058
1059 assert_equal(42, TextPos.anybody)
1060 TextPos.anybody = 12
1061 assert_equal(12, TextPos.anybody)
1062 TextPos.anybody += 5
1063 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001064 END
1065 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001066
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001067 # example in the help
1068 lines =<< trim END
1069 vim9script
1070 class OtherThing
1071 this.size: number
1072 static totalSize: number
1073
1074 def new(this.size)
1075 totalSize += this.size
1076 enddef
1077 endclass
1078 assert_equal(0, OtherThing.totalSize)
1079 var to3 = OtherThing.new(3)
1080 assert_equal(3, OtherThing.totalSize)
1081 var to7 = OtherThing.new(7)
1082 assert_equal(10, OtherThing.totalSize)
1083 END
1084 v9.CheckScriptSuccess(lines)
1085
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001086 # using static class member twice
1087 lines =<< trim END
1088 vim9script
1089
1090 class HTML
1091 static author: string = 'John Doe'
1092
1093 static def MacroSubstitute(s: string): string
1094 return substitute(s, '{{author}}', author, 'gi')
1095 enddef
1096 endclass
1097
1098 assert_equal('some text', HTML.MacroSubstitute('some text'))
1099 assert_equal('some text', HTML.MacroSubstitute('some text'))
1100 END
1101 v9.CheckScriptSuccess(lines)
1102
Bram Moolenaar62a69232023-01-24 15:07:04 +00001103 # access private member in lambda
1104 lines =<< trim END
1105 vim9script
1106
1107 class Foo
1108 this._x: number = 0
1109
1110 def Add(n: number): number
1111 const F = (): number => this._x + n
1112 return F()
1113 enddef
1114 endclass
1115
1116 var foo = Foo.new()
1117 assert_equal(5, foo.Add(5))
1118 END
1119 v9.CheckScriptSuccess(lines)
1120
h-east2bd6a092023-05-19 19:01:17 +01001121 # access private member in lambda body
1122 lines =<< trim END
1123 vim9script
1124
1125 class Foo
1126 this._x: number = 6
1127
1128 def Add(n: number): number
1129 var Lam = () => {
1130 this._x = this._x + n
1131 }
1132 Lam()
1133 return this._x
1134 enddef
1135 endclass
1136
1137 var foo = Foo.new()
1138 assert_equal(13, foo.Add(7))
1139 END
1140 v9.CheckScriptSuccess(lines)
1141
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001142 # check shadowing
1143 lines =<< trim END
1144 vim9script
1145
1146 class Some
1147 static count = 0
1148 def Method(count: number)
1149 echo count
1150 enddef
1151 endclass
1152
1153 var s = Some.new()
1154 s.Method(7)
1155 END
1156 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
1157
1158 lines =<< trim END
1159 vim9script
1160
1161 class Some
1162 static count = 0
1163 def Method(arg: number)
1164 var count = 3
1165 echo arg count
1166 enddef
1167 endclass
1168
1169 var s = Some.new()
1170 s.Method(7)
1171 END
1172 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001173
1174 # Test for using an invalid type for a member variable
1175 lines =<< trim END
1176 vim9script
1177 class A
1178 this.val: xxx
1179 endclass
1180 END
1181 v9.CheckScriptFailure(lines, 'E1010:')
1182
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001183 # Test for setting a member on a null object
1184 lines =<< trim END
1185 vim9script
1186 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001187 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001188 endclass
1189
1190 def F()
1191 var obj: A
1192 obj.val = ""
1193 enddef
1194 F()
1195 END
1196 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1197
1198 # Test for accessing a member on a null object
1199 lines =<< trim END
1200 vim9script
1201 class A
1202 this.val: string
1203 endclass
1204
1205 def F()
1206 var obj: A
1207 echo obj.val
1208 enddef
1209 F()
1210 END
1211 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1212
1213 # Test for setting a member on a null object, at script level
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 var obj: A
1221 obj.val = ""
1222 END
1223 # FIXME(in source): this should give E1360 as well!
1224 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
1225
1226 # Test for accessing a member on a null object, at script level
1227 lines =<< trim END
1228 vim9script
1229 class A
1230 this.val: string
1231 endclass
1232
1233 var obj: A
1234 echo obj.val
1235 END
1236 v9.CheckScriptFailure(lines, 'E1360: Using a null object')
1237
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001238 # Test for no space before or after the '=' when initializing a member
1239 # variable
1240 lines =<< trim END
1241 vim9script
1242 class A
1243 this.val: number= 10
1244 endclass
1245 END
1246 v9.CheckScriptFailure(lines, 'E1004:')
1247 lines =<< trim END
1248 vim9script
1249 class A
1250 this.val: number =10
1251 endclass
1252 END
1253 v9.CheckScriptFailure(lines, 'E1004:')
1254
1255 # Access a non-existing member
1256 lines =<< trim END
1257 vim9script
1258 class A
1259 endclass
1260 var a = A.new()
1261 var v = a.bar
1262 END
1263 v9.CheckScriptFailure(lines, 'E1326:')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001264enddef
1265
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001266func Test_class_garbagecollect()
1267 let lines =<< trim END
1268 vim9script
1269
1270 class Point
1271 this.p = [2, 3]
1272 static pl = ['a', 'b']
1273 static pd = {a: 'a', b: 'b'}
1274 endclass
1275
1276 echo Point.pl Point.pd
1277 call test_garbagecollect_now()
1278 echo Point.pl Point.pd
1279 END
1280 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001281
1282 let lines =<< trim END
1283 vim9script
1284
1285 interface View
1286 endinterface
1287
1288 class Widget
1289 this.view: View
1290 endclass
1291
1292 class MyView implements View
1293 this.widget: Widget
1294
1295 def new()
1296 # this will result in a circular reference to this object
1297 this.widget = Widget.new(this)
1298 enddef
1299 endclass
1300
1301 var view = MyView.new()
1302
1303 # overwrite "view", will be garbage-collected next
1304 view = MyView.new()
1305 test_garbagecollect_now()
1306 END
1307 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001308endfunc
1309
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001310" Test interface garbage collection
1311func Test_interface_garbagecollect()
1312 let lines =<< trim END
1313 vim9script
1314
1315 interface I
1316 static ro_class_var: number
1317 public static rw_class_var: number
1318 static _priv_class_var: number
1319 this.ro_obj_var: number
1320 public this.rw_obj_var: number
1321 this._priv_obj_var: number
1322
1323 static def ClassFoo(): number
1324 static def _ClassBar(): number
1325 def ObjFoo(): number
1326 def _ObjBar(): number
1327 endinterface
1328
1329 class A implements I
1330 static ro_class_var: number = 10
1331 public static rw_class_var: number = 20
1332 static _priv_class_var: number = 30
1333 this.ro_obj_var: number = 40
1334 public this.rw_obj_var: number = 50
1335 this._priv_obj_var: number = 60
1336
1337 static def _ClassBar(): number
1338 return _priv_class_var
1339 enddef
1340
1341 static def ClassFoo(): number
1342 return ro_class_var + rw_class_var + A._ClassBar()
1343 enddef
1344
1345 def _ObjBar(): number
1346 return this._priv_obj_var
1347 enddef
1348
1349 def ObjFoo(): number
1350 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1351 enddef
1352 endclass
1353
1354 assert_equal(60, A.ClassFoo())
1355 var o = A.new()
1356 assert_equal(150, o.ObjFoo())
1357 test_garbagecollect_now()
1358 assert_equal(60, A.ClassFoo())
1359 assert_equal(150, o.ObjFoo())
1360 END
1361 call v9.CheckScriptSuccess(lines)
1362endfunc
1363
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001364def Test_class_function()
1365 var lines =<< trim END
1366 vim9script
1367 class Value
1368 this.value = 0
1369 static objects = 0
1370
1371 def new(v: number)
1372 this.value = v
1373 ++objects
1374 enddef
1375
1376 static def GetCount(): number
1377 return objects
1378 enddef
1379 endclass
1380
1381 assert_equal(0, Value.GetCount())
1382 var v1 = Value.new(2)
1383 assert_equal(1, Value.GetCount())
1384 var v2 = Value.new(7)
1385 assert_equal(2, Value.GetCount())
1386 END
1387 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001388
1389 # Test for cleaning up after a class definition failure when using class
1390 # functions.
1391 lines =<< trim END
1392 vim9script
1393 class A
1394 static def Foo()
1395 enddef
1396 aaa
1397 endclass
1398 END
1399 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001400enddef
1401
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001402def Test_class_defcompile()
1403 var lines =<< trim END
1404 vim9script
1405
1406 class C
1407 def Fo(i: number): string
1408 return i
1409 enddef
1410 endclass
1411
1412 defcompile C.Fo
1413 END
1414 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1415
1416 lines =<< trim END
1417 vim9script
1418
1419 class C
1420 static def Fc(): number
1421 return 'x'
1422 enddef
1423 endclass
1424
1425 defcompile C.Fc
1426 END
1427 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001428
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001429 lines =<< trim END
1430 vim9script
1431
1432 class C
1433 static def new()
1434 enddef
1435 endclass
1436
1437 defcompile C.new
1438 END
1439 v9.CheckScriptFailure(lines, 'E1370: Cannot define a "new" function as static')
1440
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001441 # Trying to compile a function using a non-existing class variable
1442 lines =<< trim END
1443 vim9script
1444 defcompile x.Foo()
1445 END
1446 v9.CheckScriptFailure(lines, 'E475:')
1447
1448 # Trying to compile a function using a variable which is not a class
1449 lines =<< trim END
1450 vim9script
1451 var x: number
1452 defcompile x.Foo()
1453 END
1454 v9.CheckScriptFailure(lines, 'E475:')
1455
1456 # Trying to compile a function without specifying the name
1457 lines =<< trim END
1458 vim9script
1459 class A
1460 endclass
1461 defcompile A.
1462 END
1463 v9.CheckScriptFailure(lines, 'E475:')
1464
1465 # Trying to compile a non-existing class object member function
1466 lines =<< trim END
1467 vim9script
1468 class A
1469 endclass
1470 var a = A.new()
1471 defcompile a.Foo()
1472 END
1473 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001474enddef
1475
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001476def Test_class_object_to_string()
1477 var lines =<< trim END
1478 vim9script
1479 class TextPosition
1480 this.lnum = 1
1481 this.col = 22
1482 endclass
1483
1484 assert_equal("class TextPosition", string(TextPosition))
1485
1486 var pos = TextPosition.new()
1487 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1488 END
1489 v9.CheckScriptSuccess(lines)
1490enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001491
Bram Moolenaar554d0312023-01-05 19:59:18 +00001492def Test_interface_basics()
1493 var lines =<< trim END
1494 vim9script
1495 interface Something
1496 this.value: string
1497 static count: number
1498 def GetCount(): number
1499 endinterface
1500 END
1501 v9.CheckScriptSuccess(lines)
1502
1503 lines =<< trim END
1504 interface SomethingWrong
1505 static count = 7
1506 endinterface
1507 END
1508 v9.CheckScriptFailure(lines, 'E1342:')
1509
1510 lines =<< trim END
1511 vim9script
1512
1513 interface Some
1514 static count: number
1515 def Method(count: number)
1516 endinterface
1517 END
h-east61378a12023-04-18 19:07:29 +01001518 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001519
1520 lines =<< trim END
1521 vim9script
1522
1523 interface Some
1524 this.value: number
1525 def Method(value: number)
1526 endinterface
1527 END
h-east61378a12023-04-18 19:07:29 +01001528 # The argument name and the object member name are the same, but this is not a
1529 # problem because object members are always accessed with the "this." prefix.
1530 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001531
1532 lines =<< trim END
1533 vim9script
1534 interface somethingWrong
1535 static count = 7
1536 endinterface
1537 END
1538 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1539
1540 lines =<< trim END
1541 vim9script
1542 interface SomethingWrong
1543 this.value: string
1544 static count = 7
1545 def GetCount(): number
1546 endinterface
1547 END
1548 v9.CheckScriptFailure(lines, 'E1344:')
1549
1550 lines =<< trim END
1551 vim9script
1552 interface SomethingWrong
1553 this.value: string
1554 static count: number
1555 def GetCount(): number
1556 return 5
1557 enddef
1558 endinterface
1559 END
1560 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001561
1562 lines =<< trim END
1563 vim9script
1564 export interface EnterExit
1565 def Enter(): void
1566 def Exit(): void
1567 endinterface
1568 END
1569 writefile(lines, 'XdefIntf.vim', 'D')
1570
1571 lines =<< trim END
1572 vim9script
1573 import './XdefIntf.vim' as defIntf
1574 export def With(ee: defIntf.EnterExit, F: func)
1575 ee.Enter()
1576 try
1577 F()
1578 finally
1579 ee.Exit()
1580 endtry
1581 enddef
1582 END
1583 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001584
1585 var imported =<< trim END
1586 vim9script
1587 export abstract class EnterExit
1588 def Enter(): void
1589 enddef
1590 def Exit(): void
1591 enddef
1592 endclass
1593 END
1594 writefile(imported, 'XdefIntf2.vim', 'D')
1595
1596 lines[1] = " import './XdefIntf2.vim' as defIntf"
1597 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001598enddef
1599
Bram Moolenaar94674f22023-01-06 18:42:20 +00001600def Test_class_implements_interface()
1601 var lines =<< trim END
1602 vim9script
1603
1604 interface Some
1605 static count: number
1606 def Method(nr: number)
1607 endinterface
1608
1609 class SomeImpl implements Some
1610 static count: number
1611 def Method(nr: number)
1612 echo nr
1613 enddef
1614 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001615
1616 interface Another
1617 this.member: string
1618 endinterface
1619
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001620 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001621 this.member = 'abc'
1622 static count: number
1623 def Method(nr: number)
1624 echo nr
1625 enddef
1626 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001627 END
1628 v9.CheckScriptSuccess(lines)
1629
1630 lines =<< trim END
1631 vim9script
1632
1633 interface Some
1634 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001635 endinterface
1636
1637 class SomeImpl implements Some implements Some
1638 static count: number
1639 endclass
1640 END
1641 v9.CheckScriptFailure(lines, 'E1350:')
1642
1643 lines =<< trim END
1644 vim9script
1645
1646 interface Some
1647 static counter: number
1648 endinterface
1649
1650 class SomeImpl implements Some, Some
1651 static count: number
1652 endclass
1653 END
1654 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1655
1656 lines =<< trim END
1657 vim9script
1658
1659 interface Some
1660 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001661 def Method(nr: number)
1662 endinterface
1663
1664 class SomeImpl implements Some
1665 static count: number
1666 def Method(nr: number)
1667 echo nr
1668 enddef
1669 endclass
1670 END
1671 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1672
1673 lines =<< trim END
1674 vim9script
1675
1676 interface Some
1677 static count: number
1678 def Methods(nr: number)
1679 endinterface
1680
1681 class SomeImpl implements Some
1682 static count: number
1683 def Method(nr: number)
1684 echo nr
1685 enddef
1686 endclass
1687 END
1688 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001689
1690 # Check different order of members in class and interface works.
1691 lines =<< trim END
1692 vim9script
1693
1694 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001695 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001696 this.errpos: number
1697 endinterface
1698
1699 # order of members is opposite of interface
1700 class Failure implements Result
1701 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001702 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001703 endclass
1704
1705 def Test()
1706 var result: Result = Failure.new()
1707
1708 assert_equal('label', result.label)
1709 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001710
1711 result.label = 'different'
1712 assert_equal('different', result.label)
1713 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001714 enddef
1715
1716 Test()
1717 END
1718 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001719
1720 # Interface name after "extends" doesn't end in a space or NUL character
1721 lines =<< trim END
1722 vim9script
1723 interface A
1724 endinterface
1725 class B extends A"
1726 endclass
1727 END
1728 v9.CheckScriptFailure(lines, 'E1315:')
1729
1730 # Trailing characters after a class name
1731 lines =<< trim END
1732 vim9script
1733 class A bbb
1734 endclass
1735 END
1736 v9.CheckScriptFailure(lines, 'E488:')
1737
1738 # using "implements" with a non-existing class
1739 lines =<< trim END
1740 vim9script
1741 class A implements B
1742 endclass
1743 END
1744 v9.CheckScriptFailure(lines, 'E1346:')
1745
1746 # using "implements" with a regular class
1747 lines =<< trim END
1748 vim9script
1749 class A
1750 endclass
1751 class B implements A
1752 endclass
1753 END
1754 v9.CheckScriptFailure(lines, 'E1347:')
1755
1756 # using "implements" with a variable
1757 lines =<< trim END
1758 vim9script
1759 var T: number = 10
1760 class A implements T
1761 endclass
1762 END
1763 v9.CheckScriptFailure(lines, 'E1347:')
1764
1765 # all the class methods in an "interface" should be implemented
1766 lines =<< trim END
1767 vim9script
1768 interface A
1769 static def Foo()
1770 endinterface
1771 class B implements A
1772 endclass
1773 END
1774 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001775
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02001776 # implements should be followed by a white space
1777 lines =<< trim END
1778 vim9script
1779 interface A
1780 endinterface
1781 class B implements A;
1782 endclass
1783 END
1784 v9.CheckScriptFailure(lines, 'E1315:')
1785
LemonBoyc5d27442023-08-19 13:02:35 +02001786 lines =<< trim END
1787 vim9script
1788
1789 interface One
1790 static matching: bool
1791 static as_any: any
1792 static not_matching: number
1793 endinterface
1794 class Two implements One
1795 static not_matching: string
1796 static as_any: string
1797 static matching: bool
1798 endclass
1799 END
1800 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1801
1802 lines =<< trim END
1803 vim9script
1804
1805 interface One
1806 def IsEven(nr: number): bool
1807 endinterface
1808 class Two implements One
1809 def IsEven(nr: number): string
1810 enddef
1811 endclass
1812 END
1813 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1814
1815 lines =<< trim END
1816 vim9script
1817
1818 interface One
1819 def IsEven(nr: number): bool
1820 endinterface
1821 class Two implements One
1822 def IsEven(nr: bool): bool
1823 enddef
1824 endclass
1825 END
1826 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1827
1828 lines =<< trim END
1829 vim9script
1830
1831 interface One
1832 def IsEven(nr: number): bool
1833 endinterface
1834 class Two implements One
1835 def IsEven(nr: number, ...extra: list<number>): bool
1836 enddef
1837 endclass
1838 END
1839 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 +00001840enddef
1841
Bram Moolenaard0200c82023-01-28 15:19:40 +00001842def Test_call_interface_method()
1843 var lines =<< trim END
1844 vim9script
1845 interface Base
1846 def Enter(): void
1847 endinterface
1848
1849 class Child implements Base
1850 def Enter(): void
1851 g:result ..= 'child'
1852 enddef
1853 endclass
1854
1855 def F(obj: Base)
1856 obj.Enter()
1857 enddef
1858
1859 g:result = ''
1860 F(Child.new())
1861 assert_equal('child', g:result)
1862 unlet g:result
1863 END
1864 v9.CheckScriptSuccess(lines)
1865
1866 lines =<< trim END
1867 vim9script
1868 class Base
1869 def Enter(): void
1870 g:result ..= 'base'
1871 enddef
1872 endclass
1873
1874 class Child extends Base
1875 def Enter(): void
1876 g:result ..= 'child'
1877 enddef
1878 endclass
1879
1880 def F(obj: Base)
1881 obj.Enter()
1882 enddef
1883
1884 g:result = ''
1885 F(Child.new())
1886 assert_equal('child', g:result)
1887 unlet g:result
1888 END
1889 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001890
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001891 # method of interface returns a value
1892 lines =<< trim END
1893 vim9script
1894 interface Base
1895 def Enter(): string
1896 endinterface
1897
1898 class Child implements Base
1899 def Enter(): string
1900 g:result ..= 'child'
1901 return "/resource"
1902 enddef
1903 endclass
1904
1905 def F(obj: Base)
1906 var r = obj.Enter()
1907 g:result ..= r
1908 enddef
1909
1910 g:result = ''
1911 F(Child.new())
1912 assert_equal('child/resource', g:result)
1913 unlet g:result
1914 END
1915 v9.CheckScriptSuccess(lines)
1916
1917 lines =<< trim END
1918 vim9script
1919 class Base
1920 def Enter(): string
1921 return null_string
1922 enddef
1923 endclass
1924
1925 class Child extends Base
1926 def Enter(): string
1927 g:result ..= 'child'
1928 return "/resource"
1929 enddef
1930 endclass
1931
1932 def F(obj: Base)
1933 var r = obj.Enter()
1934 g:result ..= r
1935 enddef
1936
1937 g:result = ''
1938 F(Child.new())
1939 assert_equal('child/resource', g:result)
1940 unlet g:result
1941 END
1942 v9.CheckScriptSuccess(lines)
1943
1944
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001945 # No class that implements the interface.
1946 lines =<< trim END
1947 vim9script
1948
1949 interface IWithEE
1950 def Enter(): any
1951 def Exit(): void
1952 endinterface
1953
1954 def With1(ee: IWithEE, F: func)
1955 var r = ee.Enter()
1956 enddef
1957
1958 defcompile
1959 END
1960 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001961enddef
1962
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001963def Test_class_used_as_type()
1964 var lines =<< trim END
1965 vim9script
1966
1967 class Point
1968 this.x = 0
1969 this.y = 0
1970 endclass
1971
1972 var p: Point
1973 p = Point.new(2, 33)
1974 assert_equal(2, p.x)
1975 assert_equal(33, p.y)
1976 END
1977 v9.CheckScriptSuccess(lines)
1978
1979 lines =<< trim END
1980 vim9script
1981
1982 interface HasX
1983 this.x: number
1984 endinterface
1985
1986 class Point implements HasX
1987 this.x = 0
1988 this.y = 0
1989 endclass
1990
1991 var p: Point
1992 p = Point.new(2, 33)
1993 var hx = p
1994 assert_equal(2, hx.x)
1995 END
1996 v9.CheckScriptSuccess(lines)
1997
1998 lines =<< trim END
1999 vim9script
2000
2001 class Point
2002 this.x = 0
2003 this.y = 0
2004 endclass
2005
2006 var p: Point
2007 p = 'text'
2008 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002009 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002010enddef
2011
Bram Moolenaar83677162023-01-08 19:54:10 +00002012def Test_class_extends()
2013 var lines =<< trim END
2014 vim9script
2015 class Base
2016 this.one = 1
2017 def GetOne(): number
2018 return this.one
2019 enddef
2020 endclass
2021 class Child extends Base
2022 this.two = 2
2023 def GetTotal(): number
2024 return this.one + this.two
2025 enddef
2026 endclass
2027 var o = Child.new()
2028 assert_equal(1, o.one)
2029 assert_equal(2, o.two)
2030 assert_equal(1, o.GetOne())
2031 assert_equal(3, o.GetTotal())
2032 END
2033 v9.CheckScriptSuccess(lines)
2034
2035 lines =<< trim END
2036 vim9script
2037 class Base
2038 this.one = 1
2039 endclass
2040 class Child extends Base
2041 this.two = 2
2042 endclass
2043 var o = Child.new(3, 44)
2044 assert_equal(3, o.one)
2045 assert_equal(44, o.two)
2046 END
2047 v9.CheckScriptSuccess(lines)
2048
2049 lines =<< trim END
2050 vim9script
2051 class Base
2052 this.one = 1
2053 endclass
2054 class Child extends Base extends Base
2055 this.two = 2
2056 endclass
2057 END
2058 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
2059
2060 lines =<< trim END
2061 vim9script
2062 class Child extends BaseClass
2063 this.two = 2
2064 endclass
2065 END
2066 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
2067
2068 lines =<< trim END
2069 vim9script
2070 var SomeVar = 99
2071 class Child extends SomeVar
2072 this.two = 2
2073 endclass
2074 END
2075 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002076
2077 lines =<< trim END
2078 vim9script
2079 class Base
2080 this.name: string
2081 def ToString(): string
2082 return this.name
2083 enddef
2084 endclass
2085
2086 class Child extends Base
2087 this.age: number
2088 def ToString(): string
2089 return super.ToString() .. ': ' .. this.age
2090 enddef
2091 endclass
2092
2093 var o = Child.new('John', 42)
2094 assert_equal('John: 42', o.ToString())
2095 END
2096 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002097
2098 lines =<< trim END
2099 vim9script
2100 class Child
2101 this.age: number
2102 def ToString(): number
2103 return this.age
2104 enddef
2105 def ToString(): string
2106 return this.age
2107 enddef
2108 endclass
2109 END
2110 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
2111
2112 lines =<< trim END
2113 vim9script
2114 class Child
2115 this.age: number
2116 def ToString(): string
2117 return super .ToString() .. ': ' .. this.age
2118 enddef
2119 endclass
2120 var o = Child.new(42)
2121 echo o.ToString()
2122 END
2123 v9.CheckScriptFailure(lines, 'E1356:')
2124
2125 lines =<< trim END
2126 vim9script
2127 class Base
2128 this.name: string
2129 def ToString(): string
2130 return this.name
2131 enddef
2132 endclass
2133
2134 var age = 42
2135 def ToString(): string
2136 return super.ToString() .. ': ' .. age
2137 enddef
2138 echo ToString()
2139 END
2140 v9.CheckScriptFailure(lines, 'E1357:')
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, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002154
2155 lines =<< trim END
2156 vim9script
2157 class Base
2158 this.name: string
2159 static def ToString(): string
2160 return 'Base class'
2161 enddef
2162 endclass
2163
2164 class Child extends Base
2165 this.age: number
2166 def ToString(): string
2167 return Base.ToString() .. ': ' .. this.age
2168 enddef
2169 endclass
2170
2171 var o = Child.new('John', 42)
2172 assert_equal('Base class: 42', o.ToString())
2173 END
2174 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002175
2176 lines =<< trim END
2177 vim9script
2178 class Base
2179 this.value = 1
2180 def new(init: number)
2181 this.value = number + 1
2182 enddef
2183 endclass
2184 class Child extends Base
2185 def new()
2186 this.new(3)
2187 enddef
2188 endclass
2189 var c = Child.new()
2190 END
2191 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002192
2193 # base class with more than one object member
2194 lines =<< trim END
2195 vim9script
2196
2197 class Result
2198 this.success: bool
2199 this.value: any = null
2200 endclass
2201
2202 class Success extends Result
2203 def new(this.value = v:none)
2204 this.success = true
2205 enddef
2206 endclass
2207
2208 var v = Success.new('asdf')
2209 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2210 END
2211 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002212
2213 # class name after "extends" doesn't end in a space or NUL character
2214 lines =<< trim END
2215 vim9script
2216 class A
2217 endclass
2218 class B extends A"
2219 endclass
2220 END
2221 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002222enddef
2223
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002224def Test_using_base_class()
2225 var lines =<< trim END
2226 vim9script
2227
2228 class BaseEE
2229 def Enter(): any
2230 return null
2231 enddef
2232 def Exit(resource: any): void
2233 enddef
2234 endclass
2235
2236 class ChildEE extends BaseEE
2237 def Enter(): any
2238 return 42
2239 enddef
2240
2241 def Exit(resource: number): void
2242 g:result ..= '/exit'
2243 enddef
2244 endclass
2245
2246 def With(ee: BaseEE)
2247 var r = ee.Enter()
2248 try
2249 g:result ..= r
2250 finally
2251 g:result ..= '/finally'
2252 ee.Exit(r)
2253 endtry
2254 enddef
2255
2256 g:result = ''
2257 With(ChildEE.new())
2258 assert_equal('42/finally/exit', g:result)
2259 END
2260 v9.CheckScriptSuccess(lines)
2261 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002262
2263 # Using super, Child invokes Base method which has optional arg. #12471
2264 lines =<< trim END
2265 vim9script
2266
2267 class Base
2268 this.success: bool = false
2269 def Method(arg = 0)
2270 this.success = true
2271 enddef
2272 endclass
2273
2274 class Child extends Base
2275 def new()
2276 super.Method()
2277 enddef
2278 endclass
2279
2280 var obj = Child.new()
2281 assert_equal(true, obj.success)
2282 END
2283 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002284enddef
2285
2286
Bram Moolenaara86655a2023-01-12 17:06:27 +00002287def Test_class_import()
2288 var lines =<< trim END
2289 vim9script
2290 export class Animal
2291 this.kind: string
2292 this.name: string
2293 endclass
2294 END
2295 writefile(lines, 'Xanimal.vim', 'D')
2296
2297 lines =<< trim END
2298 vim9script
2299 import './Xanimal.vim' as animal
2300
2301 var a: animal.Animal
2302 a = animal.Animal.new('fish', 'Eric')
2303 assert_equal('fish', a.kind)
2304 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002305
2306 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2307 assert_equal('cat', b.kind)
2308 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002309 END
2310 v9.CheckScriptSuccess(lines)
2311enddef
2312
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002313def Test_abstract_class()
2314 var lines =<< trim END
2315 vim9script
2316 abstract class Base
2317 this.name: string
2318 endclass
2319 class Person extends Base
2320 this.age: number
2321 endclass
2322 var p: Base = Person.new('Peter', 42)
2323 assert_equal('Peter', p.name)
2324 assert_equal(42, p.age)
2325 END
2326 v9.CheckScriptSuccess(lines)
2327
2328 lines =<< trim END
2329 vim9script
2330 abstract class Base
2331 this.name: string
2332 endclass
2333 class Person extends Base
2334 this.age: number
2335 endclass
2336 var p = Base.new('Peter')
2337 END
2338 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2339
2340 lines =<< trim END
2341 abstract class Base
2342 this.name: string
2343 endclass
2344 END
2345 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002346
2347 # Abstract class cannot have a "new" function
2348 lines =<< trim END
2349 vim9script
2350 abstract class Base
2351 def new()
2352 enddef
2353 endclass
2354 END
2355 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002356enddef
2357
Bram Moolenaar486fc252023-01-18 14:51:07 +00002358def Test_closure_in_class()
2359 var lines =<< trim END
2360 vim9script
2361
2362 class Foo
2363 this.y: list<string> = ['B']
2364
2365 def new()
2366 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2367 enddef
2368 endclass
2369
2370 Foo.new()
2371 assert_equal(['A'], g:result)
2372 END
2373 v9.CheckScriptSuccess(lines)
2374enddef
2375
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002376def Test_call_constructor_from_legacy()
2377 var lines =<< trim END
2378 vim9script
2379
2380 var newCalled = 'false'
2381
2382 class A
2383 def new()
2384 newCalled = 'true'
2385 enddef
2386 endclass
2387
2388 export def F(options = {}): any
2389 return A
2390 enddef
2391
2392 g:p = F()
2393 legacy call p.new()
2394 assert_equal('true', newCalled)
2395 END
2396 v9.CheckScriptSuccess(lines)
2397enddef
2398
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002399def Test_defer_with_object()
2400 var lines =<< trim END
2401 vim9script
2402
2403 class CWithEE
2404 def Enter()
2405 g:result ..= "entered/"
2406 enddef
2407 def Exit()
2408 g:result ..= "exited"
2409 enddef
2410 endclass
2411
2412 def With(ee: CWithEE, F: func)
2413 ee.Enter()
2414 defer ee.Exit()
2415 F()
2416 enddef
2417
2418 g:result = ''
2419 var obj = CWithEE.new()
2420 obj->With(() => {
2421 g:result ..= "called/"
2422 })
2423 assert_equal('entered/called/exited', g:result)
2424 END
2425 v9.CheckScriptSuccess(lines)
2426 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002427
2428 lines =<< trim END
2429 vim9script
2430
2431 class BaseWithEE
2432 def Enter()
2433 g:result ..= "entered-base/"
2434 enddef
2435 def Exit()
2436 g:result ..= "exited-base"
2437 enddef
2438 endclass
2439
2440 class CWithEE extends BaseWithEE
2441 def Enter()
2442 g:result ..= "entered-child/"
2443 enddef
2444 def Exit()
2445 g:result ..= "exited-child"
2446 enddef
2447 endclass
2448
2449 def With(ee: BaseWithEE, F: func)
2450 ee.Enter()
2451 defer ee.Exit()
2452 F()
2453 enddef
2454
2455 g:result = ''
2456 var obj = CWithEE.new()
2457 obj->With(() => {
2458 g:result ..= "called/"
2459 })
2460 assert_equal('entered-child/called/exited-child', g:result)
2461 END
2462 v9.CheckScriptSuccess(lines)
2463 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002464enddef
2465
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002466" The following test used to crash Vim (Github issue #12676)
2467def Test_extends_method_crashes_vim()
2468 var lines =<< trim END
2469 vim9script
2470
2471 class Observer
2472 endclass
2473
2474 class Property
2475 this.value: any
2476
2477 def Set(v: any)
2478 if v != this.value
2479 this.value = v
2480 endif
2481 enddef
2482
2483 def Register(observer: Observer)
2484 enddef
2485 endclass
2486
2487 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002488 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002489 endclass
2490
2491 def Observe(obj: Property, who: Observer)
2492 obj.Register(who)
2493 enddef
2494
2495 var p = Bool.new(false)
2496 var myObserver = Observer.new()
2497
2498 Observe(p, myObserver)
2499
2500 p.Set(true)
2501 END
2502 v9.CheckScriptSuccess(lines)
2503enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002504
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002505" Test for calling a method in a class that is extended
2506def Test_call_method_in_extended_class()
2507 var lines =<< trim END
2508 vim9script
2509
2510 var prop_init_called = false
2511 var prop_register_called = false
2512
2513 class Property
2514 def Init()
2515 prop_init_called = true
2516 enddef
2517
2518 def Register()
2519 prop_register_called = true
2520 enddef
2521 endclass
2522
2523 class Bool extends Property
2524 endclass
2525
2526 def Observe(obj: Property)
2527 obj.Register()
2528 enddef
2529
2530 var p = Property.new()
2531 Observe(p)
2532
2533 p.Init()
2534 assert_true(prop_init_called)
2535 assert_true(prop_register_called)
2536 END
2537 v9.CheckScriptSuccess(lines)
2538enddef
2539
LemonBoyafe04662023-08-23 21:08:11 +02002540def Test_instanceof()
2541 var lines =<< trim END
2542 vim9script
2543
2544 class Base1
2545 endclass
2546
2547 class Base2 extends Base1
2548 endclass
2549
2550 interface Intf1
2551 endinterface
2552
2553 class Mix1 implements Intf1
2554 endclass
2555
2556 class Base3 extends Mix1
2557 endclass
2558
2559 var b1 = Base1.new()
2560 var b2 = Base2.new()
2561 var b3 = Base3.new()
2562
2563 assert_true(instanceof(b1, Base1))
2564 assert_true(instanceof(b2, Base1))
2565 assert_false(instanceof(b1, Base2))
2566 assert_true(instanceof(b3, Mix1))
2567 assert_false(instanceof(b3, []))
2568 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002569
2570 def Foo()
2571 var a1 = Base1.new()
2572 var a2 = Base2.new()
2573 var a3 = Base3.new()
2574
2575 assert_true(instanceof(a1, Base1))
2576 assert_true(instanceof(a2, Base1))
2577 assert_false(instanceof(a1, Base2))
2578 assert_true(instanceof(a3, Mix1))
2579 assert_false(instanceof(a3, []))
2580 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2581 enddef
2582 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002583 END
2584 v9.CheckScriptSuccess(lines)
2585enddef
2586
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002587" Test for calling a method in the parent class that is extended partially.
2588" This used to fail with the 'E118: Too many arguments for function: Text' error
2589" message (Github issue #12524).
2590def Test_call_method_in_parent_class()
2591 var lines =<< trim END
2592 vim9script
2593
2594 class Widget
2595 this._lnum: number = 1
2596
2597 def SetY(lnum: number)
2598 this._lnum = lnum
2599 enddef
2600
2601 def Text(): string
2602 return ''
2603 enddef
2604 endclass
2605
2606 class Foo extends Widget
2607 def Text(): string
2608 return '<Foo>'
2609 enddef
2610 endclass
2611
2612 def Stack(w1: Widget, w2: Widget): list<Widget>
2613 w1.SetY(1)
2614 w2.SetY(2)
2615 return [w1, w2]
2616 enddef
2617
2618 var foo1 = Foo.new()
2619 var foo2 = Foo.new()
2620 var l = Stack(foo1, foo2)
2621 END
2622 v9.CheckScriptSuccess(lines)
2623enddef
2624
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002625" Test for calling methods from three levels of classes
2626def Test_multi_level_method_call()
2627 var lines =<< trim END
2628 vim9script
2629
2630 var A_func1: number = 0
2631 var A_func2: number = 0
2632 var A_func3: number = 0
2633 var B_func2: number = 0
2634 var B_func3: number = 0
2635 var C_func3: number = 0
2636
2637 class A
2638 def Func1()
2639 A_func1 += 1
2640 enddef
2641
2642 def Func2()
2643 A_func2 += 1
2644 enddef
2645
2646 def Func3()
2647 A_func3 += 1
2648 enddef
2649 endclass
2650
2651 class B extends A
2652 def Func2()
2653 B_func2 += 1
2654 enddef
2655
2656 def Func3()
2657 B_func3 += 1
2658 enddef
2659 endclass
2660
2661 class C extends B
2662 def Func3()
2663 C_func3 += 1
2664 enddef
2665 endclass
2666
2667 def A_CallFuncs(a: A)
2668 a.Func1()
2669 a.Func2()
2670 a.Func3()
2671 enddef
2672
2673 def B_CallFuncs(b: B)
2674 b.Func1()
2675 b.Func2()
2676 b.Func3()
2677 enddef
2678
2679 def C_CallFuncs(c: C)
2680 c.Func1()
2681 c.Func2()
2682 c.Func3()
2683 enddef
2684
2685 var cobj = C.new()
2686 A_CallFuncs(cobj)
2687 B_CallFuncs(cobj)
2688 C_CallFuncs(cobj)
2689 assert_equal(3, A_func1)
2690 assert_equal(0, A_func2)
2691 assert_equal(0, A_func3)
2692 assert_equal(3, B_func2)
2693 assert_equal(0, B_func3)
2694 assert_equal(3, C_func3)
2695 END
2696 v9.CheckScriptSuccess(lines)
2697enddef
2698
2699" Test for using members from three levels of classes
2700def Test_multi_level_member_access()
2701 var lines =<< trim END
2702 vim9script
2703
2704 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002705 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002706 endclass
2707
2708 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002709 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002710 endclass
2711
2712 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002713 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002714 endclass
2715
2716 def A_members(a: A)
2717 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002718 enddef
2719
2720 def B_members(b: B)
2721 b.val1 += 1
2722 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002723 enddef
2724
2725 def C_members(c: C)
2726 c.val1 += 1
2727 c.val2 += 1
2728 c.val3 += 1
2729 enddef
2730
2731 var cobj = C.new()
2732 A_members(cobj)
2733 B_members(cobj)
2734 C_members(cobj)
2735 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002736 assert_equal(2, cobj.val2)
2737 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002738 END
2739 v9.CheckScriptSuccess(lines)
2740enddef
2741
LemonBoy0ffc17a2023-08-20 18:09:11 +02002742" Test expansion of <stack> with class methods.
2743def Test_stack_expansion_with_methods()
2744 var lines =<< trim END
2745 vim9script
2746
2747 class C
2748 def M1()
2749 F0()
2750 enddef
2751 endclass
2752
2753 def F0()
2754 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2755 enddef
2756
2757 def F()
2758 C.new().M1()
2759 enddef
2760
2761 F()
2762 END
2763 v9.CheckScriptSuccess(lines)
2764enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002765
2766" Test the return type of the new() constructor
2767def Test_new_return_type()
2768 # new() uses the default return type and there is no return statement
2769 var lines =<< trim END
2770 vim9script
2771
2772 class C
2773 this._bufnr: number
2774
2775 def new(this._bufnr)
2776 if !bufexists(this._bufnr)
2777 this._bufnr = -1
2778 endif
2779 enddef
2780 endclass
2781
2782 var c = C.new(12345)
2783 assert_equal('object<C>', typename(c))
2784
2785 var v1: C
2786 v1 = C.new(12345)
2787 assert_equal('object<C>', typename(v1))
2788
2789 def F()
2790 var v2: C
2791 v2 = C.new(12345)
2792 assert_equal('object<C>', typename(v2))
2793 enddef
2794 F()
2795 END
2796 v9.CheckScriptSuccess(lines)
2797
2798 # new() uses the default return type and an empty 'return' statement
2799 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 return
2809 endif
2810 enddef
2811 endclass
2812
2813 var c = C.new(12345)
2814 assert_equal('object<C>', typename(c))
2815
2816 var v1: C
2817 v1 = C.new(12345)
2818 assert_equal('object<C>', typename(v1))
2819
2820 def F()
2821 var v2: C
2822 v2 = C.new(12345)
2823 assert_equal('object<C>', typename(v2))
2824 enddef
2825 F()
2826 END
2827 v9.CheckScriptSuccess(lines)
2828
2829 # new() uses "any" return type and returns "this"
2830 lines =<< trim END
2831 vim9script
2832
2833 class C
2834 this._bufnr: number
2835
2836 def new(this._bufnr): any
2837 if !bufexists(this._bufnr)
2838 this._bufnr = -1
2839 return this
2840 endif
2841 enddef
2842 endclass
2843 END
2844 v9.CheckScriptFailure(lines, 'E1365:')
2845
2846 # new() uses 'Dict' return type and returns a Dict
2847 lines =<< trim END
2848 vim9script
2849
2850 class C
2851 this._state: dict<any>
2852
2853 def new(): dict<any>
2854 this._state = {}
2855 return this._state
2856 enddef
2857 endclass
2858
2859 var c = C.new()
2860 assert_equal('object<C>', typename(c))
2861 END
2862 v9.CheckScriptFailure(lines, 'E1365:')
2863enddef
2864
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02002865" Test for checking a member initialization type at run time.
2866def Test_runtime_type_check_for_member_init()
2867 var lines =<< trim END
2868 vim9script
2869
2870 var retnum: bool = false
2871
2872 def F(): any
2873 retnum = !retnum
2874 if retnum
2875 return 1
2876 else
2877 return "hello"
2878 endif
2879 enddef
2880
2881 class C
2882 this._foo: bool = F()
2883 endclass
2884
2885 var c1 = C.new()
2886 var c2 = C.new()
2887 END
2888 v9.CheckScriptFailure(lines, 'E1012:')
2889enddef
2890
2891" Test for locking a variable referring to an object and reassigning to another
2892" object.
2893def Test_object_lockvar()
2894 var lines =<< trim END
2895 vim9script
2896
2897 class C
2898 this.val: number
2899 def new(this.val)
2900 enddef
2901 endclass
2902
2903 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
2904 lockvar 2 some_dict
2905
2906 var current: C
2907 current = some_dict['c']
2908 assert_equal(3, current.val)
2909 current = some_dict['b']
2910 assert_equal(2, current.val)
2911
2912 def F()
2913 current = some_dict['c']
2914 enddef
2915
2916 def G()
2917 current = some_dict['b']
2918 enddef
2919
2920 F()
2921 assert_equal(3, current.val)
2922 G()
2923 assert_equal(2, current.val)
2924 END
2925 v9.CheckScriptSuccess(lines)
2926enddef
2927
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02002928" Test for a private object method
2929def Test_private_object_method()
2930 # Try calling a private method using an object (at the script level)
2931 var lines =<< trim END
2932 vim9script
2933
2934 class A
2935 def _Foo(): number
2936 return 1234
2937 enddef
2938 endclass
2939 var a = A.new()
2940 a._Foo()
2941 END
2942 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2943
2944 # Try calling a private method using an object (from a def function)
2945 lines =<< trim END
2946 vim9script
2947
2948 class A
2949 def _Foo(): number
2950 return 1234
2951 enddef
2952 endclass
2953 def T()
2954 var a = A.new()
2955 a._Foo()
2956 enddef
2957 T()
2958 END
2959 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2960
2961 # Use a private method from another object method (in script context)
2962 lines =<< trim END
2963 vim9script
2964
2965 class A
2966 def _Foo(): number
2967 return 1234
2968 enddef
2969 def Bar(): number
2970 return this._Foo()
2971 enddef
2972 endclass
2973 var a = A.new()
2974 assert_equal(1234, a.Bar())
2975 END
2976 v9.CheckScriptSuccess(lines)
2977
2978 # Use a private method from another object method (def function context)
2979 lines =<< trim END
2980 vim9script
2981
2982 class A
2983 def _Foo(): number
2984 return 1234
2985 enddef
2986 def Bar(): number
2987 return this._Foo()
2988 enddef
2989 endclass
2990 def T()
2991 var a = A.new()
2992 assert_equal(1234, a.Bar())
2993 enddef
2994 T()
2995 END
2996 v9.CheckScriptSuccess(lines)
2997
2998 # Try calling a private method without the "this" prefix
2999 lines =<< trim END
3000 vim9script
3001
3002 class A
3003 def _Foo(): number
3004 return 1234
3005 enddef
3006 def Bar(): number
3007 return _Foo()
3008 enddef
3009 endclass
3010 var a = A.new()
3011 a.Bar()
3012 END
3013 v9.CheckScriptFailure(lines, 'E117: Unknown function: _Foo')
3014
3015 # Try calling a private method using the class name
3016 lines =<< trim END
3017 vim9script
3018
3019 class A
3020 def _Foo(): number
3021 return 1234
3022 enddef
3023 endclass
3024 A._Foo()
3025 END
3026 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3027
3028 # Try to use "public" keyword when defining a private method
3029 lines =<< trim END
3030 vim9script
3031
3032 class A
3033 public def _Foo()
3034 enddef
3035 endclass
3036 var a = A.new()
3037 a._Foo()
3038 END
3039 v9.CheckScriptFailure(lines, 'E1331: Public must be followed by "this" or "static"')
3040
3041 # Define two private methods with the same name
3042 lines =<< trim END
3043 vim9script
3044
3045 class A
3046 def _Foo()
3047 enddef
3048 def _Foo()
3049 enddef
3050 endclass
3051 var a = A.new()
3052 END
3053 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3054
3055 # Define a private method and a object method with the same name
3056 lines =<< trim END
3057 vim9script
3058
3059 class A
3060 def _Foo()
3061 enddef
3062 def Foo()
3063 enddef
3064 endclass
3065 var a = A.new()
3066 END
3067 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3068
3069 # Define an object method and a private method with the same name
3070 lines =<< trim END
3071 vim9script
3072
3073 class A
3074 def Foo()
3075 enddef
3076 def _Foo()
3077 enddef
3078 endclass
3079 var a = A.new()
3080 END
3081 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3082
3083 # Call a public method and a private method from a private method
3084 lines =<< trim END
3085 vim9script
3086
3087 class A
3088 def Foo(): number
3089 return 100
3090 enddef
3091 def _Bar(): number
3092 return 200
3093 enddef
3094 def _Baz()
3095 assert_equal(100, this.Foo())
3096 assert_equal(200, this._Bar())
3097 enddef
3098 def T()
3099 this._Baz()
3100 enddef
3101 endclass
3102 var a = A.new()
3103 a.T()
3104 END
3105 v9.CheckScriptSuccess(lines)
3106
3107 # Try calling a private method from another class
3108 lines =<< trim END
3109 vim9script
3110
3111 class A
3112 def _Foo(): number
3113 return 100
3114 enddef
3115 endclass
3116 class B
3117 def Foo(): number
3118 var a = A.new()
3119 a._Foo()
3120 enddef
3121 endclass
3122 var b = B.new()
3123 b.Foo()
3124 END
3125 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3126
3127 # Call a private object method from a child class object method
3128 lines =<< trim END
3129 vim9script
3130 class A
3131 def _Foo(): number
3132 return 1234
3133 enddef
3134 endclass
3135 class B extends A
3136 def Bar()
3137 enddef
3138 endclass
3139 class C extends B
3140 def Baz(): number
3141 return this._Foo()
3142 enddef
3143 endclass
3144 var c = C.new()
3145 assert_equal(1234, c.Baz())
3146 END
3147 v9.CheckScriptSuccess(lines)
3148
3149 # Call a private object method from a child class object
3150 lines =<< trim END
3151 vim9script
3152 class A
3153 def _Foo(): number
3154 return 1234
3155 enddef
3156 endclass
3157 class B extends A
3158 def Bar()
3159 enddef
3160 endclass
3161 class C extends B
3162 def Baz(): number
3163 enddef
3164 endclass
3165 var c = C.new()
3166 assert_equal(1234, c._Foo())
3167 END
3168 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3169
3170 # Using "_" prefix in a method name should fail outside of a class
3171 lines =<< trim END
3172 vim9script
3173 def _Foo(): number
3174 return 1234
3175 enddef
3176 var a = _Foo()
3177 END
3178 v9.CheckScriptFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
3179enddef
3180
3181" Test for an private class method
3182def Test_private_class_method()
3183 # Try calling a class private method (at the script level)
3184 var lines =<< trim END
3185 vim9script
3186
3187 class A
3188 static def _Foo(): number
3189 return 1234
3190 enddef
3191 endclass
3192 A._Foo()
3193 END
3194 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3195
3196 # Try calling a class private method (from a def function)
3197 lines =<< trim END
3198 vim9script
3199
3200 class A
3201 static def _Foo(): number
3202 return 1234
3203 enddef
3204 endclass
3205 def T()
3206 A._Foo()
3207 enddef
3208 T()
3209 END
3210 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3211
3212 # Try calling a class private method using an object (at the script level)
3213 lines =<< trim END
3214 vim9script
3215
3216 class A
3217 static def _Foo(): number
3218 return 1234
3219 enddef
3220 endclass
3221 var a = A.new()
3222 a._Foo()
3223 END
3224 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3225
3226 # Try calling a class private method using an object (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 var a = A.new()
3237 a._Foo()
3238 enddef
3239 T()
3240 END
3241 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3242
3243 # Use a class private method from an object method
3244 lines =<< trim END
3245 vim9script
3246
3247 class A
3248 static def _Foo(): number
3249 return 1234
3250 enddef
3251 def Bar()
3252 assert_equal(1234, A._Foo())
3253 enddef
3254 endclass
3255 var a = A.new()
3256 a.Bar()
3257 END
3258 v9.CheckScriptSuccess(lines)
3259
3260 # Use a class private method from another class private method
3261 lines =<< trim END
3262 vim9script
3263
3264 class A
3265 static def _Foo1(): number
3266 return 1234
3267 enddef
3268 static def _Foo2()
3269 assert_equal(1234, A._Foo1())
3270 enddef
3271 def Bar()
3272 A._Foo2()
3273 enddef
3274 endclass
3275 var a = A.new()
3276 a.Bar()
3277 END
3278 v9.CheckScriptSuccess(lines)
3279
3280 # Declare a class method and a class private method with the same name
3281 lines =<< trim END
3282 vim9script
3283
3284 class A
3285 static def _Foo()
3286 enddef
3287 static def Foo()
3288 enddef
3289 endclass
3290 var a = A.new()
3291 END
3292 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3293
3294 # Try calling a class private method from another class
3295 lines =<< trim END
3296 vim9script
3297
3298 class A
3299 static def _Foo(): number
3300 return 1234
3301 enddef
3302 endclass
3303 class B
3304 def Foo(): number
3305 return A._Foo()
3306 enddef
3307 endclass
3308 var b = B.new()
3309 assert_equal(1234, b.Foo())
3310 END
3311 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3312
3313 # Call a private class method from a child class object method
3314 lines =<< trim END
3315 vim9script
3316 class A
3317 static def _Foo(): number
3318 return 1234
3319 enddef
3320 endclass
3321 class B extends A
3322 def Bar()
3323 enddef
3324 endclass
3325 class C extends B
3326 def Baz(): number
3327 return A._Foo()
3328 enddef
3329 endclass
3330 var c = C.new()
3331 assert_equal(1234, c.Baz())
3332 END
3333 v9.CheckScriptSuccess(lines)
3334
3335 # Call a private class method from a child class private class method
3336 lines =<< trim END
3337 vim9script
3338 class A
3339 static def _Foo(): number
3340 return 1234
3341 enddef
3342 endclass
3343 class B extends A
3344 def Bar()
3345 enddef
3346 endclass
3347 class C extends B
3348 static def Baz(): number
3349 return A._Foo()
3350 enddef
3351 endclass
3352 assert_equal(1234, C.Baz())
3353 END
3354 v9.CheckScriptSuccess(lines)
3355
3356 # Call a private class method from a child class object
3357 lines =<< trim END
3358 vim9script
3359 class A
3360 static def _Foo(): number
3361 return 1234
3362 enddef
3363 endclass
3364 class B extends A
3365 def Bar()
3366 enddef
3367 endclass
3368 class C extends B
3369 def Baz(): number
3370 enddef
3371 endclass
3372 var c = C.new()
3373 assert_equal(1234, C._Foo())
3374 END
3375 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3376enddef
3377
3378" Test for an interface private object_method
3379def Test_interface_private_object_method()
3380 # Implement an interface private method and use it from a public method
3381 var lines =<< trim END
3382 vim9script
3383 interface Intf
3384 def _Foo(): number
3385 endinterface
3386 class A implements Intf
3387 def _Foo(): number
3388 return 1234
3389 enddef
3390 def Bar(): number
3391 return this._Foo()
3392 enddef
3393 endclass
3394 var a = A.new()
3395 assert_equal(1234, a.Bar())
3396 END
3397 v9.CheckScriptSuccess(lines)
3398
3399 # Call an interface private class method (script context)
3400 lines =<< trim END
3401 vim9script
3402 interface Intf
3403 def _Foo(): number
3404 endinterface
3405 class A implements Intf
3406 def _Foo(): number
3407 return 1234
3408 enddef
3409 endclass
3410 var a = A.new()
3411 assert_equal(1234, a._Foo())
3412 END
3413 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3414
3415 # Call an interface private class method (def context)
3416 lines =<< trim END
3417 vim9script
3418 interface Intf
3419 def _Foo(): number
3420 endinterface
3421 class A implements Intf
3422 def _Foo(): number
3423 return 1234
3424 enddef
3425 endclass
3426 def T()
3427 var a = A.new()
3428 assert_equal(1234, a._Foo())
3429 enddef
3430 T()
3431 END
3432 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3433
3434 # Implement an interface private object method as a private class method
3435 lines =<< trim END
3436 vim9script
3437 interface Intf
3438 def _Foo(): number
3439 endinterface
3440 class A implements Intf
3441 static def _Foo(): number
3442 return 1234
3443 enddef
3444 endclass
3445 END
3446 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3447enddef
3448
3449" Test for an interface private class method
3450def Test_interface_private_class_method()
3451 # Implement an interface private class method and use it from a public method
3452 var lines =<< trim END
3453 vim9script
3454 interface Intf
3455 static def _Foo(): number
3456 endinterface
3457 class A implements Intf
3458 static def _Foo(): number
3459 return 1234
3460 enddef
3461 def Bar(): number
3462 return A._Foo()
3463 enddef
3464 endclass
3465 var a = A.new()
3466 assert_equal(1234, a.Bar())
3467 END
3468 v9.CheckScriptSuccess(lines)
3469
3470 # Call an interface private class method (script context)
3471 lines =<< trim END
3472 vim9script
3473 interface Intf
3474 static def _Foo(): number
3475 endinterface
3476 class A implements Intf
3477 static def _Foo(): number
3478 return 1234
3479 enddef
3480 endclass
3481 assert_equal(1234, A._Foo())
3482 END
3483 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3484
3485 # Call an interface private class method (def context)
3486 lines =<< trim END
3487 vim9script
3488 interface Intf
3489 static def _Foo(): number
3490 endinterface
3491 class A implements Intf
3492 static def _Foo(): number
3493 return 1234
3494 enddef
3495 endclass
3496 def T()
3497 assert_equal(1234, A._Foo())
3498 enddef
3499 T()
3500 END
3501 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3502
3503 # Implement an interface private class method as a private object method
3504 lines =<< trim END
3505 vim9script
3506 interface Intf
3507 static def _Foo(): number
3508 endinterface
3509 class A implements Intf
3510 def _Foo(): number
3511 return 1234
3512 enddef
3513 endclass
3514 END
3515 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3516enddef
3517
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003518" Test for using the return value of a class/object method as a function
3519" argument.
3520def Test_objmethod_funcarg()
3521 var lines =<< trim END
3522 vim9script
3523
3524 class C
3525 def Foo(): string
3526 return 'foo'
3527 enddef
3528 endclass
3529
3530 def Bar(a: number, s: string): string
3531 return s
3532 enddef
3533
3534 def Baz(c: C)
3535 assert_equal('foo', Bar(10, c.Foo()))
3536 enddef
3537
3538 var t = C.new()
3539 Baz(t)
3540 END
3541 v9.CheckScriptSuccess(lines)
3542
3543 lines =<< trim END
3544 vim9script
3545
3546 class C
3547 static def Foo(): string
3548 return 'foo'
3549 enddef
3550 endclass
3551
3552 def Bar(a: number, s: string): string
3553 return s
3554 enddef
3555
3556 def Baz()
3557 assert_equal('foo', Bar(10, C.Foo()))
3558 enddef
3559
3560 Baz()
3561 END
3562 v9.CheckScriptSuccess(lines)
3563enddef
3564
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003565" Test for declaring duplicate object and class members
3566def Test_dup_member_variable()
3567 # Duplicate member variable
3568 var lines =<< trim END
3569 vim9script
3570 class C
3571 this.val = 10
3572 this.val = 20
3573 endclass
3574 END
3575 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3576
3577 # Duplicate private member variable
3578 lines =<< trim END
3579 vim9script
3580 class C
3581 this._val = 10
3582 this._val = 20
3583 endclass
3584 END
3585 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3586
3587 # Duplicate public member variable
3588 lines =<< trim END
3589 vim9script
3590 class C
3591 public this.val = 10
3592 public this.val = 20
3593 endclass
3594 END
3595 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3596
3597 # Duplicate private member variable
3598 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 public and private member variable
3608 lines =<< trim END
3609 vim9script
3610 class C
3611 this._val = 20
3612 public this.val = 10
3613 endclass
3614 END
3615 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3616
3617 # Duplicate class member variable
3618 lines =<< trim END
3619 vim9script
3620 class C
3621 static s: string = "abc"
3622 static _s: string = "def"
3623 endclass
3624 END
3625 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3626
3627 # Duplicate public and private class member variable
3628 lines =<< trim END
3629 vim9script
3630 class C
3631 public static s: string = "abc"
3632 static _s: string = "def"
3633 endclass
3634 END
3635 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3636
3637 # Duplicate class and object member variable
3638 lines =<< trim END
3639 vim9script
3640 class C
3641 static val = 10
3642 this.val = 20
3643 def new()
3644 enddef
3645 endclass
3646 var c = C.new()
3647 assert_equal(10, C.val)
3648 assert_equal(20, c.val)
3649 END
3650 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003651
3652 # Duplicate object member variable in a derived class
3653 lines =<< trim END
3654 vim9script
3655 class A
3656 this.val = 10
3657 endclass
3658 class B extends A
3659 endclass
3660 class C extends B
3661 this.val = 20
3662 endclass
3663 END
3664 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3665
3666 # Duplicate object private member variable in a derived class
3667 lines =<< trim END
3668 vim9script
3669 class A
3670 this._val = 10
3671 endclass
3672 class B extends A
3673 endclass
3674 class C extends B
3675 this._val = 20
3676 endclass
3677 END
3678 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3679
3680 # Duplicate object private member variable in a derived class
3681 lines =<< trim END
3682 vim9script
3683 class A
3684 this.val = 10
3685 endclass
3686 class B extends A
3687 endclass
3688 class C extends B
3689 this._val = 20
3690 endclass
3691 END
3692 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3693
3694 # Duplicate object member variable in a derived class
3695 lines =<< trim END
3696 vim9script
3697 class A
3698 this._val = 10
3699 endclass
3700 class B extends A
3701 endclass
3702 class C extends B
3703 this.val = 20
3704 endclass
3705 END
3706 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3707
3708 # Duplicate class member variable in a derived class
3709 lines =<< trim END
3710 vim9script
3711 class A
3712 static val = 10
3713 endclass
3714 class B extends A
3715 endclass
3716 class C extends B
3717 static val = 20
3718 endclass
3719 END
3720 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3721
3722 # Duplicate private class member variable in a derived class
3723 lines =<< trim END
3724 vim9script
3725 class A
3726 static _val = 10
3727 endclass
3728 class B extends A
3729 endclass
3730 class C extends B
3731 static _val = 20
3732 endclass
3733 END
3734 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3735
3736 # Duplicate private class member variable in a derived class
3737 lines =<< trim END
3738 vim9script
3739 class A
3740 static val = 10
3741 endclass
3742 class B extends A
3743 endclass
3744 class C extends B
3745 static _val = 20
3746 endclass
3747 END
3748 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3749
3750 # Duplicate class member variable in a derived class
3751 lines =<< trim END
3752 vim9script
3753 class A
3754 static _val = 10
3755 endclass
3756 class B extends A
3757 endclass
3758 class C extends B
3759 static val = 20
3760 endclass
3761 END
3762 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003763enddef
3764
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003765" Test for accessing a private member outside a class in a def function
3766def Test_private_member_access_outside_class()
3767 # private object member variable
3768 var lines =<< trim END
3769 vim9script
3770 class A
3771 this._val = 10
3772 def GetVal(): number
3773 return this._val
3774 enddef
3775 endclass
3776 def T()
3777 var a = A.new()
3778 a._val = 20
3779 enddef
3780 T()
3781 END
3782 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
3783
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003784 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003785 lines =<< trim END
3786 vim9script
3787 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003788 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003789 endclass
3790 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003791 var a = A.new()
3792 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003793 enddef
3794 T()
3795 END
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003796 v9.CheckScriptFailure(lines, 'E1089: Unknown variable: _a = 1')
3797enddef
3798
3799" Test for changing the member access of an interface in a implementation class
3800def Test_change_interface_member_access()
3801 var lines =<< trim END
3802 vim9script
3803 interface A
3804 public this.val: number
3805 endinterface
3806 class B implements A
3807 this.val = 10
3808 endclass
3809 END
3810 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
3811
3812 lines =<< trim END
3813 vim9script
3814 interface A
3815 this.val: number
3816 endinterface
3817 class B implements A
3818 public this.val = 10
3819 endclass
3820 END
3821 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
3822enddef
3823
3824" Test for trying to change a readonly member from a def function
3825def Test_readonly_member_change_in_def_func()
3826 var lines =<< trim END
3827 vim9script
3828 class A
3829 this.val: number
3830 endclass
3831 def T()
3832 var a = A.new()
3833 a.val = 20
3834 enddef
3835 T()
3836 END
3837 v9.CheckScriptFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003838enddef
3839
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02003840" Test for reading and writing a class member from a def function
3841def Test_modify_class_member_from_def_function()
3842 var lines =<< trim END
3843 vim9script
3844 class A
3845 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02003846 public static var2: list<number> = [1, 2]
3847 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02003848 static _priv_var4: number = 40
3849 endclass
3850 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02003851 assert_equal([1, 2], A.var2)
3852 assert_equal({a: 1, b: 2}, A.var3)
3853 A.var2 = [3, 4]
3854 A.var3 = {c: 3, d: 4}
3855 assert_equal([3, 4], A.var2)
3856 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02003857 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
3858 enddef
3859 T()
3860 END
3861 v9.CheckScriptSuccess(lines)
3862enddef
3863
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003864" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker