blob: 7ad53c763eff8fd7f5da6e26c524743a0b3b0fbe [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
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001310def Test_class_function()
1311 var lines =<< trim END
1312 vim9script
1313 class Value
1314 this.value = 0
1315 static objects = 0
1316
1317 def new(v: number)
1318 this.value = v
1319 ++objects
1320 enddef
1321
1322 static def GetCount(): number
1323 return objects
1324 enddef
1325 endclass
1326
1327 assert_equal(0, Value.GetCount())
1328 var v1 = Value.new(2)
1329 assert_equal(1, Value.GetCount())
1330 var v2 = Value.new(7)
1331 assert_equal(2, Value.GetCount())
1332 END
1333 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001334
1335 # Test for cleaning up after a class definition failure when using class
1336 # functions.
1337 lines =<< trim END
1338 vim9script
1339 class A
1340 static def Foo()
1341 enddef
1342 aaa
1343 endclass
1344 END
1345 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001346enddef
1347
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001348def Test_class_defcompile()
1349 var lines =<< trim END
1350 vim9script
1351
1352 class C
1353 def Fo(i: number): string
1354 return i
1355 enddef
1356 endclass
1357
1358 defcompile C.Fo
1359 END
1360 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1361
1362 lines =<< trim END
1363 vim9script
1364
1365 class C
1366 static def Fc(): number
1367 return 'x'
1368 enddef
1369 endclass
1370
1371 defcompile C.Fc
1372 END
1373 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001374
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001375 lines =<< trim END
1376 vim9script
1377
1378 class C
1379 static def new()
1380 enddef
1381 endclass
1382
1383 defcompile C.new
1384 END
1385 v9.CheckScriptFailure(lines, 'E1370: Cannot define a "new" function as static')
1386
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001387 # Trying to compile a function using a non-existing class variable
1388 lines =<< trim END
1389 vim9script
1390 defcompile x.Foo()
1391 END
1392 v9.CheckScriptFailure(lines, 'E475:')
1393
1394 # Trying to compile a function using a variable which is not a class
1395 lines =<< trim END
1396 vim9script
1397 var x: number
1398 defcompile x.Foo()
1399 END
1400 v9.CheckScriptFailure(lines, 'E475:')
1401
1402 # Trying to compile a function without specifying the name
1403 lines =<< trim END
1404 vim9script
1405 class A
1406 endclass
1407 defcompile A.
1408 END
1409 v9.CheckScriptFailure(lines, 'E475:')
1410
1411 # Trying to compile a non-existing class object member function
1412 lines =<< trim END
1413 vim9script
1414 class A
1415 endclass
1416 var a = A.new()
1417 defcompile a.Foo()
1418 END
1419 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001420enddef
1421
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001422def Test_class_object_to_string()
1423 var lines =<< trim END
1424 vim9script
1425 class TextPosition
1426 this.lnum = 1
1427 this.col = 22
1428 endclass
1429
1430 assert_equal("class TextPosition", string(TextPosition))
1431
1432 var pos = TextPosition.new()
1433 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1434 END
1435 v9.CheckScriptSuccess(lines)
1436enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001437
Bram Moolenaar554d0312023-01-05 19:59:18 +00001438def Test_interface_basics()
1439 var lines =<< trim END
1440 vim9script
1441 interface Something
1442 this.value: string
1443 static count: number
1444 def GetCount(): number
1445 endinterface
1446 END
1447 v9.CheckScriptSuccess(lines)
1448
1449 lines =<< trim END
1450 interface SomethingWrong
1451 static count = 7
1452 endinterface
1453 END
1454 v9.CheckScriptFailure(lines, 'E1342:')
1455
1456 lines =<< trim END
1457 vim9script
1458
1459 interface Some
1460 static count: number
1461 def Method(count: number)
1462 endinterface
1463 END
h-east61378a12023-04-18 19:07:29 +01001464 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001465
1466 lines =<< trim END
1467 vim9script
1468
1469 interface Some
1470 this.value: number
1471 def Method(value: number)
1472 endinterface
1473 END
h-east61378a12023-04-18 19:07:29 +01001474 # The argument name and the object member name are the same, but this is not a
1475 # problem because object members are always accessed with the "this." prefix.
1476 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001477
1478 lines =<< trim END
1479 vim9script
1480 interface somethingWrong
1481 static count = 7
1482 endinterface
1483 END
1484 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1485
1486 lines =<< trim END
1487 vim9script
1488 interface SomethingWrong
1489 this.value: string
1490 static count = 7
1491 def GetCount(): number
1492 endinterface
1493 END
1494 v9.CheckScriptFailure(lines, 'E1344:')
1495
1496 lines =<< trim END
1497 vim9script
1498 interface SomethingWrong
1499 this.value: string
1500 static count: number
1501 def GetCount(): number
1502 return 5
1503 enddef
1504 endinterface
1505 END
1506 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001507
1508 lines =<< trim END
1509 vim9script
1510 export interface EnterExit
1511 def Enter(): void
1512 def Exit(): void
1513 endinterface
1514 END
1515 writefile(lines, 'XdefIntf.vim', 'D')
1516
1517 lines =<< trim END
1518 vim9script
1519 import './XdefIntf.vim' as defIntf
1520 export def With(ee: defIntf.EnterExit, F: func)
1521 ee.Enter()
1522 try
1523 F()
1524 finally
1525 ee.Exit()
1526 endtry
1527 enddef
1528 END
1529 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001530
1531 var imported =<< trim END
1532 vim9script
1533 export abstract class EnterExit
1534 def Enter(): void
1535 enddef
1536 def Exit(): void
1537 enddef
1538 endclass
1539 END
1540 writefile(imported, 'XdefIntf2.vim', 'D')
1541
1542 lines[1] = " import './XdefIntf2.vim' as defIntf"
1543 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001544enddef
1545
Bram Moolenaar94674f22023-01-06 18:42:20 +00001546def Test_class_implements_interface()
1547 var lines =<< trim END
1548 vim9script
1549
1550 interface Some
1551 static count: number
1552 def Method(nr: number)
1553 endinterface
1554
1555 class SomeImpl implements Some
1556 static count: number
1557 def Method(nr: number)
1558 echo nr
1559 enddef
1560 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001561
1562 interface Another
1563 this.member: string
1564 endinterface
1565
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001566 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001567 this.member = 'abc'
1568 static count: number
1569 def Method(nr: number)
1570 echo nr
1571 enddef
1572 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001573 END
1574 v9.CheckScriptSuccess(lines)
1575
1576 lines =<< trim END
1577 vim9script
1578
1579 interface Some
1580 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001581 endinterface
1582
1583 class SomeImpl implements Some implements Some
1584 static count: number
1585 endclass
1586 END
1587 v9.CheckScriptFailure(lines, 'E1350:')
1588
1589 lines =<< trim END
1590 vim9script
1591
1592 interface Some
1593 static counter: number
1594 endinterface
1595
1596 class SomeImpl implements Some, Some
1597 static count: number
1598 endclass
1599 END
1600 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1601
1602 lines =<< trim END
1603 vim9script
1604
1605 interface Some
1606 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001607 def Method(nr: number)
1608 endinterface
1609
1610 class SomeImpl implements Some
1611 static count: number
1612 def Method(nr: number)
1613 echo nr
1614 enddef
1615 endclass
1616 END
1617 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1618
1619 lines =<< trim END
1620 vim9script
1621
1622 interface Some
1623 static count: number
1624 def Methods(nr: number)
1625 endinterface
1626
1627 class SomeImpl implements Some
1628 static count: number
1629 def Method(nr: number)
1630 echo nr
1631 enddef
1632 endclass
1633 END
1634 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001635
1636 # Check different order of members in class and interface works.
1637 lines =<< trim END
1638 vim9script
1639
1640 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001641 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001642 this.errpos: number
1643 endinterface
1644
1645 # order of members is opposite of interface
1646 class Failure implements Result
1647 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001648 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001649 endclass
1650
1651 def Test()
1652 var result: Result = Failure.new()
1653
1654 assert_equal('label', result.label)
1655 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001656
1657 result.label = 'different'
1658 assert_equal('different', result.label)
1659 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001660 enddef
1661
1662 Test()
1663 END
1664 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001665
1666 # Interface name after "extends" doesn't end in a space or NUL character
1667 lines =<< trim END
1668 vim9script
1669 interface A
1670 endinterface
1671 class B extends A"
1672 endclass
1673 END
1674 v9.CheckScriptFailure(lines, 'E1315:')
1675
1676 # Trailing characters after a class name
1677 lines =<< trim END
1678 vim9script
1679 class A bbb
1680 endclass
1681 END
1682 v9.CheckScriptFailure(lines, 'E488:')
1683
1684 # using "implements" with a non-existing class
1685 lines =<< trim END
1686 vim9script
1687 class A implements B
1688 endclass
1689 END
1690 v9.CheckScriptFailure(lines, 'E1346:')
1691
1692 # using "implements" with a regular class
1693 lines =<< trim END
1694 vim9script
1695 class A
1696 endclass
1697 class B implements A
1698 endclass
1699 END
1700 v9.CheckScriptFailure(lines, 'E1347:')
1701
1702 # using "implements" with a variable
1703 lines =<< trim END
1704 vim9script
1705 var T: number = 10
1706 class A implements T
1707 endclass
1708 END
1709 v9.CheckScriptFailure(lines, 'E1347:')
1710
1711 # all the class methods in an "interface" should be implemented
1712 lines =<< trim END
1713 vim9script
1714 interface A
1715 static def Foo()
1716 endinterface
1717 class B implements A
1718 endclass
1719 END
1720 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001721
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02001722 # implements should be followed by a white space
1723 lines =<< trim END
1724 vim9script
1725 interface A
1726 endinterface
1727 class B implements A;
1728 endclass
1729 END
1730 v9.CheckScriptFailure(lines, 'E1315:')
1731
LemonBoyc5d27442023-08-19 13:02:35 +02001732 lines =<< trim END
1733 vim9script
1734
1735 interface One
1736 static matching: bool
1737 static as_any: any
1738 static not_matching: number
1739 endinterface
1740 class Two implements One
1741 static not_matching: string
1742 static as_any: string
1743 static matching: bool
1744 endclass
1745 END
1746 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1747
1748 lines =<< trim END
1749 vim9script
1750
1751 interface One
1752 def IsEven(nr: number): bool
1753 endinterface
1754 class Two implements One
1755 def IsEven(nr: number): string
1756 enddef
1757 endclass
1758 END
1759 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1760
1761 lines =<< trim END
1762 vim9script
1763
1764 interface One
1765 def IsEven(nr: number): bool
1766 endinterface
1767 class Two implements One
1768 def IsEven(nr: bool): bool
1769 enddef
1770 endclass
1771 END
1772 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1773
1774 lines =<< trim END
1775 vim9script
1776
1777 interface One
1778 def IsEven(nr: number): bool
1779 endinterface
1780 class Two implements One
1781 def IsEven(nr: number, ...extra: list<number>): bool
1782 enddef
1783 endclass
1784 END
1785 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 +00001786enddef
1787
Bram Moolenaard0200c82023-01-28 15:19:40 +00001788def Test_call_interface_method()
1789 var lines =<< trim END
1790 vim9script
1791 interface Base
1792 def Enter(): void
1793 endinterface
1794
1795 class Child implements Base
1796 def Enter(): void
1797 g:result ..= 'child'
1798 enddef
1799 endclass
1800
1801 def F(obj: Base)
1802 obj.Enter()
1803 enddef
1804
1805 g:result = ''
1806 F(Child.new())
1807 assert_equal('child', g:result)
1808 unlet g:result
1809 END
1810 v9.CheckScriptSuccess(lines)
1811
1812 lines =<< trim END
1813 vim9script
1814 class Base
1815 def Enter(): void
1816 g:result ..= 'base'
1817 enddef
1818 endclass
1819
1820 class Child extends Base
1821 def Enter(): void
1822 g:result ..= 'child'
1823 enddef
1824 endclass
1825
1826 def F(obj: Base)
1827 obj.Enter()
1828 enddef
1829
1830 g:result = ''
1831 F(Child.new())
1832 assert_equal('child', g:result)
1833 unlet g:result
1834 END
1835 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001836
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001837 # method of interface returns a value
1838 lines =<< trim END
1839 vim9script
1840 interface Base
1841 def Enter(): string
1842 endinterface
1843
1844 class Child implements Base
1845 def Enter(): string
1846 g:result ..= 'child'
1847 return "/resource"
1848 enddef
1849 endclass
1850
1851 def F(obj: Base)
1852 var r = obj.Enter()
1853 g:result ..= r
1854 enddef
1855
1856 g:result = ''
1857 F(Child.new())
1858 assert_equal('child/resource', g:result)
1859 unlet g:result
1860 END
1861 v9.CheckScriptSuccess(lines)
1862
1863 lines =<< trim END
1864 vim9script
1865 class Base
1866 def Enter(): string
1867 return null_string
1868 enddef
1869 endclass
1870
1871 class Child extends Base
1872 def Enter(): string
1873 g:result ..= 'child'
1874 return "/resource"
1875 enddef
1876 endclass
1877
1878 def F(obj: Base)
1879 var r = obj.Enter()
1880 g:result ..= r
1881 enddef
1882
1883 g:result = ''
1884 F(Child.new())
1885 assert_equal('child/resource', g:result)
1886 unlet g:result
1887 END
1888 v9.CheckScriptSuccess(lines)
1889
1890
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001891 # No class that implements the interface.
1892 lines =<< trim END
1893 vim9script
1894
1895 interface IWithEE
1896 def Enter(): any
1897 def Exit(): void
1898 endinterface
1899
1900 def With1(ee: IWithEE, F: func)
1901 var r = ee.Enter()
1902 enddef
1903
1904 defcompile
1905 END
1906 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001907enddef
1908
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001909def Test_class_used_as_type()
1910 var lines =<< trim END
1911 vim9script
1912
1913 class Point
1914 this.x = 0
1915 this.y = 0
1916 endclass
1917
1918 var p: Point
1919 p = Point.new(2, 33)
1920 assert_equal(2, p.x)
1921 assert_equal(33, p.y)
1922 END
1923 v9.CheckScriptSuccess(lines)
1924
1925 lines =<< trim END
1926 vim9script
1927
1928 interface HasX
1929 this.x: number
1930 endinterface
1931
1932 class Point implements HasX
1933 this.x = 0
1934 this.y = 0
1935 endclass
1936
1937 var p: Point
1938 p = Point.new(2, 33)
1939 var hx = p
1940 assert_equal(2, hx.x)
1941 END
1942 v9.CheckScriptSuccess(lines)
1943
1944 lines =<< trim END
1945 vim9script
1946
1947 class Point
1948 this.x = 0
1949 this.y = 0
1950 endclass
1951
1952 var p: Point
1953 p = 'text'
1954 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001955 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001956enddef
1957
Bram Moolenaar83677162023-01-08 19:54:10 +00001958def Test_class_extends()
1959 var lines =<< trim END
1960 vim9script
1961 class Base
1962 this.one = 1
1963 def GetOne(): number
1964 return this.one
1965 enddef
1966 endclass
1967 class Child extends Base
1968 this.two = 2
1969 def GetTotal(): number
1970 return this.one + this.two
1971 enddef
1972 endclass
1973 var o = Child.new()
1974 assert_equal(1, o.one)
1975 assert_equal(2, o.two)
1976 assert_equal(1, o.GetOne())
1977 assert_equal(3, o.GetTotal())
1978 END
1979 v9.CheckScriptSuccess(lines)
1980
1981 lines =<< trim END
1982 vim9script
1983 class Base
1984 this.one = 1
1985 endclass
1986 class Child extends Base
1987 this.two = 2
1988 endclass
1989 var o = Child.new(3, 44)
1990 assert_equal(3, o.one)
1991 assert_equal(44, o.two)
1992 END
1993 v9.CheckScriptSuccess(lines)
1994
1995 lines =<< trim END
1996 vim9script
1997 class Base
1998 this.one = 1
1999 endclass
2000 class Child extends Base extends Base
2001 this.two = 2
2002 endclass
2003 END
2004 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
2005
2006 lines =<< trim END
2007 vim9script
2008 class Child extends BaseClass
2009 this.two = 2
2010 endclass
2011 END
2012 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
2013
2014 lines =<< trim END
2015 vim9script
2016 var SomeVar = 99
2017 class Child extends SomeVar
2018 this.two = 2
2019 endclass
2020 END
2021 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002022
2023 lines =<< trim END
2024 vim9script
2025 class Base
2026 this.name: string
2027 def ToString(): string
2028 return this.name
2029 enddef
2030 endclass
2031
2032 class Child extends Base
2033 this.age: number
2034 def ToString(): string
2035 return super.ToString() .. ': ' .. this.age
2036 enddef
2037 endclass
2038
2039 var o = Child.new('John', 42)
2040 assert_equal('John: 42', o.ToString())
2041 END
2042 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002043
2044 lines =<< trim END
2045 vim9script
2046 class Child
2047 this.age: number
2048 def ToString(): number
2049 return this.age
2050 enddef
2051 def ToString(): string
2052 return this.age
2053 enddef
2054 endclass
2055 END
2056 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
2057
2058 lines =<< trim END
2059 vim9script
2060 class Child
2061 this.age: number
2062 def ToString(): string
2063 return super .ToString() .. ': ' .. this.age
2064 enddef
2065 endclass
2066 var o = Child.new(42)
2067 echo o.ToString()
2068 END
2069 v9.CheckScriptFailure(lines, 'E1356:')
2070
2071 lines =<< trim END
2072 vim9script
2073 class Base
2074 this.name: string
2075 def ToString(): string
2076 return this.name
2077 enddef
2078 endclass
2079
2080 var age = 42
2081 def ToString(): string
2082 return super.ToString() .. ': ' .. age
2083 enddef
2084 echo ToString()
2085 END
2086 v9.CheckScriptFailure(lines, 'E1357:')
2087
2088 lines =<< trim END
2089 vim9script
2090 class Child
2091 this.age: number
2092 def ToString(): string
2093 return super.ToString() .. ': ' .. this.age
2094 enddef
2095 endclass
2096 var o = Child.new(42)
2097 echo o.ToString()
2098 END
2099 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002100
2101 lines =<< trim END
2102 vim9script
2103 class Base
2104 this.name: string
2105 static def ToString(): string
2106 return 'Base class'
2107 enddef
2108 endclass
2109
2110 class Child extends Base
2111 this.age: number
2112 def ToString(): string
2113 return Base.ToString() .. ': ' .. this.age
2114 enddef
2115 endclass
2116
2117 var o = Child.new('John', 42)
2118 assert_equal('Base class: 42', o.ToString())
2119 END
2120 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002121
2122 lines =<< trim END
2123 vim9script
2124 class Base
2125 this.value = 1
2126 def new(init: number)
2127 this.value = number + 1
2128 enddef
2129 endclass
2130 class Child extends Base
2131 def new()
2132 this.new(3)
2133 enddef
2134 endclass
2135 var c = Child.new()
2136 END
2137 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002138
2139 # base class with more than one object member
2140 lines =<< trim END
2141 vim9script
2142
2143 class Result
2144 this.success: bool
2145 this.value: any = null
2146 endclass
2147
2148 class Success extends Result
2149 def new(this.value = v:none)
2150 this.success = true
2151 enddef
2152 endclass
2153
2154 var v = Success.new('asdf')
2155 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2156 END
2157 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002158
2159 # class name after "extends" doesn't end in a space or NUL character
2160 lines =<< trim END
2161 vim9script
2162 class A
2163 endclass
2164 class B extends A"
2165 endclass
2166 END
2167 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002168enddef
2169
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002170def Test_using_base_class()
2171 var lines =<< trim END
2172 vim9script
2173
2174 class BaseEE
2175 def Enter(): any
2176 return null
2177 enddef
2178 def Exit(resource: any): void
2179 enddef
2180 endclass
2181
2182 class ChildEE extends BaseEE
2183 def Enter(): any
2184 return 42
2185 enddef
2186
2187 def Exit(resource: number): void
2188 g:result ..= '/exit'
2189 enddef
2190 endclass
2191
2192 def With(ee: BaseEE)
2193 var r = ee.Enter()
2194 try
2195 g:result ..= r
2196 finally
2197 g:result ..= '/finally'
2198 ee.Exit(r)
2199 endtry
2200 enddef
2201
2202 g:result = ''
2203 With(ChildEE.new())
2204 assert_equal('42/finally/exit', g:result)
2205 END
2206 v9.CheckScriptSuccess(lines)
2207 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002208
2209 # Using super, Child invokes Base method which has optional arg. #12471
2210 lines =<< trim END
2211 vim9script
2212
2213 class Base
2214 this.success: bool = false
2215 def Method(arg = 0)
2216 this.success = true
2217 enddef
2218 endclass
2219
2220 class Child extends Base
2221 def new()
2222 super.Method()
2223 enddef
2224 endclass
2225
2226 var obj = Child.new()
2227 assert_equal(true, obj.success)
2228 END
2229 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002230enddef
2231
2232
Bram Moolenaara86655a2023-01-12 17:06:27 +00002233def Test_class_import()
2234 var lines =<< trim END
2235 vim9script
2236 export class Animal
2237 this.kind: string
2238 this.name: string
2239 endclass
2240 END
2241 writefile(lines, 'Xanimal.vim', 'D')
2242
2243 lines =<< trim END
2244 vim9script
2245 import './Xanimal.vim' as animal
2246
2247 var a: animal.Animal
2248 a = animal.Animal.new('fish', 'Eric')
2249 assert_equal('fish', a.kind)
2250 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002251
2252 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2253 assert_equal('cat', b.kind)
2254 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002255 END
2256 v9.CheckScriptSuccess(lines)
2257enddef
2258
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002259def Test_abstract_class()
2260 var lines =<< trim END
2261 vim9script
2262 abstract class Base
2263 this.name: string
2264 endclass
2265 class Person extends Base
2266 this.age: number
2267 endclass
2268 var p: Base = Person.new('Peter', 42)
2269 assert_equal('Peter', p.name)
2270 assert_equal(42, p.age)
2271 END
2272 v9.CheckScriptSuccess(lines)
2273
2274 lines =<< trim END
2275 vim9script
2276 abstract class Base
2277 this.name: string
2278 endclass
2279 class Person extends Base
2280 this.age: number
2281 endclass
2282 var p = Base.new('Peter')
2283 END
2284 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2285
2286 lines =<< trim END
2287 abstract class Base
2288 this.name: string
2289 endclass
2290 END
2291 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002292
2293 # Abstract class cannot have a "new" function
2294 lines =<< trim END
2295 vim9script
2296 abstract class Base
2297 def new()
2298 enddef
2299 endclass
2300 END
2301 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002302enddef
2303
Bram Moolenaar486fc252023-01-18 14:51:07 +00002304def Test_closure_in_class()
2305 var lines =<< trim END
2306 vim9script
2307
2308 class Foo
2309 this.y: list<string> = ['B']
2310
2311 def new()
2312 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2313 enddef
2314 endclass
2315
2316 Foo.new()
2317 assert_equal(['A'], g:result)
2318 END
2319 v9.CheckScriptSuccess(lines)
2320enddef
2321
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002322def Test_call_constructor_from_legacy()
2323 var lines =<< trim END
2324 vim9script
2325
2326 var newCalled = 'false'
2327
2328 class A
2329 def new()
2330 newCalled = 'true'
2331 enddef
2332 endclass
2333
2334 export def F(options = {}): any
2335 return A
2336 enddef
2337
2338 g:p = F()
2339 legacy call p.new()
2340 assert_equal('true', newCalled)
2341 END
2342 v9.CheckScriptSuccess(lines)
2343enddef
2344
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002345def Test_defer_with_object()
2346 var lines =<< trim END
2347 vim9script
2348
2349 class CWithEE
2350 def Enter()
2351 g:result ..= "entered/"
2352 enddef
2353 def Exit()
2354 g:result ..= "exited"
2355 enddef
2356 endclass
2357
2358 def With(ee: CWithEE, F: func)
2359 ee.Enter()
2360 defer ee.Exit()
2361 F()
2362 enddef
2363
2364 g:result = ''
2365 var obj = CWithEE.new()
2366 obj->With(() => {
2367 g:result ..= "called/"
2368 })
2369 assert_equal('entered/called/exited', g:result)
2370 END
2371 v9.CheckScriptSuccess(lines)
2372 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002373
2374 lines =<< trim END
2375 vim9script
2376
2377 class BaseWithEE
2378 def Enter()
2379 g:result ..= "entered-base/"
2380 enddef
2381 def Exit()
2382 g:result ..= "exited-base"
2383 enddef
2384 endclass
2385
2386 class CWithEE extends BaseWithEE
2387 def Enter()
2388 g:result ..= "entered-child/"
2389 enddef
2390 def Exit()
2391 g:result ..= "exited-child"
2392 enddef
2393 endclass
2394
2395 def With(ee: BaseWithEE, F: func)
2396 ee.Enter()
2397 defer ee.Exit()
2398 F()
2399 enddef
2400
2401 g:result = ''
2402 var obj = CWithEE.new()
2403 obj->With(() => {
2404 g:result ..= "called/"
2405 })
2406 assert_equal('entered-child/called/exited-child', g:result)
2407 END
2408 v9.CheckScriptSuccess(lines)
2409 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002410enddef
2411
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002412" The following test used to crash Vim (Github issue #12676)
2413def Test_extends_method_crashes_vim()
2414 var lines =<< trim END
2415 vim9script
2416
2417 class Observer
2418 endclass
2419
2420 class Property
2421 this.value: any
2422
2423 def Set(v: any)
2424 if v != this.value
2425 this.value = v
2426 endif
2427 enddef
2428
2429 def Register(observer: Observer)
2430 enddef
2431 endclass
2432
2433 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002434 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002435 endclass
2436
2437 def Observe(obj: Property, who: Observer)
2438 obj.Register(who)
2439 enddef
2440
2441 var p = Bool.new(false)
2442 var myObserver = Observer.new()
2443
2444 Observe(p, myObserver)
2445
2446 p.Set(true)
2447 END
2448 v9.CheckScriptSuccess(lines)
2449enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002450
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002451" Test for calling a method in a class that is extended
2452def Test_call_method_in_extended_class()
2453 var lines =<< trim END
2454 vim9script
2455
2456 var prop_init_called = false
2457 var prop_register_called = false
2458
2459 class Property
2460 def Init()
2461 prop_init_called = true
2462 enddef
2463
2464 def Register()
2465 prop_register_called = true
2466 enddef
2467 endclass
2468
2469 class Bool extends Property
2470 endclass
2471
2472 def Observe(obj: Property)
2473 obj.Register()
2474 enddef
2475
2476 var p = Property.new()
2477 Observe(p)
2478
2479 p.Init()
2480 assert_true(prop_init_called)
2481 assert_true(prop_register_called)
2482 END
2483 v9.CheckScriptSuccess(lines)
2484enddef
2485
LemonBoyafe04662023-08-23 21:08:11 +02002486def Test_instanceof()
2487 var lines =<< trim END
2488 vim9script
2489
2490 class Base1
2491 endclass
2492
2493 class Base2 extends Base1
2494 endclass
2495
2496 interface Intf1
2497 endinterface
2498
2499 class Mix1 implements Intf1
2500 endclass
2501
2502 class Base3 extends Mix1
2503 endclass
2504
2505 var b1 = Base1.new()
2506 var b2 = Base2.new()
2507 var b3 = Base3.new()
2508
2509 assert_true(instanceof(b1, Base1))
2510 assert_true(instanceof(b2, Base1))
2511 assert_false(instanceof(b1, Base2))
2512 assert_true(instanceof(b3, Mix1))
2513 assert_false(instanceof(b3, []))
2514 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002515
2516 def Foo()
2517 var a1 = Base1.new()
2518 var a2 = Base2.new()
2519 var a3 = Base3.new()
2520
2521 assert_true(instanceof(a1, Base1))
2522 assert_true(instanceof(a2, Base1))
2523 assert_false(instanceof(a1, Base2))
2524 assert_true(instanceof(a3, Mix1))
2525 assert_false(instanceof(a3, []))
2526 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2527 enddef
2528 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002529 END
2530 v9.CheckScriptSuccess(lines)
2531enddef
2532
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002533" Test for calling a method in the parent class that is extended partially.
2534" This used to fail with the 'E118: Too many arguments for function: Text' error
2535" message (Github issue #12524).
2536def Test_call_method_in_parent_class()
2537 var lines =<< trim END
2538 vim9script
2539
2540 class Widget
2541 this._lnum: number = 1
2542
2543 def SetY(lnum: number)
2544 this._lnum = lnum
2545 enddef
2546
2547 def Text(): string
2548 return ''
2549 enddef
2550 endclass
2551
2552 class Foo extends Widget
2553 def Text(): string
2554 return '<Foo>'
2555 enddef
2556 endclass
2557
2558 def Stack(w1: Widget, w2: Widget): list<Widget>
2559 w1.SetY(1)
2560 w2.SetY(2)
2561 return [w1, w2]
2562 enddef
2563
2564 var foo1 = Foo.new()
2565 var foo2 = Foo.new()
2566 var l = Stack(foo1, foo2)
2567 END
2568 v9.CheckScriptSuccess(lines)
2569enddef
2570
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002571" Test for calling methods from three levels of classes
2572def Test_multi_level_method_call()
2573 var lines =<< trim END
2574 vim9script
2575
2576 var A_func1: number = 0
2577 var A_func2: number = 0
2578 var A_func3: number = 0
2579 var B_func2: number = 0
2580 var B_func3: number = 0
2581 var C_func3: number = 0
2582
2583 class A
2584 def Func1()
2585 A_func1 += 1
2586 enddef
2587
2588 def Func2()
2589 A_func2 += 1
2590 enddef
2591
2592 def Func3()
2593 A_func3 += 1
2594 enddef
2595 endclass
2596
2597 class B extends A
2598 def Func2()
2599 B_func2 += 1
2600 enddef
2601
2602 def Func3()
2603 B_func3 += 1
2604 enddef
2605 endclass
2606
2607 class C extends B
2608 def Func3()
2609 C_func3 += 1
2610 enddef
2611 endclass
2612
2613 def A_CallFuncs(a: A)
2614 a.Func1()
2615 a.Func2()
2616 a.Func3()
2617 enddef
2618
2619 def B_CallFuncs(b: B)
2620 b.Func1()
2621 b.Func2()
2622 b.Func3()
2623 enddef
2624
2625 def C_CallFuncs(c: C)
2626 c.Func1()
2627 c.Func2()
2628 c.Func3()
2629 enddef
2630
2631 var cobj = C.new()
2632 A_CallFuncs(cobj)
2633 B_CallFuncs(cobj)
2634 C_CallFuncs(cobj)
2635 assert_equal(3, A_func1)
2636 assert_equal(0, A_func2)
2637 assert_equal(0, A_func3)
2638 assert_equal(3, B_func2)
2639 assert_equal(0, B_func3)
2640 assert_equal(3, C_func3)
2641 END
2642 v9.CheckScriptSuccess(lines)
2643enddef
2644
2645" Test for using members from three levels of classes
2646def Test_multi_level_member_access()
2647 var lines =<< trim END
2648 vim9script
2649
2650 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002651 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002652 endclass
2653
2654 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002655 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002656 endclass
2657
2658 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02002659 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002660 endclass
2661
2662 def A_members(a: A)
2663 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002664 enddef
2665
2666 def B_members(b: B)
2667 b.val1 += 1
2668 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002669 enddef
2670
2671 def C_members(c: C)
2672 c.val1 += 1
2673 c.val2 += 1
2674 c.val3 += 1
2675 enddef
2676
2677 var cobj = C.new()
2678 A_members(cobj)
2679 B_members(cobj)
2680 C_members(cobj)
2681 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002682 assert_equal(2, cobj.val2)
2683 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002684 END
2685 v9.CheckScriptSuccess(lines)
2686enddef
2687
LemonBoy0ffc17a2023-08-20 18:09:11 +02002688" Test expansion of <stack> with class methods.
2689def Test_stack_expansion_with_methods()
2690 var lines =<< trim END
2691 vim9script
2692
2693 class C
2694 def M1()
2695 F0()
2696 enddef
2697 endclass
2698
2699 def F0()
2700 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2701 enddef
2702
2703 def F()
2704 C.new().M1()
2705 enddef
2706
2707 F()
2708 END
2709 v9.CheckScriptSuccess(lines)
2710enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002711
2712" Test the return type of the new() constructor
2713def Test_new_return_type()
2714 # new() uses the default return type and there is no return statement
2715 var lines =<< trim END
2716 vim9script
2717
2718 class C
2719 this._bufnr: number
2720
2721 def new(this._bufnr)
2722 if !bufexists(this._bufnr)
2723 this._bufnr = -1
2724 endif
2725 enddef
2726 endclass
2727
2728 var c = C.new(12345)
2729 assert_equal('object<C>', typename(c))
2730
2731 var v1: C
2732 v1 = C.new(12345)
2733 assert_equal('object<C>', typename(v1))
2734
2735 def F()
2736 var v2: C
2737 v2 = C.new(12345)
2738 assert_equal('object<C>', typename(v2))
2739 enddef
2740 F()
2741 END
2742 v9.CheckScriptSuccess(lines)
2743
2744 # new() uses the default return type and an empty 'return' statement
2745 lines =<< trim END
2746 vim9script
2747
2748 class C
2749 this._bufnr: number
2750
2751 def new(this._bufnr)
2752 if !bufexists(this._bufnr)
2753 this._bufnr = -1
2754 return
2755 endif
2756 enddef
2757 endclass
2758
2759 var c = C.new(12345)
2760 assert_equal('object<C>', typename(c))
2761
2762 var v1: C
2763 v1 = C.new(12345)
2764 assert_equal('object<C>', typename(v1))
2765
2766 def F()
2767 var v2: C
2768 v2 = C.new(12345)
2769 assert_equal('object<C>', typename(v2))
2770 enddef
2771 F()
2772 END
2773 v9.CheckScriptSuccess(lines)
2774
2775 # new() uses "any" return type and returns "this"
2776 lines =<< trim END
2777 vim9script
2778
2779 class C
2780 this._bufnr: number
2781
2782 def new(this._bufnr): any
2783 if !bufexists(this._bufnr)
2784 this._bufnr = -1
2785 return this
2786 endif
2787 enddef
2788 endclass
2789 END
2790 v9.CheckScriptFailure(lines, 'E1365:')
2791
2792 # new() uses 'Dict' return type and returns a Dict
2793 lines =<< trim END
2794 vim9script
2795
2796 class C
2797 this._state: dict<any>
2798
2799 def new(): dict<any>
2800 this._state = {}
2801 return this._state
2802 enddef
2803 endclass
2804
2805 var c = C.new()
2806 assert_equal('object<C>', typename(c))
2807 END
2808 v9.CheckScriptFailure(lines, 'E1365:')
2809enddef
2810
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02002811" Test for checking a member initialization type at run time.
2812def Test_runtime_type_check_for_member_init()
2813 var lines =<< trim END
2814 vim9script
2815
2816 var retnum: bool = false
2817
2818 def F(): any
2819 retnum = !retnum
2820 if retnum
2821 return 1
2822 else
2823 return "hello"
2824 endif
2825 enddef
2826
2827 class C
2828 this._foo: bool = F()
2829 endclass
2830
2831 var c1 = C.new()
2832 var c2 = C.new()
2833 END
2834 v9.CheckScriptFailure(lines, 'E1012:')
2835enddef
2836
2837" Test for locking a variable referring to an object and reassigning to another
2838" object.
2839def Test_object_lockvar()
2840 var lines =<< trim END
2841 vim9script
2842
2843 class C
2844 this.val: number
2845 def new(this.val)
2846 enddef
2847 endclass
2848
2849 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
2850 lockvar 2 some_dict
2851
2852 var current: C
2853 current = some_dict['c']
2854 assert_equal(3, current.val)
2855 current = some_dict['b']
2856 assert_equal(2, current.val)
2857
2858 def F()
2859 current = some_dict['c']
2860 enddef
2861
2862 def G()
2863 current = some_dict['b']
2864 enddef
2865
2866 F()
2867 assert_equal(3, current.val)
2868 G()
2869 assert_equal(2, current.val)
2870 END
2871 v9.CheckScriptSuccess(lines)
2872enddef
2873
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02002874" Test for a private object method
2875def Test_private_object_method()
2876 # Try calling a private method using an object (at the script level)
2877 var lines =<< trim END
2878 vim9script
2879
2880 class A
2881 def _Foo(): number
2882 return 1234
2883 enddef
2884 endclass
2885 var a = A.new()
2886 a._Foo()
2887 END
2888 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2889
2890 # Try calling a private method using an object (from a def function)
2891 lines =<< trim END
2892 vim9script
2893
2894 class A
2895 def _Foo(): number
2896 return 1234
2897 enddef
2898 endclass
2899 def T()
2900 var a = A.new()
2901 a._Foo()
2902 enddef
2903 T()
2904 END
2905 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2906
2907 # Use a private method from another object method (in script context)
2908 lines =<< trim END
2909 vim9script
2910
2911 class A
2912 def _Foo(): number
2913 return 1234
2914 enddef
2915 def Bar(): number
2916 return this._Foo()
2917 enddef
2918 endclass
2919 var a = A.new()
2920 assert_equal(1234, a.Bar())
2921 END
2922 v9.CheckScriptSuccess(lines)
2923
2924 # Use a private method from another object method (def function context)
2925 lines =<< trim END
2926 vim9script
2927
2928 class A
2929 def _Foo(): number
2930 return 1234
2931 enddef
2932 def Bar(): number
2933 return this._Foo()
2934 enddef
2935 endclass
2936 def T()
2937 var a = A.new()
2938 assert_equal(1234, a.Bar())
2939 enddef
2940 T()
2941 END
2942 v9.CheckScriptSuccess(lines)
2943
2944 # Try calling a private method without the "this" prefix
2945 lines =<< trim END
2946 vim9script
2947
2948 class A
2949 def _Foo(): number
2950 return 1234
2951 enddef
2952 def Bar(): number
2953 return _Foo()
2954 enddef
2955 endclass
2956 var a = A.new()
2957 a.Bar()
2958 END
2959 v9.CheckScriptFailure(lines, 'E117: Unknown function: _Foo')
2960
2961 # Try calling a private method using the class name
2962 lines =<< trim END
2963 vim9script
2964
2965 class A
2966 def _Foo(): number
2967 return 1234
2968 enddef
2969 endclass
2970 A._Foo()
2971 END
2972 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
2973
2974 # Try to use "public" keyword when defining a private method
2975 lines =<< trim END
2976 vim9script
2977
2978 class A
2979 public def _Foo()
2980 enddef
2981 endclass
2982 var a = A.new()
2983 a._Foo()
2984 END
2985 v9.CheckScriptFailure(lines, 'E1331: Public must be followed by "this" or "static"')
2986
2987 # Define two private methods with the same name
2988 lines =<< trim END
2989 vim9script
2990
2991 class A
2992 def _Foo()
2993 enddef
2994 def _Foo()
2995 enddef
2996 endclass
2997 var a = A.new()
2998 END
2999 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3000
3001 # Define a private method and a object method with the same name
3002 lines =<< trim END
3003 vim9script
3004
3005 class A
3006 def _Foo()
3007 enddef
3008 def Foo()
3009 enddef
3010 endclass
3011 var a = A.new()
3012 END
3013 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3014
3015 # Define an object method and a private method with the same name
3016 lines =<< trim END
3017 vim9script
3018
3019 class A
3020 def Foo()
3021 enddef
3022 def _Foo()
3023 enddef
3024 endclass
3025 var a = A.new()
3026 END
3027 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
3028
3029 # Call a public method and a private method from a private method
3030 lines =<< trim END
3031 vim9script
3032
3033 class A
3034 def Foo(): number
3035 return 100
3036 enddef
3037 def _Bar(): number
3038 return 200
3039 enddef
3040 def _Baz()
3041 assert_equal(100, this.Foo())
3042 assert_equal(200, this._Bar())
3043 enddef
3044 def T()
3045 this._Baz()
3046 enddef
3047 endclass
3048 var a = A.new()
3049 a.T()
3050 END
3051 v9.CheckScriptSuccess(lines)
3052
3053 # Try calling a private method from another class
3054 lines =<< trim END
3055 vim9script
3056
3057 class A
3058 def _Foo(): number
3059 return 100
3060 enddef
3061 endclass
3062 class B
3063 def Foo(): number
3064 var a = A.new()
3065 a._Foo()
3066 enddef
3067 endclass
3068 var b = B.new()
3069 b.Foo()
3070 END
3071 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3072
3073 # Call a private object method from a child class object method
3074 lines =<< trim END
3075 vim9script
3076 class A
3077 def _Foo(): number
3078 return 1234
3079 enddef
3080 endclass
3081 class B extends A
3082 def Bar()
3083 enddef
3084 endclass
3085 class C extends B
3086 def Baz(): number
3087 return this._Foo()
3088 enddef
3089 endclass
3090 var c = C.new()
3091 assert_equal(1234, c.Baz())
3092 END
3093 v9.CheckScriptSuccess(lines)
3094
3095 # Call a private object method from a child class object
3096 lines =<< trim END
3097 vim9script
3098 class A
3099 def _Foo(): number
3100 return 1234
3101 enddef
3102 endclass
3103 class B extends A
3104 def Bar()
3105 enddef
3106 endclass
3107 class C extends B
3108 def Baz(): number
3109 enddef
3110 endclass
3111 var c = C.new()
3112 assert_equal(1234, c._Foo())
3113 END
3114 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3115
3116 # Using "_" prefix in a method name should fail outside of a class
3117 lines =<< trim END
3118 vim9script
3119 def _Foo(): number
3120 return 1234
3121 enddef
3122 var a = _Foo()
3123 END
3124 v9.CheckScriptFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
3125enddef
3126
3127" Test for an private class method
3128def Test_private_class_method()
3129 # Try calling a class private method (at the script level)
3130 var lines =<< trim END
3131 vim9script
3132
3133 class A
3134 static def _Foo(): number
3135 return 1234
3136 enddef
3137 endclass
3138 A._Foo()
3139 END
3140 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3141
3142 # Try calling a class private method (from a def function)
3143 lines =<< trim END
3144 vim9script
3145
3146 class A
3147 static def _Foo(): number
3148 return 1234
3149 enddef
3150 endclass
3151 def T()
3152 A._Foo()
3153 enddef
3154 T()
3155 END
3156 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3157
3158 # Try calling a class private method using an object (at the script level)
3159 lines =<< trim END
3160 vim9script
3161
3162 class A
3163 static def _Foo(): number
3164 return 1234
3165 enddef
3166 endclass
3167 var a = A.new()
3168 a._Foo()
3169 END
3170 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3171
3172 # Try calling a class private method using an object (from a def function)
3173 lines =<< trim END
3174 vim9script
3175
3176 class A
3177 static def _Foo(): number
3178 return 1234
3179 enddef
3180 endclass
3181 def T()
3182 var a = A.new()
3183 a._Foo()
3184 enddef
3185 T()
3186 END
3187 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3188
3189 # Use a class private method from an object method
3190 lines =<< trim END
3191 vim9script
3192
3193 class A
3194 static def _Foo(): number
3195 return 1234
3196 enddef
3197 def Bar()
3198 assert_equal(1234, A._Foo())
3199 enddef
3200 endclass
3201 var a = A.new()
3202 a.Bar()
3203 END
3204 v9.CheckScriptSuccess(lines)
3205
3206 # Use a class private method from another class private method
3207 lines =<< trim END
3208 vim9script
3209
3210 class A
3211 static def _Foo1(): number
3212 return 1234
3213 enddef
3214 static def _Foo2()
3215 assert_equal(1234, A._Foo1())
3216 enddef
3217 def Bar()
3218 A._Foo2()
3219 enddef
3220 endclass
3221 var a = A.new()
3222 a.Bar()
3223 END
3224 v9.CheckScriptSuccess(lines)
3225
3226 # Declare a class method and a class private method with the same name
3227 lines =<< trim END
3228 vim9script
3229
3230 class A
3231 static def _Foo()
3232 enddef
3233 static def Foo()
3234 enddef
3235 endclass
3236 var a = A.new()
3237 END
3238 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3239
3240 # Try calling a class private method from another class
3241 lines =<< trim END
3242 vim9script
3243
3244 class A
3245 static def _Foo(): number
3246 return 1234
3247 enddef
3248 endclass
3249 class B
3250 def Foo(): number
3251 return A._Foo()
3252 enddef
3253 endclass
3254 var b = B.new()
3255 assert_equal(1234, b.Foo())
3256 END
3257 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3258
3259 # Call a private class method from a child class object method
3260 lines =<< trim END
3261 vim9script
3262 class A
3263 static def _Foo(): number
3264 return 1234
3265 enddef
3266 endclass
3267 class B extends A
3268 def Bar()
3269 enddef
3270 endclass
3271 class C extends B
3272 def Baz(): number
3273 return A._Foo()
3274 enddef
3275 endclass
3276 var c = C.new()
3277 assert_equal(1234, c.Baz())
3278 END
3279 v9.CheckScriptSuccess(lines)
3280
3281 # Call a private class method from a child class private class method
3282 lines =<< trim END
3283 vim9script
3284 class A
3285 static def _Foo(): number
3286 return 1234
3287 enddef
3288 endclass
3289 class B extends A
3290 def Bar()
3291 enddef
3292 endclass
3293 class C extends B
3294 static def Baz(): number
3295 return A._Foo()
3296 enddef
3297 endclass
3298 assert_equal(1234, C.Baz())
3299 END
3300 v9.CheckScriptSuccess(lines)
3301
3302 # Call a private class method from a child class object
3303 lines =<< trim END
3304 vim9script
3305 class A
3306 static def _Foo(): number
3307 return 1234
3308 enddef
3309 endclass
3310 class B extends A
3311 def Bar()
3312 enddef
3313 endclass
3314 class C extends B
3315 def Baz(): number
3316 enddef
3317 endclass
3318 var c = C.new()
3319 assert_equal(1234, C._Foo())
3320 END
3321 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3322enddef
3323
3324" Test for an interface private object_method
3325def Test_interface_private_object_method()
3326 # Implement an interface private method and use it from a public method
3327 var lines =<< trim END
3328 vim9script
3329 interface Intf
3330 def _Foo(): number
3331 endinterface
3332 class A implements Intf
3333 def _Foo(): number
3334 return 1234
3335 enddef
3336 def Bar(): number
3337 return this._Foo()
3338 enddef
3339 endclass
3340 var a = A.new()
3341 assert_equal(1234, a.Bar())
3342 END
3343 v9.CheckScriptSuccess(lines)
3344
3345 # Call an interface private class method (script context)
3346 lines =<< trim END
3347 vim9script
3348 interface Intf
3349 def _Foo(): number
3350 endinterface
3351 class A implements Intf
3352 def _Foo(): number
3353 return 1234
3354 enddef
3355 endclass
3356 var a = A.new()
3357 assert_equal(1234, a._Foo())
3358 END
3359 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3360
3361 # Call an interface private class method (def context)
3362 lines =<< trim END
3363 vim9script
3364 interface Intf
3365 def _Foo(): number
3366 endinterface
3367 class A implements Intf
3368 def _Foo(): number
3369 return 1234
3370 enddef
3371 endclass
3372 def T()
3373 var a = A.new()
3374 assert_equal(1234, a._Foo())
3375 enddef
3376 T()
3377 END
3378 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3379
3380 # Implement an interface private object method as a private class method
3381 lines =<< trim END
3382 vim9script
3383 interface Intf
3384 def _Foo(): number
3385 endinterface
3386 class A implements Intf
3387 static def _Foo(): number
3388 return 1234
3389 enddef
3390 endclass
3391 END
3392 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3393enddef
3394
3395" Test for an interface private class method
3396def Test_interface_private_class_method()
3397 # Implement an interface private class method and use it from a public method
3398 var lines =<< trim END
3399 vim9script
3400 interface Intf
3401 static def _Foo(): number
3402 endinterface
3403 class A implements Intf
3404 static def _Foo(): number
3405 return 1234
3406 enddef
3407 def Bar(): number
3408 return A._Foo()
3409 enddef
3410 endclass
3411 var a = A.new()
3412 assert_equal(1234, a.Bar())
3413 END
3414 v9.CheckScriptSuccess(lines)
3415
3416 # Call an interface private class method (script context)
3417 lines =<< trim END
3418 vim9script
3419 interface Intf
3420 static def _Foo(): number
3421 endinterface
3422 class A implements Intf
3423 static def _Foo(): number
3424 return 1234
3425 enddef
3426 endclass
3427 assert_equal(1234, A._Foo())
3428 END
3429 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3430
3431 # Call an interface private class method (def context)
3432 lines =<< trim END
3433 vim9script
3434 interface Intf
3435 static def _Foo(): number
3436 endinterface
3437 class A implements Intf
3438 static def _Foo(): number
3439 return 1234
3440 enddef
3441 endclass
3442 def T()
3443 assert_equal(1234, A._Foo())
3444 enddef
3445 T()
3446 END
3447 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3448
3449 # Implement an interface private class method as a private object method
3450 lines =<< trim END
3451 vim9script
3452 interface Intf
3453 static def _Foo(): number
3454 endinterface
3455 class A implements Intf
3456 def _Foo(): number
3457 return 1234
3458 enddef
3459 endclass
3460 END
3461 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3462enddef
3463
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003464" Test for using the return value of a class/object method as a function
3465" argument.
3466def Test_objmethod_funcarg()
3467 var lines =<< trim END
3468 vim9script
3469
3470 class C
3471 def Foo(): string
3472 return 'foo'
3473 enddef
3474 endclass
3475
3476 def Bar(a: number, s: string): string
3477 return s
3478 enddef
3479
3480 def Baz(c: C)
3481 assert_equal('foo', Bar(10, c.Foo()))
3482 enddef
3483
3484 var t = C.new()
3485 Baz(t)
3486 END
3487 v9.CheckScriptSuccess(lines)
3488
3489 lines =<< trim END
3490 vim9script
3491
3492 class C
3493 static def Foo(): string
3494 return 'foo'
3495 enddef
3496 endclass
3497
3498 def Bar(a: number, s: string): string
3499 return s
3500 enddef
3501
3502 def Baz()
3503 assert_equal('foo', Bar(10, C.Foo()))
3504 enddef
3505
3506 Baz()
3507 END
3508 v9.CheckScriptSuccess(lines)
3509enddef
3510
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003511" Test for declaring duplicate object and class members
3512def Test_dup_member_variable()
3513 # Duplicate member variable
3514 var lines =<< trim END
3515 vim9script
3516 class C
3517 this.val = 10
3518 this.val = 20
3519 endclass
3520 END
3521 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3522
3523 # Duplicate private member variable
3524 lines =<< trim END
3525 vim9script
3526 class C
3527 this._val = 10
3528 this._val = 20
3529 endclass
3530 END
3531 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3532
3533 # Duplicate public member variable
3534 lines =<< trim END
3535 vim9script
3536 class C
3537 public this.val = 10
3538 public this.val = 20
3539 endclass
3540 END
3541 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3542
3543 # Duplicate private member variable
3544 lines =<< trim END
3545 vim9script
3546 class C
3547 this.val = 10
3548 this._val = 20
3549 endclass
3550 END
3551 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3552
3553 # Duplicate public and private member variable
3554 lines =<< trim END
3555 vim9script
3556 class C
3557 this._val = 20
3558 public this.val = 10
3559 endclass
3560 END
3561 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3562
3563 # Duplicate class member variable
3564 lines =<< trim END
3565 vim9script
3566 class C
3567 static s: string = "abc"
3568 static _s: string = "def"
3569 endclass
3570 END
3571 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3572
3573 # Duplicate public and private class member variable
3574 lines =<< trim END
3575 vim9script
3576 class C
3577 public static s: string = "abc"
3578 static _s: string = "def"
3579 endclass
3580 END
3581 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3582
3583 # Duplicate class and object member variable
3584 lines =<< trim END
3585 vim9script
3586 class C
3587 static val = 10
3588 this.val = 20
3589 def new()
3590 enddef
3591 endclass
3592 var c = C.new()
3593 assert_equal(10, C.val)
3594 assert_equal(20, c.val)
3595 END
3596 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003597
3598 # Duplicate object member variable in a derived class
3599 lines =<< trim END
3600 vim9script
3601 class A
3602 this.val = 10
3603 endclass
3604 class B extends A
3605 endclass
3606 class C extends B
3607 this.val = 20
3608 endclass
3609 END
3610 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3611
3612 # Duplicate object private member variable in a derived class
3613 lines =<< trim END
3614 vim9script
3615 class A
3616 this._val = 10
3617 endclass
3618 class B extends A
3619 endclass
3620 class C extends B
3621 this._val = 20
3622 endclass
3623 END
3624 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3625
3626 # Duplicate object private member variable in a derived class
3627 lines =<< trim END
3628 vim9script
3629 class A
3630 this.val = 10
3631 endclass
3632 class B extends A
3633 endclass
3634 class C extends B
3635 this._val = 20
3636 endclass
3637 END
3638 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3639
3640 # Duplicate object member variable in a derived class
3641 lines =<< trim END
3642 vim9script
3643 class A
3644 this._val = 10
3645 endclass
3646 class B extends A
3647 endclass
3648 class C extends B
3649 this.val = 20
3650 endclass
3651 END
3652 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3653
3654 # Duplicate class member variable in a derived class
3655 lines =<< trim END
3656 vim9script
3657 class A
3658 static val = 10
3659 endclass
3660 class B extends A
3661 endclass
3662 class C extends B
3663 static val = 20
3664 endclass
3665 END
3666 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3667
3668 # Duplicate private class member variable in a derived class
3669 lines =<< trim END
3670 vim9script
3671 class A
3672 static _val = 10
3673 endclass
3674 class B extends A
3675 endclass
3676 class C extends B
3677 static _val = 20
3678 endclass
3679 END
3680 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3681
3682 # Duplicate private class member variable in a derived class
3683 lines =<< trim END
3684 vim9script
3685 class A
3686 static val = 10
3687 endclass
3688 class B extends A
3689 endclass
3690 class C extends B
3691 static _val = 20
3692 endclass
3693 END
3694 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3695
3696 # Duplicate class member variable in a derived class
3697 lines =<< trim END
3698 vim9script
3699 class A
3700 static _val = 10
3701 endclass
3702 class B extends A
3703 endclass
3704 class C extends B
3705 static val = 20
3706 endclass
3707 END
3708 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003709enddef
3710
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003711" Test for accessing a private member outside a class in a def function
3712def Test_private_member_access_outside_class()
3713 # private object member variable
3714 var lines =<< trim END
3715 vim9script
3716 class A
3717 this._val = 10
3718 def GetVal(): number
3719 return this._val
3720 enddef
3721 endclass
3722 def T()
3723 var a = A.new()
3724 a._val = 20
3725 enddef
3726 T()
3727 END
3728 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
3729
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003730 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003731 lines =<< trim END
3732 vim9script
3733 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003734 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003735 endclass
3736 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003737 var a = A.new()
3738 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003739 enddef
3740 T()
3741 END
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003742 v9.CheckScriptFailure(lines, 'E1089: Unknown variable: _a = 1')
3743enddef
3744
3745" Test for changing the member access of an interface in a implementation class
3746def Test_change_interface_member_access()
3747 var lines =<< trim END
3748 vim9script
3749 interface A
3750 public this.val: number
3751 endinterface
3752 class B implements A
3753 this.val = 10
3754 endclass
3755 END
3756 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
3757
3758 lines =<< trim END
3759 vim9script
3760 interface A
3761 this.val: number
3762 endinterface
3763 class B implements A
3764 public this.val = 10
3765 endclass
3766 END
3767 v9.CheckScriptFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
3768enddef
3769
3770" Test for trying to change a readonly member from a def function
3771def Test_readonly_member_change_in_def_func()
3772 var lines =<< trim END
3773 vim9script
3774 class A
3775 this.val: number
3776 endclass
3777 def T()
3778 var a = A.new()
3779 a.val = 20
3780 enddef
3781 T()
3782 END
3783 v9.CheckScriptFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003784enddef
3785
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02003786" Test for reading and writing a class member from a def function
3787def Test_modify_class_member_from_def_function()
3788 var lines =<< trim END
3789 vim9script
3790 class A
3791 this.var1: number = 10
3792 public static var2 = 20
3793 public static var3 = 30
3794 static _priv_var4: number = 40
3795 endclass
3796 def T()
3797 assert_equal(20, A.var2)
3798 assert_equal(30, A.var3)
3799 A.var2 = 50
3800 A.var3 = 60
3801 assert_equal(50, A.var2)
3802 assert_equal(60, A.var3)
3803 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
3804 enddef
3805 T()
3806 END
3807 v9.CheckScriptSuccess(lines)
3808enddef
3809
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003810" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker